Page MenuHomePhabricator

D16162.id.diff
No OneTemporary

D16162.id.diff

diff --git a/src/__phutil_library_map__.php b/src/__phutil_library_map__.php
--- a/src/__phutil_library_map__.php
+++ b/src/__phutil_library_map__.php
@@ -350,7 +350,6 @@
'DefaultDatabaseConfigurationProvider' => 'infrastructure/storage/configuration/DefaultDatabaseConfigurationProvider.php',
'DifferentialAction' => 'applications/differential/constants/DifferentialAction.php',
'DifferentialActionEmailCommand' => 'applications/differential/command/DifferentialActionEmailCommand.php',
- 'DifferentialActionMenuEventListener' => 'applications/differential/event/DifferentialActionMenuEventListener.php',
'DifferentialAddCommentView' => 'applications/differential/view/DifferentialAddCommentView.php',
'DifferentialAdjustmentMapTestCase' => 'applications/differential/storage/__tests__/DifferentialAdjustmentMapTestCase.php',
'DifferentialAffectedPath' => 'applications/differential/storage/DifferentialAffectedPath.php',
@@ -1420,8 +1419,11 @@
'ManiphestTaskEditController' => 'applications/maniphest/controller/ManiphestTaskEditController.php',
'ManiphestTaskFulltextEngine' => 'applications/maniphest/search/ManiphestTaskFulltextEngine.php',
'ManiphestTaskHasCommitEdgeType' => 'applications/maniphest/edge/ManiphestTaskHasCommitEdgeType.php',
+ 'ManiphestTaskHasCommitRelationship' => 'applications/maniphest/relationship/ManiphestTaskHasCommitRelationship.php',
'ManiphestTaskHasMockEdgeType' => 'applications/maniphest/edge/ManiphestTaskHasMockEdgeType.php',
+ 'ManiphestTaskHasMockRelationship' => 'applications/maniphest/relationship/ManiphestTaskHasMockRelationship.php',
'ManiphestTaskHasRevisionEdgeType' => 'applications/maniphest/edge/ManiphestTaskHasRevisionEdgeType.php',
+ 'ManiphestTaskHasRevisionRelationship' => 'applications/maniphest/relationship/ManiphestTaskHasRevisionRelationship.php',
'ManiphestTaskHeraldField' => 'applications/maniphest/herald/ManiphestTaskHeraldField.php',
'ManiphestTaskHeraldFieldGroup' => 'applications/maniphest/herald/ManiphestTaskHeraldFieldGroup.php',
'ManiphestTaskListController' => 'applications/maniphest/controller/ManiphestTaskListController.php',
@@ -1437,6 +1439,7 @@
'ManiphestTaskPriorityHeraldAction' => 'applications/maniphest/herald/ManiphestTaskPriorityHeraldAction.php',
'ManiphestTaskPriorityHeraldField' => 'applications/maniphest/herald/ManiphestTaskPriorityHeraldField.php',
'ManiphestTaskQuery' => 'applications/maniphest/query/ManiphestTaskQuery.php',
+ 'ManiphestTaskRelationship' => 'applications/maniphest/relationship/ManiphestTaskRelationship.php',
'ManiphestTaskResultListView' => 'applications/maniphest/view/ManiphestTaskResultListView.php',
'ManiphestTaskSearchEngine' => 'applications/maniphest/query/ManiphestTaskSearchEngine.php',
'ManiphestTaskStatus' => 'applications/maniphest/constants/ManiphestTaskStatus.php',
@@ -2860,6 +2863,8 @@
'PhabricatorObjectMentionedByObjectEdgeType' => 'applications/transactions/edges/PhabricatorObjectMentionedByObjectEdgeType.php',
'PhabricatorObjectMentionsObjectEdgeType' => 'applications/transactions/edges/PhabricatorObjectMentionsObjectEdgeType.php',
'PhabricatorObjectQuery' => 'applications/phid/query/PhabricatorObjectQuery.php',
+ 'PhabricatorObjectRelationship' => 'applications/search/relationship/PhabricatorObjectRelationship.php',
+ 'PhabricatorObjectRelationshipList' => 'applications/search/relationship/PhabricatorObjectRelationshipList.php',
'PhabricatorObjectRemarkupRule' => 'infrastructure/markup/rule/PhabricatorObjectRemarkupRule.php',
'PhabricatorObjectSelectorDialog' => 'view/control/PhabricatorObjectSelectorDialog.php',
'PhabricatorOffsetPagedQuery' => 'infrastructure/query/PhabricatorOffsetPagedQuery.php',
@@ -3834,7 +3839,6 @@
'PhluxVariablePHIDType' => 'applications/phlux/phid/PhluxVariablePHIDType.php',
'PhluxVariableQuery' => 'applications/phlux/query/PhluxVariableQuery.php',
'PhluxViewController' => 'applications/phlux/controller/PhluxViewController.php',
- 'PholioActionMenuEventListener' => 'applications/pholio/event/PholioActionMenuEventListener.php',
'PholioController' => 'applications/pholio/controller/PholioController.php',
'PholioDAO' => 'applications/pholio/storage/PholioDAO.php',
'PholioDefaultEditCapability' => 'applications/pholio/capability/PholioDefaultEditCapability.php',
@@ -4662,7 +4666,6 @@
),
'DifferentialAction' => 'Phobject',
'DifferentialActionEmailCommand' => 'MetaMTAEmailTransactionCommand',
- 'DifferentialActionMenuEventListener' => 'PhabricatorEventListener',
'DifferentialAddCommentView' => 'AphrontView',
'DifferentialAdjustmentMapTestCase' => 'PhutilTestCase',
'DifferentialAffectedPath' => 'DifferentialDAO',
@@ -5906,8 +5909,11 @@
'ManiphestTaskEditController' => 'ManiphestController',
'ManiphestTaskFulltextEngine' => 'PhabricatorFulltextEngine',
'ManiphestTaskHasCommitEdgeType' => 'PhabricatorEdgeType',
+ 'ManiphestTaskHasCommitRelationship' => 'ManiphestTaskRelationship',
'ManiphestTaskHasMockEdgeType' => 'PhabricatorEdgeType',
+ 'ManiphestTaskHasMockRelationship' => 'ManiphestTaskRelationship',
'ManiphestTaskHasRevisionEdgeType' => 'PhabricatorEdgeType',
+ 'ManiphestTaskHasRevisionRelationship' => 'ManiphestTaskRelationship',
'ManiphestTaskHeraldField' => 'HeraldField',
'ManiphestTaskHeraldFieldGroup' => 'HeraldFieldGroup',
'ManiphestTaskListController' => 'ManiphestController',
@@ -5923,6 +5929,7 @@
'ManiphestTaskPriorityHeraldAction' => 'HeraldAction',
'ManiphestTaskPriorityHeraldField' => 'ManiphestTaskHeraldField',
'ManiphestTaskQuery' => 'PhabricatorCursorPagedPolicyAwareQuery',
+ 'ManiphestTaskRelationship' => 'PhabricatorObjectRelationship',
'ManiphestTaskResultListView' => 'ManiphestView',
'ManiphestTaskSearchEngine' => 'PhabricatorApplicationSearchEngine',
'ManiphestTaskStatus' => 'ManiphestConstants',
@@ -7547,6 +7554,8 @@
'PhabricatorObjectMentionedByObjectEdgeType' => 'PhabricatorEdgeType',
'PhabricatorObjectMentionsObjectEdgeType' => 'PhabricatorEdgeType',
'PhabricatorObjectQuery' => 'PhabricatorCursorPagedPolicyAwareQuery',
+ 'PhabricatorObjectRelationship' => 'Phobject',
+ 'PhabricatorObjectRelationshipList' => 'Phobject',
'PhabricatorObjectRemarkupRule' => 'PhutilRemarkupRule',
'PhabricatorObjectSelectorDialog' => 'Phobject',
'PhabricatorOffsetPagedQuery' => 'PhabricatorQuery',
@@ -8730,7 +8739,6 @@
'PhluxVariablePHIDType' => 'PhabricatorPHIDType',
'PhluxVariableQuery' => 'PhabricatorCursorPagedPolicyAwareQuery',
'PhluxViewController' => 'PhluxController',
- 'PholioActionMenuEventListener' => 'PhabricatorEventListener',
'PholioController' => 'PhabricatorController',
'PholioDAO' => 'PhabricatorLiskDAO',
'PholioDefaultEditCapability' => 'PhabricatorPolicyCapability',
diff --git a/src/applications/differential/application/PhabricatorDifferentialApplication.php b/src/applications/differential/application/PhabricatorDifferentialApplication.php
--- a/src/applications/differential/application/PhabricatorDifferentialApplication.php
+++ b/src/applications/differential/application/PhabricatorDifferentialApplication.php
@@ -43,7 +43,6 @@
public function getEventListeners() {
return array(
- new DifferentialActionMenuEventListener(),
new DifferentialLandingActionMenuEventListener(),
);
}
diff --git a/src/applications/differential/event/DifferentialActionMenuEventListener.php b/src/applications/differential/event/DifferentialActionMenuEventListener.php
deleted file mode 100644
--- a/src/applications/differential/event/DifferentialActionMenuEventListener.php
+++ /dev/null
@@ -1,50 +0,0 @@
-<?php
-
-final class DifferentialActionMenuEventListener
- extends PhabricatorEventListener {
-
- public function register() {
- $this->listen(PhabricatorEventType::TYPE_UI_DIDRENDERACTIONS);
- }
-
- public function handleEvent(PhutilEvent $event) {
- switch ($event->getType()) {
- case PhabricatorEventType::TYPE_UI_DIDRENDERACTIONS:
- $this->handleActionsEvent($event);
- break;
- }
- }
-
- private function handleActionsEvent(PhutilEvent $event) {
- $object = $event->getValue('object');
-
- $actions = null;
- if ($object instanceof ManiphestTask) {
- $actions = $this->renderTaskItems($event);
- $this->addActionMenuItems($event, $actions);
- }
-
- }
-
- private function renderTaskItems(PhutilEvent $event) {
- if (!$this->canUseApplication($event->getUser())) {
- return null;
- }
-
- $task = $event->getValue('object');
- $phid = $task->getPHID();
-
- $can_edit = PhabricatorPolicyFilter::hasCapability(
- $event->getUser(),
- $task,
- PhabricatorPolicyCapability::CAN_EDIT);
-
- return id(new PhabricatorActionView())
- ->setName(pht('Edit Differential Revisions'))
- ->setHref("/search/attach/{$phid}/DREV/")
- ->setIcon('fa-cog')
- ->setDisabled(!$can_edit)
- ->setWorkflow(true);
- }
-
-}
diff --git a/src/applications/maniphest/controller/ManiphestTaskDetailController.php b/src/applications/maniphest/controller/ManiphestTaskDetailController.php
--- a/src/applications/maniphest/controller/ManiphestTaskDetailController.php
+++ b/src/applications/maniphest/controller/ManiphestTaskDetailController.php
@@ -215,6 +215,15 @@
->setIcon('fa-anchor')
->setSubmenu($task_submenu));
+ $relationship_list = PhabricatorObjectRelationshipList::newForObject(
+ $viewer,
+ $task);
+
+ $relationship_submenu = $relationship_list->newActionMenu();
+ if ($relationship_submenu) {
+ $curtain->addAction($relationship_submenu);
+ }
+
$owner_phid = $task->getOwnerPHID();
$author_phid = $task->getAuthorPHID();
$handles = $viewer->loadHandles(array($owner_phid, $author_phid));
diff --git a/src/applications/maniphest/relationship/ManiphestTaskHasCommitRelationship.php b/src/applications/maniphest/relationship/ManiphestTaskHasCommitRelationship.php
new file mode 100644
--- /dev/null
+++ b/src/applications/maniphest/relationship/ManiphestTaskHasCommitRelationship.php
@@ -0,0 +1,27 @@
+<?php
+
+final class ManiphestTaskHasCommitRelationship
+ extends ManiphestTaskRelationship {
+
+ const RELATIONSHIPKEY = 'task.has-commit';
+
+ public function getEdgeConstant() {
+ return ManiphestTaskHasCommitEdgeType::EDGECONST;
+ }
+
+ protected function getActionName() {
+ return pht('Edit Commits');
+ }
+
+ protected function getActionIcon() {
+ return 'fa-code';
+ }
+
+ public function shouldAppearInActionMenu() {
+ // TODO: For now, the default search for commits is not very good, so
+ // it is hard to find objects to link to. Until that works better, just
+ // hide this item.
+ return false;
+ }
+
+}
diff --git a/src/applications/maniphest/relationship/ManiphestTaskHasMockRelationship.php b/src/applications/maniphest/relationship/ManiphestTaskHasMockRelationship.php
new file mode 100644
--- /dev/null
+++ b/src/applications/maniphest/relationship/ManiphestTaskHasMockRelationship.php
@@ -0,0 +1,20 @@
+<?php
+
+final class ManiphestTaskHasMockRelationship
+ extends ManiphestTaskRelationship {
+
+ const RELATIONSHIPKEY = 'task.has-mock';
+
+ public function getEdgeConstant() {
+ return ManiphestTaskHasMockEdgeType::EDGECONST;
+ }
+
+ protected function getActionName() {
+ return pht('Edit Mocks');
+ }
+
+ protected function getActionIcon() {
+ return 'fa-camera-retro';
+ }
+
+}
diff --git a/src/applications/maniphest/relationship/ManiphestTaskHasRevisionRelationship.php b/src/applications/maniphest/relationship/ManiphestTaskHasRevisionRelationship.php
new file mode 100644
--- /dev/null
+++ b/src/applications/maniphest/relationship/ManiphestTaskHasRevisionRelationship.php
@@ -0,0 +1,20 @@
+<?php
+
+final class ManiphestTaskHasRevisionRelationship
+ extends ManiphestTaskRelationship {
+
+ const RELATIONSHIPKEY = 'task.has-revision';
+
+ public function getEdgeConstant() {
+ return ManiphestTaskHasRevisionEdgeType::EDGECONST;
+ }
+
+ protected function getActionName() {
+ return pht('Edit Revisions');
+ }
+
+ protected function getActionIcon() {
+ return 'fa-cog';
+ }
+
+}
diff --git a/src/applications/maniphest/relationship/ManiphestTaskRelationship.php b/src/applications/maniphest/relationship/ManiphestTaskRelationship.php
new file mode 100644
--- /dev/null
+++ b/src/applications/maniphest/relationship/ManiphestTaskRelationship.php
@@ -0,0 +1,19 @@
+<?php
+
+abstract class ManiphestTaskRelationship
+ extends PhabricatorObjectRelationship {
+
+ public function isEnabledForObject($object) {
+ $viewer = $this->getViewer();
+
+ $has_app = PhabricatorApplication::isClassInstalledForViewer(
+ 'PhabricatorManiphestApplication',
+ $viewer);
+ if (!$has_app) {
+ return false;
+ }
+
+ return ($object instanceof ManiphestTask);
+ }
+
+}
diff --git a/src/applications/pholio/application/PhabricatorPholioApplication.php b/src/applications/pholio/application/PhabricatorPholioApplication.php
--- a/src/applications/pholio/application/PhabricatorPholioApplication.php
+++ b/src/applications/pholio/application/PhabricatorPholioApplication.php
@@ -26,12 +26,6 @@
return pht('Things before they were cool.');
}
- public function getEventListeners() {
- return array(
- new PholioActionMenuEventListener(),
- );
- }
-
public function getRemarkupRules() {
return array(
new PholioRemarkupRule(),
diff --git a/src/applications/pholio/event/PholioActionMenuEventListener.php b/src/applications/pholio/event/PholioActionMenuEventListener.php
deleted file mode 100644
--- a/src/applications/pholio/event/PholioActionMenuEventListener.php
+++ /dev/null
@@ -1,50 +0,0 @@
-<?php
-
-final class PholioActionMenuEventListener
- extends PhabricatorEventListener {
-
- public function register() {
- $this->listen(PhabricatorEventType::TYPE_UI_DIDRENDERACTIONS);
- }
-
- public function handleEvent(PhutilEvent $event) {
- switch ($event->getType()) {
- case PhabricatorEventType::TYPE_UI_DIDRENDERACTIONS:
- $this->handleActionsEvent($event);
- break;
- }
- }
-
- private function handleActionsEvent(PhutilEvent $event) {
- $object = $event->getValue('object');
-
- $actions = null;
- if ($object instanceof ManiphestTask) {
- $actions = $this->renderTaskItems($event);
- }
-
- $this->addActionMenuItems($event, $actions);
- }
-
- private function renderTaskItems(PhutilEvent $event) {
- if (!$this->canUseApplication($event->getUser())) {
- return;
- }
-
- $task = $event->getValue('object');
- $phid = $task->getPHID();
-
- $can_edit = PhabricatorPolicyFilter::hasCapability(
- $event->getUser(),
- $task,
- PhabricatorPolicyCapability::CAN_EDIT);
-
- return id(new PhabricatorActionView())
- ->setName(pht('Edit Pholio Mocks'))
- ->setHref("/search/attach/{$phid}/MOCK/edge/")
- ->setIcon('fa-camera-retro')
- ->setDisabled(!$can_edit)
- ->setWorkflow(true);
- }
-
-}
diff --git a/src/applications/search/relationship/PhabricatorObjectRelationship.php b/src/applications/search/relationship/PhabricatorObjectRelationship.php
new file mode 100644
--- /dev/null
+++ b/src/applications/search/relationship/PhabricatorObjectRelationship.php
@@ -0,0 +1,81 @@
+<?php
+
+abstract class PhabricatorObjectRelationship extends Phobject {
+
+ private $viewer;
+
+ public function setViewer(PhabricatorUser $viewer) {
+ $this->viewer = $viewer;
+ return $this;
+ }
+
+ public function getViewer() {
+ return $this->viewer;
+ }
+
+ final public function getRelationshipConstant() {
+ return $this->getPhobjectClassConstant('RELATIONSHIPKEY');
+ }
+
+ abstract public function isEnabledForObject($object);
+
+ abstract public function getEdgeConstant();
+
+ abstract protected function getActionName();
+ abstract protected function getActionIcon();
+
+ public function shouldAppearInActionMenu() {
+ return true;
+ }
+
+ protected function isActionEnabled($object) {
+ $viewer = $this->getViewer();
+
+ return PhabricatorPolicyFilter::hasCapability(
+ $viewer,
+ $object,
+ PhabricatorPolicyCapability::CAN_EDIT);
+ }
+
+ final public function newAction($object) {
+ $is_enabled = $this->isActionEnabled($object);
+ $action_uri = $this->getActionURI($object);
+
+ return id(new PhabricatorActionView())
+ ->setName($this->getActionName())
+ ->setHref($action_uri)
+ ->setIcon($this->getActionIcon())
+ ->setDisabled(!$is_enabled)
+ ->setWorkflow(true);
+ }
+
+ final public static function getAllRelationships() {
+ return id(new PhutilClassMapQuery())
+ ->setAncestorClass(__CLASS__)
+ ->setUniqueMethod('getRelationshipConstant')
+ ->execute();
+ }
+
+ private function getActionURI($object) {
+ $phid = $object->getPHID();
+
+ // TODO: Remove this, this is just legacy support for the current
+ // controller until a new one gets built.
+ $legacy_kinds = array(
+ ManiphestTaskHasCommitEdgeType::EDGECONST => 'CMIT',
+ ManiphestTaskHasMockEdgeType::EDGECONST => 'MOCK',
+ ManiphestTaskHasRevisionEdgeType::EDGECONST => 'DREV',
+ );
+
+ $edge_type = $this->getEdgeConstant();
+ $legacy_kind = idx($legacy_kinds, $edge_type);
+ if (!$legacy_kind) {
+ throw new Exception(
+ pht(
+ 'Only specific legacy relationships are supported!'));
+ }
+
+ return "/search/attach/{$phid}/{$legacy_kind}/";
+ }
+
+}
diff --git a/src/applications/search/relationship/PhabricatorObjectRelationshipList.php b/src/applications/search/relationship/PhabricatorObjectRelationshipList.php
new file mode 100644
--- /dev/null
+++ b/src/applications/search/relationship/PhabricatorObjectRelationshipList.php
@@ -0,0 +1,95 @@
+<?php
+
+final class PhabricatorObjectRelationshipList extends Phobject {
+
+ private $viewer;
+ private $object;
+ private $relationships;
+
+ public function setViewer(PhabricatorUser $viewer) {
+ $this->viewer = $viewer;
+ return $this;
+ }
+
+ public function getViewer() {
+ if ($this->viewer === null) {
+ throw new PhutilInvalidStateException('setViewer');
+ }
+
+ return $this->viewer;
+ }
+
+ public function setObject($object) {
+ $this->object = $object;
+ return $this;
+ }
+
+ public function getObject() {
+ if ($this->object === null) {
+ throw new PhutilInvalidStateException('setObject');
+ }
+
+ return $this->object;
+ }
+
+ public function setRelationships(array $relationships) {
+ assert_instances_of($relationships, 'PhabricatorObjectRelationship');
+ $this->relationships = $relationships;
+ return $this;
+ }
+
+ public function getRelationships() {
+ if ($this->relationships === null) {
+ throw new PhutilInvalidStateException('setRelationships');
+ }
+
+ return $this->relationships;
+ }
+
+ public function newActionMenu() {
+ $relationships = $this->getRelationships();
+ $object = $this->getObject();
+
+ $actions = array();
+ foreach ($relationships as $key => $relationship) {
+ if (!$relationship->shouldAppearInActionMenu()) {
+ continue;
+ }
+
+ $actions[$key] = $relationship->newAction($object);
+ }
+
+ if (!$actions) {
+ return null;
+ }
+
+ $actions = msort($actions, 'getName');
+
+ return id(new PhabricatorActionView())
+ ->setName(pht('Edit Related Objects...'))
+ ->setIcon('fa-link')
+ ->setSubmenu($actions);
+ }
+
+ public static function newForObject(PhabricatorUser $viewer, $object) {
+ $relationships = PhabricatorObjectRelationship::getAllRelationships();
+
+ $results = array();
+ foreach ($relationships as $key => $relationship) {
+ $relationship = clone $relationship;
+
+ $relationship->setViewer($viewer);
+ if (!$relationship->isEnabledForObject($object)) {
+ continue;
+ }
+
+ $results[$key] = $relationship;
+ }
+
+ return id(new self())
+ ->setViewer($viewer)
+ ->setObject($object)
+ ->setRelationships($results);
+ }
+
+}
diff --git a/src/view/layout/PhabricatorActionView.php b/src/view/layout/PhabricatorActionView.php
--- a/src/view/layout/PhabricatorActionView.php
+++ b/src/view/layout/PhabricatorActionView.php
@@ -70,6 +70,10 @@
return $this;
}
+ public function getName() {
+ return $this->name;
+ }
+
public function setLabel($label) {
$this->label = $label;
return $this;

File Metadata

Mime Type
text/plain
Expires
Wed, Dec 3, 9:05 AM (18 h, 53 m)
Storage Engine
blob
Storage Format
Encrypted (AES-256-CBC)
Storage Handle
9002393
Default Alt Text
D16162.id.diff (20 KB)

Event Timeline