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

Modularize Almanac Namespace transactions

Summary: Depends on D19318. Ref T13120. Ref T12414. Move transactions for Almanac Namespaces ("name" is the only meaningful one) to ModularTransactions.

Test Plan:
- Created a new namespace.
- Edited a namespace.
- Tried to choose no name, an invalid name, a duplicate name, and a name in a namespace I can't edit; got appropriate errors.
- Grepped for `AlmanacNamespaceTransaction::TYPE_NAME`.

Reviewers: amckinley

Reviewed By: amckinley

Maniphest Tasks: T13120, T12414

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

+112 -163
+5 -1
src/__phutil_library_map__.php
··· 75 75 'AlmanacNamespaceEditor' => 'applications/almanac/editor/AlmanacNamespaceEditor.php', 76 76 'AlmanacNamespaceListController' => 'applications/almanac/controller/AlmanacNamespaceListController.php', 77 77 'AlmanacNamespaceNameNgrams' => 'applications/almanac/storage/AlmanacNamespaceNameNgrams.php', 78 + 'AlmanacNamespaceNameTransaction' => 'applications/almanac/xaction/AlmanacNamespaceNameTransaction.php', 78 79 'AlmanacNamespacePHIDType' => 'applications/almanac/phid/AlmanacNamespacePHIDType.php', 79 80 'AlmanacNamespaceQuery' => 'applications/almanac/query/AlmanacNamespaceQuery.php', 80 81 'AlmanacNamespaceSearchEngine' => 'applications/almanac/query/AlmanacNamespaceSearchEngine.php', 81 82 'AlmanacNamespaceTransaction' => 'applications/almanac/storage/AlmanacNamespaceTransaction.php', 82 83 'AlmanacNamespaceTransactionQuery' => 'applications/almanac/query/AlmanacNamespaceTransactionQuery.php', 84 + 'AlmanacNamespaceTransactionType' => 'applications/almanac/xaction/AlmanacNamespaceTransactionType.php', 83 85 'AlmanacNamespaceViewController' => 'applications/almanac/controller/AlmanacNamespaceViewController.php', 84 86 'AlmanacNetwork' => 'applications/almanac/storage/AlmanacNetwork.php', 85 87 'AlmanacNetworkController' => 'applications/almanac/controller/AlmanacNetworkController.php', ··· 5263 5265 'AlmanacNamespaceEditor' => 'PhabricatorApplicationTransactionEditor', 5264 5266 'AlmanacNamespaceListController' => 'AlmanacNamespaceController', 5265 5267 'AlmanacNamespaceNameNgrams' => 'PhabricatorSearchNgrams', 5268 + 'AlmanacNamespaceNameTransaction' => 'AlmanacNamespaceTransactionType', 5266 5269 'AlmanacNamespacePHIDType' => 'PhabricatorPHIDType', 5267 5270 'AlmanacNamespaceQuery' => 'AlmanacQuery', 5268 5271 'AlmanacNamespaceSearchEngine' => 'PhabricatorApplicationSearchEngine', 5269 - 'AlmanacNamespaceTransaction' => 'PhabricatorApplicationTransaction', 5272 + 'AlmanacNamespaceTransaction' => 'PhabricatorModularTransaction', 5270 5273 'AlmanacNamespaceTransactionQuery' => 'PhabricatorApplicationTransactionQuery', 5274 + 'AlmanacNamespaceTransactionType' => 'AlmanacTransactionType', 5271 5275 'AlmanacNamespaceViewController' => 'AlmanacNamespaceController', 5272 5276 'AlmanacNetwork' => array( 5273 5277 'AlmanacDAO',
+1 -1
src/applications/almanac/editor/AlmanacNamespaceEditEngine.php
··· 81 81 ->setKey('name') 82 82 ->setLabel(pht('Name')) 83 83 ->setDescription(pht('Name of the namespace.')) 84 - ->setTransactionType(AlmanacNamespaceTransaction::TYPE_NAME) 84 + ->setTransactionType(AlmanacNamespaceNameTransaction::TRANSACTIONTYPE) 85 85 ->setIsRequired(true) 86 86 ->setValue($object->getName()), 87 87 );
+8 -137
src/applications/almanac/editor/AlmanacNamespaceEditor.php
··· 11 11 return pht('Almanac Namespace'); 12 12 } 13 13 14 + public function getCreateObjectTitle($author, $object) { 15 + return pht('%s created this namespace.', $author); 16 + } 17 + 18 + public function getCreateObjectTitleForFeed($author, $object) { 19 + return pht('%s created %s.', $author, $object); 20 + } 21 + 14 22 protected function supportsSearch() { 15 23 return true; 16 24 } ··· 18 26 public function getTransactionTypes() { 19 27 $types = parent::getTransactionTypes(); 20 28 21 - $types[] = AlmanacNamespaceTransaction::TYPE_NAME; 22 29 $types[] = PhabricatorTransactions::TYPE_VIEW_POLICY; 23 30 $types[] = PhabricatorTransactions::TYPE_EDIT_POLICY; 24 31 25 32 return $types; 26 - } 27 - 28 - protected function getCustomTransactionOldValue( 29 - PhabricatorLiskDAO $object, 30 - PhabricatorApplicationTransaction $xaction) { 31 - switch ($xaction->getTransactionType()) { 32 - case AlmanacNamespaceTransaction::TYPE_NAME: 33 - return $object->getName(); 34 - } 35 - 36 - return parent::getCustomTransactionOldValue($object, $xaction); 37 - } 38 - 39 - protected function getCustomTransactionNewValue( 40 - PhabricatorLiskDAO $object, 41 - PhabricatorApplicationTransaction $xaction) { 42 - 43 - switch ($xaction->getTransactionType()) { 44 - case AlmanacNamespaceTransaction::TYPE_NAME: 45 - return $xaction->getNewValue(); 46 - } 47 - 48 - return parent::getCustomTransactionNewValue($object, $xaction); 49 - } 50 - 51 - protected function applyCustomInternalTransaction( 52 - PhabricatorLiskDAO $object, 53 - PhabricatorApplicationTransaction $xaction) { 54 - 55 - switch ($xaction->getTransactionType()) { 56 - case AlmanacNamespaceTransaction::TYPE_NAME: 57 - $object->setName($xaction->getNewValue()); 58 - return; 59 - } 60 - 61 - return parent::applyCustomInternalTransaction($object, $xaction); 62 - } 63 - 64 - protected function applyCustomExternalTransaction( 65 - PhabricatorLiskDAO $object, 66 - PhabricatorApplicationTransaction $xaction) { 67 - 68 - switch ($xaction->getTransactionType()) { 69 - case AlmanacNamespaceTransaction::TYPE_NAME: 70 - return; 71 - } 72 - 73 - return parent::applyCustomExternalTransaction($object, $xaction); 74 - } 75 - 76 - protected function validateTransaction( 77 - PhabricatorLiskDAO $object, 78 - $type, 79 - array $xactions) { 80 - 81 - $errors = parent::validateTransaction($object, $type, $xactions); 82 - 83 - switch ($type) { 84 - case AlmanacNamespaceTransaction::TYPE_NAME: 85 - $missing = $this->validateIsEmptyTextField( 86 - $object->getName(), 87 - $xactions); 88 - 89 - if ($missing) { 90 - $error = new PhabricatorApplicationTransactionValidationError( 91 - $type, 92 - pht('Required'), 93 - pht('Namespace name is required.'), 94 - nonempty(last($xactions), null)); 95 - 96 - $error->setIsMissingFieldError(true); 97 - $errors[] = $error; 98 - } else { 99 - foreach ($xactions as $xaction) { 100 - $name = $xaction->getNewValue(); 101 - 102 - $message = null; 103 - try { 104 - AlmanacNames::validateName($name); 105 - } catch (Exception $ex) { 106 - $message = $ex->getMessage(); 107 - } 108 - 109 - if ($message !== null) { 110 - $error = new PhabricatorApplicationTransactionValidationError( 111 - $type, 112 - pht('Invalid'), 113 - $message, 114 - $xaction); 115 - $errors[] = $error; 116 - continue; 117 - } 118 - 119 - $other = id(new AlmanacNamespaceQuery()) 120 - ->setViewer(PhabricatorUser::getOmnipotentUser()) 121 - ->withNames(array($name)) 122 - ->executeOne(); 123 - if ($other && ($other->getID() != $object->getID())) { 124 - $error = new PhabricatorApplicationTransactionValidationError( 125 - $type, 126 - pht('Not Unique'), 127 - pht( 128 - 'The namespace name "%s" is already in use by another '. 129 - 'namespace. Each namespace must have a unique name.', 130 - $name), 131 - $xaction); 132 - $errors[] = $error; 133 - continue; 134 - } 135 - 136 - if ($name === $object->getName()) { 137 - continue; 138 - } 139 - 140 - $namespace = AlmanacNamespace::loadRestrictedNamespace( 141 - $this->getActor(), 142 - $name); 143 - if ($namespace) { 144 - $error = new PhabricatorApplicationTransactionValidationError( 145 - $type, 146 - pht('Restricted'), 147 - pht( 148 - 'You do not have permission to create Almanac namespaces '. 149 - 'within the "%s" namespace.', 150 - $namespace->getName()), 151 - $xaction); 152 - $errors[] = $error; 153 - continue; 154 - } 155 - } 156 - } 157 - 158 - break; 159 - } 160 - 161 - return $errors; 162 33 } 163 34 164 35 protected function didCatchDuplicateKeyException(
+3 -24
src/applications/almanac/storage/AlmanacNamespaceTransaction.php
··· 1 1 <?php 2 2 3 3 final class AlmanacNamespaceTransaction 4 - extends PhabricatorApplicationTransaction { 5 - 6 - const TYPE_NAME = 'almanac:namespace:name'; 4 + extends PhabricatorModularTransaction { 7 5 8 6 public function getApplicationName() { 9 7 return 'almanac'; ··· 17 15 return null; 18 16 } 19 17 20 - public function getTitle() { 21 - $author_phid = $this->getAuthorPHID(); 22 - 23 - $old = $this->getOldValue(); 24 - $new = $this->getNewValue(); 25 - 26 - switch ($this->getTransactionType()) { 27 - case PhabricatorTransactions::TYPE_CREATE: 28 - return pht( 29 - '%s created this namespace.', 30 - $this->renderHandleLink($author_phid)); 31 - break; 32 - case self::TYPE_NAME: 33 - return pht( 34 - '%s renamed this namespace from "%s" to "%s".', 35 - $this->renderHandleLink($author_phid), 36 - $old, 37 - $new); 38 - } 39 - 40 - return parent::getTitle(); 18 + public function getBaseTransactionClass() { 19 + return 'AlmanacNamespaceTransactionType'; 41 20 } 42 21 43 22 }
+91
src/applications/almanac/xaction/AlmanacNamespaceNameTransaction.php
··· 1 + <?php 2 + 3 + final class AlmanacNamespaceNameTransaction 4 + extends AlmanacNamespaceTransactionType { 5 + 6 + const TRANSACTIONTYPE = 'almanac:namespace:name'; 7 + 8 + public function generateOldValue($object) { 9 + return $object->getName(); 10 + } 11 + 12 + public function applyInternalEffects($object, $value) { 13 + $object->setName($value); 14 + } 15 + 16 + public function getTitle() { 17 + return pht( 18 + '%s renamed this namespace from %s to %s.', 19 + $this->renderAuthor(), 20 + $this->renderOldValue(), 21 + $this->renderNewValue()); 22 + } 23 + 24 + public function getTitleForFeed() { 25 + return pht( 26 + '%s renamed %s from %s to %s.', 27 + $this->renderAuthor(), 28 + $this->renderObject(), 29 + $this->renderOldValue(), 30 + $this->renderNewValue()); 31 + } 32 + 33 + public function validateTransactions($object, array $xactions) { 34 + $errors = array(); 35 + 36 + if ($this->isEmptyTextTransaction($object->getName(), $xactions)) { 37 + $errors[] = $this->newRequiredError( 38 + pht('Namespace name is required.')); 39 + } 40 + 41 + foreach ($xactions as $xaction) { 42 + $name = $xaction->getNewValue(); 43 + 44 + $message = null; 45 + try { 46 + AlmanacNames::validateName($name); 47 + } catch (Exception $ex) { 48 + $message = $ex->getMessage(); 49 + } 50 + 51 + if ($message !== null) { 52 + $errors[] = $this->newInvalidError($message, $xaction); 53 + continue; 54 + } 55 + 56 + if ($name === $object->getName()) { 57 + continue; 58 + } 59 + 60 + $other = id(new AlmanacNamespaceQuery()) 61 + ->setViewer(PhabricatorUser::getOmnipotentUser()) 62 + ->withNames(array($name)) 63 + ->executeOne(); 64 + if ($other && ($other->getID() != $object->getID())) { 65 + $errors[] = $this->newInvalidError( 66 + pht( 67 + 'The namespace name "%s" is already in use by another '. 68 + 'namespace. Each namespace must have a unique name.', 69 + $name), 70 + $xaction); 71 + continue; 72 + } 73 + 74 + $namespace = AlmanacNamespace::loadRestrictedNamespace( 75 + $this->getActor(), 76 + $name); 77 + if ($namespace) { 78 + $errors[] = $this->newInvalidError( 79 + pht( 80 + 'You do not have permission to create Almanac namespaces '. 81 + 'within the "%s" namespace.', 82 + $namespace->getName()), 83 + $xaction); 84 + continue; 85 + } 86 + } 87 + 88 + return $errors; 89 + } 90 + 91 + }
+4
src/applications/almanac/xaction/AlmanacNamespaceTransactionType.php
··· 1 + <?php 2 + 3 + abstract class AlmanacNamespaceTransactionType 4 + extends AlmanacTransactionType {}