@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.

Remove PhabricatorProjectEditor

Summary:
Ref T4379. Perform all editing with modern transaction infrastructure. A few practical changes here:

- Message for "project name required" should be a little nicer. I'll deal with this once more stuff gets straightened out. You get a reasonable message now, it's just not nicely handled as part of the form.
- Message for "project name is not unique" should be a little nicer. Same as above.
- Previously, we would automatically archive a project when the last member left or was removed. I'll probably restore this in a bit but am omitting it for the moment for simplicity.
- Previously, we would create projects with goofy nonsensical permissions. Now we create them with reasonable permissions.

Test Plan:
- Created project.
- Edited project.
- Ran unit tests.
- Viewed project edit history.

Reviewers: btrahan

Reviewed By: btrahan

CC: aran

Maniphest Tasks: T4379

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

+155 -319
-2
src/__phutil_library_map__.php
··· 1836 1836 'PhabricatorProjectCustomFieldStorage' => 'applications/project/storage/PhabricatorProjectCustomFieldStorage.php', 1837 1837 'PhabricatorProjectCustomFieldStringIndex' => 'applications/project/storage/PhabricatorProjectCustomFieldStringIndex.php', 1838 1838 'PhabricatorProjectDAO' => 'applications/project/storage/PhabricatorProjectDAO.php', 1839 - 'PhabricatorProjectEditor' => 'applications/project/editor/PhabricatorProjectEditor.php', 1840 1839 'PhabricatorProjectEditorTestCase' => 'applications/project/editor/__tests__/PhabricatorProjectEditorTestCase.php', 1841 1840 'PhabricatorProjectHistoryController' => 'applications/project/controller/PhabricatorProjectHistoryController.php', 1842 1841 'PhabricatorProjectListController' => 'applications/project/controller/PhabricatorProjectListController.php', ··· 4572 4571 'PhabricatorProjectCustomFieldStorage' => 'PhabricatorCustomFieldStorage', 4573 4572 'PhabricatorProjectCustomFieldStringIndex' => 'PhabricatorCustomFieldStringIndexStorage', 4574 4573 'PhabricatorProjectDAO' => 'PhabricatorLiskDAO', 4575 - 'PhabricatorProjectEditor' => 'PhabricatorEditor', 4576 4574 'PhabricatorProjectEditorTestCase' => 'PhabricatorTestCase', 4577 4575 'PhabricatorProjectHistoryController' => 'PhabricatorProjectController', 4578 4576 'PhabricatorProjectListController' =>
+18 -23
src/applications/project/controller/PhabricatorProjectCreateController.php
··· 12 12 $this->requireApplicationCapability( 13 13 ProjectCapabilityCreateProjects::CAPABILITY); 14 14 15 - $project = new PhabricatorProject(); 16 - $project->setAuthorPHID($user->getPHID()); 17 - $project->attachMemberPHIDs(array()); 15 + $project = PhabricatorProject::initializeNewProject($user); 18 16 $profile = new PhabricatorProjectProfile(); 19 17 20 18 $e_name = true; 21 19 $errors = array(); 22 20 if ($request->isFormPost()) { 21 + $xactions = array(); 23 22 24 - try { 25 - $xactions = array(); 23 + $xactions[] = id(new PhabricatorProjectTransaction()) 24 + ->setTransactionType(PhabricatorProjectTransaction::TYPE_NAME) 25 + ->setNewValue($request->getStr('name')); 26 26 27 - $xaction = new PhabricatorProjectTransaction(); 28 - $xaction->setTransactionType( 29 - PhabricatorProjectTransaction::TYPE_NAME); 30 - $xaction->setNewValue($request->getStr('name')); 31 - $xactions[] = $xaction; 27 + $xactions[] = id(new PhabricatorProjectTransaction()) 28 + ->setTransactionType(PhabricatorTransactions::TYPE_EDGE) 29 + ->setMetadataValue('edge:type', PhabricatorEdgeConfig::TYPE_PROJ_MEMBER) 30 + ->setNewValue( 31 + array( 32 + '+' => array($user->getPHID() => $user->getPHID()), 33 + )); 32 34 33 - $xaction = new PhabricatorProjectTransaction(); 34 - $xaction->setTransactionType( 35 - PhabricatorProjectTransaction::TYPE_MEMBERS); 36 - $xaction->setNewValue(array($user->getPHID())); 37 - $xactions[] = $xaction; 35 + $editor = id(new PhabricatorProjectTransactionEditor()) 36 + ->setActor($user) 37 + ->setContinueOnNoEffect(true) 38 + ->setContentSourceFromRequest($request) 39 + ->applyTransactions($project, $xactions); 38 40 39 - $editor = new PhabricatorProjectEditor($project); 40 - $editor->setActor($user); 41 - $editor->applyTransactions($xactions); 42 - } catch (PhabricatorProjectNameCollisionException $ex) { 43 - $e_name = 'Not Unique'; 44 - $errors[] = $ex->getMessage(); 45 - } 41 + // TODO: Deal with name collision exceptions more gracefully. 46 42 47 43 $profile->setBlurb($request->getStr('blurb')); 48 44 ··· 103 99 104 100 return id(new AphrontDialogResponse())->setDialog($dialog); 105 101 } else { 106 - 107 102 $form 108 103 ->appendChild( 109 104 id(new AphrontFormSubmitControl())
+22 -34
src/applications/project/controller/PhabricatorProjectProfileEditController.php
··· 35 35 36 36 $errors = array(); 37 37 if ($request->isFormPost()) { 38 - try { 39 - $xactions = array(); 40 - $xaction = new PhabricatorProjectTransaction(); 41 - $xaction->setTransactionType( 42 - PhabricatorProjectTransaction::TYPE_NAME); 43 - $xaction->setNewValue($request->getStr('name')); 44 - $xactions[] = $xaction; 38 + $xactions = array(); 45 39 46 - $xaction = new PhabricatorProjectTransaction(); 47 - $xaction->setTransactionType( 48 - PhabricatorProjectTransaction::TYPE_STATUS); 49 - $xaction->setNewValue($request->getStr('status')); 50 - $xactions[] = $xaction; 40 + $xactions[] = id(new PhabricatorProjectTransaction()) 41 + ->setTransactionType(PhabricatorProjectTransaction::TYPE_NAME) 42 + ->setNewValue($request->getStr('name')); 51 43 52 - $xaction = new PhabricatorProjectTransaction(); 53 - $xaction->setTransactionType( 54 - PhabricatorTransactions::TYPE_VIEW_POLICY); 55 - $xaction->setNewValue($request->getStr('can_view')); 56 - $xactions[] = $xaction; 44 + $xactions[] = id(new PhabricatorProjectTransaction()) 45 + ->setTransactionType(PhabricatorProjectTransaction::TYPE_STATUS) 46 + ->setNewValue($request->getStr('status')); 57 47 58 - $xaction = new PhabricatorProjectTransaction(); 59 - $xaction->setTransactionType( 60 - PhabricatorTransactions::TYPE_EDIT_POLICY); 61 - $xaction->setNewValue($request->getStr('can_edit')); 62 - $xactions[] = $xaction; 48 + $xactions[] = id(new PhabricatorProjectTransaction()) 49 + ->setTransactionType(PhabricatorTransactions::TYPE_VIEW_POLICY) 50 + ->setNewValue($request->getStr('can_view')); 63 51 64 - $xaction = new PhabricatorProjectTransaction(); 65 - $xaction->setTransactionType( 66 - PhabricatorTransactions::TYPE_JOIN_POLICY); 67 - $xaction->setNewValue($request->getStr('can_join')); 68 - $xactions[] = $xaction; 52 + $xactions[] = id(new PhabricatorProjectTransaction()) 53 + ->setTransactionType(PhabricatorTransactions::TYPE_EDIT_POLICY) 54 + ->setNewValue($request->getStr('can_edit')); 69 55 70 - $editor = new PhabricatorProjectEditor($project); 71 - $editor->setActor($user); 72 - $editor->applyTransactions($xactions); 73 - } catch (PhabricatorProjectNameCollisionException $ex) { 74 - $e_name = pht('Not Unique'); 75 - $errors[] = $ex->getMessage(); 76 - } 56 + $xactions[] = id(new PhabricatorProjectTransaction()) 57 + ->setTransactionType(PhabricatorTransactions::TYPE_JOIN_POLICY) 58 + ->setNewValue($request->getStr('can_join')); 59 + 60 + $editor = id(new PhabricatorProjectTransactionEditor()) 61 + ->setActor($user) 62 + ->setContentSourceFromRequest($request) 63 + ->setContinueOnNoEffect(true) 64 + ->applyTransactions($project, $xactions); 77 65 78 66 $profile->setBlurb($request->getStr('blurb')); 79 67
-255
src/applications/project/editor/PhabricatorProjectEditor.php
··· 1 - <?php 2 - 3 - final class PhabricatorProjectEditor extends PhabricatorEditor { 4 - 5 - private $project; 6 - private $projectName; 7 - 8 - private $addEdges = array(); 9 - private $remEdges = array(); 10 - 11 - private $shouldArchive = false; 12 - 13 - private function setShouldArchive($should_archive) { 14 - $this->shouldArchive = $should_archive; 15 - return $this; 16 - } 17 - private function shouldArchive() { 18 - return $this->shouldArchive; 19 - } 20 - 21 - public function __construct(PhabricatorProject $project) { 22 - $this->project = $project; 23 - } 24 - 25 - public function applyTransactions(array $transactions) { 26 - assert_instances_of($transactions, 'PhabricatorProjectTransaction'); 27 - $actor = $this->requireActor(); 28 - 29 - $project = $this->project; 30 - 31 - $is_new = !$project->getID(); 32 - 33 - if ($is_new) { 34 - $project->setAuthorPHID($actor->getPHID()); 35 - } 36 - 37 - foreach ($transactions as $key => $xaction) { 38 - $this->setTransactionOldValue($project, $xaction); 39 - if (!$this->transactionHasEffect($xaction)) { 40 - unset($transactions[$key]); 41 - continue; 42 - } 43 - } 44 - 45 - if (!$is_new) { 46 - // You must be able to view a project in order to edit it in any capacity. 47 - PhabricatorPolicyFilter::requireCapability( 48 - $actor, 49 - $project, 50 - PhabricatorPolicyCapability::CAN_VIEW); 51 - 52 - PhabricatorPolicyFilter::requireCapability( 53 - $actor, 54 - $project, 55 - PhabricatorPolicyCapability::CAN_EDIT); 56 - } 57 - 58 - if (!$transactions) { 59 - return $this; 60 - } 61 - 62 - foreach ($transactions as $xaction) { 63 - $this->applyTransactionEffect($project, $xaction); 64 - } 65 - 66 - try { 67 - $project->openTransaction(); 68 - 69 - if ($this->shouldArchive()) { 70 - $project->setStatus(PhabricatorProjectStatus::STATUS_ARCHIVED); 71 - } 72 - $project->save(); 73 - 74 - $edge_type = PhabricatorEdgeConfig::TYPE_PROJ_MEMBER; 75 - $editor = new PhabricatorEdgeEditor(); 76 - $editor->setActor($actor); 77 - foreach ($this->remEdges as $phid) { 78 - $editor->removeEdge($project->getPHID(), $edge_type, $phid); 79 - } 80 - foreach ($this->addEdges as $phid) { 81 - $editor->addEdge($project->getPHID(), $edge_type, $phid); 82 - } 83 - $editor->save(); 84 - 85 - foreach ($transactions as $xaction) { 86 - $xaction->setAuthorPHID($actor->getPHID()); 87 - $xaction->setObjectPHID($project->getPHID()); 88 - $xaction->setViewPolicy('public'); 89 - $xaction->setEditPolicy($actor->getPHID()); 90 - $xaction->setContentSource( 91 - PhabricatorContentSource::newForSource( 92 - PhabricatorContentSource::SOURCE_LEGACY, 93 - array())); 94 - $xaction->save(); 95 - } 96 - $project->saveTransaction(); 97 - } catch (AphrontQueryDuplicateKeyException $ex) { 98 - // We already validated the slug, but might race. Try again to see if 99 - // that's the issue. If it is, we'll throw a more specific exception. If 100 - // not, throw the original exception. 101 - $this->validateName($project); 102 - throw $ex; 103 - } 104 - 105 - id(new PhabricatorSearchIndexer()) 106 - ->queueDocumentForIndexing($project->getPHID()); 107 - 108 - return $this; 109 - } 110 - 111 - private function validateName(PhabricatorProject $project) { 112 - $slug = $project->getPhrictionSlug(); 113 - $name = $project->getName(); 114 - 115 - if ($slug == '/') { 116 - throw new PhabricatorProjectNameCollisionException( 117 - pht("Project names must be unique and contain some ". 118 - "letters or numbers.")); 119 - } 120 - 121 - $id = $project->getID(); 122 - $collision = id(new PhabricatorProject())->loadOneWhere( 123 - '(name = %s OR phrictionSlug = %s) AND id %Q %nd', 124 - $name, 125 - $slug, 126 - $id ? '!=' : 'IS NOT', 127 - $id ? $id : null); 128 - 129 - if ($collision) { 130 - $other_name = $collision->getName(); 131 - $other_id = $collision->getID(); 132 - throw new PhabricatorProjectNameCollisionException( 133 - pht("Project names must be unique. The name '%s' is too similar to ". 134 - "the name of another project, '%s' (Project ID: ". 135 - "%d). Choose a unique name.", $name, $other_name, $other_id)); 136 - } 137 - } 138 - 139 - private function setTransactionOldValue( 140 - PhabricatorProject $project, 141 - PhabricatorProjectTransaction $xaction) { 142 - 143 - $type = $xaction->getTransactionType(); 144 - switch ($type) { 145 - case PhabricatorProjectTransaction::TYPE_NAME: 146 - $xaction->setOldValue($project->getName()); 147 - break; 148 - case PhabricatorProjectTransaction::TYPE_STATUS: 149 - $xaction->setOldValue($project->getStatus()); 150 - break; 151 - case PhabricatorProjectTransaction::TYPE_MEMBERS: 152 - $member_phids = $project->getMemberPHIDs(); 153 - 154 - $old_value = array_values($member_phids); 155 - $xaction->setOldValue($old_value); 156 - 157 - $new_value = $xaction->getNewValue(); 158 - $new_value = array_filter($new_value); 159 - $new_value = array_unique($new_value); 160 - $new_value = array_values($new_value); 161 - $xaction->setNewValue($new_value); 162 - break; 163 - case PhabricatorTransactions::TYPE_VIEW_POLICY: 164 - $xaction->setOldValue($project->getViewPolicy()); 165 - break; 166 - case PhabricatorTransactions::TYPE_EDIT_POLICY: 167 - $xaction->setOldValue($project->getEditPolicy()); 168 - break; 169 - case PhabricatorTransactions::TYPE_JOIN_POLICY: 170 - $xaction->setOldValue($project->getJoinPolicy()); 171 - break; 172 - default: 173 - throw new Exception("Unknown transaction type '{$type}'!"); 174 - } 175 - return $this; 176 - } 177 - 178 - private function applyTransactionEffect( 179 - PhabricatorProject $project, 180 - PhabricatorProjectTransaction $xaction) { 181 - 182 - $type = $xaction->getTransactionType(); 183 - switch ($type) { 184 - case PhabricatorProjectTransaction::TYPE_NAME: 185 - $old_slug = $project->getFullPhrictionSlug(); 186 - $project->setName($xaction->getNewValue()); 187 - $project->setPhrictionSlug($xaction->getNewValue()); 188 - $changed_slug = $old_slug != $project->getFullPhrictionSlug(); 189 - if ($xaction->getOldValue() && $changed_slug) { 190 - $old_document = id(new PhrictionDocument()) 191 - ->loadOneWhere( 192 - 'slug = %s', 193 - $old_slug); 194 - if ($old_document && $old_document->getStatus() == 195 - PhrictionDocumentStatus::STATUS_EXISTS) { 196 - $content = id(new PhrictionContent()) 197 - ->load($old_document->getContentID()); 198 - $from_editor = id(PhrictionDocumentEditor::newForSlug($old_slug)) 199 - ->setActor($this->getActor()) 200 - ->setTitle($content->getTitle()) 201 - ->setContent($content->getContent()) 202 - ->setDescription($content->getDescription()); 203 - 204 - $target_editor = id(PhrictionDocumentEditor::newForSlug( 205 - $project->getFullPhrictionSlug())) 206 - ->setActor($this->getActor()) 207 - ->setTitle($content->getTitle()) 208 - ->setContent($content->getContent()) 209 - ->setDescription($content->getDescription()) 210 - ->moveHere($old_document->getID(), $old_document->getPHID()); 211 - 212 - $target_document = $target_editor->getDocument(); 213 - $from_editor->moveAway($target_document->getID()); 214 - } 215 - } 216 - $this->validateName($project); 217 - break; 218 - case PhabricatorProjectTransaction::TYPE_STATUS: 219 - $project->setStatus($xaction->getNewValue()); 220 - break; 221 - case PhabricatorProjectTransaction::TYPE_MEMBERS: 222 - $old = array_fill_keys($xaction->getOldValue(), true); 223 - $new = array_fill_keys($xaction->getNewValue(), true); 224 - $this->addEdges = array_keys(array_diff_key($new, $old)); 225 - $this->remEdges = array_keys(array_diff_key($old, $new)); 226 - if ($new === array()) { 227 - $this->setShouldArchive(true); 228 - } 229 - break; 230 - case PhabricatorTransactions::TYPE_VIEW_POLICY: 231 - $project->setViewPolicy($xaction->getNewValue()); 232 - break; 233 - case PhabricatorTransactions::TYPE_EDIT_POLICY: 234 - $project->setEditPolicy($xaction->getNewValue()); 235 - 236 - // You can't edit away your ability to edit the project. 237 - PhabricatorPolicyFilter::mustRetainCapability( 238 - $this->getActor(), 239 - $project, 240 - PhabricatorPolicyCapability::CAN_EDIT); 241 - break; 242 - case PhabricatorTransactions::TYPE_JOIN_POLICY: 243 - $project->setJoinPolicy($xaction->getNewValue()); 244 - break; 245 - default: 246 - throw new Exception("Unknown transaction type '{$type}'!"); 247 - } 248 - } 249 - 250 - private function transactionHasEffect( 251 - PhabricatorProjectTransaction $xaction) { 252 - return ($xaction->getOldValue() !== $xaction->getNewValue()); 253 - } 254 - 255 - }
+93 -1
src/applications/project/editor/PhabricatorProjectTransactionEditor.php
··· 7 7 $types = parent::getTransactionTypes(); 8 8 9 9 $types[] = PhabricatorTransactions::TYPE_EDGE; 10 + $types[] = PhabricatorTransactions::TYPE_VIEW_POLICY; 11 + $types[] = PhabricatorTransactions::TYPE_EDIT_POLICY; 12 + $types[] = PhabricatorTransactions::TYPE_JOIN_POLICY; 13 + 14 + $types[] = PhabricatorProjectTransaction::TYPE_NAME; 15 + $types[] = PhabricatorProjectTransaction::TYPE_STATUS; 10 16 11 17 return $types; 12 18 } ··· 16 22 PhabricatorApplicationTransaction $xaction) { 17 23 18 24 switch ($xaction->getTransactionType()) { 25 + case PhabricatorProjectTransaction::TYPE_NAME: 26 + return $object->getName(); 27 + case PhabricatorProjectTransaction::TYPE_STATUS: 28 + return $object->getStatus(); 19 29 } 20 30 21 31 return parent::getCustomTransactionOldValue($object, $xaction); ··· 26 36 PhabricatorApplicationTransaction $xaction) { 27 37 28 38 switch ($xaction->getTransactionType()) { 39 + case PhabricatorProjectTransaction::TYPE_NAME: 40 + case PhabricatorProjectTransaction::TYPE_STATUS: 41 + return $xaction->getNewValue(); 29 42 } 30 43 31 44 return parent::getCustomTransactionNewValue($object, $xaction); ··· 36 49 PhabricatorApplicationTransaction $xaction) { 37 50 38 51 switch ($xaction->getTransactionType()) { 52 + case PhabricatorProjectTransaction::TYPE_NAME: 53 + $object->setName($xaction->getNewValue()); 54 + return; 55 + case PhabricatorProjectTransaction::TYPE_STATUS: 56 + $object->setStatus($xaction->getNewValue()); 57 + return; 39 58 case PhabricatorTransactions::TYPE_EDGE: 40 59 return; 60 + case PhabricatorTransactions::TYPE_VIEW_POLICY: 61 + $object->setViewPolicy($xaction->getNewValue()); 62 + return; 63 + case PhabricatorTransactions::TYPE_EDIT_POLICY: 64 + $object->setEditPolicy($xaction->getNewValue()); 65 + return; 66 + case PhabricatorTransactions::TYPE_JOIN_POLICY: 67 + $object->setJoinPolicy($xaction->getNewValue()); 68 + return; 41 69 } 42 70 43 71 return parent::applyCustomInternalTransaction($object, $xaction); ··· 48 76 PhabricatorApplicationTransaction $xaction) { 49 77 50 78 switch ($xaction->getTransactionType()) { 79 + case PhabricatorProjectTransaction::TYPE_NAME: 80 + $old_slug = $object->getFullPhrictionSlug(); 81 + $object->setPhrictionSlug($xaction->getNewValue()); 82 + $changed_slug = $old_slug != $object->getFullPhrictionSlug(); 83 + if ($xaction->getOldValue() && $changed_slug) { 84 + $old_document = id(new PhrictionDocument()) 85 + ->loadOneWhere( 86 + 'slug = %s', 87 + $old_slug); 88 + if ($old_document && $old_document->getStatus() == 89 + PhrictionDocumentStatus::STATUS_EXISTS) { 90 + $content = id(new PhrictionContent()) 91 + ->load($old_document->getContentID()); 92 + $from_editor = id(PhrictionDocumentEditor::newForSlug($old_slug)) 93 + ->setActor($this->getActor()) 94 + ->setTitle($content->getTitle()) 95 + ->setContent($content->getContent()) 96 + ->setDescription($content->getDescription()); 97 + 98 + $target_editor = id(PhrictionDocumentEditor::newForSlug( 99 + $object->getFullPhrictionSlug())) 100 + ->setActor($this->getActor()) 101 + ->setTitle($content->getTitle()) 102 + ->setContent($content->getContent()) 103 + ->setDescription($content->getDescription()) 104 + ->moveHere($old_document->getID(), $old_document->getPHID()); 105 + 106 + $target_document = $target_editor->getDocument(); 107 + $from_editor->moveAway($target_document->getID()); 108 + } 109 + } 110 + return; 111 + case PhabricatorTransactions::TYPE_VIEW_POLICY: 112 + case PhabricatorTransactions::TYPE_EDIT_POLICY: 113 + case PhabricatorTransactions::TYPE_JOIN_POLICY: 51 114 case PhabricatorTransactions::TYPE_EDGE: 115 + case PhabricatorProjectTransaction::TYPE_STATUS: 52 116 return; 53 117 } 54 118 ··· 63 127 $errors = parent::validateTransaction($object, $type, $xactions); 64 128 65 129 switch ($type) { 130 + case PhabricatorProjectTransaction::TYPE_NAME: 131 + $missing = $this->validateIsEmptyTextField( 132 + $object->getName(), 133 + $xactions); 134 + 135 + if ($missing) { 136 + $error = new PhabricatorApplicationTransactionValidationError( 137 + $type, 138 + pht('Required'), 139 + pht('Project name is required.'), 140 + nonempty(last($xactions), null)); 141 + 142 + $error->setIsMissingFieldError(true); 143 + $errors[] = $error; 144 + } 145 + break; 66 146 } 67 147 68 148 return $errors; 69 149 } 70 150 151 + 71 152 protected function requireCapabilities( 72 153 PhabricatorLiskDAO $object, 73 154 PhabricatorApplicationTransaction $xaction) { 74 155 75 156 switch ($xaction->getTransactionType()) { 157 + case PhabricatorProjectTransaction::TYPE_NAME: 158 + case PhabricatorProjectTransaction::TYPE_STATUS: 159 + PhabricatorPolicyFilter::requireCapability( 160 + $this->requireActor(), 161 + $object, 162 + PhabricatorPolicyCapability::CAN_EDIT); 163 + return; 76 164 case PhabricatorTransactions::TYPE_EDGE: 77 165 switch ($xaction->getMetadataValue('edge:type')) { 78 166 case PhabricatorEdgeConfig::TYPE_PROJ_MEMBER: ··· 107 195 break; 108 196 } 109 197 110 - return parent::requireCapabilities(); 198 + return parent::requireCapabilities($object, $xaction); 199 + } 200 + 201 + protected function supportsSearch() { 202 + return true; 111 203 } 112 204 113 205 }
+3 -2
src/applications/project/editor/__tests__/PhabricatorProjectEditorTestCase.php
··· 97 97 $xaction->setTransactionType(PhabricatorProjectTransaction::TYPE_NAME); 98 98 $xaction->setNewValue($new_name); 99 99 100 - $editor = new PhabricatorProjectEditor($proj); 100 + $editor = new PhabricatorProjectTransactionEditor(); 101 101 $editor->setActor($user); 102 - $editor->applyTransactions(array($xaction)); 102 + $editor->setContentSource(PhabricatorContentSource::newConsoleSource()); 103 + $editor->applyTransactions($proj, array($xaction)); 103 104 104 105 return true; 105 106 }
+3 -2
src/applications/project/lipsum/PhabricatorProjectTestDataGenerator.php
··· 32 32 PhabricatorTransactions::TYPE_JOIN_POLICY, 33 33 PhabricatorPolicies::POLICY_PUBLIC); 34 34 35 - $editor = id(new PhabricatorProjectEditor($project)) 35 + $editor = id(new PhabricatorProjectTransactionEditor()) 36 36 ->setActor($author) 37 - ->applyTransactions($this->xactions); 37 + ->setContentSource(PhabricatorContentSource::newConsoleSource()) 38 + ->applyTransactions($project, $this->xactions); 38 39 39 40 $profile = id(new PhabricatorProjectProfile()) 40 41 ->setBlurb($this->generateDescription())
+13
src/applications/project/storage/PhabricatorProject.php
··· 20 20 private $sparseMembers = self::ATTACHABLE; 21 21 private $profile = self::ATTACHABLE; 22 22 23 + public static function initializeNewProject(PhabricatorUser $actor) { 24 + return id(new PhabricatorProject()) 25 + ->setName('') 26 + ->setAuthorPHID($actor->getPHID()) 27 + ->setViewPolicy(PhabricatorPolicies::POLICY_USER) 28 + ->setEditPolicy(PhabricatorPolicies::POLICY_USER) 29 + ->setJoinPolicy(PhabricatorPolicies::POLICY_USER) 30 + ->attachMemberPHIDs(array()); 31 + } 32 + 23 33 public function getCapabilities() { 24 34 return array( 25 35 PhabricatorPolicyCapability::CAN_VIEW, ··· 73 83 } 74 84 75 85 public function isUserMember($user_phid) { 86 + if ($this->memberPHIDs !== self::ATTACHABLE) { 87 + return in_array($user_phid, $this->memberPHIDs); 88 + } 76 89 return $this->assertAttachedKey($this->sparseMembers, $user_phid); 77 90 } 78 91
+3
src/applications/transactions/editor/PhabricatorApplicationTransactionEditor.php
··· 139 139 return $object->getViewPolicy(); 140 140 case PhabricatorTransactions::TYPE_EDIT_POLICY: 141 141 return $object->getEditPolicy(); 142 + case PhabricatorTransactions::TYPE_JOIN_POLICY: 143 + return $object->getJoinPolicy(); 142 144 case PhabricatorTransactions::TYPE_EDGE: 143 145 $edge_type = $xaction->getMetadataValue('edge:type'); 144 146 if (!$edge_type) { ··· 175 177 return $this->getPHIDTransactionNewValue($xaction); 176 178 case PhabricatorTransactions::TYPE_VIEW_POLICY: 177 179 case PhabricatorTransactions::TYPE_EDIT_POLICY: 180 + case PhabricatorTransactions::TYPE_JOIN_POLICY: 178 181 return $xaction->getNewValue(); 179 182 case PhabricatorTransactions::TYPE_EDGE: 180 183 return $this->getEdgeTransactionNewValue($xaction);