@recaptime-dev's working patches + fork for Phorge, a community fork of Phabricator. (Upstream dev and stable branches are at upstream/main and upstream/stable respectively.) hq.recaptime.dev/wiki/Phorge
phorge phabricator
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Allow Spaces to be archived

Summary:
Ref T8377. This adds a standard disable/enable feature to Spaces, with a couple of twists:

- You can't create new stuff in an archived space, and you can't move stuff into an archived space.
- We don't show results from an archived space by default in ApplicationSearch queries. You can still find these objects if you explicitly search for "Spaces: <the archived space>".

So this is a "put it in a box in the attic" sort of operation, but that seems fairly nice/reasonable.

Test Plan:
- Archived and activated spaces.
- Used ApplicationSearch, which omitted archived objects by default but allowed searches for them, specifically, to succeed.
- Tried to create objects into an archived space (this is not allowed).
- Edited objects in an archived space (this is OK).

Reviewers: btrahan

Reviewed By: btrahan

Subscribers: epriestley

Maniphest Tasks: T8377

Differential Revision: https://secure.phabricator.com/D13238

+308 -37
+2
resources/sql/autopatches/20150610.spaces.3.archive.sql
··· 1 + ALTER TABLE {$NAMESPACE}_spaces.spaces_namespace 2 + ADD isArchived BOOL NOT NULL;
+2
src/__phutil_library_map__.php
··· 2577 2577 'PhabricatorSortTableUIExample' => 'applications/uiexample/examples/PhabricatorSortTableUIExample.php', 2578 2578 'PhabricatorSourceCodeView' => 'view/layout/PhabricatorSourceCodeView.php', 2579 2579 'PhabricatorSpacesApplication' => 'applications/spaces/application/PhabricatorSpacesApplication.php', 2580 + 'PhabricatorSpacesArchiveController' => 'applications/spaces/controller/PhabricatorSpacesArchiveController.php', 2580 2581 'PhabricatorSpacesCapabilityCreateSpaces' => 'applications/spaces/capability/PhabricatorSpacesCapabilityCreateSpaces.php', 2581 2582 'PhabricatorSpacesCapabilityDefaultEdit' => 'applications/spaces/capability/PhabricatorSpacesCapabilityDefaultEdit.php', 2582 2583 'PhabricatorSpacesCapabilityDefaultView' => 'applications/spaces/capability/PhabricatorSpacesCapabilityDefaultView.php', ··· 6089 6090 'PhabricatorSortTableUIExample' => 'PhabricatorUIExample', 6090 6091 'PhabricatorSourceCodeView' => 'AphrontView', 6091 6092 'PhabricatorSpacesApplication' => 'PhabricatorApplication', 6093 + 'PhabricatorSpacesArchiveController' => 'PhabricatorSpacesController', 6092 6094 'PhabricatorSpacesCapabilityCreateSpaces' => 'PhabricatorPolicyCapability', 6093 6095 'PhabricatorSpacesCapabilityDefaultEdit' => 'PhabricatorPolicyCapability', 6094 6096 'PhabricatorSpacesCapabilityDefaultView' => 'PhabricatorPolicyCapability',
+1 -1
src/applications/people/storage/PhabricatorUser.php
··· 759 759 // for now just use the global space if one exists. 760 760 761 761 // If the viewer has access to the default space, use that. 762 - $spaces = PhabricatorSpacesNamespaceQuery::getViewerSpaces($this); 762 + $spaces = PhabricatorSpacesNamespaceQuery::getViewerActiveSpaces($this); 763 763 foreach ($spaces as $space) { 764 764 if ($space->getIsDefaultNamespace()) { 765 765 return $space->getPHID();
+4
src/applications/search/engine/PhabricatorApplicationSearchEngine.php
··· 149 149 if ($object instanceof PhabricatorSpacesInterface) { 150 150 if (!empty($map['spacePHIDs'])) { 151 151 $query->withSpacePHIDs($map['spacePHIDs']); 152 + } else { 153 + // If the user doesn't search for objects in specific spaces, we 154 + // default to "all active spaces you have permission to view". 155 + $query->withSpaceIsArchived(false); 152 156 } 153 157 } 154 158
+11
src/applications/spaces/application/PhabricatorSpacesApplication.php
··· 38 38 return true; 39 39 } 40 40 41 + public function getHelpDocumentationArticles(PhabricatorUser $viewer) { 42 + return array( 43 + array( 44 + 'name' => pht('Spaces User Guide'), 45 + 'href' => PhabricatorEnv::getDoclink('Spaces User Guide'), 46 + ), 47 + ); 48 + } 49 + 41 50 public function getRemarkupRules() { 42 51 return array( 43 52 new PhabricatorSpacesRemarkupRule(), ··· 51 60 '(?:query/(?P<queryKey>[^/]+)/)?' => 'PhabricatorSpacesListController', 52 61 'create/' => 'PhabricatorSpacesEditController', 53 62 'edit/(?:(?P<id>\d+)/)?' => 'PhabricatorSpacesEditController', 63 + '(?P<action>activate|archive)/(?P<id>\d+)/' 64 + => 'PhabricatorSpacesArchiveController', 54 65 ), 55 66 ); 56 67 }
+76
src/applications/spaces/controller/PhabricatorSpacesArchiveController.php
··· 1 + <?php 2 + 3 + final class PhabricatorSpacesArchiveController 4 + extends PhabricatorSpacesController { 5 + 6 + public function handleRequest(AphrontRequest $request) { 7 + $viewer = $request->getUser(); 8 + 9 + $space = id(new PhabricatorSpacesNamespaceQuery()) 10 + ->setViewer($viewer) 11 + ->withIDs(array($request->getURIData('id'))) 12 + ->requireCapabilities( 13 + array( 14 + PhabricatorPolicyCapability::CAN_VIEW, 15 + PhabricatorPolicyCapability::CAN_EDIT, 16 + )) 17 + ->executeOne(); 18 + if (!$space) { 19 + return new Aphront404Response(); 20 + } 21 + 22 + $is_archive = ($request->getURIData('action') == 'archive'); 23 + $cancel_uri = '/'.$space->getMonogram(); 24 + 25 + if ($request->isFormPost()) { 26 + $type_archive = PhabricatorSpacesNamespaceTransaction::TYPE_ARCHIVE; 27 + 28 + $xactions = array(); 29 + $xactions[] = id(new PhabricatorSpacesNamespaceTransaction()) 30 + ->setTransactionType($type_archive) 31 + ->setNewValue($is_archive ? 1 : 0); 32 + 33 + $editor = id(new PhabricatorSpacesNamespaceEditor()) 34 + ->setActor($viewer) 35 + ->setContinueOnNoEffect(true) 36 + ->setContinueOnMissingFields(true) 37 + ->setContentSourceFromRequest($request); 38 + 39 + $editor->applyTransactions($space, $xactions); 40 + 41 + return id(new AphrontRedirectResponse())->setURI($cancel_uri); 42 + } 43 + 44 + $body = array(); 45 + if ($is_archive) { 46 + $title = pht('Archive Space: %s', $space->getNamespaceName()); 47 + $body[] = pht( 48 + 'If you archive this Space, you will no longer be able to create '. 49 + 'new objects inside it.'); 50 + $body[] = pht( 51 + 'Existing objects in this Space will be hidden from query results '. 52 + 'by default.'); 53 + $button = pht('Archive Space'); 54 + } else { 55 + $title = pht('Activate Space: %s', $space->getNamespaceName()); 56 + $body[] = pht( 57 + 'If you activate this space, you will be able to create objects '. 58 + 'inside it again.'); 59 + $body[] = pht( 60 + 'Existing objects will no longer be hidden from query results.'); 61 + $button = pht('Activate Space'); 62 + } 63 + 64 + 65 + $dialog = $this->newDialog() 66 + ->setTitle($title) 67 + ->addCancelButton($cancel_uri) 68 + ->addSubmitButton($button); 69 + 70 + foreach ($body as $paragraph) { 71 + $dialog->appendParagraph($paragraph); 72 + } 73 + 74 + return $dialog; 75 + } 76 + }
+26
src/applications/spaces/controller/PhabricatorSpacesViewController.php
··· 37 37 ->setHeader($space->getNamespaceName()) 38 38 ->setPolicyObject($space); 39 39 40 + if ($space->getIsArchived()) { 41 + $header->setStatus('fa-ban', 'red', pht('Archived')); 42 + } else { 43 + $header->setStatus('fa-check', 'bluegrey', pht('Active')); 44 + } 45 + 40 46 $box = id(new PHUIObjectBoxView()) 41 47 ->setHeader($header) 42 48 ->addPropertyList($property_list); ··· 111 117 ->setHref($this->getApplicationURI('edit/'.$space->getID().'/')) 112 118 ->setWorkflow(!$can_edit) 113 119 ->setDisabled(!$can_edit)); 120 + 121 + $id = $space->getID(); 122 + 123 + if ($space->getIsArchived()) { 124 + $list->addAction( 125 + id(new PhabricatorActionView()) 126 + ->setName(pht('Activate Space')) 127 + ->setIcon('fa-check') 128 + ->setHref($this->getApplicationURI("activate/{$id}/")) 129 + ->setDisabled(!$can_edit) 130 + ->setWorkflow(true)); 131 + } else { 132 + $list->addAction( 133 + id(new PhabricatorActionView()) 134 + ->setName(pht('Archive Space')) 135 + ->setIcon('fa-ban') 136 + ->setHref($this->getApplicationURI("archive/{$id}/")) 137 + ->setDisabled(!$can_edit) 138 + ->setWorkflow(true)); 139 + } 114 140 115 141 return $list; 116 142 }
+24 -1
src/applications/spaces/editor/PhabricatorSpacesNamespaceEditor.php
··· 17 17 $types[] = PhabricatorSpacesNamespaceTransaction::TYPE_NAME; 18 18 $types[] = PhabricatorSpacesNamespaceTransaction::TYPE_DESCRIPTION; 19 19 $types[] = PhabricatorSpacesNamespaceTransaction::TYPE_DEFAULT; 20 + $types[] = PhabricatorSpacesNamespaceTransaction::TYPE_ARCHIVE; 20 21 21 22 $types[] = PhabricatorTransactions::TYPE_VIEW_POLICY; 22 23 $types[] = PhabricatorTransactions::TYPE_EDIT_POLICY; ··· 40 41 return null; 41 42 } 42 43 return $object->getDescription(); 44 + case PhabricatorSpacesNamespaceTransaction::TYPE_ARCHIVE: 45 + return $object->getIsArchived(); 43 46 case PhabricatorSpacesNamespaceTransaction::TYPE_DEFAULT: 44 47 return $object->getIsDefaultNamespace() ? 1 : null; 45 48 case PhabricatorTransactions::TYPE_VIEW_POLICY: ··· 61 64 case PhabricatorTransactions::TYPE_VIEW_POLICY: 62 65 case PhabricatorTransactions::TYPE_EDIT_POLICY: 63 66 return $xaction->getNewValue(); 67 + case PhabricatorSpacesNamespaceTransaction::TYPE_ARCHIVE: 68 + return $xaction->getNewValue() ? 1 : 0; 64 69 case PhabricatorSpacesNamespaceTransaction::TYPE_DEFAULT: 65 70 return $xaction->getNewValue() ? 1 : null; 66 71 } ··· 84 89 case PhabricatorSpacesNamespaceTransaction::TYPE_DEFAULT: 85 90 $object->setIsDefaultNamespace($new ? 1 : null); 86 91 return; 92 + case PhabricatorSpacesNamespaceTransaction::TYPE_ARCHIVE: 93 + $object->setIsArchived($new ? 1 : 0); 94 + return; 87 95 case PhabricatorTransactions::TYPE_VIEW_POLICY: 88 96 $object->setViewPolicy($new); 89 97 return; ··· 103 111 case PhabricatorSpacesNamespaceTransaction::TYPE_NAME: 104 112 case PhabricatorSpacesNamespaceTransaction::TYPE_DESCRIPTION: 105 113 case PhabricatorSpacesNamespaceTransaction::TYPE_DEFAULT: 114 + case PhabricatorSpacesNamespaceTransaction::TYPE_ARCHIVE: 106 115 case PhabricatorTransactions::TYPE_VIEW_POLICY: 107 116 case PhabricatorTransactions::TYPE_EDIT_POLICY: 108 117 return; ··· 128 137 $error = new PhabricatorApplicationTransactionValidationError( 129 138 $type, 130 139 pht('Required'), 131 - pht('Spaces must have a name.'), 140 + pht('Spaces must have a name.'), 132 141 nonempty(last($xactions), null)); 133 142 134 143 $error->setIsMissingFieldError(true); 135 144 $errors[] = $error; 136 145 } 137 146 break; 147 + case PhabricatorSpacesNamespaceTransaction::TYPE_DEFAULT: 148 + if (!$this->getIsNewObject()) { 149 + foreach ($xactions as $xaction) { 150 + $errors[] = new PhabricatorApplicationTransactionValidationError( 151 + $type, 152 + pht('Invalid'), 153 + pht( 154 + 'Only the first space created can be the default space, and '. 155 + 'it must remain the default space evermore.'), 156 + $xaction); 157 + } 158 + } 159 + break; 160 + 138 161 } 139 162 140 163 return $errors;
+4
src/applications/spaces/phid/PhabricatorSpacesNamespacePHIDType.php
··· 39 39 $handle->setName($name); 40 40 $handle->setFullName(pht('%s %s', $monogram, $name)); 41 41 $handle->setURI('/'.$monogram); 42 + 43 + if ($namespace->getIsArchived()) { 44 + $handle->setStatus(PhabricatorObjectHandle::STATUS_CLOSED); 45 + } 42 46 } 43 47 } 44 48
+36 -20
src/applications/spaces/query/PhabricatorSpacesNamespaceQuery.php
··· 9 9 private $ids; 10 10 private $phids; 11 11 private $isDefaultNamespace; 12 + private $isArchived; 12 13 13 14 public function withIDs(array $ids) { 14 15 $this->ids = $ids; ··· 25 26 return $this; 26 27 } 27 28 29 + public function withIsArchived($archived) { 30 + $this->isArchived = $archived; 31 + return $this; 32 + } 33 + 28 34 public function getQueryApplicationClass() { 29 35 return 'PhabricatorSpacesApplication'; 30 36 } 31 37 32 38 protected function loadPage() { 33 - $table = new PhabricatorSpacesNamespace(); 34 - $conn_r = $table->establishConnection('r'); 35 - 36 - $rows = queryfx_all( 37 - $conn_r, 38 - 'SELECT * FROM %T %Q %Q %Q', 39 - $table->getTableName(), 40 - $this->buildWhereClause($conn_r), 41 - $this->buildOrderClause($conn_r), 42 - $this->buildLimitClause($conn_r)); 43 - 44 - return $table->loadAllFromArray($rows); 39 + return $this->loadStandardPage(new PhabricatorSpacesNamespace()); 45 40 } 46 41 47 - protected function buildWhereClause(AphrontDatabaseConnection $conn_r) { 48 - $where = array(); 42 + protected function buildWhereClauseParts(AphrontDatabaseConnection $conn) { 43 + $where = parent::buildWhereClauseParts($conn); 49 44 50 45 if ($this->ids !== null) { 51 46 $where[] = qsprintf( 52 - $conn_r, 47 + $conn, 53 48 'id IN (%Ld)', 54 49 $this->ids); 55 50 } 56 51 57 52 if ($this->phids !== null) { 58 53 $where[] = qsprintf( 59 - $conn_r, 54 + $conn, 60 55 'phid IN (%Ls)', 61 56 $this->phids); 62 57 } ··· 64 59 if ($this->isDefaultNamespace !== null) { 65 60 if ($this->isDefaultNamespace) { 66 61 $where[] = qsprintf( 67 - $conn_r, 62 + $conn, 68 63 'isDefaultNamespace = 1'); 69 64 } else { 70 65 $where[] = qsprintf( 71 - $conn_r, 66 + $conn, 72 67 'isDefaultNamespace IS NULL'); 73 68 } 74 69 } 75 70 76 - $where[] = $this->buildPagingClause($conn_r); 77 - return $this->formatWhereClause($where); 71 + if ($this->isArchived !== null) { 72 + $where[] = qsprintf( 73 + $conn, 74 + 'isArchived = %d', 75 + (int)$this->isArchived); 76 + } 77 + 78 + return $where; 78 79 } 79 80 80 81 public static function destroySpacesCache() { ··· 155 156 156 157 return $result; 157 158 } 159 + 160 + 161 + public static function getViewerActiveSpaces(PhabricatorUser $viewer) { 162 + $spaces = self::getViewerSpaces($viewer); 163 + 164 + foreach ($spaces as $key => $space) { 165 + if ($space->getIsArchived()) { 166 + unset($spaces[$key]); 167 + } 168 + } 169 + 170 + return $spaces; 171 + } 172 + 173 + 158 174 159 175 /** 160 176 * Get the Space PHID for an object, if one exists.
+26 -10
src/applications/spaces/query/PhabricatorSpacesNamespaceSearchEngine.php
··· 11 11 return pht('Spaces'); 12 12 } 13 13 14 - public function buildSavedQueryFromRequest(AphrontRequest $request) { 15 - $saved = new PhabricatorSavedQuery(); 14 + public function newQuery() { 15 + return new PhabricatorSpacesNamespaceQuery(); 16 + } 16 17 17 - return $saved; 18 + public function buildCustomSearchFields() { 19 + return array( 20 + id(new PhabricatorSearchThreeStateField()) 21 + ->setLabel(pht('Active')) 22 + ->setKey('active') 23 + ->setOptions( 24 + pht('(Show All)'), 25 + pht('Show Only Active Spaces'), 26 + pht('Hide Active Spaces')), 27 + ); 18 28 } 19 29 20 - public function buildQueryFromSavedQuery(PhabricatorSavedQuery $saved) { 21 - $query = id(new PhabricatorSpacesNamespaceQuery()); 30 + public function buildQueryFromParameters(array $map) { 31 + $query = $this->newQuery(); 32 + 33 + if ($map['active']) { 34 + $query->withIsArchived(!$map['active']); 35 + } 22 36 23 37 return $query; 24 38 } 25 39 26 - public function buildSearchForm( 27 - AphrontFormView $form, 28 - PhabricatorSavedQuery $saved_query) {} 29 - 30 40 protected function getURI($path) { 31 41 return '/spaces/'.$path; 32 42 } 33 43 34 44 protected function getBuiltinQueryNames() { 35 45 $names = array( 46 + 'active' => pht('Active Spaces'), 36 47 'all' => pht('All Spaces'), 37 48 ); 38 49 ··· 40 51 } 41 52 42 53 public function buildSavedQueryFromBuiltin($query_key) { 43 - 44 54 $query = $this->newSavedQuery(); 45 55 $query->setQueryKey($query_key); 46 56 47 57 switch ($query_key) { 58 + case 'active': 59 + return $query->setParameter('active', true); 48 60 case 'all': 49 61 return $query; 50 62 } ··· 70 82 71 83 if ($space->getIsDefaultNamespace()) { 72 84 $item->addIcon('fa-certificate', pht('Default Space')); 85 + } 86 + 87 + if ($space->getIsArchived()) { 88 + $item->setDisabled(true); 73 89 } 74 90 75 91 $list->addItem($item);
+4 -1
src/applications/spaces/storage/PhabricatorSpacesNamespace.php
··· 12 12 protected $editPolicy; 13 13 protected $isDefaultNamespace; 14 14 protected $description; 15 + protected $isArchived; 15 16 16 17 public static function initializeNewNamespace(PhabricatorUser $actor) { 17 18 $app = id(new PhabricatorApplicationQuery()) ··· 28 29 ->setIsDefaultNamespace(null) 29 30 ->setViewPolicy($view_policy) 30 31 ->setEditPolicy($edit_policy) 31 - ->setDescription(''); 32 + ->setDescription('') 33 + ->setIsArchived(0); 32 34 } 33 35 34 36 protected function getConfiguration() { ··· 38 40 'namespaceName' => 'text255', 39 41 'isDefaultNamespace' => 'bool?', 40 42 'description' => 'text', 43 + 'isArchived' => 'bool', 41 44 ), 42 45 self::CONFIG_KEY_SCHEMA => array( 43 46 'key_default' => array(
+11
src/applications/spaces/storage/PhabricatorSpacesNamespaceTransaction.php
··· 6 6 const TYPE_NAME = 'spaces:name'; 7 7 const TYPE_DEFAULT = 'spaces:default'; 8 8 const TYPE_DESCRIPTION = 'spaces:description'; 9 + const TYPE_ARCHIVE = 'spaces:archive'; 9 10 10 11 public function getApplicationName() { 11 12 return 'spaces'; ··· 78 79 return pht( 79 80 '%s made this the default space.', 80 81 $this->renderHandleLink($author_phid)); 82 + case self::TYPE_ARCHIVE: 83 + if ($new) { 84 + return pht( 85 + '%s archived this space.', 86 + $this->renderHandleLink($author_phid)); 87 + } else { 88 + return pht( 89 + '%s activated this space.', 90 + $this->renderHandleLink($author_phid)); 91 + } 81 92 } 82 93 83 94 return parent::getTitle();
+13 -2
src/applications/spaces/typeahead/PhabricatorSpacesNamespaceDatasource.php
··· 21 21 $spaces = $this->executeQuery($query); 22 22 $results = array(); 23 23 foreach ($spaces as $space) { 24 - $results[] = id(new PhabricatorTypeaheadResult()) 25 - ->setName($space->getNamespaceName()) 24 + $full_name = pht( 25 + '%s %s', 26 + $space->getMonogram(), 27 + $space->getNamespaceName()); 28 + 29 + $result = id(new PhabricatorTypeaheadResult()) 30 + ->setName($full_name) 26 31 ->setPHID($space->getPHID()); 32 + 33 + if ($space->getIsArchived()) { 34 + $result->setClosed(pht('Archived')); 35 + } 36 + 37 + $results[] = $result; 27 38 } 28 39 29 40 return $this->filterResultsAgainstTokens($results);
+20
src/applications/transactions/editor/PhabricatorApplicationTransactionEditor.php
··· 310 310 $space_phid = $default_space->getPHID(); 311 311 } 312 312 } 313 + 313 314 return $space_phid; 314 315 case PhabricatorTransactions::TYPE_EDGE: 315 316 $edge_type = $xaction->getMetadataValue('edge:type'); ··· 2011 2012 2012 2013 $has_spaces = PhabricatorSpacesNamespaceQuery::getViewerSpacesExist($actor); 2013 2014 $actor_spaces = PhabricatorSpacesNamespaceQuery::getViewerSpaces($actor); 2015 + $active_spaces = PhabricatorSpacesNamespaceQuery::getViewerActiveSpaces( 2016 + $actor); 2014 2017 foreach ($xactions as $xaction) { 2015 2018 $space_phid = $xaction->getNewValue(); 2016 2019 ··· 2039 2042 pht( 2040 2043 'You can not shift this object in the selected space, because '. 2041 2044 'the space does not exist or you do not have access to it.'), 2045 + $xaction); 2046 + } else if (empty($active_spaces[$space_phid])) { 2047 + 2048 + // It's OK to edit objects in an archived space, so just move on if 2049 + // we aren't adjusting the value. 2050 + $old_space_phid = $this->getTransactionOldValue($object, $xaction); 2051 + if ($space_phid == $old_space_phid) { 2052 + continue; 2053 + } 2054 + 2055 + $errors[] = new PhabricatorApplicationTransactionValidationError( 2056 + $transaction_type, 2057 + pht('Archived'), 2058 + pht( 2059 + 'You can not shift this object into the selected space, because '. 2060 + 'the space is archived. Objects can not be created inside (or '. 2061 + 'moved into) archived spaces.'), 2042 2062 $xaction); 2043 2063 } 2044 2064 }
+27
src/docs/user/userguide/spaces.diviner
··· 1 + @title Spaces User Guide 2 + @group userguide 3 + 4 + Guide to the Spaces application. 5 + 6 + Overview 7 + ======== 8 + 9 + IMPORTANT: Spaces is a prototype application. 10 + 11 + Archiving Spaces 12 + ================ 13 + 14 + If you no longer need a Space, you can archive it by choosing 15 + {nav Archive Space} from the detail view. This hides the space and all the 16 + objects in it without deleting any data. 17 + 18 + New objects can't be created into archived spaces, and existing objects can't 19 + be shifted into archived spaces. The UI won't give you options to choose 20 + these spaces when creating or editing objects. 21 + 22 + Additionally, objects (like tasks) in archived spaces won't be shown in most 23 + search result lists by default. If you need to find objects in an archived 24 + space, use the `Spaces` constraint to specifically search for objects in that 25 + space. 26 + 27 + You can reactivate a space later by choosing {nav Activate Space}.
+11
src/infrastructure/query/policy/PhabricatorCursorPagedPolicyAwareQuery.php
··· 25 25 private $edgeLogicConstraints = array(); 26 26 private $edgeLogicConstraintsAreValid = false; 27 27 private $spacePHIDs; 28 + private $spaceIsArchived; 28 29 29 30 protected function getPageCursors(array $page) { 30 31 return array( ··· 1722 1723 return $this; 1723 1724 } 1724 1725 1726 + public function withSpaceIsArchived($archived) { 1727 + $this->spaceIsArchived = $archived; 1728 + return $this; 1729 + } 1730 + 1725 1731 1726 1732 /** 1727 1733 * Constrain the query to include only results in valid Spaces. ··· 1760 1766 $viewer_spaces = PhabricatorSpacesNamespaceQuery::getViewerSpaces( 1761 1767 $viewer); 1762 1768 foreach ($viewer_spaces as $viewer_space) { 1769 + if ($this->spaceIsArchived !== null) { 1770 + if ($viewer_space->getIsArchived() != $this->spaceIsArchived) { 1771 + continue; 1772 + } 1773 + } 1763 1774 $phid = $viewer_space->getPHID(); 1764 1775 $space_phids[$phid] = $phid; 1765 1776 if ($viewer_space->getIsDefaultNamespace()) {
+10 -2
src/view/form/control/AphrontFormPolicyControl.php
··· 265 265 266 266 $select = AphrontFormSelectControl::renderSelectTag( 267 267 $space_phid, 268 - $this->getSpaceOptions(), 268 + $this->getSpaceOptions($space_phid), 269 269 array( 270 270 'name' => 'spacePHID', 271 271 )); ··· 273 273 return $select; 274 274 } 275 275 276 - protected function getSpaceOptions() { 276 + protected function getSpaceOptions($space_phid) { 277 277 $viewer = $this->getUser(); 278 278 $viewer_spaces = PhabricatorSpacesNamespaceQuery::getViewerSpaces($viewer); 279 279 280 280 $map = array(); 281 281 foreach ($viewer_spaces as $space) { 282 + 283 + // Skip archived spaces, unless the object is already in that space. 284 + if ($space->getIsArchived()) { 285 + if ($space->getPHID() != $space_phid) { 286 + continue; 287 + } 288 + } 289 + 282 290 $map[$space->getPHID()] = pht( 283 291 'Space %s: %s', 284 292 $space->getMonogram(),