diff --git a/src/applications/calendar/xaction/PhabricatorCalendarEventDescriptionTransaction.php b/src/applications/calendar/xaction/PhabricatorCalendarEventDescriptionTransaction.php index 9c14f1ae80..343ffa2adf 100644 --- a/src/applications/calendar/xaction/PhabricatorCalendarEventDescriptionTransaction.php +++ b/src/applications/calendar/xaction/PhabricatorCalendarEventDescriptionTransaction.php @@ -1,42 +1,53 @@ getDescription(); } public function applyInternalEffects($object, $value) { $object->setDescription($value); } public function getTitle() { return pht( '%s updated the event description.', $this->renderAuthor()); } public function getTitleForFeed() { return pht( '%s updated the event description for %s.', $this->renderAuthor(), $this->renderObject()); } public function hasChangeDetailView() { return true; } public function newChangeDetailView() { $viewer = $this->getViewer(); return id(new PhabricatorApplicationTransactionTextDiffDetailView()) ->setViewer($viewer) ->setOldText($this->getOldValue()) ->setNewText($this->getNewValue()); } + public function newRemarkupChanges() { + $changes = array(); + + $changes[] = $this->newRemarkupChange() + ->setOldValue($this->getOldValue()) + ->setNewValue($this->getNewValue()); + + return $changes; + } + + } diff --git a/src/applications/transactions/storage/PhabricatorModularTransaction.php b/src/applications/transactions/storage/PhabricatorModularTransaction.php index 8ea6248563..c93a559108 100644 --- a/src/applications/transactions/storage/PhabricatorModularTransaction.php +++ b/src/applications/transactions/storage/PhabricatorModularTransaction.php @@ -1,152 +1,156 @@ implementation) { $this->implementation = $this->newTransactionImplementation(); } return $this->implementation; } public function newModularTransactionTypes() { $base_class = $this->getBaseTransactionClass(); $types = id(new PhutilClassMapQuery()) ->setAncestorClass($base_class) ->setUniqueMethod('getTransactionTypeConstant') ->execute(); // Add core transaction types. $types += id(new PhutilClassMapQuery()) ->setAncestorClass('PhabricatorCoreTransactionType') ->setUniqueMethod('getTransactionTypeConstant') ->execute(); return $types; } private function newTransactionImplementation() { $types = $this->newModularTransactionTypes(); $key = $this->getTransactionType(); if (empty($types[$key])) { $type = new PhabricatorCoreVoidTransaction(); } else { $type = clone $types[$key]; } $type->setStorage($this); return $type; } final public function generateOldValue($object) { return $this->getTransactionImplementation()->generateOldValue($object); } final public function generateNewValue($object) { return $this->getTransactionImplementation() ->generateNewValue($object, $this->getNewValue()); } final public function willApplyTransactions($object, array $xactions) { return $this->getTransactionImplementation() ->willApplyTransactions($object, $xactions); } final public function applyInternalEffects($object) { return $this->getTransactionImplementation() ->applyInternalEffects($object); } final public function applyExternalEffects($object) { return $this->getTransactionImplementation() ->applyExternalEffects($object); } final public function shouldHide() { if ($this->getTransactionImplementation()->shouldHide()) { return true; } return parent::shouldHide(); } final public function getIcon() { $icon = $this->getTransactionImplementation()->getIcon(); if ($icon !== null) { return $icon; } return parent::getIcon(); } final public function getTitle() { $title = $this->getTransactionImplementation()->getTitle(); if ($title !== null) { return $title; } return parent::getTitle(); } public function getTitleForMail() { $old_target = $this->getRenderingTarget(); $new_target = self::TARGET_TEXT; $this->setRenderingTarget($new_target); $title = $this->getTitle(); $this->setRenderingTarget($old_target); return $title; } final public function getTitleForFeed() { $title = $this->getTransactionImplementation()->getTitleForFeed(); if ($title !== null) { return $title; } return parent::getTitleForFeed(); } final public function getColor() { $color = $this->getTransactionImplementation()->getColor(); if ($color !== null) { return $color; } return parent::getColor(); } public function attachViewer(PhabricatorUser $viewer) { $this->getTransactionImplementation()->setViewer($viewer); return parent::attachViewer($viewer); } final public function hasChangeDetails() { if ($this->getTransactionImplementation()->hasChangeDetailView()) { return true; } return parent::hasChangeDetails(); } final public function renderChangeDetails(PhabricatorUser $viewer) { $impl = $this->getTransactionImplementation(); $impl->setViewer($viewer); $view = $impl->newChangeDetailView(); if ($view !== null) { return $view; } return parent::renderChangeDetails($viewer); } + final protected function newRemarkupChanges() { + return $this->getTransactionImplementation()->newRemarkupChanges(); + } + } diff --git a/src/applications/transactions/storage/PhabricatorModularTransactionType.php b/src/applications/transactions/storage/PhabricatorModularTransactionType.php index a35eb02cd3..a5ddcc3e94 100644 --- a/src/applications/transactions/storage/PhabricatorModularTransactionType.php +++ b/src/applications/transactions/storage/PhabricatorModularTransactionType.php @@ -1,256 +1,265 @@ getPhobjectClassConstant('TRANSACTIONTYPE'); } public function generateOldValue($object) { throw new PhutilMethodNotImplementedException(); } public function generateNewValue($object, $value) { return $value; } public function validateTransactions($object, array $xactions) { return array(); } public function willApplyTransactions($object, array $xactions) { return; } public function applyInternalEffects($object, $value) { return; } public function applyExternalEffects($object, $value) { return; } public function extractFilePHIDs($object, $value) { return array(); } public function shouldHide() { return false; } public function getIcon() { return null; } public function getTitle() { return null; } public function getTitleForFeed() { return null; } public function getColor() { return null; } public function hasChangeDetailView() { return false; } public function newChangeDetailView() { throw new PhutilMethodNotImplementedException(); } + public function newRemarkupChanges() { + return array(); + } + final public function setStorage( PhabricatorApplicationTransaction $xaction) { $this->storage = $xaction; return $this; } private function getStorage() { return $this->storage; } final public function setViewer(PhabricatorUser $viewer) { $this->viewer = $viewer; return $this; } final protected function getViewer() { return $this->viewer; } final public function getActor() { return $this->getEditor()->getActor(); } final public function getActingAsPHID() { return $this->getEditor()->getActingAsPHID(); } final public function setEditor( PhabricatorApplicationTransactionEditor $editor) { $this->editor = $editor; return $this; } final protected function getEditor() { if (!$this->editor) { throw new PhutilInvalidStateException('setEditor'); } return $this->editor; } final protected function getAuthorPHID() { return $this->getStorage()->getAuthorPHID(); } final protected function getObjectPHID() { return $this->getStorage()->getObjectPHID(); } final protected function getObject() { return $this->getStorage()->getObject(); } final protected function getOldValue() { return $this->getStorage()->getOldValue(); } final protected function getNewValue() { return $this->getStorage()->getNewValue(); } final protected function renderAuthor() { $author_phid = $this->getAuthorPHID(); return $this->getStorage()->renderHandleLink($author_phid); } final protected function renderObject() { $object_phid = $this->getObjectPHID(); return $this->getStorage()->renderHandleLink($object_phid); } final protected function renderHandle($phid) { $viewer = $this->getViewer(); $display = $viewer->renderHandle($phid); if ($this->isTextMode()) { $display->setAsText(true); } return $display; } final protected function renderOldHandle() { return $this->renderHandle($this->getOldValue()); } final protected function renderNewHandle() { return $this->renderHandle($this->getNewValue()); } final protected function renderHandleList(array $phids) { $viewer = $this->getViewer(); $display = $viewer->renderHandleList($phids) ->setAsInline(true); if ($this->isTextMode()) { $display->setAsText(true); } return $display; } final protected function renderValue($value) { if ($this->isTextMode()) { return sprintf('"%s"', $value); } return phutil_tag( 'span', array( 'class' => 'phui-timeline-value', ), $value); } final protected function renderOldValue() { return $this->renderValue($this->getOldValue()); } final protected function renderNewValue() { return $this->renderValue($this->getNewValue()); } final protected function renderDate($epoch) { $viewer = $this->getViewer(); $display = phabricator_datetime($epoch, $viewer); // When rendering to text, we explicitly render the offset from UTC to // provide context to the date: the mail may be generating with the // server's settings, or the user may later refer back to it after changing // timezones. if ($this->isTextMode()) { $offset = $viewer->getTimeZoneOffsetInHours(); if ($offset >= 0) { $display = pht('%s (UTC+%d)', $display, $offset); } else { $display = pht('%s (UTC-%d)', $display, abs($offset)); } } return $this->renderValue($display); } final protected function renderOldDate() { return $this->renderDate($this->getOldValue()); } final protected function renderNewDate() { return $this->renderDate($this->getNewValue()); } final protected function newError($title, $message, $xaction = null) { return new PhabricatorApplicationTransactionValidationError( $this->getTransactionTypeConstant(), $title, $message, $xaction); } final protected function newRequiredError($message, $xaction = null) { return $this->newError(pht('Required'), $message, $xaction) ->setIsMissingFieldError(true); } final protected function newInvalidError($message, $xaction = null) { return $this->newError(pht('Invalid'), $message, $xaction); } final protected function isNewObject() { return $this->getEditor()->getIsNewObject(); } final protected function isEmptyTextTransaction($value, array $xactions) { foreach ($xactions as $xaction) { $value = $xaction->getNewValue(); } return !strlen($value); } private function isTextMode() { $target = $this->getStorage()->getRenderingTarget(); return ($target == PhabricatorApplicationTransaction::TARGET_TEXT); } + final protected function newRemarkupChange() { + return id(new PhabricatorTransactionRemarkupChange()) + ->setTransaction($this->getStorage()); + } + }