diff --git a/src/applications/maniphest/storage/ManiphestTransaction.php b/src/applications/maniphest/storage/ManiphestTransaction.php index e7777333fc..4ad89458b2 100644 --- a/src/applications/maniphest/storage/ManiphestTransaction.php +++ b/src/applications/maniphest/storage/ManiphestTransaction.php @@ -394,6 +394,198 @@ final class ManiphestTransaction return parent::getTitle(); } + public function getTitleForFeed(PhabricatorFeedStory $story) { + $author_phid = $this->getAuthorPHID(); + $object_phid = $this->getObjectPHID(); + + $old = $this->getOldValue(); + $new = $this->getNewValue(); + + switch ($this->getTransactionType()) { + case self::TYPE_TITLE: + return pht( + '%s renamed %s from "%s" to "%s".', + $this->renderHandleLink($author_phid), + $this->renderHandleLink($object_phid), + $old, + $new); + + case self::TYPE_DESCRIPTION: + return pht( + '%s edited the description of %s.', + $this->renderHandleLink($author_phid), + $this->renderHandleLink($object_phid)); + + case self::TYPE_STATUS: + if ($new == ManiphestTaskStatus::STATUS_OPEN) { + if ($old) { + return pht( + '%s reopened %s.', + $this->renderHandleLink($author_phid), + $this->renderHandleLink($object_phid)); + } else { + return pht( + '%s created %s.', + $this->renderHandleLink($author_phid), + $this->renderHandleLink($object_phid)); + } + } else { + switch ($new) { + case ManiphestTaskStatus::STATUS_CLOSED_SPITE: + return pht( + '%s closed %s out of spite.', + $this->renderHandleLink($author_phid), + $this->renderHandleLink($object_phid)); + case ManiphestTaskStatus::STATUS_CLOSED_DUPLICATE: + return pht( + '%s closed %s as a duplicate.', + $this->renderHandleLink($author_phid), + $this->renderHandleLink($object_phid)); + default: + $status_name = idx( + ManiphestTaskStatus::getTaskStatusMap(), + $new, + '???'); + return pht( + '%s closed %s as "%s".', + $this->renderHandleLink($author_phid), + $this->renderHandleLink($object_phid), + $status_name); + } + } + + case self::TYPE_OWNER: + if ($author_phid == $new) { + return pht( + '%s claimed %s.', + $this->renderHandleLink($author_phid), + $this->renderHandleLink($object_phid)); + } else if (!$new) { + return pht( + '%s placed %s up for grabs.', + $this->renderHandleLink($author_phid), + $this->renderHandleLink($object_phid)); + } else if (!$old) { + return pht( + '%s assigned %s to %s.', + $this->renderHandleLink($author_phid), + $this->renderHandleLink($object_phid), + $this->renderHandleLink($new)); + } else { + return pht( + '%s reassigned %s from %s to %s.', + $this->renderHandleLink($author_phid), + $this->renderHandleLink($object_phid), + $this->renderHandleLink($old), + $this->renderHandleLink($new)); + } + + case self::TYPE_PROJECTS: + $added = array_diff($new, $old); + $removed = array_diff($old, $new); + if ($added && !$removed) { + return pht( + '%s added %d project(s) to %s: %s', + $this->renderHandleLink($author_phid), + count($added), + $this->renderHandleLink($object_phid), + $this->renderHandleList($added)); + } else if ($removed && !$added) { + return pht( + '%s removed %d project(s) to %s: %s', + $this->renderHandleLink($author_phid), + count($removed), + $this->renderHandleLink($object_phid), + $this->renderHandleList($removed)); + } else if ($removed && $added) { + return pht( + '%s changed project(s) of %s, added %d: %s; removed %d: %s', + $this->renderHandleLink($author_phid), + $this->renderHandleLink($object_phid), + count($added), + $this->renderHandleList($added), + count($removed), + $this->renderHandleList($removed)); + } + + case self::TYPE_PRIORITY: + $old_name = ManiphestTaskPriority::getTaskPriorityName($old); + $new_name = ManiphestTaskPriority::getTaskPriorityName($new); + + if ($old == ManiphestTaskPriority::getDefaultPriority()) { + return pht( + '%s triaged %s as "%s" priority.', + $this->renderHandleLink($author_phid), + $this->renderHandleLink($object_phid), + $new_name); + } else if ($old > $new) { + return pht( + '%s lowered the priority of %s from "%s" to "%s".', + $this->renderHandleLink($author_phid), + $this->renderHandleLink($object_phid), + $old_name, + $new_name); + } else { + return pht( + '%s raised the priority of %s from "%s" to "%s".', + $this->renderHandleLink($author_phid), + $this->renderHandleLink($object_phid), + $old_name, + $new_name); + } + + case self::TYPE_CCS: + // TODO: Remove this when we switch to subscribers. Just reuse the + // code in the parent. + $clone = clone $this; + $clone->setTransactionType(PhabricatorTransactions::TYPE_SUBSCRIBERS); + return $clone->getTitleForFeed($story); + + case self::TYPE_EDGE: + // TODO: Remove this when we switch to real edges. Just reuse the + // code in the parent; + $clone = clone $this; + $clone->setTransactionType(PhabricatorTransactions::TYPE_EDGE); + return $clone->getTitleForFeed($story); + + case self::TYPE_ATTACH: + $old = nonempty($old, array()); + $new = nonempty($new, array()); + $new = array_keys(idx($new, 'FILE', array())); + $old = array_keys(idx($old, 'FILE', array())); + + $added = array_diff($new, $old); + $removed = array_diff($old, $new); + if ($added && !$removed) { + return pht( + '%s attached %d file(s) of %s: %s', + $this->renderHandleLink($author_phid), + $this->renderHandleLink($object_phid), + count($added), + $this->renderHandleList($added)); + } else if ($removed && !$added) { + return pht( + '%s detached %d file(s) of %s: %s', + $this->renderHandleLink($author_phid), + $this->renderHandleLink($object_phid), + count($removed), + $this->renderHandleList($removed)); + } else { + return pht( + '%s changed file(s) for %s, attached %d: %s; detached %d: %s', + $this->renderHandleLink($author_phid), + $this->renderHandleLink($object_phid), + count($added), + $this->renderHandleList($added), + count($removed), + $this->renderHandleList($removed)); + } + + } + + return parent::getTitleForFeed($story); + } + public function hasChangeDetails() { switch ($this->getTransactionType()) { case self::TYPE_DESCRIPTION: diff --git a/src/applications/transactions/storage/PhabricatorApplicationTransaction.php b/src/applications/transactions/storage/PhabricatorApplicationTransaction.php index 1f3089caf7..4442cd038f 100644 --- a/src/applications/transactions/storage/PhabricatorApplicationTransaction.php +++ b/src/applications/transactions/storage/PhabricatorApplicationTransaction.php @@ -425,6 +425,25 @@ abstract class PhabricatorApplicationTransaction $string, $this->renderHandleLink($author_phid), $this->renderHandleLink($object_phid)); + case PhabricatorTransactions::TYPE_CUSTOMFIELD: + $key = $this->getMetadataValue('customfield:key'); + $field = PhabricatorCustomField::getObjectField( + // TODO: This is a giant hack, but we currently don't have a way to + // get the contextual object and this pathway is only hit by + // Maniphest. We should provide a way to get the actual object here. + new ManiphestTask(), + PhabricatorCustomField::ROLE_APPLICATIONTRANSACTIONS, + $key); + if ($field) { + $field->setViewer($this->getViewer()); + return $field->getApplicationTransactionTitleForFeed($this, $story); + } else { + return pht( + '%s edited a custom field on %s.', + $this->renderHandleLink($author_phid), + $this->renderHandleLink($object_phid)); + } + } return $this->getTitle(); diff --git a/src/infrastructure/customfield/field/PhabricatorCustomField.php b/src/infrastructure/customfield/field/PhabricatorCustomField.php index ed594ec02e..f4b6ac2b10 100644 --- a/src/infrastructure/customfield/field/PhabricatorCustomField.php +++ b/src/infrastructure/customfield/field/PhabricatorCustomField.php @@ -886,6 +886,23 @@ abstract class PhabricatorCustomField { $xaction->renderHandleLink($author_phid)); } + public function getApplicationTransactionTitleForFeed( + PhabricatorApplicationTransaction $xaction, + PhabricatorFeedStory $story) { + if ($this->proxy) { + return $this->proxy->getApplicationTransactionTitleForFeed( + $xaction, + $story); + } + + $author_phid = $xaction->getAuthorPHID(); + $object_phid = $xaction->getObjectPHID(); + return pht( + '%s updated %s.', + $xaction->renderHandleLink($author_phid), + $xaction->renderHandleLink($object_phid)); + } + /* -( Edit View )---------------------------------------------------------- */ diff --git a/src/infrastructure/customfield/standard/PhabricatorStandardCustomField.php b/src/infrastructure/customfield/standard/PhabricatorStandardCustomField.php index a4691fd492..947a7ca7ae 100644 --- a/src/infrastructure/customfield/standard/PhabricatorStandardCustomField.php +++ b/src/infrastructure/customfield/standard/PhabricatorStandardCustomField.php @@ -333,5 +333,39 @@ abstract class PhabricatorStandardCustomField } } + public function getApplicationTransactionTitleForFeed( + PhabricatorApplicationTransaction $xaction, + PhabricatorFeedStory $story) { + + $author_phid = $xaction->getAuthorPHID(); + $object_phid = $xaction->getObjectPHID(); + + $old = $xaction->getOldValue(); + $new = $xaction->getNewValue(); + + if (!$old) { + return pht( + '%s set %s to %s on %s.', + $xaction->renderHandleLink($author_phid), + $this->getFieldName(), + $new, + $xaction->renderHandleLink($object_phid)); + } else if (!$new) { + return pht( + '%s removed %s on %s.', + $xaction->renderHandleLink($author_phid), + $this->getFieldName(), + $xaction->renderHandleLink($object_phid)); + } else { + return pht( + '%s changed %s from %s to %s on %s.', + $xaction->renderHandleLink($author_phid), + $this->getFieldName(), + $old, + $new, + $xaction->renderHandleLink($object_phid)); + } + } + } diff --git a/src/infrastructure/internationalization/PhabricatorBaseEnglishTranslation.php b/src/infrastructure/internationalization/PhabricatorBaseEnglishTranslation.php index 509fe3c959..749c159626 100644 --- a/src/infrastructure/internationalization/PhabricatorBaseEnglishTranslation.php +++ b/src/infrastructure/internationalization/PhabricatorBaseEnglishTranslation.php @@ -684,15 +684,15 @@ abstract class PhabricatorBaseEnglishTranslation '%s added %d project(s): %s' => array( array( - '%s added a project: %2$s', - '%s added projects: %2$s', + '%s added a project: %3$s', + '%s added projects: %3$s', ), ), '%s removed %d project(s): %s' => array( array( - '%s removed a project: %2$s', - '%s removed projects: %2$s', + '%s removed a project: %3$s', + '%s removed projects: %3$s', ), ), @@ -745,6 +745,37 @@ abstract class PhabricatorBaseEnglishTranslation ), ), + '%s added %d revision(s): %s.' => array( + array( + '%s added a revision: %3$s.', + '%s added revisions: %3$s.', + ), + ), + + '%s removed %d revision(s): %s.' => array( + array( + '%s removed a revision: %3$s.', + '%s removed revisions: %3$s.', + ), + ), + + '%s added %d commit(s): %s.' => array( + array( + '%s added a commit: %3$s.', + '%s added commits: %3$s.', + ), + ), + + '%s removed %d commit(s): %s.' => array( + array( + '%s removed a commit: %3$s.', + '%s removed commits: %3$s.', + ), + ), + + '%s edited commit(s), added %d: %s; removed %d: %s.' => + '%s edited commits, added %3$s; removed %5$s.', + ); }