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

Partially modularize AlmanacService transactions

Summary:
Ref T13120. Ref T12414. See PHI145. See PHI473. This partially modernizes AlmanacService transactions by moving them to ModularTransactions.

This isn't complete because the "update property" and "remove property" transactions aren't modularized. They still //work//, since the parent Editor implements them, but they no longer render properly on the timeline since the `Transaction` object no longer has rendering logic for them.

Tentatively, I'm going to try to convert the rest of the Almanac objects and then modularize those transactions. (Currently, all of Binding, Device, Namespace and Service support properties, although they can only actually be edited on Service, Device and Binding.)

If that turns out to be really tricky for some reason I can just copy/paste the timeline rendering for now, but I think it won't be too hard.

Test Plan:
- Created and edited Services.
- Tried to create a service with: a bad name, no name, a name which put it in a namespace I can't edit (got errors in all cases).
- Edited and removed properties. The edits worked, the timeline just renders a generic story now ('X edited this object (transaction type "almanac:property:update").').

Reviewers: amckinley

Reviewed By: amckinley

Maniphest Tasks: T13120, T12414

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

+121 -164
+7 -1
src/__phutil_library_map__.php
··· 114 114 'AlmanacServiceEditor' => 'applications/almanac/editor/AlmanacServiceEditor.php', 115 115 'AlmanacServiceListController' => 'applications/almanac/controller/AlmanacServiceListController.php', 116 116 'AlmanacServiceNameNgrams' => 'applications/almanac/storage/AlmanacServiceNameNgrams.php', 117 + 'AlmanacServiceNameTransaction' => 'applications/almanac/xaction/AlmanacServiceNameTransaction.php', 117 118 'AlmanacServicePHIDType' => 'applications/almanac/phid/AlmanacServicePHIDType.php', 118 119 'AlmanacServicePropertyEditEngine' => 'applications/almanac/editor/AlmanacServicePropertyEditEngine.php', 119 120 'AlmanacServiceQuery' => 'applications/almanac/query/AlmanacServiceQuery.php', ··· 121 122 'AlmanacServiceSearchEngine' => 'applications/almanac/query/AlmanacServiceSearchEngine.php', 122 123 'AlmanacServiceTransaction' => 'applications/almanac/storage/AlmanacServiceTransaction.php', 123 124 'AlmanacServiceTransactionQuery' => 'applications/almanac/query/AlmanacServiceTransactionQuery.php', 125 + 'AlmanacServiceTransactionType' => 'applications/almanac/xaction/AlmanacServiceTransactionType.php', 124 126 'AlmanacServiceType' => 'applications/almanac/servicetype/AlmanacServiceType.php', 125 127 'AlmanacServiceTypeDatasource' => 'applications/almanac/typeahead/AlmanacServiceTypeDatasource.php', 126 128 'AlmanacServiceTypeTestCase' => 'applications/almanac/servicetype/__tests__/AlmanacServiceTypeTestCase.php', 127 129 'AlmanacServiceViewController' => 'applications/almanac/controller/AlmanacServiceViewController.php', 128 130 'AlmanacTransaction' => 'applications/almanac/storage/AlmanacTransaction.php', 131 + 'AlmanacTransactionType' => 'applications/almanac/xaction/AlmanacTransactionType.php', 129 132 'AphlictDropdownDataQuery' => 'applications/aphlict/query/AphlictDropdownDataQuery.php', 130 133 'Aphront304Response' => 'aphront/response/Aphront304Response.php', 131 134 'Aphront400Response' => 'aphront/response/Aphront400Response.php', ··· 5316 5319 'AlmanacServiceEditor' => 'AlmanacEditor', 5317 5320 'AlmanacServiceListController' => 'AlmanacServiceController', 5318 5321 'AlmanacServiceNameNgrams' => 'PhabricatorSearchNgrams', 5322 + 'AlmanacServiceNameTransaction' => 'AlmanacServiceTransactionType', 5319 5323 'AlmanacServicePHIDType' => 'PhabricatorPHIDType', 5320 5324 'AlmanacServicePropertyEditEngine' => 'AlmanacPropertyEditEngine', 5321 5325 'AlmanacServiceQuery' => 'AlmanacQuery', 5322 5326 'AlmanacServiceSearchConduitAPIMethod' => 'PhabricatorSearchEngineAPIMethod', 5323 5327 'AlmanacServiceSearchEngine' => 'PhabricatorApplicationSearchEngine', 5324 - 'AlmanacServiceTransaction' => 'AlmanacTransaction', 5328 + 'AlmanacServiceTransaction' => 'PhabricatorModularTransaction', 5325 5329 'AlmanacServiceTransactionQuery' => 'PhabricatorApplicationTransactionQuery', 5330 + 'AlmanacServiceTransactionType' => 'AlmanacTransactionType', 5326 5331 'AlmanacServiceType' => 'Phobject', 5327 5332 'AlmanacServiceTypeDatasource' => 'PhabricatorTypeaheadDatasource', 5328 5333 'AlmanacServiceTypeTestCase' => 'PhabricatorTestCase', 5329 5334 'AlmanacServiceViewController' => 'AlmanacServiceController', 5330 5335 'AlmanacTransaction' => 'PhabricatorApplicationTransaction', 5336 + 'AlmanacTransactionType' => 'PhabricatorModularTransactionType', 5331 5337 'AphlictDropdownDataQuery' => 'Phobject', 5332 5338 'Aphront304Response' => 'AphrontResponse', 5333 5339 'Aphront400Response' => 'AphrontResponse',
+1 -1
src/applications/almanac/editor/AlmanacServiceEditEngine.php
··· 98 98 ->setKey('name') 99 99 ->setLabel(pht('Name')) 100 100 ->setDescription(pht('Name of the service.')) 101 - ->setTransactionType(AlmanacServiceTransaction::TYPE_NAME) 101 + ->setTransactionType(AlmanacServiceNameTransaction::TRANSACTIONTYPE) 102 102 ->setIsRequired(true) 103 103 ->setValue($object->getName()), 104 104 );
+8 -137
src/applications/almanac/editor/AlmanacServiceEditor.php
··· 7 7 return pht('Almanac Service'); 8 8 } 9 9 10 + public function getCreateObjectTitle($author, $object) { 11 + return pht('%s created this service.', $author); 12 + } 13 + 14 + public function getCreateObjectTitleForFeed($author, $object) { 15 + return pht('%s created %s.', $author, $object); 16 + } 17 + 10 18 public function getTransactionTypes() { 11 19 $types = parent::getTransactionTypes(); 12 - 13 - $types[] = AlmanacServiceTransaction::TYPE_NAME; 14 20 15 21 $types[] = PhabricatorTransactions::TYPE_VIEW_POLICY; 16 22 $types[] = PhabricatorTransactions::TYPE_EDIT_POLICY; 17 23 18 24 return $types; 19 25 } 20 - 21 - protected function getCustomTransactionOldValue( 22 - PhabricatorLiskDAO $object, 23 - PhabricatorApplicationTransaction $xaction) { 24 - switch ($xaction->getTransactionType()) { 25 - case AlmanacServiceTransaction::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 AlmanacServiceTransaction::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 AlmanacServiceTransaction::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 AlmanacServiceTransaction::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 AlmanacServiceTransaction::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('Service 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 - 95 - $name = $xaction->getNewValue(); 96 - 97 - try { 98 - AlmanacNames::validateName($name); 99 - } catch (Exception $ex) { 100 - $message = $ex->getMessage(); 101 - } 102 - 103 - if ($message !== null) { 104 - $error = new PhabricatorApplicationTransactionValidationError( 105 - $type, 106 - pht('Invalid'), 107 - $message, 108 - $xaction); 109 - $errors[] = $error; 110 - continue; 111 - } 112 - 113 - $other = id(new AlmanacServiceQuery()) 114 - ->setViewer(PhabricatorUser::getOmnipotentUser()) 115 - ->withNames(array($name)) 116 - ->executeOne(); 117 - if ($other && ($other->getID() != $object->getID())) { 118 - $error = new PhabricatorApplicationTransactionValidationError( 119 - $type, 120 - pht('Not Unique'), 121 - pht('Almanac services must have unique names.'), 122 - last($xactions)); 123 - $errors[] = $error; 124 - continue; 125 - } 126 - 127 - if ($name === $object->getName()) { 128 - continue; 129 - } 130 - 131 - $namespace = AlmanacNamespace::loadRestrictedNamespace( 132 - $this->getActor(), 133 - $name); 134 - if ($namespace) { 135 - $error = new PhabricatorApplicationTransactionValidationError( 136 - $type, 137 - pht('Restricted'), 138 - pht( 139 - 'You do not have permission to create Almanac services '. 140 - 'within the "%s" namespace.', 141 - $namespace->getName()), 142 - $xaction); 143 - $errors[] = $error; 144 - continue; 145 - } 146 - } 147 - } 148 - 149 - break; 150 - } 151 - 152 - return $errors; 153 - } 154 - 155 26 156 27 protected function validateAllTransactions( 157 28 PhabricatorLiskDAO $object,
+10 -25
src/applications/almanac/storage/AlmanacServiceTransaction.php
··· 1 1 <?php 2 2 3 3 final class AlmanacServiceTransaction 4 - extends AlmanacTransaction { 4 + extends PhabricatorModularTransaction { 5 5 6 - const TYPE_NAME = 'almanac:service:name'; 6 + public function getApplicationName() { 7 + return 'almanac'; 8 + } 9 + 10 + public function getApplicationTransactionCommentObject() { 11 + return null; 12 + } 7 13 8 14 public function getApplicationTransactionType() { 9 15 return AlmanacServicePHIDType::TYPECONST; 10 16 } 11 17 12 - public function getTitle() { 13 - $author_phid = $this->getAuthorPHID(); 14 - 15 - $old = $this->getOldValue(); 16 - $new = $this->getNewValue(); 17 - 18 - switch ($this->getTransactionType()) { 19 - case self::TYPE_NAME: 20 - if ($old === null) { 21 - return pht( 22 - '%s created this service.', 23 - $this->renderHandleLink($author_phid)); 24 - } else { 25 - return pht( 26 - '%s renamed this service from "%s" to "%s".', 27 - $this->renderHandleLink($author_phid), 28 - $old, 29 - $new); 30 - } 31 - break; 32 - } 33 - 34 - return parent::getTitle(); 18 + public function getBaseTransactionClass() { 19 + return 'AlmanacServiceTransactionType'; 35 20 } 36 21 37 22 }
+87
src/applications/almanac/xaction/AlmanacServiceNameTransaction.php
··· 1 + <?php 2 + 3 + final class AlmanacServiceNameTransaction 4 + extends AlmanacServiceTransactionType { 5 + 6 + const TRANSACTIONTYPE = 'almanac:service: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 service from %s to %s.', 19 + $this->renderAuthorLink(), 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->renderAuthorLink(), 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('Almanac services must have a name.')); 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 AlmanacServiceQuery()) 61 + ->setViewer(PhabricatorUser::getOmnipotentUser()) 62 + ->withNames(array($name)) 63 + ->executeOne(); 64 + if ($other && ($other->getID() != $object->getID())) { 65 + $errors[] = $this->newInvalidError( 66 + pht('Almanac services must have unique names.'), 67 + $xaction); 68 + continue; 69 + } 70 + 71 + $namespace = AlmanacNamespace::loadRestrictedNamespace( 72 + $this->getActor(), 73 + $name); 74 + if ($namespace) { 75 + $errors[] = $this->newInvalidError( 76 + pht( 77 + 'You do not have permission to create Almanac services '. 78 + 'within the "%s" namespace.', 79 + $namespace->getName()), 80 + $xaction); 81 + continue; 82 + } 83 + } 84 + 85 + return $errors; 86 + } 87 + }
+4
src/applications/almanac/xaction/AlmanacServiceTransactionType.php
··· 1 + <?php 2 + 3 + abstract class AlmanacServiceTransactionType 4 + extends AlmanacTransactionType {}
+4
src/applications/almanac/xaction/AlmanacTransactionType.php
··· 1 + <?php 2 + 3 + abstract class AlmanacTransactionType 4 + extends PhabricatorModularTransactionType {}