@recaptime-dev's working patches + fork for Phorge, a community fork of Phabricator. (Upstream dev and stable branches are at upstream/main and upstream/stable respectively.) hq.recaptime.dev/wiki/Phorge
phorge phabricator
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Share target filtering code in HeraldAction

Ref T8726. This shares some target filtering code with the base class.

+116 -449
-1
src/applications/differential/herald/DifferentialReviewersAddBlockingReviewersHeraldAction.php
··· 30 30 } 31 31 32 32 } 33 -
-1
src/applications/differential/herald/DifferentialReviewersAddBlockingSelfHeraldAction.php
··· 27 27 } 28 28 29 29 } 30 -
-1
src/applications/differential/herald/DifferentialReviewersAddReviewersHeraldAction.php
··· 30 30 } 31 31 32 32 } 33 -
-1
src/applications/differential/herald/DifferentialReviewersAddSelfHeraldAction.php
··· 27 27 } 28 28 29 29 } 30 -
+12 -103
src/applications/differential/herald/DifferentialReviewersHeraldAction.php
··· 3 3 abstract class DifferentialReviewersHeraldAction 4 4 extends HeraldAction { 5 5 6 - const DO_NO_TARGETS = 'do.no-targets'; 7 6 const DO_AUTHORS = 'do.authors'; 8 - const DO_INVALID = 'do.invalid'; 9 - const DO_ALREADY_REVIEWERS = 'do.already-reviewers'; 10 - const DO_PERMISSION = 'do.permission'; 11 7 const DO_ADD_REVIEWERS = 'do.add-reviewers'; 12 8 const DO_ADD_BLOCKING_REVIEWERS = 'do.add-blocking-reviewers'; 13 9 ··· 24 20 $object = $adapter->getObject(); 25 21 26 22 $phids = array_fuse($phids); 27 - if (!$phids) { 28 - $this->logEffect(self::DO_NO_TARGETS); 29 - return; 30 - } 31 23 32 24 // Don't try to add revision authors as reviewers. 33 25 $authors = array(); ··· 40 32 41 33 if ($authors) { 42 34 $this->logEffect(self::DO_AUTHORS, $authors); 43 - } 44 - 45 - if (!$phids) { 46 - return; 35 + if (!$phids) { 36 + return; 37 + } 47 38 } 48 39 49 40 $reviewers = $object->getReviewerStatus(); ··· 58 49 $new_strength = DifferentialReviewerStatus::getStatusStrength( 59 50 $new_status); 60 51 61 - $already = array(); 52 + $current = array(); 62 53 foreach ($phids as $phid) { 63 54 if (!isset($reviewers[$phid])) { 64 55 continue; ··· 72 63 continue; 73 64 } 74 65 75 - $already[] = $phid; 76 - unset($phids[$phid]); 77 - } 78 - 79 - if ($already) { 80 - $this->logEffect(self::DO_ALREADY_REVIEWERS, $already); 81 - } 82 - 83 - if (!$phids) { 84 - return; 85 - } 86 - 87 - $targets = id(new PhabricatorObjectQuery()) 88 - ->setViewer(PhabricatorUser::getOmnipotentUser()) 89 - ->withPHIDs($phids) 90 - ->execute(); 91 - $targets = mpull($targets, null, 'getPHID'); 92 - 93 - $invalid = array(); 94 - foreach ($phids as $phid) { 95 - if (empty($targets[$phid])) { 96 - $invalid[] = $phid; 97 - unset($phids[$phid]); 98 - } 66 + $current[] = $phid; 99 67 } 100 68 101 - if ($invalid) { 102 - $this->logEffect(self::DO_INVALID, $invalid); 103 - } 69 + $allowed_types = array( 70 + PhabricatorPeopleUserPHIDType::TYPECONST, 71 + PhabricatorProjectProjectPHIDType::TYPECONST, 72 + ); 104 73 105 - if (!$phids) { 74 + $targets = $this->loadStandardTargets($phids, $allowed_types, $current); 75 + if (!$targets) { 106 76 return; 107 77 } 108 78 109 - $no_access = array(); 110 - foreach ($targets as $phid => $target) { 111 - if (!($target instanceof PhabricatorUser)) { 112 - continue; 113 - } 114 - 115 - $can_view = PhabricatorPolicyFilter::hasCapability( 116 - $target, 117 - $object, 118 - PhabricatorPolicyCapability::CAN_VIEW); 119 - if ($can_view) { 120 - continue; 121 - } 122 - 123 - $no_access[] = $phid; 124 - unset($phids[$phid]); 125 - } 126 - 127 - if ($no_access) { 128 - $this->logEffect(self::DO_PERMISSION, $no_access); 129 - } 130 - 131 - if (!$phids) { 132 - return; 133 - } 79 + $phids = array_fuse(array_keys($targets)); 134 80 135 81 $value = array(); 136 82 foreach ($phids as $phid) { ··· 162 108 163 109 protected function getActionEffectMap() { 164 110 return array( 165 - self::DO_NO_TARGETS => array( 166 - 'icon' => 'fa-ban', 167 - 'color' => 'grey', 168 - 'name' => pht('No Targets'), 169 - ), 170 111 self::DO_AUTHORS => array( 171 112 'icon' => 'fa-user', 172 113 'color' => 'grey', 173 114 'name' => pht('Revision Author'), 174 115 ), 175 - self::DO_INVALID => array( 176 - 'icon' => 'fa-ban', 177 - 'color' => 'red', 178 - 'name' => pht('Invalid Targets'), 179 - ), 180 - self::DO_ALREADY_REVIEWERS => array( 181 - 'icon' => 'fa-user', 182 - 'color' => 'grey', 183 - 'name' => pht('Already Reviewers'), 184 - ), 185 - self::DO_PERMISSION => array( 186 - 'icon' => 'fa-ban', 187 - 'color' => 'red', 188 - 'name' => pht('No Permission'), 189 - ), 190 116 self::DO_ADD_REVIEWERS => array( 191 117 'icon' => 'fa-user', 192 118 'color' => 'green', ··· 202 128 203 129 protected function renderActionEffectDescription($type, $data) { 204 130 switch ($type) { 205 - case self::DO_NO_TARGETS: 206 - return pht('Rule lists no targets.'); 207 131 case self::DO_AUTHORS: 208 132 return pht( 209 133 'Declined to add revision author as reviewer: %s.', 210 - $this->renderHandleList($data)); 211 - case self::DO_INVALID: 212 - return pht( 213 - 'Declined to act on %s invalid target(s): %s.', 214 - new PhutilNumber(count($data)), 215 - $this->renderHandleList($data)); 216 - case self::DO_ALREADY_REVIEWERS: 217 - return pht( 218 - '%s target(s) were already reviewers: %s.', 219 - new PhutilNumber(count($data)), 220 - $this->renderHandleList($data)); 221 - case self::DO_PERMISSION: 222 - return pht( 223 - '%s target(s) do not have permission to see the revision: %s.', 224 - new PhutilNumber(count($data)), 225 134 $this->renderHandleList($data)); 226 135 case self::DO_ADD_REVIEWERS: 227 136 return pht(
+7 -43
src/applications/harbormaster/herald/HarbormasterRunBuildPlansHeraldAction.php
··· 3 3 final class HarbormasterRunBuildPlansHeraldAction 4 4 extends HeraldAction { 5 5 6 - const DO_NO_TARGETS = 'do.no-targets'; 7 - const DO_INVALID = 'do.invalid'; 8 6 const DO_BUILD = 'do.build'; 9 7 10 8 const ACTIONCONST = 'harbormaster.build'; ··· 21 19 protected function applyBuilds(array $phids) { 22 20 $adapter = $this->getAdapter(); 23 21 24 - $phids = array_fuse($phids); 25 - if (!$phids) { 26 - $this->logEffect(self::DO_NO_TARGETS); 27 - return; 28 - } 29 - 30 - $plans = id(new HarbormasterBuildPlanQuery()) 31 - ->setViewer(PhabricatorUser::getOmnipotentUser()) 32 - ->withPHIDs($phids) 33 - ->execute(); 34 - $plans = mpull($plans, null, 'getPHID'); 35 - 36 - $invalid = array(); 37 - foreach ($phids as $phid) { 38 - if (empty($plans[$phid])) { 39 - $invalid[] = $phid; 40 - unset($plans[$phid]); 41 - } 42 - } 43 - 44 - if ($invalid) { 45 - $this->logEffect(self::DO_INVALID, $phids); 46 - } 22 + $allowed_types = array( 23 + HarbormasterBuildPlanPHIDType::TYPECONST, 24 + ); 47 25 48 - if (!$phids) { 26 + $targets = $this->loadStandardTargets($phids, $allowed_types, array()); 27 + if (!$targets) { 49 28 return; 50 29 } 30 + 31 + $phids = array_fuse(array_keys($targets)); 51 32 52 33 foreach ($phids as $phid) { 53 34 $adapter->queueHarbormasterBuildPlanPHID($phid); ··· 58 39 59 40 protected function getActionEffectMap() { 60 41 return array( 61 - self::DO_NO_TARGETS => array( 62 - 'icon' => 'fa-ban', 63 - 'color' => 'grey', 64 - 'name' => pht('No Targets'), 65 - ), 66 - self::DO_INVALID => array( 67 - 'icon' => 'fa-ban', 68 - 'color' => 'red', 69 - 'name' => pht('Invalid Targets'), 70 - ), 71 42 self::DO_BUILD => array( 72 43 'icon' => 'fa-play', 73 44 'color' => 'green', ··· 78 49 79 50 protected function renderActionEffectDescription($type, $data) { 80 51 switch ($type) { 81 - case self::DO_NO_TARGETS: 82 - return pht('Rule lists no targets.'); 83 - case self::DO_INVALID: 84 - return pht( 85 - '%s build plan(s) are not valid: %s.', 86 - new PhutilNumber(count($data)), 87 - $this->renderHandleList($data)); 88 52 case self::DO_BUILD: 89 53 return pht( 90 54 'Started %s build(s): %s.',
+7 -71
src/applications/legalpad/herald/LegalpadRequireSignatureHeraldAction.php
··· 3 3 final class LegalpadRequireSignatureHeraldAction 4 4 extends HeraldAction { 5 5 6 - const DO_NO_TARGETS = 'do.no-targets'; 7 - const DO_ALREADY_REQUIRED = 'do.already-required'; 8 - const DO_INVALID = 'do.invalid'; 9 6 const DO_SIGNED = 'do.signed'; 10 7 const DO_REQUIRED = 'do.required'; 11 8 ··· 24 21 25 22 protected function applyRequire(array $phids) { 26 23 $adapter = $this->getAdapter(); 27 - $edgetype_legal = LegalpadObjectNeedsSignatureEdgeType::EDGECONST; 28 24 29 - $phids = array_fuse($phids); 30 - 31 - if (!$phids) { 32 - $this->logEffect(self::DO_NO_TARGETS); 33 - return; 34 - } 35 - 25 + $edgetype_legal = LegalpadObjectNeedsSignatureEdgeType::EDGECONST; 36 26 $current = $adapter->loadEdgePHIDs($edgetype_legal); 37 27 38 - $already = array(); 39 - foreach ($phids as $phid) { 40 - if (isset($current[$phid])) { 41 - $already[] = $phid; 42 - unset($phids[$phid]); 43 - } 44 - } 28 + $allowed_types = array( 29 + PhabricatorLegalpadDocumentPHIDType::TYPECONST, 30 + ); 45 31 46 - if ($already) { 47 - $this->logEffect(self::DO_ALREADY_REQUIRED, $phids); 48 - } 49 - 50 - if (!$phids) { 32 + $targets = $this->loadStandardTargets($phids, $allowed_types, $current); 33 + if (!$targets) { 51 34 return; 52 35 } 53 36 54 - $documents = id(new LegalpadDocumentQuery()) 55 - ->setViewer(PhabricatorUser::getOmnipotentUser()) 56 - ->withPHIDs($phids) 57 - ->execute(); 58 - $documents = mpull($documents, null, 'getPHID'); 59 - 60 - $invalid = array(); 61 - foreach ($phids as $phid) { 62 - if (empty($documents[$phid])) { 63 - $invalid[] = $phid; 64 - unset($documents[$phid]); 65 - } 66 - } 67 - 68 - if ($invalid) { 69 - $this->logEffect(self::DO_INVALID, $phids); 70 - } 71 - 72 - if (!$phids) { 73 - return; 74 - } 37 + $phids = array_fuse(array_keys($targets)); 75 38 76 39 $object = $adapter->getObject(); 77 40 $author_phid = $object->getAuthorPHID(); ··· 114 77 115 78 protected function getActionEffectMap() { 116 79 return array( 117 - self::DO_NO_TARGETS => array( 118 - 'icon' => 'fa-ban', 119 - 'color' => 'grey', 120 - 'name' => pht('No Targets'), 121 - ), 122 - self::DO_INVALID => array( 123 - 'icon' => 'fa-ban', 124 - 'color' => 'red', 125 - 'name' => pht('Invalid Targets'), 126 - ), 127 - self::DO_ALREADY_REQUIRED => array( 128 - 'icon' => 'fa-terminal', 129 - 'color' => 'grey', 130 - 'name' => pht('Already Required'), 131 - ), 132 80 self::DO_SIGNED => array( 133 81 'icon' => 'fa-terminal', 134 82 'color' => 'green', ··· 144 92 145 93 protected function renderActionEffectDescription($type, $data) { 146 94 switch ($type) { 147 - case self::DO_NO_TARGETS: 148 - return pht('Rule lists no targets.'); 149 - case self::DO_INVALID: 150 - return pht( 151 - '%s document(s) are not valid: %s.', 152 - new PhutilNumber(count($data)), 153 - $this->renderHandleList($data)); 154 - case self::DO_ALREADY_REQUIRED: 155 - return pht( 156 - '%s document signature(s) are already required: %s.', 157 - new PhutilNumber(count($data)), 158 - $this->renderHandleList($data)); 159 95 case self::DO_SIGNED: 160 96 return pht( 161 97 '%s document(s) are already signed: %s.',
+8 -63
src/applications/maniphest/herald/ManiphestTaskAssignHeraldAction.php
··· 3 3 abstract class ManiphestTaskAssignHeraldAction 4 4 extends HeraldAction { 5 5 6 - const DO_EMPTY = 'do.send'; 7 - const DO_ALREADY = 'do.already'; 8 - const DO_INVALID = 'do.invalid'; 9 - const DO_PERMISSION = 'do.permission'; 10 6 const DO_ASSIGN = 'do.assign'; 11 7 12 8 public function supportsObject($object) { ··· 18 14 } 19 15 20 16 protected function applyAssign(array $phids) { 21 - $phid = head($phids); 22 - 23 - if (!$phid) { 24 - $this->logEffect(self::DO_EMPTY); 25 - return; 26 - } 27 - 28 17 $adapter = $this->getAdapter(); 29 18 $object = $adapter->getObject(); 30 19 31 - if ($object->getOwnerPHID() == $phid) { 32 - $this->logEffect(self::DO_ALREADY, array($phid)); 33 - return; 34 - } 20 + $current = array($object->getOwnerPHID()); 35 21 36 - $user = id(new PhabricatorPeopleQuery()) 37 - ->setViewer(PhabricatorUser::getOmnipotentUser()) 38 - ->withPHIDs(array($phid)) 39 - ->executeOne(); 40 - if (!$user) { 41 - $this->logEffect(self::DO_INVALID, array($phid)); 22 + $allowed_types = array( 23 + PhabricatorPeopleUserPHIDType::TYPECONST, 24 + ); 25 + 26 + $targets = $this->loadStandardTargets($phids, $allowed_types, $current); 27 + if (!$targets) { 42 28 return; 43 29 } 44 30 45 - $can_view = PhabricatorPolicyFilter::hasCapability( 46 - $user, 47 - $object, 48 - PhabricatorPolicyCapability::CAN_VIEW); 49 - if (!$can_view) { 50 - $this->logEffect(self::DO_PERMISSION, array($phid)); 51 - return; 52 - } 31 + $phid = head_key($targets); 53 32 54 33 $xaction = $adapter->newTransaction() 55 34 ->setTransactionType(ManiphestTransaction::TYPE_OWNER) ··· 62 41 63 42 protected function getActionEffectMap() { 64 43 return array( 65 - self::DO_EMPTY => array( 66 - 'icon' => 'fa-ban', 67 - 'color' => 'grey', 68 - 'name' => pht('Empty Action'), 69 - ), 70 - self::DO_ALREADY => array( 71 - 'icon' => 'fa-user', 72 - 'color' => 'grey', 73 - 'name' => pht('Already Assigned'), 74 - ), 75 - self::DO_INVALID => array( 76 - 'icon' => 'fa-ban', 77 - 'color' => 'red', 78 - 'name' => pht('Invalid Owner'), 79 - ), 80 - self::DO_PERMISSION => array( 81 - 'icon' => 'fa-ban', 82 - 'color' => 'red', 83 - 'name' => pht('No Permission'), 84 - ), 85 44 self::DO_ASSIGN => array( 86 45 'icon' => 'fa-user', 87 46 'color' => 'green', ··· 92 51 93 52 protected function renderActionEffectDescription($type, $data) { 94 53 switch ($type) { 95 - case self::DO_EMPTY: 96 - return pht('Action lists no user to assign.'); 97 - case self::DO_ALREADY: 98 - return pht( 99 - 'User is already task owner: %s.', 100 - $this->renderHandleList($data)); 101 - case self::DO_INVALID: 102 - return pht( 103 - 'User is invalid: %s.', 104 - $this->renderHandleList($data)); 105 - case self::DO_PERMISSION: 106 - return pht( 107 - 'User does not have permission to see task: %s.', 108 - $this->renderHandleList($data)); 109 54 case self::DO_ASSIGN: 110 55 return pht( 111 56 'Assigned task to: %s.',
+16
src/applications/metamta/herald/PhabricatorMetaMTAEmailHeraldAction.php
··· 24 24 protected function applyEmail(array $phids, $force) { 25 25 $adapter = $this->getAdapter(); 26 26 27 + $allowed_types = array( 28 + PhabricatorPeopleUserPHIDType::TYPECONST, 29 + PhabricatorProjectProjectPHIDType::TYPECONST, 30 + ); 31 + 32 + // There's no stateful behavior for this action: we always just send an 33 + // email. 34 + $current = array(); 35 + 36 + $targets = $this->loadStandardTargets($phids, $allowed_types, $current); 37 + if (!$targets) { 38 + return; 39 + } 40 + 41 + $phids = array_fuse(array_keys($targets)); 42 + 27 43 foreach ($phids as $phid) { 28 44 $adapter->addEmailPHID($phid, $force); 29 45 }
+12 -67
src/applications/project/herald/PhabricatorProjectHeraldAction.php
··· 3 3 abstract class PhabricatorProjectHeraldAction 4 4 extends HeraldAction { 5 5 6 - const DO_NO_TARGETS = 'do.no-targets'; 7 - const DO_INVALID = 'do.invalid'; 8 - const DO_ALREADY_ASSOCIATED = 'do.already-associated'; 9 - const DO_ALREADY_UNASSOCIATED = 'do.already-unassociated'; 10 6 const DO_ADD_PROJECTS = 'do.add-projects'; 11 7 const DO_REMOVE_PROJECTS = 'do.remove-projects'; 12 8 ··· 23 19 } 24 20 25 21 protected function applyProjects(array $phids, $is_add) { 26 - $phids = array_fuse($phids); 27 22 $adapter = $this->getAdapter(); 28 23 29 - if (!$phids) { 30 - $this->logEffect(self::DO_NO_TARGETS); 31 - return; 32 - } 33 - 34 - $projects = id(new PhabricatorProjectQuery()) 35 - ->setViewer(PhabricatorUser::getOmnipotentUser()) 36 - ->withPHIDs($phids) 37 - ->execute(); 38 - $projects = mpull($projects, null, 'getPHID'); 39 - 40 - $invalid = array(); 41 - foreach ($phids as $phid) { 42 - if (empty($projects[$phid])) { 43 - $invalid[] = $phid; 44 - unset($phids[$phid]); 45 - } 46 - } 24 + $allowed_types = array( 25 + PhabricatorProjectProjectPHIDType::TYPECONST, 26 + ); 47 27 48 - if ($invalid) { 49 - $this->logEffect(self::DO_INVALID, $invalid); 50 - } 28 + // Detection of "No Effect" is a bit tricky for this action, so just do it 29 + // manually a little later on. 30 + $current = array(); 51 31 52 - if (!$phids) { 32 + $targets = $this->loadStandardTargets($phids, $allowed_types, $current); 33 + if (!$targets) { 53 34 return; 54 35 } 55 36 56 - $project_type = PhabricatorProjectObjectHasProjectEdgeType::EDGECONST; 37 + $phids = array_fuse(array_keys($targets)); 57 38 39 + $project_type = PhabricatorProjectObjectHasProjectEdgeType::EDGECONST; 58 40 $current = $adapter->loadEdgePHIDs($project_type); 59 41 60 42 if ($is_add) { ··· 67 49 } 68 50 69 51 if ($already) { 70 - $this->logEffect(self::DO_ALREADY_ASSOCIATED, $already); 52 + $this->logEffect(self::DO_STANDARD_NO_EFFECT, $already); 71 53 } 72 54 } else { 73 55 $already = array(); ··· 79 61 } 80 62 81 63 if ($already) { 82 - $this->logEffect(self::DO_ALREADY_UNASSOCIATED, $already); 64 + $this->logEffect(self::DO_STANDARD_NO_EFFECT, $already); 83 65 } 84 66 } 85 67 ··· 112 94 113 95 protected function getActionEffectMap() { 114 96 return array( 115 - self::DO_NO_TARGETS => array( 116 - 'icon' => 'fa-ban', 117 - 'color' => 'grey', 118 - 'name' => pht('No Targets'), 119 - ), 120 - self::DO_INVALID => array( 121 - 'icon' => 'fa-ban', 122 - 'color' => 'red', 123 - 'name' => pht('Invalid Targets'), 124 - ), 125 - self::DO_ALREADY_ASSOCIATED => array( 126 - 'icon' => 'fa-chevron-right', 127 - 'color' => 'grey', 128 - 'name' => pht('Already Associated'), 129 - ), 130 - self::DO_ALREADY_UNASSOCIATED => array( 131 - 'icon' => 'fa-chevron-right', 132 - 'color' => 'grey', 133 - 'name' => pht('Already Unassociated'), 134 - ), 135 97 self::DO_ADD_PROJECTS => array( 136 98 'icon' => 'fa-briefcase', 137 99 'color' => 'green', ··· 147 109 148 110 protected function renderActionEffectDescription($type, $data) { 149 111 switch ($type) { 150 - case self::DO_NO_TARGETS: 151 - return pht('Rule lists no projects.'); 152 - case self::DO_INVALID: 153 - return pht( 154 - 'Declined to act on %s invalid project(s): %s.', 155 - new PhutilNumber(count($data)), 156 - $this->renderHandleList($data)); 157 - case self::DO_ALREADY_ASSOCIATED: 158 - return pht( 159 - '%s project(s) are already associated: %s.', 160 - new PhutilNumber(count($data)), 161 - $this->renderHandleList($data)); 162 - case self::DO_ALREADY_UNASSOCIATED: 163 - return pht( 164 - '%s project(s) are not associated: %s.', 165 - new PhutilNumber(count($data)), 166 - $this->renderHandleList($data)); 167 112 case self::DO_ADD_PROJECTS: 168 113 return pht( 169 114 'Added %s project(s): %s.',
+34 -90
src/applications/subscriptions/herald/PhabricatorSubscriptionsHeraldAction.php
··· 3 3 abstract class PhabricatorSubscriptionsHeraldAction 4 4 extends HeraldAction { 5 5 6 - const DO_NO_TARGETS = 'do.no-targets'; 7 6 const DO_PREVIOUSLY_UNSUBSCRIBED = 'do.previously-unsubscribed'; 8 - const DO_INVALID = 'do.invalid'; 9 7 const DO_AUTOSUBSCRIBED = 'do.autosubscribed'; 10 - const DO_ALREADY_SUBSCRIBED = 'do.already-subscribed'; 11 - const DO_ALREADY_UNSUBSCRIBED = 'do.already-unsubscribed'; 12 8 const DO_SUBSCRIBED = 'do.subscribed'; 13 9 const DO_UNSUBSCRIBED = 'do.unsubscribed'; 14 10 ··· 23 19 protected function applySubscribe(array $phids, $is_add) { 24 20 $adapter = $this->getAdapter(); 25 21 26 - if ($is_add) { 27 - $kind = '+'; 28 - } else { 29 - $kind = '-'; 30 - } 22 + $allowed_types = array( 23 + PhabricatorPeopleUserPHIDType::TYPECONST, 24 + PhabricatorProjectProjectPHIDType::TYPECONST, 25 + ); 26 + 27 + // Evaluating "No Effect" is a bit tricky for this rule type, so just 28 + // do it manually below. 29 + $current = array(); 31 30 32 - $subscriber_phids = array_fuse($phids); 33 - if (!$subscriber_phids) { 34 - $this->logEffect(self::DO_NO_TARGETS); 31 + $targets = $this->loadStandardTargets($phids, $allowed_types, $current); 32 + if (!$targets) { 35 33 return; 36 34 } 35 + 36 + $phids = array_fuse(array_keys($targets)); 37 37 38 38 // The "Add Subscribers" rule only adds subscribers who haven't previously 39 39 // unsubscribed from the object explicitly. Filter these subscribers out ··· 43 43 PhabricatorObjectHasUnsubscriberEdgeType::EDGECONST); 44 44 45 45 foreach ($unsubscribed as $phid) { 46 - if (isset($subscriber_phids[$phid])) { 46 + if (isset($phids[$phid])) { 47 47 $unsubscribed[$phid] = $phid; 48 - unset($subscriber_phids[$phid]); 48 + unset($phids[$phid]); 49 49 } 50 50 } 51 51 ··· 56 56 } 57 57 } 58 58 59 - if (!$subscriber_phids) { 60 - return; 61 - } 62 - 63 - // Filter out PHIDs which aren't valid subscribers. Lower levels of the 64 - // stack will fail loudly if we try to add subscribers with invalid PHIDs 65 - // or unknown PHID types, so drop them here. 66 - $invalid = array(); 67 - foreach ($subscriber_phids as $phid) { 68 - $type = phid_get_type($phid); 69 - switch ($type) { 70 - case PhabricatorPeopleUserPHIDType::TYPECONST: 71 - case PhabricatorProjectProjectPHIDType::TYPECONST: 72 - break; 73 - default: 74 - $invalid[$phid] = $phid; 75 - unset($subscriber_phids[$phid]); 76 - break; 77 - } 78 - } 79 - 80 - if ($invalid) { 81 - $this->logEffect(self::DO_INVALID, array_values($invalid)); 82 - } 83 - 84 - if (!$subscriber_phids) { 59 + if (!$phids) { 85 60 return; 86 61 } 87 62 88 63 $auto = array(); 89 64 $object = $adapter->getObject(); 90 - foreach ($subscriber_phids as $phid) { 65 + foreach ($phids as $phid) { 91 66 if ($object->isAutomaticallySubscribed($phid)) { 92 67 $auto[$phid] = $phid; 93 - unset($subscriber_phids[$phid]); 68 + unset($phids[$phid]); 94 69 } 95 70 } 96 71 ··· 98 73 $this->logEffect(self::DO_AUTOSUBSCRIBED, array_values($auto)); 99 74 } 100 75 101 - if (!$subscriber_phids) { 76 + if (!$phids) { 102 77 return; 103 78 } 104 79 ··· 107 82 108 83 if ($is_add) { 109 84 $already = array(); 110 - foreach ($subscriber_phids as $phid) { 85 + foreach ($phids as $phid) { 111 86 if (isset($current[$phid])) { 112 87 $already[$phid] = $phid; 113 - unset($subscriber_phids[$phid]); 88 + unset($phids[$phid]); 114 89 } 115 90 } 116 91 117 92 if ($already) { 118 - $this->logEffect(self::DO_ALREADY_SUBSCRIBED, $already); 93 + $this->logEffect(self::DO_STANDARD_NO_EFFECT, $already); 119 94 } 120 95 } else { 121 96 $already = array(); 122 - foreach ($subscriber_phids as $phid) { 97 + foreach ($phids as $phid) { 123 98 if (empty($current[$phid])) { 124 99 $already[$phid] = $phid; 125 - unset($subscriber_phids[$phid]); 100 + unset($phids[$phid]); 126 101 } 127 102 } 128 103 129 104 if ($already) { 130 - $this->logEffect(self::DO_ALREADY_UNSUBSCRIBED, $already); 105 + $this->logEffect(self::DO_STANDARD_NO_EFFECT, $already); 131 106 } 132 107 } 133 108 134 - if (!$subscriber_phids) { 109 + if (!$phids) { 135 110 return; 136 111 } 137 112 113 + if ($is_add) { 114 + $kind = '+'; 115 + } else { 116 + $kind = '-'; 117 + } 118 + 138 119 $xaction = $adapter->newTransaction() 139 120 ->setTransactionType(PhabricatorTransactions::TYPE_SUBSCRIBERS) 140 121 ->setNewValue( 141 122 array( 142 - $kind => $subscriber_phids, 123 + $kind => $phids, 143 124 )); 144 125 145 126 $adapter->queueTransaction($xaction); 146 127 147 128 if ($is_add) { 148 - $this->logEffect(self::DO_SUBSCRIBED, $subscriber_phids); 129 + $this->logEffect(self::DO_SUBSCRIBED, $phids); 149 130 } else { 150 - $this->logEffect(self::DO_UNSUBSCRIBED, $subscriber_phids); 131 + $this->logEffect(self::DO_UNSUBSCRIBED, $phids); 151 132 } 152 133 } 153 134 154 135 protected function getActionEffectMap() { 155 136 return array( 156 - self::DO_NO_TARGETS => array( 157 - 'icon' => 'fa-ban', 158 - 'color' => 'grey', 159 - 'name' => pht('No Targets'), 160 - ), 161 137 self::DO_PREVIOUSLY_UNSUBSCRIBED => array( 162 138 'icon' => 'fa-minus-circle', 163 139 'color' => 'grey', ··· 168 144 'color' => 'grey', 169 145 'name' => pht('Automatically Subscribed'), 170 146 ), 171 - self::DO_INVALID => array( 172 - 'icon' => 'fa-ban', 173 - 'color' => 'red', 174 - 'name' => pht('Invalid Targets'), 175 - ), 176 - self::DO_ALREADY_SUBSCRIBED => array( 177 - 'icon' => 'fa-chevron-right', 178 - 'color' => 'grey', 179 - 'name' => pht('Already Subscribed'), 180 - ), 181 - self::DO_ALREADY_UNSUBSCRIBED => array( 182 - 'icon' => 'fa-chevron-right', 183 - 'color' => 'grey', 184 - 'name' => pht('Already Unsubscribed'), 185 - ), 186 147 self::DO_SUBSCRIBED => array( 187 148 'icon' => 'fa-envelope', 188 149 'color' => 'green', ··· 198 159 199 160 protected function renderActionEffectDescription($type, $data) { 200 161 switch ($type) { 201 - case self::DO_NO_TARGETS: 202 - return pht('Rule lists no targets.'); 203 162 case self::DO_PREVIOUSLY_UNSUBSCRIBED: 204 163 return pht( 205 164 'Declined to resubscribe %s target(s) because they previously '. 206 165 'unsubscribed: %s.', 207 166 new PhutilNumber(count($data)), 208 167 $this->renderHandleList($data)); 209 - case self::DO_INVALID: 210 - return pht( 211 - 'Declined to act on %s invalid target(s): %s.', 212 - new PhutilNumber(count($data)), 213 - $this->renderHandleList($data)); 214 168 case self::DO_AUTOSUBSCRIBED: 215 169 return pht( 216 170 '%s automatically subscribed target(s) were not affected: %s.', 217 - new PhutilNumber(count($data)), 218 - $this->renderHandleList($data)); 219 - case self::DO_ALREADY_SUBSCRIBED: 220 - return pht( 221 - '%s target(s) are already subscribed: %s.', 222 - new PhutilNumber(count($data)), 223 - $this->renderHandleList($data)); 224 - case self::DO_ALREADY_UNSUBSCRIBED: 225 - return pht( 226 - '%s target(s) are not subscribed: %s.', 227 171 new PhutilNumber(count($data)), 228 172 $this->renderHandleList($data)); 229 173 case self::DO_SUBSCRIBED:
+10 -8
src/applications/transactions/editor/PhabricatorApplicationTransactionEditor.php
··· 1706 1706 1707 1707 $lists = array($new_set, $new_add, $new_rem); 1708 1708 foreach ($lists as $list) { 1709 - $this->checkEdgeList($list); 1709 + $this->checkEdgeList($list, $xaction->getMetadataValue('edge:type')); 1710 1710 } 1711 1711 1712 1712 $result = array(); ··· 1743 1743 return $result; 1744 1744 } 1745 1745 1746 - private function checkEdgeList($list) { 1746 + private function checkEdgeList($list, $edge_type) { 1747 1747 if (!$list) { 1748 1748 return; 1749 1749 } ··· 1751 1751 if (phid_get_type($key) === PhabricatorPHIDConstants::PHID_TYPE_UNKNOWN) { 1752 1752 throw new Exception( 1753 1753 pht( 1754 - "Edge transactions must have destination PHIDs as in edge ". 1755 - "lists (found key '%s').", 1756 - $key)); 1754 + 'Edge transactions must have destination PHIDs as in edge '. 1755 + 'lists (found key "%s" on transaction of type "%s").', 1756 + $key, 1757 + $edge_type)); 1757 1758 } 1758 1759 if (!is_array($item) && $item !== $key) { 1759 1760 throw new Exception( 1760 1761 pht( 1761 - "Edge transactions must have PHIDs or edge specs as values ". 1762 - "(found value '%s').", 1763 - $item)); 1762 + 'Edge transactions must have PHIDs or edge specs as values '. 1763 + '(found value "%s" on transaction of type "%s").', 1764 + $item, 1765 + $edge_type)); 1764 1766 } 1765 1767 } 1766 1768 }
+10
src/infrastructure/internationalization/translation/PhabricatorUSEnglishTranslation.php
··· 1348 1348 'Added auditors: %2$s.', 1349 1349 ), 1350 1350 1351 + '%s target(s) do not have permission to see this object: %s.' => array( 1352 + 'A target does not have permission to see this object: %2$s.', 1353 + 'Targets do not have permission to see this object: %2$s.', 1354 + ), 1355 + 1356 + 'This action has no effect on %s target(s): %s.' => array( 1357 + 'This action has no effect on a target: %2$s.', 1358 + 'This action has no effect on targets: %2$s.', 1359 + ), 1360 + 1351 1361 ); 1352 1362 } 1353 1363