1
0
Fork 0
mirror of https://we.phorge.it/source/phorge.git synced 2024-12-21 21:10:56 +01:00

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
This commit is contained in:
Bob Trahan 2013-07-19 15:59:29 -07:00
parent e777f7ad91
commit 3854599428
10 changed files with 799 additions and 42 deletions

View file

@ -42,6 +42,7 @@ final class ManiphestTaskDetailController extends ManiphestController {
$e_dep_on = PhabricatorEdgeConfig::TYPE_TASK_DEPENDS_ON_TASK; $e_dep_on = PhabricatorEdgeConfig::TYPE_TASK_DEPENDS_ON_TASK;
$e_dep_by = PhabricatorEdgeConfig::TYPE_TASK_DEPENDED_ON_BY_TASK; $e_dep_by = PhabricatorEdgeConfig::TYPE_TASK_DEPENDED_ON_BY_TASK;
$e_rev = PhabricatorEdgeConfig::TYPE_TASK_HAS_RELATED_DREV; $e_rev = PhabricatorEdgeConfig::TYPE_TASK_HAS_RELATED_DREV;
$e_mock = PhabricatorEdgeConfig::TYPE_TASK_HAS_MOCK;
$phid = $task->getPHID(); $phid = $task->getPHID();
@ -53,6 +54,7 @@ final class ManiphestTaskDetailController extends ManiphestController {
$e_dep_on, $e_dep_on,
$e_dep_by, $e_dep_by,
$e_rev, $e_rev,
$e_mock,
)); ));
$edges = idx($query->execute(), $phid); $edges = idx($query->execute(), $phid);
$phids = array_fill_keys($query->getDestinationPHIDs(), true); $phids = array_fill_keys($query->getDestinationPHIDs(), true);
@ -438,6 +440,17 @@ final class ManiphestTaskDetailController extends ManiphestController {
->setWorkflow(true) ->setWorkflow(true)
->setIcon('attach')); ->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; return $view;
} }
@ -456,8 +469,8 @@ final class ManiphestTaskDetailController extends ManiphestController {
$view->addProperty( $view->addProperty(
pht('Assigned To'), pht('Assigned To'),
$task->getOwnerPHID() $task->getOwnerPHID()
? $this->getHandle($task->getOwnerPHID())->renderLink() ? $this->getHandle($task->getOwnerPHID())->renderLink()
: phutil_tag('em', array(), pht('None'))); : phutil_tag('em', array(), pht('None')));
$view->addProperty( $view->addProperty(
pht('Priority'), pht('Priority'),
@ -466,8 +479,8 @@ final class ManiphestTaskDetailController extends ManiphestController {
$view->addProperty( $view->addProperty(
pht('Subscribers'), pht('Subscribers'),
$task->getCCPHIDs() $task->getCCPHIDs()
? $this->renderHandlesForPHIDs($task->getCCPHIDs(), ',') ? $this->renderHandlesForPHIDs($task->getCCPHIDs(), ',')
: phutil_tag('em', array(), pht('None'))); : phutil_tag('em', array(), pht('None')));
$view->addProperty( $view->addProperty(
pht('Author'), pht('Author'),
@ -482,15 +495,15 @@ final class ManiphestTaskDetailController extends ManiphestController {
'a', 'a',
array( array(
'href' => 'mailto:'.$source.'?subject='.$subject 'href' => 'mailto:'.$source.'?subject='.$subject
), ),
$source)); $source));
} }
$view->addProperty( $view->addProperty(
pht('Projects'), pht('Projects'),
$task->getProjectPHIDs() $task->getProjectPHIDs()
? $this->renderHandlesForPHIDs($task->getProjectPHIDs(), ',') ? $this->renderHandlesForPHIDs($task->getProjectPHIDs(), ',')
: phutil_tag('em', array(), pht('None'))); : phutil_tag('em', array(), pht('None')));
foreach ($aux_fields as $aux_field) { foreach ($aux_fields as $aux_field) {
$value = $aux_field->renderForDetailView(); $value = $aux_field->renderForDetailView();
@ -502,11 +515,13 @@ final class ManiphestTaskDetailController extends ManiphestController {
$edge_types = array( $edge_types = array(
PhabricatorEdgeConfig::TYPE_TASK_DEPENDED_ON_BY_TASK PhabricatorEdgeConfig::TYPE_TASK_DEPENDED_ON_BY_TASK
=> pht('Dependent Tasks'), => pht('Dependent Tasks'),
PhabricatorEdgeConfig::TYPE_TASK_DEPENDS_ON_TASK PhabricatorEdgeConfig::TYPE_TASK_DEPENDS_ON_TASK
=> pht('Depends On'), => pht('Depends On'),
PhabricatorEdgeConfig::TYPE_TASK_HAS_RELATED_DREV PhabricatorEdgeConfig::TYPE_TASK_HAS_RELATED_DREV
=> pht('Differential Revisions'), => pht('Differential Revisions'),
PhabricatorEdgeConfig::TYPE_TASK_HAS_MOCK
=> pht('Pholio Mocks'),
); );
$revisions_commits = array(); $revisions_commits = array();
@ -583,5 +598,4 @@ final class ManiphestTaskDetailController extends ManiphestController {
return $view; return $view;
} }
} }

View file

@ -674,6 +674,8 @@ final class ManiphestTransactionDetailView extends ManiphestView {
return pht('DEPENDENT %d TASK(s)', $count); return pht('DEPENDENT %d TASK(s)', $count);
case PhabricatorEdgeConfig::TYPE_TASK_HAS_COMMIT: case PhabricatorEdgeConfig::TYPE_TASK_HAS_COMMIT:
return pht('ATTACHED %d COMMIT(S)', $count); return pht('ATTACHED %d COMMIT(S)', $count);
case PhabricatorEdgeConfig::TYPE_TASK_HAS_MOCK:
return pht('ATTACHED %d MOCK(S)', $count);
default: default:
return pht('ATTACHED %d OBJECT(S)', $count); return pht('ATTACHED %d OBJECT(S)', $count);
} }
@ -693,6 +695,8 @@ final class ManiphestTransactionDetailView extends ManiphestView {
return pht('Added Dependent Task'); return pht('Added Dependent Task');
case PhabricatorEdgeConfig::TYPE_TASK_HAS_COMMIT: case PhabricatorEdgeConfig::TYPE_TASK_HAS_COMMIT:
return pht('Added Commit'); return pht('Added Commit');
case PhabricatorEdgeConfig::TYPE_TASK_HAS_MOCK:
return pht('Added Mock');
default: default:
return pht('Added Object'); return pht('Added Object');
} }
@ -712,6 +716,8 @@ final class ManiphestTransactionDetailView extends ManiphestView {
return pht('Removed Dependent Task'); return pht('Removed Dependent Task');
case PhabricatorEdgeConfig::TYPE_TASK_HAS_COMMIT: case PhabricatorEdgeConfig::TYPE_TASK_HAS_COMMIT:
return pht('Removed Commit'); return pht('Removed Commit');
case PhabricatorEdgeConfig::TYPE_TASK_HAS_MOCK:
return pht('Removed Mock');
default: default:
return pht('Removed Object'); return pht('Removed Object');
} }
@ -731,6 +737,8 @@ final class ManiphestTransactionDetailView extends ManiphestView {
return pht('Changed Dependent Tasks'); return pht('Changed Dependent Tasks');
case PhabricatorEdgeConfig::TYPE_TASK_HAS_COMMIT: case PhabricatorEdgeConfig::TYPE_TASK_HAS_COMMIT:
return pht('Changed Commits'); return pht('Changed Commits');
case PhabricatorEdgeConfig::TYPE_TASK_HAS_MOCK:
return pht('Changed Mocks');
default: default:
return pht('Changed Objects'); return pht('Changed Objects');
} }
@ -753,6 +761,8 @@ final class ManiphestTransactionDetailView extends ManiphestView {
return pht('added %d dependent task(s): %s', $count, $list); return pht('added %d dependent task(s): %s', $count, $list);
case PhabricatorEdgeConfig::TYPE_TASK_HAS_COMMIT: case PhabricatorEdgeConfig::TYPE_TASK_HAS_COMMIT:
return pht('added %d commit(s): %s', $count, $list); 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: default:
return pht('added %d object(s): %s', $count, $list); 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); return pht('removed %d dependent task(s): %s', $count, $list);
case PhabricatorEdgeConfig::TYPE_TASK_HAS_COMMIT: case PhabricatorEdgeConfig::TYPE_TASK_HAS_COMMIT:
return pht('removed %d commit(s): %s', $count, $list); 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: default:
return pht('removed %d object(s): %s', $count, $list); return pht('removed %d object(s): %s', $count, $list);
} }
@ -823,6 +835,14 @@ final class ManiphestTransactionDetailView extends ManiphestView {
$add_list, $add_list,
$rem_count, $rem_count,
$rem_list); $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: default:
return pht( return pht(
'changed %d object(s), added %d: %s; removed %d: %s', 'changed %d object(s), added %d: %s; removed %d: %s',

View file

@ -7,6 +7,15 @@ final class PholioMockViewController extends PholioController {
private $id; private $id;
private $imageID; 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() { public function shouldAllowPublic() {
return true; return true;
@ -37,7 +46,11 @@ final class PholioMockViewController extends PholioController {
->withObjectPHIDs(array($mock->getPHID())) ->withObjectPHIDs(array($mock->getPHID()))
->execute(); ->execute();
$phids = array($mock->getAuthorPHID()); $phids = PhabricatorEdgeQuery::loadDestinationPHIDs(
$mock->getPHID(),
PhabricatorEdgeConfig::TYPE_MOCK_HAS_TASK);
$this->setManiphestTaskPHIDs($phids);
$phids[] = $mock->getAuthorPHID();
$this->loadHandles($phids); $this->loadHandles($phids);
$engine = id(new PhabricatorMarkupEngine()) $engine = id(new PhabricatorMarkupEngine())
@ -119,11 +132,19 @@ final class PholioMockViewController extends PholioController {
$actions->addAction( $actions->addAction(
id(new PhabricatorActionView()) id(new PhabricatorActionView())
->setIcon('edit') ->setIcon('edit')
->setName(pht('Edit Mock')) ->setName(pht('Edit Mock'))
->setHref($this->getApplicationURI('/edit/'.$mock->getID().'/')) ->setHref($this->getApplicationURI('/edit/'.$mock->getID().'/'))
->setDisabled(!$can_edit) ->setDisabled(!$can_edit)
->setWorkflow(!$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; return $actions;
} }
@ -154,6 +175,12 @@ final class PholioMockViewController extends PholioController {
pht('Visible To'), pht('Visible To'),
$descriptions[PhabricatorPolicyCapability::CAN_VIEW]); $descriptions[PhabricatorPolicyCapability::CAN_VIEW]);
if ($this->getManiphestTaskPHIDs()) {
$properties->addProperty(
pht('Maniphest Tasks'),
$this->renderHandlesForPHIDs($this->getManiphestTaskPHIDs()));
}
$properties->invokeWillRenderEvent(); $properties->invokeWillRenderEvent();
$properties->addImageContent( $properties->addImageContent(

View file

@ -18,6 +18,7 @@ final class PholioMockEditor extends PhabricatorApplicationTransactionEditor {
public function getTransactionTypes() { public function getTransactionTypes() {
$types = parent::getTransactionTypes(); $types = parent::getTransactionTypes();
$types[] = PhabricatorTransactions::TYPE_EDGE;
$types[] = PhabricatorTransactions::TYPE_COMMENT; $types[] = PhabricatorTransactions::TYPE_COMMENT;
$types[] = PhabricatorTransactions::TYPE_VIEW_POLICY; $types[] = PhabricatorTransactions::TYPE_VIEW_POLICY;
$types[] = PhabricatorTransactions::TYPE_EDIT_POLICY; $types[] = PhabricatorTransactions::TYPE_EDIT_POLICY;

View file

@ -56,25 +56,42 @@ final class PhabricatorSearchAttachController
$phids = array_values($phids); $phids = array_values($phids);
if ($edge_type) { if ($edge_type) {
$do_txn = $object instanceof PhabricatorApplicationTransactionInterface;
$old_phids = PhabricatorEdgeQuery::loadDestinationPHIDs( $old_phids = PhabricatorEdgeQuery::loadDestinationPHIDs(
$this->phid, $this->phid,
$edge_type); $edge_type);
$add_phids = $phids; $add_phids = $phids;
$rem_phids = array_diff($old_phids, $add_phids); $rem_phids = array_diff($old_phids, $add_phids);
$editor = id(new PhabricatorEdgeEditor()); if ($do_txn) {
$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 { $txn_editor = $object->getApplicationTransactionEditor()
$editor->save(); ->setActor($user)
} catch (PhabricatorEdgeCycleException $ex) { ->setContentSourceFromRequest($request);
$this->raiseGraphCycleException($ex); $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()); return id(new AphrontReloadResponse())->setURI($handle->getURI());
@ -100,12 +117,7 @@ final class PhabricatorSearchAttachController
$obj_dialog $obj_dialog
->setUser($user) ->setUser($user)
->setHandles($handles) ->setHandles($handles)
->setFilters(array( ->setFilters($this->getFilters($strings))
'assigned' => 'Assigned to Me',
'created' => 'Created By Me',
'open' => 'All Open '.$strings['target_plural_noun'],
'all' => 'All '.$strings['target_plural_noun'],
))
->setSelectedFilter($strings['selected']) ->setSelectedFilter($strings['selected'])
->setExcluded($this->phid) ->setExcluded($this->phid)
->setCancelURI($handle->getURI()) ->setCancelURI($handle->getURI())
@ -198,6 +210,10 @@ final class PhabricatorSearchAttachController
$noun = 'Commits'; $noun = 'Commits';
$selected = 'created'; $selected = 'created';
break; break;
case PhabricatorPHIDConstants::PHID_TYPE_MOCK:
$noun = 'Mocks';
$selected = 'created';
break;
} }
switch ($this->action) { 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) { private function getEdgeType($src_type, $dst_type) {
$t_cmit = PhabricatorPHIDConstants::PHID_TYPE_CMIT; $t_cmit = PhabricatorPHIDConstants::PHID_TYPE_CMIT;
$t_task = PhabricatorPHIDConstants::PHID_TYPE_TASK; $t_task = PhabricatorPHIDConstants::PHID_TYPE_TASK;
$t_drev = PhabricatorPHIDConstants::PHID_TYPE_DREV; $t_drev = PhabricatorPHIDConstants::PHID_TYPE_DREV;
$t_mock = PhabricatorPHIDConstants::PHID_TYPE_MOCK;
$map = array( $map = array(
$t_cmit => array( $t_cmit => array(
@ -247,11 +282,15 @@ final class PhabricatorSearchAttachController
$t_cmit => PhabricatorEdgeConfig::TYPE_TASK_HAS_COMMIT, $t_cmit => PhabricatorEdgeConfig::TYPE_TASK_HAS_COMMIT,
$t_task => PhabricatorEdgeConfig::TYPE_TASK_DEPENDS_ON_TASK, $t_task => PhabricatorEdgeConfig::TYPE_TASK_DEPENDS_ON_TASK,
$t_drev => PhabricatorEdgeConfig::TYPE_TASK_HAS_RELATED_DREV, $t_drev => PhabricatorEdgeConfig::TYPE_TASK_HAS_RELATED_DREV,
$t_mock => PhabricatorEdgeConfig::TYPE_TASK_HAS_MOCK,
), ),
$t_drev => array( $t_drev => array(
$t_drev => PhabricatorEdgeConfig::TYPE_DREV_DEPENDS_ON_DREV, $t_drev => PhabricatorEdgeConfig::TYPE_DREV_DEPENDS_ON_DREV,
$t_task => PhabricatorEdgeConfig::TYPE_DREV_HAS_RELATED_TASK, $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])) { if (empty($map[$src_type][$dst_type])) {

View file

@ -31,7 +31,11 @@ final class PhabricatorSearchSelectController
break; break;
case 'created'; case 'created';
$query->setParameter('author', array($user->getPHID())); $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; break;
case 'open': case 'open':
$query->setParameter('open', 1); $query->setParameter('open', 1);
@ -69,6 +73,9 @@ final class PhabricatorSearchSelectController
case PhabricatorPHIDConstants::PHID_TYPE_DREV: case PhabricatorPHIDConstants::PHID_TYPE_DREV:
$pattern = '/\bD(\d+)\b/i'; $pattern = '/\bD(\d+)\b/i';
break; break;
case PhabricatorPHIDConstants::PHID_TYPE_MOCK:
$pattern = '/\bM(\d+)\b/i';
break;
} }
if (!$pattern) { if (!$pattern) {
@ -97,6 +104,11 @@ final class PhabricatorSearchSelectController
'id IN (%Ld)', 'id IN (%Ld)',
$object_ids); $object_ids);
break; 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); return array_fill_keys(mpull($objects, 'getPHID'), true);

View file

@ -116,7 +116,6 @@ abstract class PhabricatorApplicationTransactionEditor
$edge_src = $object->getPHID(); $edge_src = $object->getPHID();
$old_edges = id(new PhabricatorEdgeQuery()) $old_edges = id(new PhabricatorEdgeQuery())
->setViewer($this->getActor())
->withSourcePHIDs(array($edge_src)) ->withSourcePHIDs(array($edge_src))
->withEdgeTypes(array($edge_type)) ->withEdgeTypes(array($edge_type))
->needEdgeData(true) ->needEdgeData(true)

View file

@ -298,11 +298,38 @@ abstract class PhabricatorApplicationTransaction
} }
break; break;
case PhabricatorTransactions::TYPE_EDGE: 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'); $type = $this->getMetadata('edge:type');
return pht( $type = head($type);
'%s edited edges of type %s.',
$this->renderHandleLink($author_phid), if ($add && $rem) {
$type); $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: default:
return pht( return pht(
'%s edited this %s.', '%s edited this %s.',
@ -340,8 +367,11 @@ abstract class PhabricatorApplicationTransaction
$this->renderHandleLink($author_phid), $this->renderHandleLink($author_phid),
$this->renderHandleLink($object_phid)); $this->renderHandleLink($object_phid));
case PhabricatorTransactions::TYPE_EDGE: case PhabricatorTransactions::TYPE_EDGE:
$type = $this->getMetadata('edge:type');
$type = head($type);
$string = PhabricatorEdgeConfig::getFeedStringForEdgeType($type);
return pht( return pht(
'%s updated edges of %s.', $string,
$this->renderHandleLink($author_phid), $this->renderHandleLink($author_phid),
$this->renderHandleLink($object_phid)); $this->renderHandleLink($object_phid));
} }

View file

@ -57,6 +57,9 @@ final class PhabricatorEdgeConfig extends PhabricatorEdgeConstants {
const TYPE_DREV_HAS_REVIEWER = 35; const TYPE_DREV_HAS_REVIEWER = 35;
const TYPE_REVIEWER_FOR_DREV = 36; 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_TEST_NO_CYCLE = 9000;
const TYPE_PHOB_HAS_ASANATASK = 80001; 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_OBJECT_HAS_CONTRIBUTOR => self::TYPE_SUBSCRIBED_TO_OBJECT,
self::TYPE_CONTRIBUTED_TO_OBJECT => self::TYPE_OBJECT_HAS_CONTRIBUTOR, 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_PHOB_HAS_ASANATASK => self::TYPE_ASANATASK_HAS_PHOB,
self::TYPE_ASANATASK_HAS_PHOB => self::TYPE_PHOB_HAS_ASANATASK, 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); 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.';
}
}
} }

View file

@ -58,6 +58,24 @@ abstract class PhabricatorBaseEnglishTranslation
'ATTACHED COMMITS', '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 %d dependencie(s): %s' => array(
'added dependency: %2$s', 'added dependency: %2$s',
'added dependencies: %2$s', 'added dependencies: %2$s',
@ -112,6 +130,9 @@ abstract class PhabricatorBaseEnglishTranslation
'changed %d revision(s), added %d: %s; removed %d: %s' => 'changed %d revision(s), added %d: %s; removed %d: %s' =>
'changed revisions, added %3$s; removed %5$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 are %d raw fact(s) in storage.' => array(
'There is %d raw fact in storage.', 'There is %d raw fact in storage.',
'There are %d raw facts in storage.', 'There are %d raw facts in storage.',
@ -194,6 +215,298 @@ abstract class PhabricatorBaseEnglishTranslation
'Actions With No Effect', '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( '%s added %d subscriber(s): %s.' => array(
array( array(
'%s added a subscriber: %3$s.', '%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( '%s added %d participant(s): %s.' => array(
array( array(
'%s added a participant: %3$s.', '%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( '%s added %d image(s): %s.' => array(
array( array(
'%s added an image: %3$s.', '%s added an image: %3$s.',