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

Reimplement Countdown transactions using Modular Transaction framework

Test Plan: owls

Reviewers: epriestley

Reviewed By: epriestley

Subscribers: Korvin

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

+192 -209
+9 -1
src/__phutil_library_map__.php
··· 2413 2413 'PhabricatorCountdownDAO' => 'applications/countdown/storage/PhabricatorCountdownDAO.php', 2414 2414 'PhabricatorCountdownDefaultEditCapability' => 'applications/countdown/capability/PhabricatorCountdownDefaultEditCapability.php', 2415 2415 'PhabricatorCountdownDefaultViewCapability' => 'applications/countdown/capability/PhabricatorCountdownDefaultViewCapability.php', 2416 + 'PhabricatorCountdownDescriptionTransaction' => 'applications/countdown/xaction/PhabricatorCountdownDescriptionTransaction.php', 2416 2417 'PhabricatorCountdownEditController' => 'applications/countdown/controller/PhabricatorCountdownEditController.php', 2417 2418 'PhabricatorCountdownEditEngine' => 'applications/countdown/editor/PhabricatorCountdownEditEngine.php', 2418 2419 'PhabricatorCountdownEditor' => 'applications/countdown/editor/PhabricatorCountdownEditor.php', 2420 + 'PhabricatorCountdownEpochTransaction' => 'applications/countdown/xaction/PhabricatorCountdownEpochTransaction.php', 2419 2421 'PhabricatorCountdownListController' => 'applications/countdown/controller/PhabricatorCountdownListController.php', 2420 2422 'PhabricatorCountdownMailReceiver' => 'applications/countdown/mail/PhabricatorCountdownMailReceiver.php', 2421 2423 'PhabricatorCountdownQuery' => 'applications/countdown/query/PhabricatorCountdownQuery.php', ··· 2423 2425 'PhabricatorCountdownReplyHandler' => 'applications/countdown/mail/PhabricatorCountdownReplyHandler.php', 2424 2426 'PhabricatorCountdownSchemaSpec' => 'applications/countdown/storage/PhabricatorCountdownSchemaSpec.php', 2425 2427 'PhabricatorCountdownSearchEngine' => 'applications/countdown/query/PhabricatorCountdownSearchEngine.php', 2428 + 'PhabricatorCountdownTitleTransaction' => 'applications/countdown/xaction/PhabricatorCountdownTitleTransaction.php', 2426 2429 'PhabricatorCountdownTransaction' => 'applications/countdown/storage/PhabricatorCountdownTransaction.php', 2427 2430 'PhabricatorCountdownTransactionComment' => 'applications/countdown/storage/PhabricatorCountdownTransactionComment.php', 2428 2431 'PhabricatorCountdownTransactionQuery' => 'applications/countdown/query/PhabricatorCountdownTransactionQuery.php', 2432 + 'PhabricatorCountdownTransactionType' => 'applications/countdown/xaction/PhabricatorCountdownTransactionType.php', 2429 2433 'PhabricatorCountdownView' => 'applications/countdown/view/PhabricatorCountdownView.php', 2430 2434 'PhabricatorCountdownViewController' => 'applications/countdown/controller/PhabricatorCountdownViewController.php', 2431 2435 'PhabricatorCursorPagedPolicyAwareQuery' => 'infrastructure/query/policy/PhabricatorCursorPagedPolicyAwareQuery.php', ··· 7516 7520 'PhabricatorCountdownDAO' => 'PhabricatorLiskDAO', 7517 7521 'PhabricatorCountdownDefaultEditCapability' => 'PhabricatorPolicyCapability', 7518 7522 'PhabricatorCountdownDefaultViewCapability' => 'PhabricatorPolicyCapability', 7523 + 'PhabricatorCountdownDescriptionTransaction' => 'PhabricatorCountdownTransactionType', 7519 7524 'PhabricatorCountdownEditController' => 'PhabricatorCountdownController', 7520 7525 'PhabricatorCountdownEditEngine' => 'PhabricatorEditEngine', 7521 7526 'PhabricatorCountdownEditor' => 'PhabricatorApplicationTransactionEditor', 7527 + 'PhabricatorCountdownEpochTransaction' => 'PhabricatorCountdownTransactionType', 7522 7528 'PhabricatorCountdownListController' => 'PhabricatorCountdownController', 7523 7529 'PhabricatorCountdownMailReceiver' => 'PhabricatorObjectMailReceiver', 7524 7530 'PhabricatorCountdownQuery' => 'PhabricatorCursorPagedPolicyAwareQuery', ··· 7526 7532 'PhabricatorCountdownReplyHandler' => 'PhabricatorApplicationTransactionReplyHandler', 7527 7533 'PhabricatorCountdownSchemaSpec' => 'PhabricatorConfigSchemaSpec', 7528 7534 'PhabricatorCountdownSearchEngine' => 'PhabricatorApplicationSearchEngine', 7529 - 'PhabricatorCountdownTransaction' => 'PhabricatorApplicationTransaction', 7535 + 'PhabricatorCountdownTitleTransaction' => 'PhabricatorCountdownTransactionType', 7536 + 'PhabricatorCountdownTransaction' => 'PhabricatorModularTransaction', 7530 7537 'PhabricatorCountdownTransactionComment' => 'PhabricatorApplicationTransactionComment', 7531 7538 'PhabricatorCountdownTransactionQuery' => 'PhabricatorApplicationTransactionQuery', 7539 + 'PhabricatorCountdownTransactionType' => 'PhabricatorModularTransactionType', 7532 7540 'PhabricatorCountdownView' => 'AphrontView', 7533 7541 'PhabricatorCountdownViewController' => 'PhabricatorCountdownController', 7534 7542 'PhabricatorCursorPagedPolicyAwareQuery' => 'PhabricatorPolicyAwareQuery',
+6 -3
src/applications/countdown/editor/PhabricatorCountdownEditEngine.php
··· 81 81 ->setKey('name') 82 82 ->setLabel(pht('Name')) 83 83 ->setIsRequired(true) 84 - ->setTransactionType(PhabricatorCountdownTransaction::TYPE_TITLE) 84 + ->setTransactionType( 85 + PhabricatorCountdownTitleTransaction::TRANSACTIONTYPE) 85 86 ->setDescription(pht('The countdown name.')) 86 87 ->setConduitDescription(pht('Rename the countdown.')) 87 88 ->setConduitTypeDescription(pht('New countdown name.')) ··· 89 90 id(new PhabricatorEpochEditField()) 90 91 ->setKey('epoch') 91 92 ->setLabel(pht('End Date')) 92 - ->setTransactionType(PhabricatorCountdownTransaction::TYPE_EPOCH) 93 + ->setTransactionType( 94 + PhabricatorCountdownEpochTransaction::TRANSACTIONTYPE) 93 95 ->setDescription(pht('Date when the countdown ends.')) 94 96 ->setConduitDescription(pht('Change the end date of the countdown.')) 95 97 ->setConduitTypeDescription(pht('New countdown end date.')) ··· 97 99 id(new PhabricatorRemarkupEditField()) 98 100 ->setKey('description') 99 101 ->setLabel(pht('Description')) 100 - ->setTransactionType(PhabricatorCountdownTransaction::TYPE_DESCRIPTION) 102 + ->setTransactionType( 103 + PhabricatorCountdownDescriptionTransaction::TRANSACTIONTYPE) 101 104 ->setDescription(pht('Description of the countdown.')) 102 105 ->setConduitDescription(pht('Change the countdown description.')) 103 106 ->setConduitTypeDescription(pht('New description.'))
-124
src/applications/countdown/editor/PhabricatorCountdownEditor.php
··· 14 14 public function getTransactionTypes() { 15 15 $types = parent::getTransactionTypes(); 16 16 17 - $types[] = PhabricatorCountdownTransaction::TYPE_TITLE; 18 - $types[] = PhabricatorCountdownTransaction::TYPE_EPOCH; 19 - $types[] = PhabricatorCountdownTransaction::TYPE_DESCRIPTION; 20 - 21 17 $types[] = PhabricatorTransactions::TYPE_EDGE; 22 18 $types[] = PhabricatorTransactions::TYPE_SPACE; 23 19 $types[] = PhabricatorTransactions::TYPE_VIEW_POLICY; ··· 25 21 $types[] = PhabricatorTransactions::TYPE_COMMENT; 26 22 27 23 return $types; 28 - } 29 - 30 - protected function getCustomTransactionOldValue( 31 - PhabricatorLiskDAO $object, 32 - PhabricatorApplicationTransaction $xaction) { 33 - switch ($xaction->getTransactionType()) { 34 - case PhabricatorCountdownTransaction::TYPE_TITLE: 35 - return $object->getTitle(); 36 - case PhabricatorCountdownTransaction::TYPE_DESCRIPTION: 37 - return $object->getDescription(); 38 - case PhabricatorCountdownTransaction::TYPE_EPOCH: 39 - return $object->getEpoch(); 40 - } 41 - 42 - return parent::getCustomTransactionOldValue($object, $xaction); 43 - } 44 - 45 - protected function getCustomTransactionNewValue( 46 - PhabricatorLiskDAO $object, 47 - PhabricatorApplicationTransaction $xaction) { 48 - 49 - switch ($xaction->getTransactionType()) { 50 - case PhabricatorCountdownTransaction::TYPE_TITLE: 51 - return $xaction->getNewValue(); 52 - case PhabricatorCountdownTransaction::TYPE_DESCRIPTION: 53 - return $xaction->getNewValue(); 54 - case PhabricatorCountdownTransaction::TYPE_EPOCH: 55 - return $xaction->getNewValue()->getEpoch(); 56 - } 57 - 58 - return parent::getCustomTransactionNewValue($object, $xaction); 59 - } 60 - 61 - protected function applyCustomInternalTransaction( 62 - PhabricatorLiskDAO $object, 63 - PhabricatorApplicationTransaction $xaction) { 64 - 65 - $type = $xaction->getTransactionType(); 66 - switch ($type) { 67 - case PhabricatorCountdownTransaction::TYPE_TITLE: 68 - $object->setTitle($xaction->getNewValue()); 69 - return; 70 - case PhabricatorCountdownTransaction::TYPE_DESCRIPTION: 71 - $object->setDescription($xaction->getNewValue()); 72 - return; 73 - case PhabricatorCountdownTransaction::TYPE_EPOCH: 74 - $object->setEpoch($xaction->getNewValue()); 75 - return; 76 - } 77 - 78 - return parent::applyCustomInternalTransaction($object, $xaction); 79 - } 80 - 81 - protected function applyCustomExternalTransaction( 82 - PhabricatorLiskDAO $object, 83 - PhabricatorApplicationTransaction $xaction) { 84 - 85 - $type = $xaction->getTransactionType(); 86 - switch ($type) { 87 - case PhabricatorCountdownTransaction::TYPE_TITLE: 88 - return; 89 - case PhabricatorCountdownTransaction::TYPE_DESCRIPTION: 90 - return; 91 - case PhabricatorCountdownTransaction::TYPE_EPOCH: 92 - return; 93 - } 94 - 95 - return parent::applyCustomExternalTransaction($object, $xaction); 96 - } 97 - 98 - protected function validateTransaction( 99 - PhabricatorLiskDAO $object, 100 - $type, 101 - array $xactions) { 102 - 103 - $errors = parent::validateTransaction($object, $type, $xactions); 104 - 105 - switch ($type) { 106 - case PhabricatorCountdownTransaction::TYPE_TITLE: 107 - $missing = $this->validateIsEmptyTextField( 108 - $object->getTitle(), 109 - $xactions); 110 - 111 - if ($missing) { 112 - $error = new PhabricatorApplicationTransactionValidationError( 113 - $type, 114 - pht('Required'), 115 - pht('You must give the countdown a name.'), 116 - nonempty(last($xactions), null)); 117 - 118 - $error->setIsMissingFieldError(true); 119 - $errors[] = $error; 120 - } 121 - break; 122 - case PhabricatorCountdownTransaction::TYPE_EPOCH: 123 - if (!$object->getEpoch() && !$xactions) { 124 - $error = new PhabricatorApplicationTransactionValidationError( 125 - $type, 126 - pht('Required'), 127 - pht('You must give the countdown an end date.'), 128 - null); 129 - $error->setIsMissingFieldError(true); 130 - $errors[] = $error; 131 - } 132 - 133 - foreach ($xactions as $xaction) { 134 - $value = $xaction->getNewValue(); 135 - if (!$value->isValid()) { 136 - $error = new PhabricatorApplicationTransactionValidationError( 137 - $type, 138 - pht('Invalid'), 139 - pht('You must give the countdown a valid end date.'), 140 - $xaction); 141 - $errors[] = $error; 142 - } 143 - } 144 - break; 145 - } 146 - 147 - return $errors; 148 24 } 149 25 150 26 protected function shouldSendMail(
+6 -81
src/applications/countdown/storage/PhabricatorCountdownTransaction.php
··· 1 1 <?php 2 2 3 3 final class PhabricatorCountdownTransaction 4 - extends PhabricatorApplicationTransaction { 5 - 6 - const TYPE_TITLE = 'countdown:title'; 7 - const TYPE_EPOCH = 'countdown:epoch'; 8 - const TYPE_DESCRIPTION = 'countdown:description'; 4 + extends PhabricatorModularTransaction { 9 5 10 6 const MAILTAG_DETAILS = 'countdown:details'; 11 7 const MAILTAG_COMMENT = 'countdown:comment'; ··· 23 19 return new PhabricatorCountdownTransactionComment(); 24 20 } 25 21 26 - public function getTitle() { 27 - $author_phid = $this->getAuthorPHID(); 28 - $object_phid = $this->getObjectPHID(); 29 - 30 - $old = $this->getOldValue(); 31 - $new = $this->getNewValue(); 32 - 33 - $type = $this->getTransactionType(); 34 - switch ($type) { 35 - case self::TYPE_TITLE: 36 - return pht( 37 - '%s renamed this countdown from "%s" to "%s".', 38 - $this->renderHandleLink($author_phid), 39 - $old, 40 - $new); 41 - case self::TYPE_DESCRIPTION: 42 - return pht( 43 - '%s edited the description of this countdown.', 44 - $this->renderHandleLink($author_phid)); 45 - case self::TYPE_EPOCH: 46 - return pht( 47 - '%s updated this countdown to end on %s.', 48 - $this->renderHandleLink($author_phid), 49 - phabricator_datetime($new, $this->getViewer())); 50 - } 51 - 52 - return parent::getTitle(); 53 - } 54 - 55 - public function getTitleForFeed() { 56 - $author_phid = $this->getAuthorPHID(); 57 - $object_phid = $this->getObjectPHID(); 58 - 59 - $old = $this->getOldValue(); 60 - $new = $this->getNewValue(); 61 - 62 - $type = $this->getTransactionType(); 63 - switch ($type) { 64 - case self::TYPE_TITLE: 65 - return pht( 66 - '%s renamed %s.', 67 - $this->renderHandleLink($author_phid), 68 - $this->renderHandleLink($object_phid)); 69 - case self::TYPE_DESCRIPTION: 70 - return pht( 71 - '%s edited the description of %s.', 72 - $this->renderHandleLink($author_phid), 73 - $this->renderHandleLink($object_phid)); 74 - case self::TYPE_EPOCH: 75 - return pht( 76 - '%s edited the end date of %s.', 77 - $this->renderHandleLink($author_phid), 78 - $this->renderHandleLink($object_phid)); 79 - } 80 - 81 - return parent::getTitleForFeed(); 22 + public function getBaseTransactionClass() { 23 + return 'PhabricatorCountdownTransactionType'; 82 24 } 83 25 84 26 public function getMailTags() { ··· 88 30 case PhabricatorTransactions::TYPE_COMMENT: 89 31 $tags[] = self::MAILTAG_COMMENT; 90 32 break; 91 - case self::TYPE_TITLE: 92 - case self::TYPE_EPOCH: 93 - case self::TYPE_DESCRIPTION: 33 + case PhabricatorCountdownTitleTransaction::TRANSACTIONTYPE: 34 + case PhabricatorCountdownEpochTransaction::TRANSACTIONTYPE: 35 + case PhabricatorCountdownDescriptionTransaction::TRANSACTIONTYPE: 94 36 $tags[] = self::MAILTAG_DETAILS; 95 37 break; 96 38 default: ··· 100 42 101 43 return $tags; 102 44 } 103 - 104 - public function hasChangeDetails() { 105 - switch ($this->getTransactionType()) { 106 - case self::TYPE_DESCRIPTION: 107 - return ($this->getOldValue() !== null); 108 - } 109 - 110 - return parent::hasChangeDetails(); 111 - } 112 - 113 - public function renderChangeDetails(PhabricatorUser $viewer) { 114 - return $this->renderTextCorpusChangeDetails( 115 - $viewer, 116 - $this->getOldValue(), 117 - $this->getNewValue()); 118 - } 119 - 120 45 }
+55
src/applications/countdown/xaction/PhabricatorCountdownDescriptionTransaction.php
··· 1 + <?php 2 + 3 + final class PhabricatorCountdownDescriptionTransaction 4 + extends PhabricatorCountdownTransactionType { 5 + 6 + const TRANSACTIONTYPE = 'countdown:description'; 7 + 8 + public function generateOldValue($object) { 9 + return $object->getDescription(); 10 + } 11 + 12 + public function applyInternalEffects($object, $value) { 13 + $object->setDescription($value); 14 + } 15 + 16 + public function getTitle() { 17 + return pht( 18 + '%s updated the countdown description.', 19 + $this->renderAuthor()); 20 + } 21 + 22 + public function getTitleForFeed() { 23 + return pht( 24 + '%s updated the countdown description for %s.', 25 + $this->renderAuthor(), 26 + $this->renderObject()); 27 + } 28 + 29 + public function hasChangeDetailView() { 30 + return true; 31 + } 32 + 33 + public function getMailDiffSectionHeader() { 34 + return pht('CHANGES TO COUNTDOWN DESCRIPTION'); 35 + } 36 + 37 + public function newChangeDetailView() { 38 + $viewer = $this->getViewer(); 39 + 40 + return id(new PhabricatorApplicationTransactionTextDiffDetailView()) 41 + ->setViewer($viewer) 42 + ->setOldText($this->getOldValue()) 43 + ->setNewText($this->getNewValue()); 44 + } 45 + 46 + public function newRemarkupChanges() { 47 + $changes = array(); 48 + 49 + $changes[] = $this->newRemarkupChange() 50 + ->setOldValue($this->getOldValue()) 51 + ->setNewValue($this->getNewValue()); 52 + 53 + return $changes; 54 + } 55 + }
+58
src/applications/countdown/xaction/PhabricatorCountdownEpochTransaction.php
··· 1 + <?php 2 + 3 + final class PhabricatorCountdownEpochTransaction 4 + extends PhabricatorCountdownTransactionType { 5 + 6 + const TRANSACTIONTYPE = 'countdown:epoch'; 7 + 8 + public function generateOldValue($object) { 9 + return (int)$object->getEpoch(); 10 + } 11 + 12 + public function generateNewValue($object, $value) { 13 + return $value->newPhutilDateTime() 14 + ->newAbsoluteDateTime() 15 + ->getEpoch(); 16 + } 17 + 18 + public function applyInternalEffects($object, $value) { 19 + $object->setEpoch($value); 20 + } 21 + 22 + public function getTitle() { 23 + return pht( 24 + '%s updated the countdown end from %s to %s.', 25 + $this->renderAuthor(), 26 + $this->renderOldDate(), 27 + $this->renderNewDate()); 28 + } 29 + 30 + public function getTitleForFeed() { 31 + return pht( 32 + '%s updated the countdown end for %s from %s to %s.', 33 + $this->renderAuthor(), 34 + $this->renderObject(), 35 + $this->renderOldDate(), 36 + $this->renderNewDate()); 37 + } 38 + 39 + public function validateTransactions($object, array $xactions) { 40 + $errors = array(); 41 + 42 + if (!$object->getEpoch() && !$xactions) { 43 + $errors[] = $this->newRequiredError( 44 + pht('You must give the countdown an end date.')); 45 + return $errors; 46 + } 47 + 48 + foreach ($xactions as $xaction) { 49 + $value = $xaction->getNewValue(); 50 + if (!$value->isValid()) { 51 + $errors[] = $this->newInvalidError( 52 + pht('You must give the countdown an end date.')); 53 + } 54 + } 55 + 56 + return $errors; 57 + } 58 + }
+54
src/applications/countdown/xaction/PhabricatorCountdownTitleTransaction.php
··· 1 + <?php 2 + 3 + final class PhabricatorCountdownTitleTransaction 4 + extends PhabricatorCountdownTransactionType { 5 + 6 + const TRANSACTIONTYPE = 'countdown:title'; 7 + 8 + public function generateOldValue($object) { 9 + return $object->getTitle(); 10 + } 11 + 12 + public function applyInternalEffects($object, $value) { 13 + $object->setTitle($value); 14 + } 15 + 16 + public function getTitle() { 17 + return pht( 18 + '%s updated the title for this countdown from %s to %s.', 19 + $this->renderAuthor(), 20 + $this->renderOldValue(), 21 + $this->renderNewValue()); 22 + } 23 + 24 + public function getTitleForFeed() { 25 + return pht( 26 + '%s updated the title for this countdown from %s to %s.', 27 + $this->renderAuthor(), 28 + $this->renderOldValue(), 29 + $this->renderNewValue()); 30 + } 31 + 32 + public function validateTransactions($object, array $xactions) { 33 + $errors = array(); 34 + 35 + if ($this->isEmptyTextTransaction($object->getTitle(), $xactions)) { 36 + $errors[] = $this->newRequiredError(pht('Countdowns must have a title.')); 37 + } 38 + 39 + $max_length = $object->getColumnMaximumByteLength('title'); 40 + foreach ($xactions as $xaction) { 41 + $new_value = $xaction->getNewValue(); 42 + $new_length = strlen($new_value); 43 + if ($new_length > $max_length) { 44 + $errors[] = $this->newInvalidError( 45 + pht( 46 + 'Countdown titles must not be longer than %s character(s).', 47 + new PhutilNumber($max_length))); 48 + } 49 + } 50 + 51 + return $errors; 52 + } 53 + 54 + }
+4
src/applications/countdown/xaction/PhabricatorCountdownTransactionType.php
··· 1 + <?php 2 + 3 + abstract class PhabricatorCountdownTransactionType 4 + extends PhabricatorModularTransactionType {}