Page MenuHomestyx hydra

No OneTemporary

diff --git a/src/applications/differential/xaction/DifferentialRevisionWrongStateTransaction.php b/src/applications/differential/xaction/DifferentialRevisionWrongStateTransaction.php
index e19e54199c..47678e886f 100644
--- a/src/applications/differential/xaction/DifferentialRevisionWrongStateTransaction.php
+++ b/src/applications/differential/xaction/DifferentialRevisionWrongStateTransaction.php
@@ -1,41 +1,42 @@
<?php
final class DifferentialRevisionWrongStateTransaction
extends DifferentialRevisionTransactionType {
const TRANSACTIONTYPE = 'differential.revision.wrong';
public function generateOldValue($object) {
return null;
}
public function generateNewValue($object, $value) {
return $value;
}
public function getIcon() {
return 'fa-exclamation';
}
public function getColor() {
return 'pink';
}
public function getActionStrength() {
return 4;
}
public function getTitle() {
$new_value = $this->getNewValue();
$status = DifferentialRevisionStatus::newForStatus($new_value);
return pht(
'This revision was not accepted when it landed; it landed in state %s.',
$this->renderValue($status->getDisplayName()));
}
- public function getTitleForFeed() {
- return null;
+ public function shouldHideForFeed() {
+ return true;
}
+
}
diff --git a/src/applications/maniphest/storage/ManiphestTransaction.php b/src/applications/maniphest/storage/ManiphestTransaction.php
index 6301241050..e2739c1d09 100644
--- a/src/applications/maniphest/storage/ManiphestTransaction.php
+++ b/src/applications/maniphest/storage/ManiphestTransaction.php
@@ -1,240 +1,224 @@
<?php
final class ManiphestTransaction
extends PhabricatorModularTransaction {
const MAILTAG_STATUS = 'maniphest-status';
const MAILTAG_OWNER = 'maniphest-owner';
const MAILTAG_PRIORITY = 'maniphest-priority';
const MAILTAG_CC = 'maniphest-cc';
const MAILTAG_PROJECTS = 'maniphest-projects';
const MAILTAG_COMMENT = 'maniphest-comment';
const MAILTAG_COLUMN = 'maniphest-column';
const MAILTAG_UNBLOCK = 'maniphest-unblock';
const MAILTAG_OTHER = 'maniphest-other';
public function getApplicationName() {
return 'maniphest';
}
public function getApplicationTransactionType() {
return ManiphestTaskPHIDType::TYPECONST;
}
public function getApplicationTransactionCommentObject() {
return new ManiphestTransactionComment();
}
public function getBaseTransactionClass() {
return 'ManiphestTaskTransactionType';
}
public function shouldGenerateOldValue() {
switch ($this->getTransactionType()) {
case ManiphestTaskEdgeTransaction::TRANSACTIONTYPE:
case ManiphestTaskUnblockTransaction::TRANSACTIONTYPE:
return false;
}
return parent::shouldGenerateOldValue();
}
- public function shouldHideForFeed() {
- // NOTE: Modular transactions don't currently support this, and it has
- // very few callsites, and it's publish-time rather than display-time.
- // This should probably become a supported, display-time behavior. For
- // discussion, see T12787.
-
- // Hide "alice created X, a task blocking Y." from feed because it
- // will almost always appear adjacent to "alice created Y".
- $is_new = $this->getMetadataValue('blocker.new');
- if ($is_new) {
- return true;
- }
-
- return parent::shouldHideForFeed();
- }
-
public function getRequiredHandlePHIDs() {
$phids = parent::getRequiredHandlePHIDs();
$new = $this->getNewValue();
$old = $this->getOldValue();
switch ($this->getTransactionType()) {
case ManiphestTaskOwnerTransaction::TRANSACTIONTYPE:
if ($new) {
$phids[] = $new;
}
if ($old) {
$phids[] = $old;
}
break;
case ManiphestTaskMergedIntoTransaction::TRANSACTIONTYPE:
$phids[] = $new;
break;
case ManiphestTaskMergedFromTransaction::TRANSACTIONTYPE:
$phids = array_merge($phids, $new);
break;
case ManiphestTaskEdgeTransaction::TRANSACTIONTYPE:
$phids = array_mergev(
array(
$phids,
array_keys(nonempty($old, array())),
array_keys(nonempty($new, array())),
));
break;
case ManiphestTaskAttachTransaction::TRANSACTIONTYPE:
$old = nonempty($old, array());
$new = nonempty($new, array());
$phids = array_mergev(
array(
$phids,
array_keys(idx($new, 'FILE', array())),
array_keys(idx($old, 'FILE', array())),
));
break;
case ManiphestTaskUnblockTransaction::TRANSACTIONTYPE:
foreach (array_keys($new) as $phid) {
$phids[] = $phid;
}
break;
case ManiphestTaskStatusTransaction::TRANSACTIONTYPE:
$commit_phid = $this->getMetadataValue('commitPHID');
if ($commit_phid) {
$phids[] = $commit_phid;
}
break;
}
return $phids;
}
public function getActionName() {
$old = $this->getOldValue();
$new = $this->getNewValue();
switch ($this->getTransactionType()) {
case PhabricatorTransactions::TYPE_COLUMNS:
return pht('Changed Project Column');
}
return parent::getActionName();
}
public function getIcon() {
switch ($this->getTransactionType()) {
case PhabricatorTransactions::TYPE_COLUMNS:
return 'fa-columns';
}
return parent::getIcon();
}
public function getTitle() {
$author_phid = $this->getAuthorPHID();
$old = $this->getOldValue();
$new = $this->getNewValue();
switch ($this->getTransactionType()) {
case PhabricatorTransactions::TYPE_SUBTYPE:
return pht(
'%s changed the subtype of this task from "%s" to "%s".',
$this->renderHandleLink($author_phid),
$this->renderSubtypeName($old),
$this->renderSubtypeName($new));
break;
}
return parent::getTitle();
}
public function getTitleForFeed() {
$author_phid = $this->getAuthorPHID();
$object_phid = $this->getObjectPHID();
$old = $this->getOldValue();
$new = $this->getNewValue();
switch ($this->getTransactionType()) {
case PhabricatorTransactions::TYPE_SUBTYPE:
return pht(
'%s changed the subtype of %s from "%s" to "%s".',
$this->renderHandleLink($author_phid),
$this->renderHandleLink($object_phid),
$this->renderSubtypeName($old),
$this->renderSubtypeName($new));
}
return parent::getTitleForFeed();
}
public function getMailTags() {
$tags = array();
switch ($this->getTransactionType()) {
case ManiphestTaskMergedIntoTransaction::TRANSACTIONTYPE:
case ManiphestTaskStatusTransaction::TRANSACTIONTYPE:
$tags[] = self::MAILTAG_STATUS;
break;
case ManiphestTaskOwnerTransaction::TRANSACTIONTYPE:
$tags[] = self::MAILTAG_OWNER;
break;
case PhabricatorTransactions::TYPE_SUBSCRIBERS:
$tags[] = self::MAILTAG_CC;
break;
case PhabricatorTransactions::TYPE_EDGE:
switch ($this->getMetadataValue('edge:type')) {
case PhabricatorProjectObjectHasProjectEdgeType::EDGECONST:
$tags[] = self::MAILTAG_PROJECTS;
break;
default:
$tags[] = self::MAILTAG_OTHER;
break;
}
break;
case ManiphestTaskPriorityTransaction::TRANSACTIONTYPE:
$tags[] = self::MAILTAG_PRIORITY;
break;
case ManiphestTaskUnblockTransaction::TRANSACTIONTYPE:
$tags[] = self::MAILTAG_UNBLOCK;
break;
case PhabricatorTransactions::TYPE_COLUMNS:
$tags[] = self::MAILTAG_COLUMN;
break;
case PhabricatorTransactions::TYPE_COMMENT:
$tags[] = self::MAILTAG_COMMENT;
break;
default:
$tags[] = self::MAILTAG_OTHER;
break;
}
return $tags;
}
public function getNoEffectDescription() {
switch ($this->getTransactionType()) {
case ManiphestTaskStatusTransaction::TRANSACTIONTYPE:
return pht('The task already has the selected status.');
case ManiphestTaskOwnerTransaction::TRANSACTIONTYPE:
return pht('The task already has the selected owner.');
case ManiphestTaskPriorityTransaction::TRANSACTIONTYPE:
return pht('The task already has the selected priority.');
}
return parent::getNoEffectDescription();
}
public function renderSubtypeName($value) {
$object = $this->getObject();
$map = $object->newEditEngineSubtypeMap();
if (!isset($map[$value])) {
return $value;
}
return $map[$value]->getName();
}
}
diff --git a/src/applications/maniphest/xaction/ManiphestTaskUnblockTransaction.php b/src/applications/maniphest/xaction/ManiphestTaskUnblockTransaction.php
index 1c7a88dec7..8833e62b79 100644
--- a/src/applications/maniphest/xaction/ManiphestTaskUnblockTransaction.php
+++ b/src/applications/maniphest/xaction/ManiphestTaskUnblockTransaction.php
@@ -1,116 +1,126 @@
<?php
final class ManiphestTaskUnblockTransaction
extends ManiphestTaskTransactionType {
const TRANSACTIONTYPE = 'unblock';
public function generateOldValue($object) {
return null;
}
public function getActionName() {
$old = $this->getOldValue();
$new = $this->getNewValue();
$old_status = head($old);
$new_status = head($new);
$old_closed = ManiphestTaskStatus::isClosedStatus($old_status);
$new_closed = ManiphestTaskStatus::isClosedStatus($new_status);
if ($old_closed && !$new_closed) {
return pht('Block');
} else if (!$old_closed && $new_closed) {
return pht('Unblock');
} else {
return pht('Blocker');
}
}
public function getTitle() {
$old = $this->getOldValue();
$new = $this->getNewValue();
$blocker_phid = key($new);
$old_status = head($old);
$new_status = head($new);
$old_closed = ManiphestTaskStatus::isClosedStatus($old_status);
$new_closed = ManiphestTaskStatus::isClosedStatus($new_status);
$old_name = ManiphestTaskStatus::getTaskStatusName($old_status);
$new_name = ManiphestTaskStatus::getTaskStatusName($new_status);
if ($this->getMetadataValue('blocker.new')) {
return pht(
'%s created subtask %s.',
$this->renderAuthor(),
$this->renderHandle($blocker_phid));
} else if ($old_closed && !$new_closed) {
return pht(
'%s reopened subtask %s as %s.',
$this->renderAuthor(),
$this->renderHandle($blocker_phid),
$this->renderValue($new_name));
} else if (!$old_closed && $new_closed) {
return pht(
'%s closed subtask %s as %s.',
$this->renderAuthor(),
$this->renderHandle($blocker_phid),
$this->renderValue($new_name));
} else {
return pht(
'%s changed the status of subtask %s from %s to %s.',
$this->renderAuthor(),
$this->renderHandle($blocker_phid),
$this->renderValue($old_name),
$this->renderValue($new_name));
}
}
public function getTitleForFeed() {
$old = $this->getOldValue();
$new = $this->getNewValue();
$blocker_phid = key($new);
$old_status = head($old);
$new_status = head($new);
$old_closed = ManiphestTaskStatus::isClosedStatus($old_status);
$new_closed = ManiphestTaskStatus::isClosedStatus($new_status);
$old_name = ManiphestTaskStatus::getTaskStatusName($old_status);
$new_name = ManiphestTaskStatus::getTaskStatusName($new_status);
if ($old_closed && !$new_closed) {
return pht(
'%s reopened %s, a subtask of %s, as %s.',
$this->renderAuthor(),
$this->renderHandle($blocker_phid),
$this->renderObject(),
$this->renderValue($new_name));
} else if (!$old_closed && $new_closed) {
return pht(
'%s closed %s, a subtask of %s, as %s.',
$this->renderAuthor(),
$this->renderHandle($blocker_phid),
$this->renderObject(),
$this->renderValue($new_name));
} else {
return pht(
'%s changed the status of %s, a subtask of %s, '.
'from %s to %s.',
$this->renderAuthor(),
$this->renderHandle($blocker_phid),
$this->renderObject(),
$this->renderValue($old_name),
$this->renderValue($new_name));
}
}
public function getIcon() {
return 'fa-shield';
}
+ public function shouldHideForFeed() {
+ // Hide "alice created X, a task blocking Y." from feed because it
+ // will almost always appear adjacent to "alice created Y".
+ $is_new = $this->getMetadataValue('blocker.new');
+ if ($is_new) {
+ return true;
+ }
+
+ return parent::shouldHideForFeed();
+ }
}
diff --git a/src/applications/phriction/storage/PhrictionTransaction.php b/src/applications/phriction/storage/PhrictionTransaction.php
index 2ce9d38a08..860a86be35 100644
--- a/src/applications/phriction/storage/PhrictionTransaction.php
+++ b/src/applications/phriction/storage/PhrictionTransaction.php
@@ -1,91 +1,79 @@
<?php
final class PhrictionTransaction
extends PhabricatorModularTransaction {
const MAILTAG_TITLE = 'phriction-title';
const MAILTAG_CONTENT = 'phriction-content';
const MAILTAG_DELETE = 'phriction-delete';
const MAILTAG_SUBSCRIBERS = 'phriction-subscribers';
const MAILTAG_OTHER = 'phriction-other';
public function getApplicationName() {
return 'phriction';
}
public function getApplicationTransactionType() {
return PhrictionDocumentPHIDType::TYPECONST;
}
public function getApplicationTransactionCommentObject() {
return new PhrictionTransactionComment();
}
public function getBaseTransactionClass() {
return 'PhrictionDocumentTransactionType';
}
public function getRequiredHandlePHIDs() {
$phids = parent::getRequiredHandlePHIDs();
$new = $this->getNewValue();
switch ($this->getTransactionType()) {
case PhrictionDocumentMoveToTransaction::TRANSACTIONTYPE:
case PhrictionDocumentMoveAwayTransaction::TRANSACTIONTYPE:
$phids[] = $new['phid'];
break;
case PhrictionDocumentTitleTransaction::TRANSACTIONTYPE:
if ($this->getMetadataValue('stub:create:phid')) {
$phids[] = $this->getMetadataValue('stub:create:phid');
}
break;
}
return $phids;
}
public function shouldHideForMail(array $xactions) {
switch ($this->getTransactionType()) {
case PhrictionDocumentMoveToTransaction::TRANSACTIONTYPE:
case PhrictionDocumentMoveAwayTransaction::TRANSACTIONTYPE:
return true;
case PhrictionDocumentTitleTransaction::TRANSACTIONTYPE:
return $this->getMetadataValue('stub:create:phid', false);
}
return parent::shouldHideForMail($xactions);
}
- public function shouldHideForFeed() {
- switch ($this->getTransactionType()) {
- case PhrictionDocumentMoveToTransaction::TRANSACTIONTYPE:
- case PhrictionDocumentMoveAwayTransaction::TRANSACTIONTYPE:
- return true;
- case PhrictionDocumentTitleTransaction::TRANSACTIONTYPE:
- return $this->getMetadataValue('stub:create:phid', false);
- }
- return parent::shouldHideForFeed();
- }
-
-
public function getMailTags() {
$tags = array();
switch ($this->getTransactionType()) {
case PhrictionDocumentTitleTransaction::TRANSACTIONTYPE:
$tags[] = self::MAILTAG_TITLE;
break;
case PhrictionDocumentContentTransaction::TRANSACTIONTYPE:
$tags[] = self::MAILTAG_CONTENT;
break;
case PhrictionDocumentDeleteTransaction::TRANSACTIONTYPE:
$tags[] = self::MAILTAG_DELETE;
break;
case PhabricatorTransactions::TYPE_SUBSCRIBERS:
$tags[] = self::MAILTAG_SUBSCRIBERS;
break;
default:
$tags[] = self::MAILTAG_OTHER;
break;
}
return $tags;
}
}
diff --git a/src/applications/phriction/xaction/PhrictionDocumentMoveAwayTransaction.php b/src/applications/phriction/xaction/PhrictionDocumentMoveAwayTransaction.php
index c827f7337d..3cd45f73b7 100644
--- a/src/applications/phriction/xaction/PhrictionDocumentMoveAwayTransaction.php
+++ b/src/applications/phriction/xaction/PhrictionDocumentMoveAwayTransaction.php
@@ -1,62 +1,66 @@
<?php
final class PhrictionDocumentMoveAwayTransaction
extends PhrictionDocumentTransactionType {
const TRANSACTIONTYPE = 'move-away';
public function generateOldValue($object) {
return null;
}
public function generateNewValue($object, $value) {
$document = $value;
$dict = array(
'id' => $document->getID(),
'phid' => $document->getPHID(),
'content' => $document->getContent()->getContent(),
'title' => $document->getContent()->getTitle(),
);
return $dict;
}
public function applyInternalEffects($object, $value) {
$object->setStatus(PhrictionDocumentStatus::STATUS_MOVED);
}
public function applyExternalEffects($object, $value) {
$dict = $value;
$this->getEditor()->getNewContent()->setContent('');
$this->getEditor()->getNewContent()->setChangeType(
PhrictionChangeType::CHANGE_MOVE_AWAY);
$this->getEditor()->getNewContent()->setChangeRef($dict['id']);
}
public function getActionName() {
return pht('Moved Away');
}
public function getTitle() {
$new = $this->getNewValue();
return pht(
'%s moved this document to %s',
$this->renderAuthor(),
$this->renderHandleLink($new['phid']));
}
public function getTitleForFeed() {
$new = $this->getNewValue();
return pht(
'%s moved %s to %s',
$this->renderAuthor(),
$this->renderObject(),
$this->renderHandleLink($new['phid']));
}
public function getIcon() {
return 'fa-arrows';
}
+ public function shouldHideForFeed() {
+ return true;
+ }
+
}
diff --git a/src/applications/phriction/xaction/PhrictionDocumentMoveToTransaction.php b/src/applications/phriction/xaction/PhrictionDocumentMoveToTransaction.php
index a95e70ebdb..bdf2c5d8fc 100644
--- a/src/applications/phriction/xaction/PhrictionDocumentMoveToTransaction.php
+++ b/src/applications/phriction/xaction/PhrictionDocumentMoveToTransaction.php
@@ -1,105 +1,109 @@
<?php
final class PhrictionDocumentMoveToTransaction
extends PhrictionDocumentTransactionType {
const TRANSACTIONTYPE = 'move-to';
public function generateOldValue($object) {
return null;
}
public function generateNewValue($object, $value) {
$document = $value;
$dict = array(
'id' => $document->getID(),
'phid' => $document->getPHID(),
'content' => $document->getContent()->getContent(),
'title' => $document->getContent()->getTitle(),
);
$editor = $this->getEditor();
$editor->setMoveAwayDocument($document);
return $dict;
}
public function applyInternalEffects($object, $value) {
$object->setStatus(PhrictionDocumentStatus::STATUS_EXISTS);
}
public function applyExternalEffects($object, $value) {
$dict = $value;
$this->getEditor()->getNewContent()->setContent($dict['content']);
$this->getEditor()->getNewContent()->setTitle($dict['title']);
$this->getEditor()->getNewContent()->setChangeType(
PhrictionChangeType::CHANGE_MOVE_HERE);
$this->getEditor()->getNewContent()->setChangeRef($dict['id']);
}
public function getActionStrength() {
return 1.0;
}
public function getActionName() {
return pht('Moved');
}
public function getTitle() {
$old = $this->getOldValue();
$new = $this->getNewValue();
return pht(
'%s moved this document from %s',
$this->renderAuthor(),
$this->renderHandle($new['phid']));
}
public function getTitleForFeed() {
$old = $this->getOldValue();
$new = $this->getNewValue();
return pht(
'%s moved %s from %s',
$this->renderAuthor(),
$this->renderObject(),
$this->renderHandle($new['phid']));
}
public function validateTransactions($object, array $xactions) {
$errors = array();
$e_text = null;
foreach ($xactions as $xaction) {
$source_document = $xaction->getNewValue();
switch ($source_document->getStatus()) {
case PhrictionDocumentStatus::STATUS_DELETED:
$e_text = pht('A deleted document can not be moved.');
break;
case PhrictionDocumentStatus::STATUS_MOVED:
$e_text = pht('A moved document can not be moved again.');
break;
case PhrictionDocumentStatus::STATUS_STUB:
$e_text = pht('A stub document can not be moved.');
break;
default:
$e_text = null;
break;
}
if ($e_text !== null) {
$errors[] = $this->newInvalidError($e_text);
}
}
// TODO: Move Ancestry validation here once all types are converted.
return $errors;
}
public function getIcon() {
return 'fa-arrows';
}
+ public function shouldHideForFeed() {
+ return true;
+ }
+
}
diff --git a/src/applications/transactions/feed/PhabricatorApplicationTransactionFeedStory.php b/src/applications/transactions/feed/PhabricatorApplicationTransactionFeedStory.php
index 6cc18d5181..305e38ab09 100644
--- a/src/applications/transactions/feed/PhabricatorApplicationTransactionFeedStory.php
+++ b/src/applications/transactions/feed/PhabricatorApplicationTransactionFeedStory.php
@@ -1,171 +1,202 @@
<?php
/**
* @concrete-extensible
*/
class PhabricatorApplicationTransactionFeedStory
extends PhabricatorFeedStory {
+ private $primaryTransactionPHID;
+
public function getPrimaryObjectPHID() {
return $this->getValue('objectPHID');
}
public function getRequiredObjectPHIDs() {
return $this->getValue('transactionPHIDs');
}
public function getRequiredHandlePHIDs() {
$phids = array();
$phids[] = $this->getValue('objectPHID');
foreach ($this->getValue('transactionPHIDs') as $xaction_phid) {
$xaction = $this->getObject($xaction_phid);
foreach ($xaction->getRequiredHandlePHIDs() as $handle_phid) {
$phids[] = $handle_phid;
}
}
return $phids;
}
protected function getPrimaryTransactionPHID() {
- return head($this->getValue('transactionPHIDs'));
+ if ($this->primaryTransactionPHID === null) {
+ // Transactions are filtered and sorted before they're stored, but the
+ // rendering logic can change between the time an edit occurs and when
+ // we actually render the story. Recalculate the filtering at display
+ // time because it's cheap and gets us better results when things change
+ // by letting the changes apply retroactively.
+
+ $xaction_phids = $this->getValue('transactionPHIDs');
+
+ $xactions = array();
+ foreach ($xaction_phids as $xaction_phid) {
+ $xactions[] = $this->getObject($xaction_phid);
+ }
+
+ foreach ($xactions as $key => $xaction) {
+ if ($xaction->shouldHideForFeed()) {
+ unset($xactions[$key]);
+ }
+ }
+
+ if ($xactions) {
+ $primary_phid = head($xactions)->getPHID();
+ } else {
+ $primary_phid = head($xaction_phids);
+ }
+
+ $this->primaryTransactionPHID = $primary_phid;
+ }
+
+ return $this->primaryTransactionPHID;
}
public function getPrimaryTransaction() {
return $this->getObject($this->getPrimaryTransactionPHID());
}
public function getFieldStoryMarkupFields() {
$xaction_phids = $this->getValue('transactionPHIDs');
$fields = array();
foreach ($xaction_phids as $xaction_phid) {
$xaction = $this->getObject($xaction_phid);
foreach ($xaction->getMarkupFieldsForFeed($this) as $field) {
$fields[] = $field;
}
}
return $fields;
}
public function getMarkupText($field) {
$xaction_phids = $this->getValue('transactionPHIDs');
foreach ($xaction_phids as $xaction_phid) {
$xaction = $this->getObject($xaction_phid);
foreach ($xaction->getMarkupFieldsForFeed($this) as $xaction_field) {
if ($xaction_field == $field) {
return $xaction->getMarkupTextForFeed($this, $field);
}
}
}
return null;
}
public function renderView() {
$view = $this->newStoryView();
$handle = $this->getHandle($this->getPrimaryObjectPHID());
$view->setHref($handle->getURI());
$type = phid_get_type($handle->getPHID());
$phid_types = PhabricatorPHIDType::getAllTypes();
$icon = null;
if (!empty($phid_types[$type])) {
$phid_type = $phid_types[$type];
$class = $phid_type->getPHIDTypeApplicationClass();
if ($class) {
$application = PhabricatorApplication::getByClass($class);
$icon = $application->getIcon();
}
}
$view->setAppIcon($icon);
$xaction_phids = $this->getValue('transactionPHIDs');
$xaction = $this->getPrimaryTransaction();
$xaction->setHandles($this->getHandles());
$view->setTitle($xaction->getTitleForFeed());
foreach ($xaction_phids as $xaction_phid) {
$secondary_xaction = $this->getObject($xaction_phid);
$secondary_xaction->setHandles($this->getHandles());
$body = $secondary_xaction->getBodyForFeed($this);
if (nonempty($body)) {
$view->appendChild($body);
}
}
$author_phid = $xaction->getAuthorPHID();
$author_handle = $this->getHandle($author_phid);
$author_image = $author_handle->getImageURI();
if ($author_image) {
$view->setImage($author_image);
$view->setImageHref($author_handle->getURI());
} else {
$view->setAuthorIcon($author_handle->getIcon());
}
return $view;
}
public function renderText() {
$xaction = $this->getPrimaryTransaction();
$old_target = $xaction->getRenderingTarget();
$new_target = PhabricatorApplicationTransaction::TARGET_TEXT;
$xaction->setRenderingTarget($new_target);
$xaction->setHandles($this->getHandles());
$text = $xaction->getTitleForFeed();
$xaction->setRenderingTarget($old_target);
return $text;
}
public function renderTextBody() {
$all_bodies = '';
$new_target = PhabricatorApplicationTransaction::TARGET_TEXT;
$xaction_phids = $this->getValue('transactionPHIDs');
foreach ($xaction_phids as $xaction_phid) {
$secondary_xaction = $this->getObject($xaction_phid);
$old_target = $secondary_xaction->getRenderingTarget();
$secondary_xaction->setRenderingTarget($new_target);
$secondary_xaction->setHandles($this->getHandles());
$body = $secondary_xaction->getBodyForMail();
if (nonempty($body)) {
$all_bodies .= $body."\n";
}
$secondary_xaction->setRenderingTarget($old_target);
}
return trim($all_bodies);
}
public function getImageURI() {
$author_phid = $this->getPrimaryTransaction()->getAuthorPHID();
return $this->getHandle($author_phid)->getImageURI();
}
public function getURI() {
$handle = $this->getHandle($this->getPrimaryObjectPHID());
return PhabricatorEnv::getProductionURI($handle->getURI());
}
public function renderAsTextForDoorkeeper(
DoorkeeperFeedStoryPublisher $publisher) {
$xactions = array();
$xaction_phids = $this->getValue('transactionPHIDs');
foreach ($xaction_phids as $xaction_phid) {
$xaction = $this->getObject($xaction_phid);
$xaction->setHandles($this->getHandles());
$xactions[] = $xaction;
}
$primary = $this->getPrimaryTransaction();
return $primary->renderAsTextForDoorkeeper($publisher, $this, $xactions);
}
}
diff --git a/src/applications/transactions/storage/PhabricatorModularTransaction.php b/src/applications/transactions/storage/PhabricatorModularTransaction.php
index 9f3c24b946..fff2b842d1 100644
--- a/src/applications/transactions/storage/PhabricatorModularTransaction.php
+++ b/src/applications/transactions/storage/PhabricatorModularTransaction.php
@@ -1,186 +1,194 @@
<?php
// TODO: Some "final" modifiers have been VERY TEMPORARILY moved aside to
// allow DifferentialTransaction to extend this class without converting
// fully to ModularTransactions.
abstract class PhabricatorModularTransaction
extends PhabricatorApplicationTransaction {
private $implementation;
abstract public function getBaseTransactionClass();
public function getModularType() {
return $this->getTransactionImplementation();
}
final protected function getTransactionImplementation() {
if (!$this->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 = $this->newFallbackModularTransactionType();
} else {
$type = clone $types[$key];
}
$type->setStorage($this);
return $type;
}
protected function newFallbackModularTransactionType() {
return new PhabricatorCoreVoidTransaction();
}
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 shouldHideForFeed() {
+ if ($this->getTransactionImplementation()->shouldHideForFeed()) {
+ return true;
+ }
+
+ return parent::shouldHideForFeed();
+ }
+
/* 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();
}
/* final */ public function getActionName() {
$action = $this->getTransactionImplementation()->getActionName();
if ($action !== null) {
return $action;
}
return parent::getActionName();
}
/* final */ public function getActionStrength() {
$strength = $this->getTransactionImplementation()->getActionStrength();
if ($strength !== null) {
return $strength;
}
return parent::getActionStrength();
}
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 f2b59c8a2b..d93831affc 100644
--- a/src/applications/transactions/storage/PhabricatorModularTransactionType.php
+++ b/src/applications/transactions/storage/PhabricatorModularTransactionType.php
@@ -1,351 +1,355 @@
<?php
abstract class PhabricatorModularTransactionType
extends Phobject {
private $storage;
private $viewer;
private $editor;
final public function getTransactionTypeConstant() {
return $this->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 getTransactionHasEffect($object, $old, $new) {
return ($old !== $new);
}
public function extractFilePHIDs($object, $value) {
return array();
}
public function shouldHide() {
return false;
}
+ public function shouldHideForFeed() {
+ return false;
+ }
+
public function getIcon() {
return null;
}
public function getTitle() {
return null;
}
public function getTitleForFeed() {
return null;
}
public function getActionName() {
return null;
}
public function getActionStrength() {
return null;
}
public function getColor() {
return null;
}
public function hasChangeDetailView() {
return false;
}
public function newChangeDetailView() {
return null;
}
public function getMailDiffSectionHeader() {
return pht('EDIT DETAILS');
}
public function newRemarkupChanges() {
return array();
}
public function mergeTransactions(
$object,
PhabricatorApplicationTransaction $u,
PhabricatorApplicationTransaction $v) {
return null;
}
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 hasEditor() {
return (bool)$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 renderValueList(array $values) {
$result = array();
foreach ($values as $value) {
$result[] = $this->renderValue($value);
}
if ($this->isTextMode()) {
return implode(', ', $result);
}
return phutil_implode_html(', ', $result);
}
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();
// We accept either epoch timestamps or dictionaries describing a
// PhutilCalendarDateTime.
if (is_array($epoch)) {
$datetime = PhutilCalendarAbsoluteDateTime::newFromDictionary($epoch)
->setViewerTimezone($viewer->getTimezoneIdentifier());
$all_day = $datetime->getIsAllDay();
$epoch = $datetime->getEpoch();
} else {
$all_day = false;
}
if ($all_day) {
$display = phabricator_date($epoch, $viewer);
} else if ($this->isRenderingTargetExternal()) {
// 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.
$display = phabricator_datetimezone($epoch, $viewer);
} else {
$display = phabricator_datetime($epoch, $viewer);
}
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);
}
/**
* When rendering to external targets (Email/Asana/etc), we need to include
* more information that users can't obtain later.
*/
final protected function isRenderingTargetExternal() {
// Right now, this is our best proxy for this:
return $this->isTextMode();
// "TARGET_TEXT" means "EMail" and "TARGET_HTML" means "Web".
}
final protected function isTextMode() {
$target = $this->getStorage()->getRenderingTarget();
return ($target == PhabricatorApplicationTransaction::TARGET_TEXT);
}
final protected function newRemarkupChange() {
return id(new PhabricatorTransactionRemarkupChange())
->setTransaction($this->getStorage());
}
final protected function isCreateTransaction() {
return $this->getStorage()->getIsCreateTransaction();
}
final protected function getPHIDList(array $old, array $new) {
$editor = $this->getEditor();
return $editor->getPHIDList($old, $new);
}
public function getMetadataValue($key, $default = null) {
return $this->getStorage()->getMetadataValue($key, $default);
}
public function loadTransactionTypeConduitData(array $xactions) {
return null;
}
public function getTransactionTypeForConduit($xaction) {
return null;
}
public function getFieldValuesForConduit($xaction, $data) {
return array();
}
}

File Metadata

Mime Type
text/x-diff
Expires
Thu, Nov 6, 1:33 AM (1 d, 2 h)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
321379
Default Alt Text
(42 KB)

Event Timeline