Page Menu
Home
Phabricator
Search
Configure Global Search
Log In
Files
F13992506
D13705.id.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Award Token
Flag For Later
Size
16 KB
Referenced Files
None
Subscribers
None
D13705.id.diff
View Options
diff --git a/resources/sql/autopatches/20150724.herald.3.sql b/resources/sql/autopatches/20150724.herald.3.sql
new file mode 100644
--- /dev/null
+++ b/resources/sql/autopatches/20150724.herald.3.sql
@@ -0,0 +1,11 @@
+UPDATE {$NAMESPACE}_herald.herald_actionrecord a
+ JOIN {$NAMESPACE}_herald.herald_rule r
+ ON a.ruleID = r.id
+ SET a.action = 'projects.add'
+ WHERE a.action = 'addprojects';
+
+UPDATE {$NAMESPACE}_herald.herald_actionrecord a
+ JOIN {$NAMESPACE}_herald.herald_rule r
+ ON a.ruleID = r.id
+ SET a.action = 'projects.remove'
+ WHERE a.action = 'removeprojects';
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
@@ -2540,6 +2540,7 @@
'PhabricatorPolicyType' => 'applications/policy/constants/PhabricatorPolicyType.php',
'PhabricatorPonderApplication' => 'applications/ponder/application/PhabricatorPonderApplication.php',
'PhabricatorProject' => 'applications/project/storage/PhabricatorProject.php',
+ 'PhabricatorProjectAddHeraldAction' => 'applications/project/herald/PhabricatorProjectAddHeraldAction.php',
'PhabricatorProjectApplication' => 'applications/project/application/PhabricatorProjectApplication.php',
'PhabricatorProjectArchiveController' => 'applications/project/controller/PhabricatorProjectArchiveController.php',
'PhabricatorProjectBoardController' => 'applications/project/controller/PhabricatorProjectBoardController.php',
@@ -2572,6 +2573,7 @@
'PhabricatorProjectEditPictureController' => 'applications/project/controller/PhabricatorProjectEditPictureController.php',
'PhabricatorProjectEditorTestCase' => 'applications/project/editor/__tests__/PhabricatorProjectEditorTestCase.php',
'PhabricatorProjectFeedController' => 'applications/project/controller/PhabricatorProjectFeedController.php',
+ 'PhabricatorProjectHeraldAction' => 'applications/project/herald/PhabricatorProjectHeraldAction.php',
'PhabricatorProjectIcon' => 'applications/project/icon/PhabricatorProjectIcon.php',
'PhabricatorProjectInterface' => 'applications/project/interface/PhabricatorProjectInterface.php',
'PhabricatorProjectListController' => 'applications/project/controller/PhabricatorProjectListController.php',
@@ -2593,6 +2595,7 @@
'PhabricatorProjectProjectHasObjectEdgeType' => 'applications/project/edge/PhabricatorProjectProjectHasObjectEdgeType.php',
'PhabricatorProjectProjectPHIDType' => 'applications/project/phid/PhabricatorProjectProjectPHIDType.php',
'PhabricatorProjectQuery' => 'applications/project/query/PhabricatorProjectQuery.php',
+ 'PhabricatorProjectRemoveHeraldAction' => 'applications/project/herald/PhabricatorProjectRemoveHeraldAction.php',
'PhabricatorProjectSchemaSpec' => 'applications/project/storage/PhabricatorProjectSchemaSpec.php',
'PhabricatorProjectSearchEngine' => 'applications/project/query/PhabricatorProjectSearchEngine.php',
'PhabricatorProjectSearchField' => 'applications/project/searchfield/PhabricatorProjectSearchField.php',
@@ -6496,6 +6499,7 @@
'PhabricatorCustomFieldInterface',
'PhabricatorDestructibleInterface',
),
+ 'PhabricatorProjectAddHeraldAction' => 'PhabricatorProjectHeraldAction',
'PhabricatorProjectApplication' => 'PhabricatorApplication',
'PhabricatorProjectArchiveController' => 'PhabricatorProjectController',
'PhabricatorProjectBoardController' => 'PhabricatorProjectController',
@@ -6539,6 +6543,7 @@
'PhabricatorProjectEditPictureController' => 'PhabricatorProjectController',
'PhabricatorProjectEditorTestCase' => 'PhabricatorTestCase',
'PhabricatorProjectFeedController' => 'PhabricatorProjectController',
+ 'PhabricatorProjectHeraldAction' => 'HeraldAction',
'PhabricatorProjectIcon' => 'Phobject',
'PhabricatorProjectListController' => 'PhabricatorProjectController',
'PhabricatorProjectLogicalAndDatasource' => 'PhabricatorTypeaheadCompositeDatasource',
@@ -6559,6 +6564,7 @@
'PhabricatorProjectProjectHasObjectEdgeType' => 'PhabricatorEdgeType',
'PhabricatorProjectProjectPHIDType' => 'PhabricatorPHIDType',
'PhabricatorProjectQuery' => 'PhabricatorCursorPagedPolicyAwareQuery',
+ 'PhabricatorProjectRemoveHeraldAction' => 'PhabricatorProjectHeraldAction',
'PhabricatorProjectSchemaSpec' => 'PhabricatorConfigSchemaSpec',
'PhabricatorProjectSearchEngine' => 'PhabricatorApplicationSearchEngine',
'PhabricatorProjectSearchField' => 'PhabricatorSearchTokenizerField',
diff --git a/src/applications/herald/adapter/HeraldAdapter.php b/src/applications/herald/adapter/HeraldAdapter.php
--- a/src/applications/herald/adapter/HeraldAdapter.php
+++ b/src/applications/herald/adapter/HeraldAdapter.php
@@ -28,8 +28,6 @@
const ACTION_AUDIT = 'audit';
const ACTION_ASSIGN_TASK = 'assigntask';
- const ACTION_ADD_PROJECTS = 'addprojects';
- const ACTION_REMOVE_PROJECTS = 'removeprojects';
const ACTION_ADD_REVIEWERS = 'addreviewers';
const ACTION_ADD_BLOCKING_REVIEWERS = 'addblockingreviewers';
const ACTION_APPLY_BUILD_PLANS = 'applybuildplans';
@@ -707,15 +705,6 @@
$actions = $custom_actions;
- $object = $this->newObject();
-
- if (($object instanceof PhabricatorProjectInterface)) {
- if ($rule_type == HeraldRuleTypeConfig::RULE_TYPE_GLOBAL) {
- $actions[] = self::ACTION_ADD_PROJECTS;
- $actions[] = self::ACTION_REMOVE_PROJECTS;
- }
- }
-
foreach ($this->getActionsForRuleType($rule_type) as $key => $action) {
$actions[] = $key;
}
@@ -730,8 +719,6 @@
$standard = array(
self::ACTION_AUDIT => pht('Trigger an Audit by'),
self::ACTION_ASSIGN_TASK => pht('Assign task to'),
- self::ACTION_ADD_PROJECTS => pht('Add projects'),
- self::ACTION_REMOVE_PROJECTS => pht('Remove projects'),
self::ACTION_ADD_REVIEWERS => pht('Add reviewers'),
self::ACTION_ADD_BLOCKING_REVIEWERS => pht('Add blocking reviewers'),
self::ACTION_APPLY_BUILD_PLANS => pht('Run build plans'),
@@ -829,17 +816,9 @@
case self::ACTION_ADD_REVIEWERS:
case self::ACTION_ADD_BLOCKING_REVIEWERS:
return new HeraldEmptyFieldValue();
- case self::ACTION_ADD_PROJECTS:
- case self::ACTION_REMOVE_PROJECTS:
- return $this->buildTokenizerFieldValue(
- new PhabricatorProjectDatasource());
}
} else {
switch ($action) {
- case self::ACTION_ADD_PROJECTS:
- case self::ACTION_REMOVE_PROJECTS:
- return $this->buildTokenizerFieldValue(
- new PhabricatorProjectDatasource());
case self::ACTION_ASSIGN_TASK:
return $this->buildTokenizerFieldValue(
new PhabricatorPeopleDatasource());
@@ -1200,14 +1179,6 @@
$rule_type));
}
- switch ($action) {
- case self::ACTION_ADD_PROJECTS:
- case self::ACTION_REMOVE_PROJECTS:
- return $this->applyProjectsEffect($effect);
- default:
- break;
- }
-
$result = $this->handleCustomHeraldEffect($effect);
if (!$result) {
@@ -1222,35 +1193,6 @@
return $result;
}
- /**
- * @task apply
- */
- private function applyProjectsEffect(HeraldEffect $effect) {
-
- if ($effect->getAction() == self::ACTION_ADD_PROJECTS) {
- $kind = '+';
- } else {
- $kind = '-';
- }
-
- $project_type = PhabricatorProjectObjectHasProjectEdgeType::EDGECONST;
- $project_phids = $effect->getTarget();
- $xaction = $this->newTransaction()
- ->setTransactionType(PhabricatorTransactions::TYPE_EDGE)
- ->setMetadataValue('edge:type', $project_type)
- ->setNewValue(
- array(
- $kind => array_fuse($project_phids),
- ));
-
- $this->queueTransaction($xaction);
-
- return new HeraldApplyTranscript(
- $effect,
- true,
- pht('Added projects.'));
- }
-
public function loadEdgePHIDs($type) {
if (!isset($this->edgeCache[$type])) {
$phids = PhabricatorEdgeQuery::loadDestinationPHIDs(
diff --git a/src/applications/project/herald/PhabricatorProjectAddHeraldAction.php b/src/applications/project/herald/PhabricatorProjectAddHeraldAction.php
new file mode 100644
--- /dev/null
+++ b/src/applications/project/herald/PhabricatorProjectAddHeraldAction.php
@@ -0,0 +1,28 @@
+<?php
+
+final class PhabricatorProjectAddHeraldAction
+ extends PhabricatorProjectHeraldAction {
+
+ const ACTIONCONST = 'projects.add';
+
+ public function getHeraldActionName() {
+ return pht('Add projects');
+ }
+
+ public function applyEffect($object, HeraldEffect $effect) {
+ return $this->applyProjects($effect->getTarget(), $is_add = true);
+ }
+
+ public function getHeraldActionStandardType() {
+ return self::STANDARD_PHID_LIST;
+ }
+
+ protected function getDatasource() {
+ return new PhabricatorProjectDatasource();
+ }
+
+ public function renderActionDescription($value) {
+ return pht('Add projects: %s.', $this->renderHandleList($value));
+ }
+
+}
diff --git a/src/applications/project/herald/PhabricatorProjectHeraldAction.php b/src/applications/project/herald/PhabricatorProjectHeraldAction.php
new file mode 100644
--- /dev/null
+++ b/src/applications/project/herald/PhabricatorProjectHeraldAction.php
@@ -0,0 +1,180 @@
+<?php
+
+abstract class PhabricatorProjectHeraldAction
+ extends HeraldAction {
+
+ const DO_NO_TARGETS = 'do.no-targets';
+ const DO_INVALID = 'do.invalid';
+ const DO_ALREADY_ASSOCIATED = 'do.already-associated';
+ const DO_ALREADY_UNASSOCIATED = 'do.already-unassociated';
+ const DO_ADD_PROJECTS = 'do.add-projects';
+ const DO_REMOVE_PROJECTS = 'do.remove-projects';
+
+ public function getActionGroupKey() {
+ return HeraldSupportActionGroup::ACTIONGROUPKEY;
+ }
+
+ public function supportsObject($object) {
+ return ($object instanceof PhabricatorProjectInterface);
+ }
+
+ public function supportsRuleType($rule_type) {
+ return ($rule_type == HeraldRuleTypeConfig::RULE_TYPE_GLOBAL);
+ }
+
+ protected function applyProjects(array $phids, $is_add) {
+ $phids = array_fuse($phids);
+ $adapter = $this->getAdapter();
+
+ if (!$phids) {
+ $this->logEffect(self::DO_NO_TARGETS);
+ return;
+ }
+
+ $projects = id(new PhabricatorProjectQuery())
+ ->setViewer(PhabricatorUser::getOmnipotentUser())
+ ->withPHIDs($phids)
+ ->execute();
+ $projects = mpull($projects, null, 'getPHID');
+
+ $invalid = array();
+ foreach ($phids as $phid) {
+ if (empty($projects[$phid])) {
+ $invalid[] = $phid;
+ unset($phids[$phid]);
+ }
+ }
+
+ if ($invalid) {
+ $this->logEffect(self::DO_INVALID, $invalid);
+ }
+
+ if (!$phids) {
+ return;
+ }
+
+ $project_type = PhabricatorProjectObjectHasProjectEdgeType::EDGECONST;
+
+ $current = $adapter->loadEdgePHIDs($project_type);
+
+ if ($is_add) {
+ $already = array();
+ foreach ($phids as $phid) {
+ if (isset($current[$phid])) {
+ $already[$phid] = $phid;
+ unset($phids[$phid]);
+ }
+ }
+
+ if ($already) {
+ $this->logEffect(self::DO_ALREADY_ASSOCIATED, $already);
+ }
+ } else {
+ $already = array();
+ foreach ($phids as $phid) {
+ if (empty($current[$phid])) {
+ $already[$phid] = $phid;
+ unset($phids[$phid]);
+ }
+ }
+
+ if ($already) {
+ $this->logEffect(self::DO_ALREADY_UNASSOCIATED, $already);
+ }
+ }
+
+ if (!$phids) {
+ return;
+ }
+
+ if ($is_add) {
+ $kind = '+';
+ } else {
+ $kind = '-';
+ }
+
+ $xaction = $adapter->newTransaction()
+ ->setTransactionType(PhabricatorTransactions::TYPE_EDGE)
+ ->setMetadataValue('edge:type', $project_type)
+ ->setNewValue(
+ array(
+ $kind => $phids,
+ ));
+
+ $adapter->queueTransaction($xaction);
+
+ if ($is_add) {
+ $this->logEffect(self::DO_ADD_PROJECTS, $phids);
+ } else {
+ $this->logEffect(self::DO_REMOVE_PROJECTS, $phids);
+ }
+ }
+
+ protected function getActionEffectMap() {
+ return array(
+ self::DO_NO_TARGETS => array(
+ 'icon' => 'fa-ban',
+ 'color' => 'grey',
+ 'name' => pht('No Targets'),
+ ),
+ self::DO_INVALID => array(
+ 'icon' => 'fa-ban',
+ 'color' => 'red',
+ 'name' => pht('Invalid Targets'),
+ ),
+ self::DO_ALREADY_ASSOCIATED => array(
+ 'icon' => 'fa-chevron-right',
+ 'color' => 'grey',
+ 'name' => pht('Already Associated'),
+ ),
+ self::DO_ALREADY_UNASSOCIATED => array(
+ 'icon' => 'fa-chevron-right',
+ 'color' => 'grey',
+ 'name' => pht('Already Unassociated'),
+ ),
+ self::DO_ADD_PROJECTS => array(
+ 'icon' => 'fa-briefcase',
+ 'color' => 'green',
+ 'name' => pht('Added Projects'),
+ ),
+ self::DO_REMOVE_PROJECTS => array(
+ 'icon' => 'fa-minus-circle',
+ 'color' => 'green',
+ 'name' => pht('Removed Projects'),
+ ),
+ );
+ }
+
+ public function renderActionEffectDescription($type, $data) {
+ switch ($type) {
+ case self::DO_NO_TARGETS:
+ return pht('Rule lists no projects.');
+ case self::DO_INVALID:
+ return pht(
+ 'Declined to act on %s invalid project(s): %s.',
+ new PhutilNumber(count($data)),
+ $this->renderHandleList($data));
+ case self::DO_ALREADY_ASSOCIATED:
+ return pht(
+ '%s project(s) are already associated: %s.',
+ new PhutilNumber(count($data)),
+ $this->renderHandleList($data));
+ case self::DO_ALREADY_UNASSOCIATED:
+ return pht(
+ '%s project(s) are not associated: %s.',
+ new PhutilNumber(count($data)),
+ $this->renderHandleList($data));
+ case self::DO_ADD_PROJECTS:
+ return pht(
+ 'Added %s project(s): %s.',
+ new PhutilNumber(count($data)),
+ $this->renderHandleList($data));
+ case self::DO_REMOVE_PROJECTS:
+ return pht(
+ 'Removed %s project(s): %s.',
+ new PhutilNumber(count($data)),
+ $this->renderHandleList($data));
+ }
+ }
+
+}
diff --git a/src/applications/project/herald/PhabricatorProjectRemoveHeraldAction.php b/src/applications/project/herald/PhabricatorProjectRemoveHeraldAction.php
new file mode 100644
--- /dev/null
+++ b/src/applications/project/herald/PhabricatorProjectRemoveHeraldAction.php
@@ -0,0 +1,28 @@
+<?php
+
+final class PhabricatorProjectRemoveHeraldAction
+ extends PhabricatorProjectHeraldAction {
+
+ const ACTIONCONST = 'projects.remove';
+
+ public function getHeraldActionName() {
+ return pht('Remove projects');
+ }
+
+ public function applyEffect($object, HeraldEffect $effect) {
+ return $this->applyProjects($effect->getTarget(), $is_add = false);
+ }
+
+ public function getHeraldActionStandardType() {
+ return self::STANDARD_PHID_LIST;
+ }
+
+ protected function getDatasource() {
+ return new PhabricatorProjectDatasource();
+ }
+
+ public function renderActionDescription($value) {
+ return pht('Remove projects: %s.', $this->renderHandleList($value));
+ }
+
+}
diff --git a/src/infrastructure/internationalization/translation/PhabricatorUSEnglishTranslation.php b/src/infrastructure/internationalization/translation/PhabricatorUSEnglishTranslation.php
--- a/src/infrastructure/internationalization/translation/PhabricatorUSEnglishTranslation.php
+++ b/src/infrastructure/internationalization/translation/PhabricatorUSEnglishTranslation.php
@@ -1303,6 +1303,26 @@
'preferences: %2$s.',
),
+ '%s project(s) are not associated: %s.' => array(
+ 'A project is not associated: %2$s.',
+ 'Projects are not associated: %2$s.',
+ ),
+
+ '%s project(s) are already associated: %s.' => array(
+ 'A project is already associated: %2$s.',
+ 'Projects are already associated: %2$s.',
+ ),
+
+ 'Added %s project(s): %s.' => array(
+ 'Added a project: %2$s.',
+ 'Added projects: %2$s.',
+ ),
+
+ 'Removed %s project(s): %s.' => array(
+ 'Removed a project: %2$s.',
+ 'Removed projects: %2$s.',
+ ),
+
);
}
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Wed, Oct 23, 5:02 PM (3 w, 4 d ago)
Storage Engine
blob
Storage Format
Encrypted (AES-256-CBC)
Storage Handle
6725141
Default Alt Text
D13705.id.diff (16 KB)
Attached To
Mode
D13705: Modularize "add projects" and "remove projects" Herald actions
Attached
Detach File
Event Timeline
Log In to Comment