From 3854599428dad62cb6ba83e702bbe7d3955e4114 Mon Sep 17 00:00:00 2001 From: Bob Trahan Date: Fri, 19 Jul 2013 15:59:29 -0700 Subject: [PATCH] Pholio - allow Pholio Mocks to be attached to Maniphest Tasks (and vice versa) Summary: Fixes T2654. Test Plan: attached lots of mocks and tasks to one another from both maniphest and pholio. verified transactions rendered okay in both applications Reviewers: epriestley Reviewed By: epriestley CC: aran, Korvin Maniphest Tasks: T2654 Differential Revision: https://secure.phabricator.com/D6501 --- .../ManiphestTaskDetailController.php | 36 +- .../view/ManiphestTransactionDetailView.php | 20 ++ .../controller/PholioMockViewController.php | 39 +- .../pholio/editor/PholioMockEditor.php | 1 + .../PhabricatorSearchAttachController.php | 75 +++- .../PhabricatorSearchSelectController.php | 14 +- ...habricatorApplicationTransactionEditor.php | 1 - .../PhabricatorApplicationTransaction.php | 40 ++- .../edges/constants/PhabricatorEdgeConfig.php | 279 +++++++++++++++ .../PhabricatorBaseEnglishTranslation.php | 336 ++++++++++++++++++ 10 files changed, 799 insertions(+), 42 deletions(-) diff --git a/src/applications/maniphest/controller/ManiphestTaskDetailController.php b/src/applications/maniphest/controller/ManiphestTaskDetailController.php index 512a834a5d..cd4450f0c7 100644 --- a/src/applications/maniphest/controller/ManiphestTaskDetailController.php +++ b/src/applications/maniphest/controller/ManiphestTaskDetailController.php @@ -42,6 +42,7 @@ final class ManiphestTaskDetailController extends ManiphestController { $e_dep_on = PhabricatorEdgeConfig::TYPE_TASK_DEPENDS_ON_TASK; $e_dep_by = PhabricatorEdgeConfig::TYPE_TASK_DEPENDED_ON_BY_TASK; $e_rev = PhabricatorEdgeConfig::TYPE_TASK_HAS_RELATED_DREV; + $e_mock = PhabricatorEdgeConfig::TYPE_TASK_HAS_MOCK; $phid = $task->getPHID(); @@ -53,6 +54,7 @@ final class ManiphestTaskDetailController extends ManiphestController { $e_dep_on, $e_dep_by, $e_rev, + $e_mock, )); $edges = idx($query->execute(), $phid); $phids = array_fill_keys($query->getDestinationPHIDs(), true); @@ -438,6 +440,17 @@ final class ManiphestTaskDetailController extends ManiphestController { ->setWorkflow(true) ->setIcon('attach')); + $pholio_app = + PhabricatorApplication::getByClass('PhabricatorApplicationPholio'); + if ($pholio_app->isInstalled()) { + $view->addAction( + id(new PhabricatorActionView()) + ->setName(pht('Edit Pholio Mocks')) + ->setHref("/search/attach/{$phid}/MOCK/edge/") + ->setWorkflow(true) + ->setIcon('attach')); + } + return $view; } @@ -456,8 +469,8 @@ final class ManiphestTaskDetailController extends ManiphestController { $view->addProperty( pht('Assigned To'), $task->getOwnerPHID() - ? $this->getHandle($task->getOwnerPHID())->renderLink() - : phutil_tag('em', array(), pht('None'))); + ? $this->getHandle($task->getOwnerPHID())->renderLink() + : phutil_tag('em', array(), pht('None'))); $view->addProperty( pht('Priority'), @@ -466,8 +479,8 @@ final class ManiphestTaskDetailController extends ManiphestController { $view->addProperty( pht('Subscribers'), $task->getCCPHIDs() - ? $this->renderHandlesForPHIDs($task->getCCPHIDs(), ',') - : phutil_tag('em', array(), pht('None'))); + ? $this->renderHandlesForPHIDs($task->getCCPHIDs(), ',') + : phutil_tag('em', array(), pht('None'))); $view->addProperty( pht('Author'), @@ -482,15 +495,15 @@ final class ManiphestTaskDetailController extends ManiphestController { 'a', array( 'href' => 'mailto:'.$source.'?subject='.$subject - ), + ), $source)); } $view->addProperty( pht('Projects'), $task->getProjectPHIDs() - ? $this->renderHandlesForPHIDs($task->getProjectPHIDs(), ',') - : phutil_tag('em', array(), pht('None'))); + ? $this->renderHandlesForPHIDs($task->getProjectPHIDs(), ',') + : phutil_tag('em', array(), pht('None'))); foreach ($aux_fields as $aux_field) { $value = $aux_field->renderForDetailView(); @@ -502,11 +515,13 @@ final class ManiphestTaskDetailController extends ManiphestController { $edge_types = array( PhabricatorEdgeConfig::TYPE_TASK_DEPENDED_ON_BY_TASK - => pht('Dependent Tasks'), + => pht('Dependent Tasks'), PhabricatorEdgeConfig::TYPE_TASK_DEPENDS_ON_TASK - => pht('Depends On'), + => pht('Depends On'), PhabricatorEdgeConfig::TYPE_TASK_HAS_RELATED_DREV - => pht('Differential Revisions'), + => pht('Differential Revisions'), + PhabricatorEdgeConfig::TYPE_TASK_HAS_MOCK + => pht('Pholio Mocks'), ); $revisions_commits = array(); @@ -583,5 +598,4 @@ final class ManiphestTaskDetailController extends ManiphestController { return $view; } - } diff --git a/src/applications/maniphest/view/ManiphestTransactionDetailView.php b/src/applications/maniphest/view/ManiphestTransactionDetailView.php index 35e40cb8d5..68cf06a888 100644 --- a/src/applications/maniphest/view/ManiphestTransactionDetailView.php +++ b/src/applications/maniphest/view/ManiphestTransactionDetailView.php @@ -674,6 +674,8 @@ final class ManiphestTransactionDetailView extends ManiphestView { return pht('DEPENDENT %d TASK(s)', $count); case PhabricatorEdgeConfig::TYPE_TASK_HAS_COMMIT: return pht('ATTACHED %d COMMIT(S)', $count); + case PhabricatorEdgeConfig::TYPE_TASK_HAS_MOCK: + return pht('ATTACHED %d MOCK(S)', $count); default: return pht('ATTACHED %d OBJECT(S)', $count); } @@ -693,6 +695,8 @@ final class ManiphestTransactionDetailView extends ManiphestView { return pht('Added Dependent Task'); case PhabricatorEdgeConfig::TYPE_TASK_HAS_COMMIT: return pht('Added Commit'); + case PhabricatorEdgeConfig::TYPE_TASK_HAS_MOCK: + return pht('Added Mock'); default: return pht('Added Object'); } @@ -712,6 +716,8 @@ final class ManiphestTransactionDetailView extends ManiphestView { return pht('Removed Dependent Task'); case PhabricatorEdgeConfig::TYPE_TASK_HAS_COMMIT: return pht('Removed Commit'); + case PhabricatorEdgeConfig::TYPE_TASK_HAS_MOCK: + return pht('Removed Mock'); default: return pht('Removed Object'); } @@ -731,6 +737,8 @@ final class ManiphestTransactionDetailView extends ManiphestView { return pht('Changed Dependent Tasks'); case PhabricatorEdgeConfig::TYPE_TASK_HAS_COMMIT: return pht('Changed Commits'); + case PhabricatorEdgeConfig::TYPE_TASK_HAS_MOCK: + return pht('Changed Mocks'); default: return pht('Changed Objects'); } @@ -753,6 +761,8 @@ final class ManiphestTransactionDetailView extends ManiphestView { return pht('added %d dependent task(s): %s', $count, $list); case PhabricatorEdgeConfig::TYPE_TASK_HAS_COMMIT: return pht('added %d commit(s): %s', $count, $list); + case PhabricatorEdgeConfig::TYPE_TASK_HAS_MOCK: + return pht('added %d mock(s): %s', $count, $list); default: return pht('added %d object(s): %s', $count, $list); } @@ -775,6 +785,8 @@ final class ManiphestTransactionDetailView extends ManiphestView { return pht('removed %d dependent task(s): %s', $count, $list); case PhabricatorEdgeConfig::TYPE_TASK_HAS_COMMIT: return pht('removed %d commit(s): %s', $count, $list); + case PhabricatorEdgeConfig::TYPE_TASK_HAS_MOCK: + return pht('removed %d mock(s): %s', $count, $list); default: return pht('removed %d object(s): %s', $count, $list); } @@ -823,6 +835,14 @@ final class ManiphestTransactionDetailView extends ManiphestView { $add_list, $rem_count, $rem_list); + case PhabricatorEdgeConfig::TYPE_TASK_HAS_MOCK: + return pht( + 'changed %d mock(s), added %d: %s; removed %d: %s', + $add_count + $rem_count, + $add_count, + $add_list, + $rem_count, + $rem_list); default: return pht( 'changed %d object(s), added %d: %s; removed %d: %s', diff --git a/src/applications/pholio/controller/PholioMockViewController.php b/src/applications/pholio/controller/PholioMockViewController.php index 3a214e5b74..8c4a14bccd 100644 --- a/src/applications/pholio/controller/PholioMockViewController.php +++ b/src/applications/pholio/controller/PholioMockViewController.php @@ -7,6 +7,15 @@ final class PholioMockViewController extends PholioController { private $id; private $imageID; + private $maniphestTaskPHIDs = array(); + + private function setManiphestTaskPHIDs($maniphest_task_phids) { + $this->maniphestTaskPHIDs = $maniphest_task_phids; + return $this; + } + private function getManiphestTaskPHIDs() { + return $this->maniphestTaskPHIDs; + } public function shouldAllowPublic() { return true; @@ -37,7 +46,11 @@ final class PholioMockViewController extends PholioController { ->withObjectPHIDs(array($mock->getPHID())) ->execute(); - $phids = array($mock->getAuthorPHID()); + $phids = PhabricatorEdgeQuery::loadDestinationPHIDs( + $mock->getPHID(), + PhabricatorEdgeConfig::TYPE_MOCK_HAS_TASK); + $this->setManiphestTaskPHIDs($phids); + $phids[] = $mock->getAuthorPHID(); $this->loadHandles($phids); $engine = id(new PhabricatorMarkupEngine()) @@ -119,11 +132,19 @@ final class PholioMockViewController extends PholioController { $actions->addAction( id(new PhabricatorActionView()) - ->setIcon('edit') - ->setName(pht('Edit Mock')) - ->setHref($this->getApplicationURI('/edit/'.$mock->getID().'/')) - ->setDisabled(!$can_edit) - ->setWorkflow(!$can_edit)); + ->setIcon('edit') + ->setName(pht('Edit Mock')) + ->setHref($this->getApplicationURI('/edit/'.$mock->getID().'/')) + ->setDisabled(!$can_edit) + ->setWorkflow(!$can_edit)); + + $actions->addAction( + id(new PhabricatorActionView()) + ->setIcon('attach') + ->setName(pht('Edit Maniphest Tasks')) + ->setHref("/search/attach/{$mock->getPHID()}/TASK/edge/") + ->setDisabled(!$user->isLoggedIn()) + ->setWorkflow(true)); return $actions; } @@ -154,6 +175,12 @@ final class PholioMockViewController extends PholioController { pht('Visible To'), $descriptions[PhabricatorPolicyCapability::CAN_VIEW]); + if ($this->getManiphestTaskPHIDs()) { + $properties->addProperty( + pht('Maniphest Tasks'), + $this->renderHandlesForPHIDs($this->getManiphestTaskPHIDs())); + } + $properties->invokeWillRenderEvent(); $properties->addImageContent( diff --git a/src/applications/pholio/editor/PholioMockEditor.php b/src/applications/pholio/editor/PholioMockEditor.php index d52a514251..d5ef09248d 100644 --- a/src/applications/pholio/editor/PholioMockEditor.php +++ b/src/applications/pholio/editor/PholioMockEditor.php @@ -18,6 +18,7 @@ final class PholioMockEditor extends PhabricatorApplicationTransactionEditor { public function getTransactionTypes() { $types = parent::getTransactionTypes(); + $types[] = PhabricatorTransactions::TYPE_EDGE; $types[] = PhabricatorTransactions::TYPE_COMMENT; $types[] = PhabricatorTransactions::TYPE_VIEW_POLICY; $types[] = PhabricatorTransactions::TYPE_EDIT_POLICY; diff --git a/src/applications/search/controller/PhabricatorSearchAttachController.php b/src/applications/search/controller/PhabricatorSearchAttachController.php index a5070368d4..b101f53f01 100644 --- a/src/applications/search/controller/PhabricatorSearchAttachController.php +++ b/src/applications/search/controller/PhabricatorSearchAttachController.php @@ -56,25 +56,42 @@ final class PhabricatorSearchAttachController $phids = array_values($phids); if ($edge_type) { + $do_txn = $object instanceof PhabricatorApplicationTransactionInterface; $old_phids = PhabricatorEdgeQuery::loadDestinationPHIDs( $this->phid, $edge_type); $add_phids = $phids; $rem_phids = array_diff($old_phids, $add_phids); - $editor = id(new PhabricatorEdgeEditor()); - $editor->setActor($user); - foreach ($add_phids as $phid) { - $editor->addEdge($this->phid, $edge_type, $phid); - } - foreach ($rem_phids as $phid) { - $editor->removeEdge($this->phid, $edge_type, $phid); - } + if ($do_txn) { - try { - $editor->save(); - } catch (PhabricatorEdgeCycleException $ex) { - $this->raiseGraphCycleException($ex); + $txn_editor = $object->getApplicationTransactionEditor() + ->setActor($user) + ->setContentSourceFromRequest($request); + $txn_template = $object->getApplicationTransactionObject() + ->setTransactionType(PhabricatorTransactions::TYPE_EDGE) + ->setMetadataValue('edge:type', $edge_type) + ->setNewValue(array( + '+' => array_fuse($add_phids), + '-' => array_fuse($rem_phids))); + $txn_editor->applyTransactions($object, array($txn_template)); + + } else { + + $editor = id(new PhabricatorEdgeEditor()); + $editor->setActor($user); + foreach ($add_phids as $phid) { + $editor->addEdge($this->phid, $edge_type, $phid); + } + foreach ($rem_phids as $phid) { + $editor->removeEdge($this->phid, $edge_type, $phid); + } + + try { + $editor->save(); + } catch (PhabricatorEdgeCycleException $ex) { + $this->raiseGraphCycleException($ex); + } } return id(new AphrontReloadResponse())->setURI($handle->getURI()); @@ -100,12 +117,7 @@ final class PhabricatorSearchAttachController $obj_dialog ->setUser($user) ->setHandles($handles) - ->setFilters(array( - 'assigned' => 'Assigned to Me', - 'created' => 'Created By Me', - 'open' => 'All Open '.$strings['target_plural_noun'], - 'all' => 'All '.$strings['target_plural_noun'], - )) + ->setFilters($this->getFilters($strings)) ->setSelectedFilter($strings['selected']) ->setExcluded($this->phid) ->setCancelURI($handle->getURI()) @@ -198,6 +210,10 @@ final class PhabricatorSearchAttachController $noun = 'Commits'; $selected = 'created'; break; + case PhabricatorPHIDConstants::PHID_TYPE_MOCK: + $noun = 'Mocks'; + $selected = 'created'; + break; } switch ($this->action) { @@ -234,10 +250,29 @@ final class PhabricatorSearchAttachController ); } + private function getFilters(array $strings) { + if ($this->type == PhabricatorPHIDConstants::PHID_TYPE_MOCK) { + $filters = array( + 'created' => 'Created By Me', + 'all' => 'All '.$strings['target_plural_noun'], + ); + } else { + $filters = array( + 'assigned' => 'Assigned to Me', + 'created' => 'Created By Me', + 'open' => 'All Open '.$strings['target_plural_noun'], + 'all' => 'All '.$strings['target_plural_noun'], + ); + } + + return $filters; + } + private function getEdgeType($src_type, $dst_type) { $t_cmit = PhabricatorPHIDConstants::PHID_TYPE_CMIT; $t_task = PhabricatorPHIDConstants::PHID_TYPE_TASK; $t_drev = PhabricatorPHIDConstants::PHID_TYPE_DREV; + $t_mock = PhabricatorPHIDConstants::PHID_TYPE_MOCK; $map = array( $t_cmit => array( @@ -247,11 +282,15 @@ final class PhabricatorSearchAttachController $t_cmit => PhabricatorEdgeConfig::TYPE_TASK_HAS_COMMIT, $t_task => PhabricatorEdgeConfig::TYPE_TASK_DEPENDS_ON_TASK, $t_drev => PhabricatorEdgeConfig::TYPE_TASK_HAS_RELATED_DREV, + $t_mock => PhabricatorEdgeConfig::TYPE_TASK_HAS_MOCK, ), $t_drev => array( $t_drev => PhabricatorEdgeConfig::TYPE_DREV_DEPENDS_ON_DREV, $t_task => PhabricatorEdgeConfig::TYPE_DREV_HAS_RELATED_TASK, ), + $t_mock => array( + $t_task => PhabricatorEdgeConfig::TYPE_MOCK_HAS_TASK, + ), ); if (empty($map[$src_type][$dst_type])) { diff --git a/src/applications/search/controller/PhabricatorSearchSelectController.php b/src/applications/search/controller/PhabricatorSearchSelectController.php index c696dc045e..03f620c9ec 100644 --- a/src/applications/search/controller/PhabricatorSearchSelectController.php +++ b/src/applications/search/controller/PhabricatorSearchSelectController.php @@ -31,7 +31,11 @@ final class PhabricatorSearchSelectController break; case 'created'; $query->setParameter('author', array($user->getPHID())); - $query->setParameter('open', 1); + // TODO - if / when we allow pholio mocks to be archived, etc + // update this + if ($this->type != PhabricatorPHIDConstants::PHID_TYPE_MOCK) { + $query->setParameter('open', 1); + } break; case 'open': $query->setParameter('open', 1); @@ -69,6 +73,9 @@ final class PhabricatorSearchSelectController case PhabricatorPHIDConstants::PHID_TYPE_DREV: $pattern = '/\bD(\d+)\b/i'; break; + case PhabricatorPHIDConstants::PHID_TYPE_MOCK: + $pattern = '/\bM(\d+)\b/i'; + break; } if (!$pattern) { @@ -97,6 +104,11 @@ final class PhabricatorSearchSelectController 'id IN (%Ld)', $object_ids); break; + case PhabricatorPHIDConstants::PHID_TYPE_MOCK: + $objects = id(new PholioMock())->loadAllWhere( + 'id IN (%Ld)', + $object_ids); + break; } return array_fill_keys(mpull($objects, 'getPHID'), true); diff --git a/src/applications/transactions/editor/PhabricatorApplicationTransactionEditor.php b/src/applications/transactions/editor/PhabricatorApplicationTransactionEditor.php index fd7dded312..88a88282e1 100644 --- a/src/applications/transactions/editor/PhabricatorApplicationTransactionEditor.php +++ b/src/applications/transactions/editor/PhabricatorApplicationTransactionEditor.php @@ -116,7 +116,6 @@ abstract class PhabricatorApplicationTransactionEditor $edge_src = $object->getPHID(); $old_edges = id(new PhabricatorEdgeQuery()) - ->setViewer($this->getActor()) ->withSourcePHIDs(array($edge_src)) ->withEdgeTypes(array($edge_type)) ->needEdgeData(true) diff --git a/src/applications/transactions/storage/PhabricatorApplicationTransaction.php b/src/applications/transactions/storage/PhabricatorApplicationTransaction.php index 0874b357d0..96b4138dfb 100644 --- a/src/applications/transactions/storage/PhabricatorApplicationTransaction.php +++ b/src/applications/transactions/storage/PhabricatorApplicationTransaction.php @@ -298,11 +298,38 @@ abstract class PhabricatorApplicationTransaction } break; case PhabricatorTransactions::TYPE_EDGE: + $new = ipull($new, 'dst'); + $old = ipull($old, 'dst'); + $add = array_diff($new, $old); + $rem = array_diff($old, $new); $type = $this->getMetadata('edge:type'); - return pht( - '%s edited edges of type %s.', - $this->renderHandleLink($author_phid), - $type); + $type = head($type); + + if ($add && $rem) { + $string = PhabricatorEdgeConfig::getEditStringForEdgeType($type); + return pht( + $string, + $this->renderHandleLink($author_phid), + count($add), + $this->renderHandleList($add), + count($rem), + $this->renderHandleList($rem)); + } else if ($add) { + $string = PhabricatorEdgeConfig::getAddStringForEdgeType($type); + return pht( + $string, + $this->renderHandleLink($author_phid), + count($add), + $this->renderHandleList($add)); + } else { + $string = PhabricatorEdgeConfig::getRemoveStringForEdgeType($type); + return pht( + $string, + $this->renderHandleLink($author_phid), + count($rem), + $this->renderHandleList($rem)); + } + default: return pht( '%s edited this %s.', @@ -340,8 +367,11 @@ abstract class PhabricatorApplicationTransaction $this->renderHandleLink($author_phid), $this->renderHandleLink($object_phid)); case PhabricatorTransactions::TYPE_EDGE: + $type = $this->getMetadata('edge:type'); + $type = head($type); + $string = PhabricatorEdgeConfig::getFeedStringForEdgeType($type); return pht( - '%s updated edges of %s.', + $string, $this->renderHandleLink($author_phid), $this->renderHandleLink($object_phid)); } diff --git a/src/infrastructure/edges/constants/PhabricatorEdgeConfig.php b/src/infrastructure/edges/constants/PhabricatorEdgeConfig.php index d57fdaf3d5..5061735a2d 100644 --- a/src/infrastructure/edges/constants/PhabricatorEdgeConfig.php +++ b/src/infrastructure/edges/constants/PhabricatorEdgeConfig.php @@ -57,6 +57,9 @@ final class PhabricatorEdgeConfig extends PhabricatorEdgeConstants { const TYPE_DREV_HAS_REVIEWER = 35; const TYPE_REVIEWER_FOR_DREV = 36; + const TYPE_MOCK_HAS_TASK = 37; + const TYPE_TASK_HAS_MOCK = 38; + const TYPE_TEST_NO_CYCLE = 9000; const TYPE_PHOB_HAS_ASANATASK = 80001; @@ -115,6 +118,9 @@ final class PhabricatorEdgeConfig extends PhabricatorEdgeConstants { self::TYPE_OBJECT_HAS_CONTRIBUTOR => self::TYPE_SUBSCRIBED_TO_OBJECT, self::TYPE_CONTRIBUTED_TO_OBJECT => self::TYPE_OBJECT_HAS_CONTRIBUTOR, + self::TYPE_TASK_HAS_MOCK => self::TYPE_MOCK_HAS_TASK, + self::TYPE_MOCK_HAS_TASK => self::TYPE_TASK_HAS_MOCK, + self::TYPE_PHOB_HAS_ASANATASK => self::TYPE_ASANATASK_HAS_PHOB, self::TYPE_ASANATASK_HAS_PHOB => self::TYPE_PHOB_HAS_ASANATASK, @@ -174,4 +180,277 @@ final class PhabricatorEdgeConfig extends PhabricatorEdgeConstants { return newv($class, array())->establishConnection($conn_type); } + public static function getEditStringForEdgeType($type) { + switch ($type) { + case self::TYPE_TASK_HAS_COMMIT: + case self::TYPE_PROJECT_HAS_COMMIT: + case self::TYPE_DREV_HAS_COMMIT: + return '%s edited commit(s), added %d: %s; removed %d: %s.'; + case self::TYPE_COMMIT_HAS_TASK: + case self::TYPE_TASK_DEPENDS_ON_TASK: + case self::TYPE_TASK_DEPENDED_ON_BY_TASK: + case self::TYPE_DREV_HAS_RELATED_TASK: + case self::TYPE_MOCK_HAS_TASK: + return '%s edited task(s), added %d: %s; removed %d: %s.'; + case self::TYPE_DREV_DEPENDS_ON_DREV: + case self::TYPE_DREV_DEPENDED_ON_BY_DREV: + case self::TYPE_TASK_HAS_RELATED_DREV: + case self::TYPE_COMMIT_HAS_DREV: + case self::TYPE_REVIEWER_FOR_DREV: + return '%s edited revision(s), added %d: %s; removed %d: %s.'; + case self::TYPE_BLOG_HAS_POST: + return '%s edited post(s), added %d: %s; removed %d: %s.'; + case self::TYPE_POST_HAS_BLOG: + case self::TYPE_BLOGGER_HAS_BLOG: + return '%s edited blog(s), added %d: %s; removed %d: %s.'; + case self::TYPE_BLOG_HAS_BLOGGER: + return '%s edited blogger(s), added %d: %s; removed %d: %s.'; + case self::TYPE_PROJ_MEMBER: + return '%s edited member(s), added %d: %s; removed %d: %s.'; + case self::TYPE_MEMBER_OF_PROJ: + case self::TYPE_COMMIT_HAS_PROJECT: + return '%s edited project(s), added %d: %s; removed %d: %s.'; + case self::TYPE_QUESTION_HAS_VOTING_USER: + case self::TYPE_ANSWER_HAS_VOTING_USER: + return '%s edited voting user(s), added %d: %s; removed %d: %s.'; + case self::TYPE_VOTING_USER_HAS_QUESTION: + return '%s edited question(s), added %d: %s; removed %d: %s.'; + case self::TYPE_VOTING_USER_HAS_ANSWER: + return '%s edited answer(s), added %d: %s; removed %d: %s.'; + case self::TYPE_OBJECT_HAS_SUBSCRIBER: + return '%s edited subscriber(s), added %d: %s; removed %d: %s.'; + case self::TYPE_SUBSCRIBED_TO_OBJECT: + case self::TYPE_UNSUBSCRIBED_FROM_OBJECT: + case self::TYPE_FILE_HAS_OBJECT: + case self::TYPE_CONTRIBUTED_TO_OBJECT: + return '%s edited object(s), added %d: %s; removed %d: %s.'; + case self::TYPE_OBJECT_HAS_UNSUBSCRIBER: + return '%s edited unsubcriber(s), added %d: %s; removed %d: %s.'; + case self::TYPE_OBJECT_HAS_FILE: + return '%s edited file(s), added %d: %s; removed %d: %s.'; + case self::TYPE_ACCOUNT_HAS_MEMBER: + return '%s edited member(s), added %d: %s; removed %d: %s.'; + case self::TYPE_MEMBER_HAS_ACCOUNT: + return '%s edited account(s), added %d: %s; removed %d: %s.'; + case self::TYPE_PURCAHSE_HAS_CHARGE: + return '%s edited charge(s), added %d: %s; removed %d: %s.'; + case self::TYPE_CHARGE_HAS_PURCHASE: + return '%s edited purchase(s), added %d: %s; removed %d: %s.'; + case self::TYPE_OBJECT_HAS_CONTRIBUTOR: + return '%s edited contributor(s), added %d: %s; removed %d: %s.'; + case self::TYPE_DREV_HAS_REVIEWER: + return '%s edited reviewer(s), added %d: %s; removed %d: %s.'; + case self::TYPE_TASK_HAS_MOCK: + return '%s edited mock(s), added %d: %s; removed %d: %s.'; + case self::TYPE_SUBSCRIBED_TO_OBJECT: + case self::TYPE_UNSUBSCRIBED_FROM_OBJECT: + case self::TYPE_FILE_HAS_OBJECT: + case self::TYPE_CONTRIBUTED_TO_OBJECT: + default: + return '%s edited object(s), added %d: %s; removed %d: %s.'; + + } + } + + public static function getAddStringForEdgeType($type) { + switch ($type) { + case self::TYPE_TASK_HAS_COMMIT: + case self::TYPE_PROJECT_HAS_COMMIT: + case self::TYPE_DREV_HAS_COMMIT: + return '%s added %d commit(s): %s.'; + case self::TYPE_COMMIT_HAS_TASK: + case self::TYPE_TASK_DEPENDS_ON_TASK: + case self::TYPE_TASK_DEPENDED_ON_BY_TASK: + case self::TYPE_DREV_HAS_RELATED_TASK: + case self::TYPE_MOCK_HAS_TASK: + return '%s added %d task(s): %s.'; + case self::TYPE_DREV_DEPENDS_ON_DREV: + case self::TYPE_DREV_DEPENDED_ON_BY_DREV: + case self::TYPE_TASK_HAS_RELATED_DREV: + case self::TYPE_COMMIT_HAS_DREV: + case self::TYPE_REVIEWER_FOR_DREV: + return '%s added %d revision(s): %s.'; + case self::TYPE_BLOG_HAS_POST: + return '%s added %d post(s): %s.'; + case self::TYPE_POST_HAS_BLOG: + case self::TYPE_BLOGGER_HAS_BLOG: + return '%s added %d blog(s): %s.'; + case self::TYPE_BLOG_HAS_BLOGGER: + return '%s added %d blogger(s): %s.'; + case self::TYPE_PROJ_MEMBER: + return '%s added %d member(s): %s.'; + case self::TYPE_MEMBER_OF_PROJ: + case self::TYPE_COMMIT_HAS_PROJECT: + return '%s added %d project(s): %s.'; + case self::TYPE_QUESTION_HAS_VOTING_USER: + case self::TYPE_ANSWER_HAS_VOTING_USER: + return '%s added %d voting user(s): %s.'; + case self::TYPE_VOTING_USER_HAS_QUESTION: + return '%s added %d question(s): %s.'; + case self::TYPE_VOTING_USER_HAS_ANSWER: + return '%s added %d answer(s): %s.'; + case self::TYPE_OBJECT_HAS_SUBSCRIBER: + return '%s added %d subscriber(s): %s.'; + case self::TYPE_OBJECT_HAS_UNSUBSCRIBER: + return '%s added %d unsubcriber(s): %s.'; + case self::TYPE_OBJECT_HAS_FILE: + return '%s added %d file(s): %s.'; + case self::TYPE_ACCOUNT_HAS_MEMBER: + return '%s added %d member(s): %s.'; + case self::TYPE_MEMBER_HAS_ACCOUNT: + return '%s added %d account(s): %s.'; + case self::TYPE_PURCAHSE_HAS_CHARGE: + return '%s added %d charge(s): %s.'; + case self::TYPE_CHARGE_HAS_PURCHASE: + return '%s added %d purchase(s): %s.'; + case self::TYPE_OBJECT_HAS_CONTRIBUTOR: + return '%s added %d contributor(s): %s.'; + case self::TYPE_DREV_HAS_REVIEWER: + return '%s added %d reviewer(s): %s.'; + case self::TYPE_TASK_HAS_MOCK: + return '%s added %d mock(s): %s.'; + case self::TYPE_SUBSCRIBED_TO_OBJECT: + case self::TYPE_UNSUBSCRIBED_FROM_OBJECT: + case self::TYPE_FILE_HAS_OBJECT: + case self::TYPE_CONTRIBUTED_TO_OBJECT: + default: + return '%s added %d object(s): %s.'; + + } + } + + public static function getRemoveStringForEdgeType($type) { + switch ($type) { + case self::TYPE_TASK_HAS_COMMIT: + case self::TYPE_PROJECT_HAS_COMMIT: + case self::TYPE_DREV_HAS_COMMIT: + return '%s removed %d commit(s): %s.'; + case self::TYPE_COMMIT_HAS_TASK: + case self::TYPE_TASK_DEPENDS_ON_TASK: + case self::TYPE_TASK_DEPENDED_ON_BY_TASK: + case self::TYPE_DREV_HAS_RELATED_TASK: + case self::TYPE_MOCK_HAS_TASK: + return '%s removed %d task(s): %s.'; + case self::TYPE_DREV_DEPENDS_ON_DREV: + case self::TYPE_DREV_DEPENDED_ON_BY_DREV: + case self::TYPE_TASK_HAS_RELATED_DREV: + case self::TYPE_COMMIT_HAS_DREV: + case self::TYPE_REVIEWER_FOR_DREV: + return '%s removed %d revision(s): %s.'; + case self::TYPE_BLOG_HAS_POST: + return '%s removed %d post(s): %s.'; + case self::TYPE_POST_HAS_BLOG: + case self::TYPE_BLOGGER_HAS_BLOG: + return '%s removed %d blog(s): %s.'; + case self::TYPE_BLOG_HAS_BLOGGER: + return '%s removed %d blogger(s): %s.'; + case self::TYPE_PROJ_MEMBER: + return '%s removed %d member(s): %s.'; + case self::TYPE_MEMBER_OF_PROJ: + case self::TYPE_COMMIT_HAS_PROJECT: + return '%s removed %d project(s): %s.'; + case self::TYPE_QUESTION_HAS_VOTING_USER: + case self::TYPE_ANSWER_HAS_VOTING_USER: + return '%s removed %d voting user(s): %s.'; + case self::TYPE_VOTING_USER_HAS_QUESTION: + return '%s removed %d question(s): %s.'; + case self::TYPE_VOTING_USER_HAS_ANSWER: + return '%s removed %d answer(s): %s.'; + case self::TYPE_OBJECT_HAS_SUBSCRIBER: + return '%s removed %d subscriber(s): %s.'; + case self::TYPE_OBJECT_HAS_UNSUBSCRIBER: + return '%s removed %d unsubcriber(s): %s.'; + case self::TYPE_OBJECT_HAS_FILE: + return '%s removed %d file(s): %s.'; + case self::TYPE_ACCOUNT_HAS_MEMBER: + return '%s removed %d member(s): %s.'; + case self::TYPE_MEMBER_HAS_ACCOUNT: + return '%s removed %d account(s): %s.'; + case self::TYPE_PURCAHSE_HAS_CHARGE: + return '%s removed %d charge(s): %s.'; + case self::TYPE_CHARGE_HAS_PURCHASE: + return '%s removed %d purchase(s): %s.'; + case self::TYPE_OBJECT_HAS_CONTRIBUTOR: + return '%s removed %d contributor(s): %s.'; + case self::TYPE_DREV_HAS_REVIEWER: + return '%s removed %d reviewer(s): %s.'; + case self::TYPE_TASK_HAS_MOCK: + return '%s removed %d mock(s): %s.'; + case self::TYPE_SUBSCRIBED_TO_OBJECT: + case self::TYPE_UNSUBSCRIBED_FROM_OBJECT: + case self::TYPE_FILE_HAS_OBJECT: + case self::TYPE_CONTRIBUTED_TO_OBJECT: + default: + return '%s removed %d object(s): %s.'; + + } + } + + public static function getFeedStringForEdgeType($type) { + switch ($type) { + case self::TYPE_TASK_HAS_COMMIT: + case self::TYPE_PROJECT_HAS_COMMIT: + case self::TYPE_DREV_HAS_COMMIT: + return '%s updated commits of %s.'; + case self::TYPE_COMMIT_HAS_TASK: + case self::TYPE_TASK_DEPENDS_ON_TASK: + case self::TYPE_TASK_DEPENDED_ON_BY_TASK: + case self::TYPE_DREV_HAS_RELATED_TASK: + case self::TYPE_MOCK_HAS_TASK: + return '%s updated tasks of %s.'; + case self::TYPE_DREV_DEPENDS_ON_DREV: + case self::TYPE_DREV_DEPENDED_ON_BY_DREV: + case self::TYPE_TASK_HAS_RELATED_DREV: + case self::TYPE_COMMIT_HAS_DREV: + case self::TYPE_REVIEWER_FOR_DREV: + return '%s updated revisions of %s.'; + case self::TYPE_BLOG_HAS_POST: + return '%s updated posts of %s.'; + case self::TYPE_POST_HAS_BLOG: + case self::TYPE_BLOGGER_HAS_BLOG: + return '%s updated blogs of %s.'; + case self::TYPE_BLOG_HAS_BLOGGER: + return '%s updated bloggers of %s.'; + case self::TYPE_PROJ_MEMBER: + return '%s updated members of %s.'; + case self::TYPE_MEMBER_OF_PROJ: + case self::TYPE_COMMIT_HAS_PROJECT: + return '%s updated projects of %s.'; + case self::TYPE_QUESTION_HAS_VOTING_USER: + case self::TYPE_ANSWER_HAS_VOTING_USER: + return '%s updated voting users of %s.'; + case self::TYPE_VOTING_USER_HAS_QUESTION: + return '%s updated questions of %s.'; + case self::TYPE_VOTING_USER_HAS_ANSWER: + return '%s updated answers of %s.'; + case self::TYPE_OBJECT_HAS_SUBSCRIBER: + return '%s updated subscribers of %s.'; + case self::TYPE_OBJECT_HAS_UNSUBSCRIBER: + return '%s updated unsubcribers of %s.'; + case self::TYPE_OBJECT_HAS_FILE: + return '%s updated files of %s.'; + case self::TYPE_ACCOUNT_HAS_MEMBER: + return '%s updated members of %s.'; + case self::TYPE_MEMBER_HAS_ACCOUNT: + return '%s updated accounts of %s.'; + case self::TYPE_PURCAHSE_HAS_CHARGE: + return '%s updated charges of %s.'; + case self::TYPE_CHARGE_HAS_PURCHASE: + return '%s updated purchases of %s.'; + case self::TYPE_OBJECT_HAS_CONTRIBUTOR: + return '%s updated contributors of %s.'; + case self::TYPE_DREV_HAS_REVIEWER: + return '%s updated reviewers of %s.'; + case self::TYPE_TASK_HAS_MOCK: + return '%s updated mocks of %s.'; + case self::TYPE_SUBSCRIBED_TO_OBJECT: + case self::TYPE_UNSUBSCRIBED_FROM_OBJECT: + case self::TYPE_FILE_HAS_OBJECT: + case self::TYPE_CONTRIBUTED_TO_OBJECT: + default: + return '%s updated objects of %s.'; + + } + } + } diff --git a/src/infrastructure/internationalization/PhabricatorBaseEnglishTranslation.php b/src/infrastructure/internationalization/PhabricatorBaseEnglishTranslation.php index 5a97e4c50c..06de456159 100644 --- a/src/infrastructure/internationalization/PhabricatorBaseEnglishTranslation.php +++ b/src/infrastructure/internationalization/PhabricatorBaseEnglishTranslation.php @@ -58,6 +58,24 @@ abstract class PhabricatorBaseEnglishTranslation 'ATTACHED COMMITS', ), + 'added %d mock(s): %s' => array( + 'added a mock: %2$s', + 'added mocks: %2$s', + ), + + 'removed %d mock(s): %s' => array( + 'removed a mock: %2$s', + 'removed mocks: %2$s', + ), + + 'changed %d mock(s), added %d: %s; removed %d: %s' => + 'changed mocks, added: %3$s; removed: %5$s', + + 'ATTACHED %d MOCK(S)' => array( + 'ATTACHED MOCK', + 'ATTACHED MOCKS', + ), + 'added %d dependencie(s): %s' => array( 'added dependency: %2$s', 'added dependencies: %2$s', @@ -112,6 +130,9 @@ abstract class PhabricatorBaseEnglishTranslation 'changed %d revision(s), added %d: %s; removed %d: %s' => 'changed revisions, added %3$s; removed %5$s', + '%s edited revision(s), added %d: %s; removed %d: %s.' => + '%s edited revisions, added: %3$s; removed: %5$s', + 'There are %d raw fact(s) in storage.' => array( 'There is %d raw fact in storage.', 'There are %d raw facts in storage.', @@ -194,6 +215,298 @@ abstract class PhabricatorBaseEnglishTranslation 'Actions With No Effect', ), + '%s edited post(s), added %d: %s; removed %d: %s.' => + '%s edited posts, added: %3$s; removed: %5$s', + + '%s added %d post(s): %s.' => array( + array( + '%s added a post: %3$s.', + '%s added posts: %3$s.', + ), + ), + + '%s removed %d post(s): %s.' => array( + array( + '%s removed a post: %3$s.', + '%s removed posts: %3$s.', + ), + ), + + '%s edited blog(s), added %d: %s; removed %d: %s.' => + '%s edited blogs, added: %3$s; removed: %5$s', + + '%s added %d blog(s): %s.' => array( + array( + '%s added a blog: %3$s.', + '%s added blogs: %3$s.', + ), + ), + + '%s removed %d blog(s): %s.' => array( + array( + '%s removed a blog: %3$s.', + '%s removed blogs: %3$s.', + ), + ), + + '%s edited blogger(s), added %d: %s; removed %d: %s.' => + '%s edited bloggers, added: %3$s; removed: %5$s', + + '%s added %d blogger(s): %s.' => array( + array( + '%s added a blogger: %3$s.', + '%s added bloggers: %3$s.', + ), + ), + + '%s removed %d blogger(s): %s.' => array( + array( + '%s removed a blogger: %3$s.', + '%s removed bloggers: %3$s.', + ), + ), + + '%s edited member(s), added %d: %s; removed %d: %s.' => + '%s edited members, added: %3$s; removed: %5$s', + + '%s added %d member(s): %s.' => array( + array( + '%s added a member: %3$s.', + '%s added members: %3$s.', + ), + ), + + '%s removed %d member(s): %s.' => array( + array( + '%s removed a member: %3$s.', + '%s removed members: %3$s.', + ), + ), + + '%s edited project(s), added %d: %s; removed %d: %s.' => + '%s edited projects, added: %3$s; removed: %5$s', + + '%s added %d project(s): %s.' => array( + array( + '%s added a project: %3$s.', + '%s added projects: %3$s.', + ), + ), + + '%s removed %d project(s): %s.' => array( + array( + '%s removed a project: %3$s.', + '%s removed projects: %3$s.', + ), + ), + + '%s edited voting user(s), added %d: %s; removed %d: %s.' => + '%s edited voting users, added: %3$s; removed: %5$s', + + '%s added %d voting user(s): %s.' => array( + array( + '%s added a voting user: %3$s.', + '%s added voting users: %3$s.', + ), + ), + + '%s removed %d voting user(s): %s.' => array( + array( + '%s removed a voting user: %3$s.', + '%s removed voting users: %3$s.', + ), + ), + + '%s edited answer(s), added %d: %s; removed %d: %s.' => + '%s edited answers, added: %3$s; removed: %5$s', + + '%s added %d answer(s): %s.' => array( + array( + '%s added a answer: %3$s.', + '%s added answers: %3$s.', + ), + ), + + '%s removed %d answer(s): %s.' => array( + array( + '%s removed a answer: %3$s.', + '%s removed answers: %3$s.', + ), + ), + + '%s edited question(s), added %d: %s; removed %d: %s.' => + '%s edited questions, added: %3$s; removed: %5$s', + + '%s added %d question(s): %s.' => array( + array( + '%s added a question: %3$s.', + '%s added questions: %3$s.', + ), + ), + + '%s removed %d question(s): %s.' => array( + array( + '%s removed a question: %3$s.', + '%s removed questions: %3$s.', + ), + ), + + '%s edited mock(s), added %d: %s; removed %d: %s.' => + '%s edited mocks, added: %3$s; removed: %5$s', + + '%s added %d mock(s): %s.' => array( + array( + '%s added a mock: %3$s.', + '%s added mocks: %3$s.', + ), + ), + + '%s removed %d mock(s): %s.' => array( + array( + '%s removed a mock: %3$s.', + '%s removed mocks: %3$s.', + ), + ), + + '%s edited task(s), added %d: %s; removed %d: %s.' => + '%s edited tasks, added: %3$s; removed: %5$s', + + '%s added %d task(s): %s.' => array( + array( + '%s added a task: %3$s.', + '%s added tasks: %3$s.', + ), + ), + + '%s removed %d task(s): %s.' => array( + array( + '%s removed a task: %3$s.', + '%s removed tasks: %3$s.', + ), + ), + + '%s edited file(s), added %d: %s; removed %d: %s.' => + '%s edited files, added: %3$s; removed: %5$s', + + '%s added %d file(s): %s.' => array( + array( + '%s added a file: %3$s.', + '%s added files: %3$s.', + ), + ), + + '%s removed %d file(s): %s.' => array( + array( + '%s removed a file: %3$s.', + '%s removed files: %3$s.', + ), + ), + + '%s edited account(s), added %d: %s; removed %d: %s.' => + '%s edited accounts, added: %3$s; removed: %5$s', + + '%s added %d account(s): %s.' => array( + array( + '%s added a account: %3$s.', + '%s added accounts: %3$s.', + ), + ), + + '%s removed %d account(s): %s.' => array( + array( + '%s removed a account: %3$s.', + '%s removed accounts: %3$s.', + ), + ), + + '%s edited charge(s), added %d: %s; removed %d: %s.' => + '%s edited charges, added: %3$s; removed: %5$s', + + '%s added %d charge(s): %s.' => array( + array( + '%s added a charge: %3$s.', + '%s added charges: %3$s.', + ), + ), + + '%s removed %d charge(s): %s.' => array( + array( + '%s removed a charge: %3$s.', + '%s removed charges: %3$s.', + ), + ), + + '%s edited purchase(s), added %d: %s; removed %d: %s.' => + '%s edited purchases, added: %3$s; removed: %5$s', + + '%s added %d purchase(s): %s.' => array( + array( + '%s added a purchase: %3$s.', + '%s added purchases: %3$s.', + ), + ), + + '%s removed %d purchase(s): %s.' => array( + array( + '%s removed a purchase: %3$s.', + '%s removed purchases: %3$s.', + ), + ), + + '%s edited contributor(s), added %d: %s; removed %d: %s.' => + '%s edited contributors, added: %3$s; removed: %5$s', + + '%s added %d contributor(s): %s.' => array( + array( + '%s added a contributor: %3$s.', + '%s added contributors: %3$s.', + ), + ), + + '%s removed %d contributor(s): %s.' => array( + array( + '%s removed a contributor: %3$s.', + '%s removed contributors: %3$s.', + ), + ), + + '%s edited reviewer(s), added %d: %s; removed %d: %s.' => + '%s edited reviewers, added: %3$s; removed: %5$s', + + '%s added %d reviewer(s): %s.' => array( + array( + '%s added a reviewer: %3$s.', + '%s added reviewers: %3$s.', + ), + ), + + '%s removed %d reviewer(s): %s.' => array( + array( + '%s removed a reviewer: %3$s.', + '%s removed reviewers: %3$s.', + ), + ), + + '%s edited object(s), added %d: %s; removed %d: %s.' => + '%s edited objects, added: %3$s; removed: %5$s', + + '%s added %d object(s): %s.' => array( + array( + '%s added a object: %3$s.', + '%s added objects: %3$s.', + ), + ), + + '%s removed %d object(s): %s.' => array( + array( + '%s removed a object: %3$s.', + '%s removed objects: %3$s.', + ), + ), + + '%s edited subscriber(s), added %d: %s; removed %d: %s.' => + '%s edited subscribers, added: %3$s; removed: %5$s', + '%s added %d subscriber(s): %s.' => array( array( '%s added a subscriber: %3$s.', @@ -208,6 +521,26 @@ abstract class PhabricatorBaseEnglishTranslation ), ), + '%s edited unsubscriber(s), added %d: %s; removed %d: %s.' => + '%s edited unsubscribers, added: %3$s; removed: %5$s', + + '%s added %d unsubscriber(s): %s.' => array( + array( + '%s added a unsubscriber: %3$s.', + '%s added unsubscribers: %3$s.', + ), + ), + + '%s removed %d unsubscriber(s): %s.' => array( + array( + '%s removed a unsubscriber: %3$s.', + '%s removed unsubscribers: %3$s.', + ), + ), + + '%s edited participant(s), added %d: %s; removed %d: %s.' => + '%s edited participants, added: %3$s; removed: %5$s', + '%s added %d participant(s): %s.' => array( array( '%s added a participant: %3$s.', @@ -222,6 +555,9 @@ abstract class PhabricatorBaseEnglishTranslation ), ), + '%s edited image(s), added %d: %s; removed %d: %s.' => + '%s edited images, added: %3$s; removed: %5$s', + '%s added %d image(s): %s.' => array( array( '%s added an image: %3$s.',