@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 transactions for Almanac Device

Summary:
Depends on D19328. Ref T13120. Ref T12414.

Prior work has left us with just a NAME transaction here, which is straightforward to modularize.

Test Plan:
- Created and renamed devices.
- Tried to set no name, a bad name, a duplicate name (got errors).
- Tried to create/rename into a namespace I could not edit (got an error).
- Grepped for `AlmanacDeviceTransaction::`.

Reviewers: amckinley

Reviewed By: amckinley

Maniphest Tasks: T13120, T12414

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

+92 -163
+5 -1
src/__phutil_library_map__.php
··· 46 46 'AlmanacDeviceEditor' => 'applications/almanac/editor/AlmanacDeviceEditor.php', 47 47 'AlmanacDeviceListController' => 'applications/almanac/controller/AlmanacDeviceListController.php', 48 48 'AlmanacDeviceNameNgrams' => 'applications/almanac/storage/AlmanacDeviceNameNgrams.php', 49 + 'AlmanacDeviceNameTransaction' => 'applications/almanac/xaction/AlmanacDeviceNameTransaction.php', 49 50 'AlmanacDevicePHIDType' => 'applications/almanac/phid/AlmanacDevicePHIDType.php', 50 51 'AlmanacDevicePropertyEditEngine' => 'applications/almanac/editor/AlmanacDevicePropertyEditEngine.php', 51 52 'AlmanacDeviceQuery' => 'applications/almanac/query/AlmanacDeviceQuery.php', ··· 53 54 'AlmanacDeviceSearchEngine' => 'applications/almanac/query/AlmanacDeviceSearchEngine.php', 54 55 'AlmanacDeviceTransaction' => 'applications/almanac/storage/AlmanacDeviceTransaction.php', 55 56 'AlmanacDeviceTransactionQuery' => 'applications/almanac/query/AlmanacDeviceTransactionQuery.php', 57 + 'AlmanacDeviceTransactionType' => 'applications/almanac/xaction/AlmanacDeviceTransactionType.php', 56 58 'AlmanacDeviceViewController' => 'applications/almanac/controller/AlmanacDeviceViewController.php', 57 59 'AlmanacDrydockPoolServiceType' => 'applications/almanac/servicetype/AlmanacDrydockPoolServiceType.php', 58 60 'AlmanacEditor' => 'applications/almanac/editor/AlmanacEditor.php', ··· 5237 5239 'AlmanacDeviceEditor' => 'AlmanacEditor', 5238 5240 'AlmanacDeviceListController' => 'AlmanacDeviceController', 5239 5241 'AlmanacDeviceNameNgrams' => 'PhabricatorSearchNgrams', 5242 + 'AlmanacDeviceNameTransaction' => 'AlmanacDeviceTransactionType', 5240 5243 'AlmanacDevicePHIDType' => 'PhabricatorPHIDType', 5241 5244 'AlmanacDevicePropertyEditEngine' => 'AlmanacPropertyEditEngine', 5242 5245 'AlmanacDeviceQuery' => 'AlmanacQuery', 5243 5246 'AlmanacDeviceSearchConduitAPIMethod' => 'PhabricatorSearchEngineAPIMethod', 5244 5247 'AlmanacDeviceSearchEngine' => 'PhabricatorApplicationSearchEngine', 5245 - 'AlmanacDeviceTransaction' => 'AlmanacTransaction', 5248 + 'AlmanacDeviceTransaction' => 'PhabricatorModularTransaction', 5246 5249 'AlmanacDeviceTransactionQuery' => 'PhabricatorApplicationTransactionQuery', 5250 + 'AlmanacDeviceTransactionType' => 'AlmanacTransactionType', 5247 5251 'AlmanacDeviceViewController' => 'AlmanacDeviceController', 5248 5252 'AlmanacDrydockPoolServiceType' => 'AlmanacServiceType', 5249 5253 'AlmanacEditor' => 'PhabricatorApplicationTransactionEditor',
+1 -1
src/applications/almanac/editor/AlmanacDeviceEditEngine.php
··· 80 80 ->setKey('name') 81 81 ->setLabel(pht('Name')) 82 82 ->setDescription(pht('Name of the device.')) 83 - ->setTransactionType(AlmanacDeviceTransaction::TYPE_NAME) 83 + ->setTransactionType(AlmanacDeviceNameTransaction::TRANSACTIONTYPE) 84 84 ->setIsRequired(true) 85 85 ->setValue($object->getName()), 86 86 );
-135
src/applications/almanac/editor/AlmanacDeviceEditor.php
··· 10 10 public function getTransactionTypes() { 11 11 $types = parent::getTransactionTypes(); 12 12 13 - $types[] = AlmanacDeviceTransaction::TYPE_NAME; 14 - 15 13 $types[] = PhabricatorTransactions::TYPE_VIEW_POLICY; 16 14 $types[] = PhabricatorTransactions::TYPE_EDIT_POLICY; 17 15 18 16 return $types; 19 - } 20 - 21 - protected function getCustomTransactionOldValue( 22 - PhabricatorLiskDAO $object, 23 - PhabricatorApplicationTransaction $xaction) { 24 - switch ($xaction->getTransactionType()) { 25 - case AlmanacDeviceTransaction::TYPE_NAME: 26 - return $object->getName(); 27 - } 28 - 29 - return parent::getCustomTransactionOldValue($object, $xaction); 30 - } 31 - 32 - protected function getCustomTransactionNewValue( 33 - PhabricatorLiskDAO $object, 34 - PhabricatorApplicationTransaction $xaction) { 35 - 36 - switch ($xaction->getTransactionType()) { 37 - case AlmanacDeviceTransaction::TYPE_NAME: 38 - return $xaction->getNewValue(); 39 - } 40 - 41 - return parent::getCustomTransactionNewValue($object, $xaction); 42 - } 43 - 44 - protected function applyCustomInternalTransaction( 45 - PhabricatorLiskDAO $object, 46 - PhabricatorApplicationTransaction $xaction) { 47 - 48 - switch ($xaction->getTransactionType()) { 49 - case AlmanacDeviceTransaction::TYPE_NAME: 50 - $object->setName($xaction->getNewValue()); 51 - return; 52 - } 53 - 54 - return parent::applyCustomInternalTransaction($object, $xaction); 55 - } 56 - 57 - protected function applyCustomExternalTransaction( 58 - PhabricatorLiskDAO $object, 59 - PhabricatorApplicationTransaction $xaction) { 60 - 61 - switch ($xaction->getTransactionType()) { 62 - case AlmanacDeviceTransaction::TYPE_NAME: 63 - return; 64 - } 65 - 66 - return parent::applyCustomExternalTransaction($object, $xaction); 67 - } 68 - 69 - protected function validateTransaction( 70 - PhabricatorLiskDAO $object, 71 - $type, 72 - array $xactions) { 73 - 74 - $errors = parent::validateTransaction($object, $type, $xactions); 75 - 76 - switch ($type) { 77 - case AlmanacDeviceTransaction::TYPE_NAME: 78 - $missing = $this->validateIsEmptyTextField( 79 - $object->getName(), 80 - $xactions); 81 - 82 - if ($missing) { 83 - $error = new PhabricatorApplicationTransactionValidationError( 84 - $type, 85 - pht('Required'), 86 - pht('Device name is required.'), 87 - nonempty(last($xactions), null)); 88 - 89 - $error->setIsMissingFieldError(true); 90 - $errors[] = $error; 91 - } else { 92 - foreach ($xactions as $xaction) { 93 - $message = null; 94 - $name = $xaction->getNewValue(); 95 - 96 - try { 97 - AlmanacNames::validateName($name); 98 - } catch (Exception $ex) { 99 - $message = $ex->getMessage(); 100 - } 101 - 102 - if ($message !== null) { 103 - $error = new PhabricatorApplicationTransactionValidationError( 104 - $type, 105 - pht('Invalid'), 106 - $message, 107 - $xaction); 108 - $errors[] = $error; 109 - continue; 110 - } 111 - 112 - $other = id(new AlmanacDeviceQuery()) 113 - ->setViewer(PhabricatorUser::getOmnipotentUser()) 114 - ->withNames(array($name)) 115 - ->executeOne(); 116 - if ($other && ($other->getID() != $object->getID())) { 117 - $error = new PhabricatorApplicationTransactionValidationError( 118 - $type, 119 - pht('Not Unique'), 120 - pht('Almanac devices must have unique names.'), 121 - $xaction); 122 - $errors[] = $error; 123 - continue; 124 - } 125 - 126 - if ($name === $object->getName()) { 127 - continue; 128 - } 129 - 130 - $namespace = AlmanacNamespace::loadRestrictedNamespace( 131 - $this->getActor(), 132 - $name); 133 - if ($namespace) { 134 - $error = new PhabricatorApplicationTransactionValidationError( 135 - $type, 136 - pht('Restricted'), 137 - pht( 138 - 'You do not have permission to create Almanac devices '. 139 - 'within the "%s" namespace.', 140 - $namespace->getName()), 141 - $xaction); 142 - $errors[] = $error; 143 - continue; 144 - } 145 - } 146 - } 147 - 148 - break; 149 - } 150 - 151 - return $errors; 152 17 } 153 18 154 19 }
+3 -26
src/applications/almanac/storage/AlmanacDeviceTransaction.php
··· 1 1 <?php 2 2 3 3 final class AlmanacDeviceTransaction 4 - extends AlmanacTransaction { 5 - 6 - const TYPE_NAME = 'almanac:device: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 self::TYPE_NAME: 28 - if ($old === null) { 29 - return pht( 30 - '%s created this device.', 31 - $this->renderHandleLink($author_phid)); 32 - } else { 33 - return pht( 34 - '%s renamed this device from "%s" to "%s".', 35 - $this->renderHandleLink($author_phid), 36 - $old, 37 - $new); 38 - } 39 - break; 40 - } 41 - 42 - return parent::getTitle(); 18 + public function getBaseTransactionClass() { 19 + return 'AlmanacDeviceTransactionType'; 43 20 } 44 21 45 22 }
+79
src/applications/almanac/xaction/AlmanacDeviceNameTransaction.php
··· 1 + <?php 2 + 3 + final class AlmanacDeviceNameTransaction 4 + extends AlmanacDeviceTransactionType { 5 + 6 + const TRANSACTIONTYPE = 'almanac:device: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 device from %s to %s.', 19 + $this->renderAuthor(), 20 + $this->renderOldValue(), 21 + $this->renderNewValue()); 22 + } 23 + 24 + public function validateTransactions($object, array $xactions) { 25 + $errors = array(); 26 + 27 + if ($this->isEmptyTextTransaction($object->getName(), $xactions)) { 28 + $errors[] = $this->newRequiredError( 29 + pht('Device name is required.')); 30 + } 31 + 32 + foreach ($xactions as $xaction) { 33 + $name = $xaction->getNewValue(); 34 + 35 + $message = null; 36 + try { 37 + AlmanacNames::validateName($name); 38 + } catch (Exception $ex) { 39 + $message = $ex->getMessage(); 40 + } 41 + 42 + if ($message !== null) { 43 + $errors[] = $this->newInvalidError($message, $xaction); 44 + continue; 45 + } 46 + 47 + if ($name === $object->getName()) { 48 + continue; 49 + } 50 + 51 + $other = id(new AlmanacDeviceQuery()) 52 + ->setViewer(PhabricatorUser::getOmnipotentUser()) 53 + ->withNames(array($name)) 54 + ->executeOne(); 55 + if ($other && ($other->getID() != $object->getID())) { 56 + $errors[] = $this->newInvalidError( 57 + pht('Almanac devices must have unique names.'), 58 + $xaction); 59 + continue; 60 + } 61 + 62 + $namespace = AlmanacNamespace::loadRestrictedNamespace( 63 + $this->getActor(), 64 + $name); 65 + if ($namespace) { 66 + $errors[] = $this->newInvalidError( 67 + pht( 68 + 'You do not have permission to create Almanac devices '. 69 + 'within the "%s" namespace.', 70 + $namespace->getName()), 71 + $xaction); 72 + continue; 73 + } 74 + } 75 + 76 + return $errors; 77 + } 78 + 79 + }
+4
src/applications/almanac/xaction/AlmanacDeviceTransactionType.php
··· 1 + <?php 2 + 3 + abstract class AlmanacDeviceTransactionType 4 + extends AlmanacTransactionType {}