Modularize the Diffusion "Add Auditors" Herald action
Ref T8726.
This commit is contained in:
		
							
								
								
									
										13
									
								
								resources/sql/autopatches/20150803.herald.1.sql
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										13
									
								
								resources/sql/autopatches/20150803.herald.1.sql
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,13 @@
 | 
				
			|||||||
 | 
					UPDATE {$NAMESPACE}_herald.herald_action a
 | 
				
			||||||
 | 
					  JOIN {$NAMESPACE}_herald.herald_rule r
 | 
				
			||||||
 | 
					  ON a.ruleID = r.id
 | 
				
			||||||
 | 
					  SET a.action = 'diffusion.auditors.add'
 | 
				
			||||||
 | 
					  WHERE r.ruleType != 'personal'
 | 
				
			||||||
 | 
					  AND a.action = 'audit';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					UPDATE {$NAMESPACE}_herald.herald_action a
 | 
				
			||||||
 | 
					  JOIN {$NAMESPACE}_herald.herald_rule r
 | 
				
			||||||
 | 
					  ON a.ruleID = r.id
 | 
				
			||||||
 | 
					  SET a.action = 'diffusion.auditors.self.add'
 | 
				
			||||||
 | 
					  WHERE r.ruleType = 'personal'
 | 
				
			||||||
 | 
					  AND a.action = 'audit';
 | 
				
			||||||
@@ -498,6 +498,9 @@ phutil_register_library_map(array(
 | 
				
			|||||||
    'DifferentialUpdateUnitResultsConduitAPIMethod' => 'applications/differential/conduit/DifferentialUpdateUnitResultsConduitAPIMethod.php',
 | 
					    'DifferentialUpdateUnitResultsConduitAPIMethod' => 'applications/differential/conduit/DifferentialUpdateUnitResultsConduitAPIMethod.php',
 | 
				
			||||||
    'DifferentialViewPolicyField' => 'applications/differential/customfield/DifferentialViewPolicyField.php',
 | 
					    'DifferentialViewPolicyField' => 'applications/differential/customfield/DifferentialViewPolicyField.php',
 | 
				
			||||||
    'DiffusionAuditorDatasource' => 'applications/diffusion/typeahead/DiffusionAuditorDatasource.php',
 | 
					    'DiffusionAuditorDatasource' => 'applications/diffusion/typeahead/DiffusionAuditorDatasource.php',
 | 
				
			||||||
 | 
					    'DiffusionAuditorsAddAuditorsHeraldAction' => 'applications/diffusion/herald/DiffusionAuditorsAddAuditorsHeraldAction.php',
 | 
				
			||||||
 | 
					    'DiffusionAuditorsAddSelfHeraldAction' => 'applications/diffusion/herald/DiffusionAuditorsAddSelfHeraldAction.php',
 | 
				
			||||||
 | 
					    'DiffusionAuditorsHeraldAction' => 'applications/diffusion/herald/DiffusionAuditorsHeraldAction.php',
 | 
				
			||||||
    'DiffusionBranchQueryConduitAPIMethod' => 'applications/diffusion/conduit/DiffusionBranchQueryConduitAPIMethod.php',
 | 
					    'DiffusionBranchQueryConduitAPIMethod' => 'applications/diffusion/conduit/DiffusionBranchQueryConduitAPIMethod.php',
 | 
				
			||||||
    'DiffusionBranchTableController' => 'applications/diffusion/controller/DiffusionBranchTableController.php',
 | 
					    'DiffusionBranchTableController' => 'applications/diffusion/controller/DiffusionBranchTableController.php',
 | 
				
			||||||
    'DiffusionBranchTableView' => 'applications/diffusion/view/DiffusionBranchTableView.php',
 | 
					    'DiffusionBranchTableView' => 'applications/diffusion/view/DiffusionBranchTableView.php',
 | 
				
			||||||
@@ -4129,6 +4132,9 @@ phutil_register_library_map(array(
 | 
				
			|||||||
    'DifferentialUpdateUnitResultsConduitAPIMethod' => 'DifferentialConduitAPIMethod',
 | 
					    'DifferentialUpdateUnitResultsConduitAPIMethod' => 'DifferentialConduitAPIMethod',
 | 
				
			||||||
    'DifferentialViewPolicyField' => 'DifferentialCoreCustomField',
 | 
					    'DifferentialViewPolicyField' => 'DifferentialCoreCustomField',
 | 
				
			||||||
    'DiffusionAuditorDatasource' => 'PhabricatorTypeaheadCompositeDatasource',
 | 
					    'DiffusionAuditorDatasource' => 'PhabricatorTypeaheadCompositeDatasource',
 | 
				
			||||||
 | 
					    'DiffusionAuditorsAddAuditorsHeraldAction' => 'DiffusionAuditorsHeraldAction',
 | 
				
			||||||
 | 
					    'DiffusionAuditorsAddSelfHeraldAction' => 'DiffusionAuditorsHeraldAction',
 | 
				
			||||||
 | 
					    'DiffusionAuditorsHeraldAction' => 'HeraldAction',
 | 
				
			||||||
    'DiffusionBranchQueryConduitAPIMethod' => 'DiffusionQueryConduitAPIMethod',
 | 
					    'DiffusionBranchQueryConduitAPIMethod' => 'DiffusionQueryConduitAPIMethod',
 | 
				
			||||||
    'DiffusionBranchTableController' => 'DiffusionController',
 | 
					    'DiffusionBranchTableController' => 'DiffusionController',
 | 
				
			||||||
    'DiffusionBranchTableView' => 'DiffusionView',
 | 
					    'DiffusionBranchTableView' => 'DiffusionView',
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -877,30 +877,6 @@ final class PhabricatorAuditEditor
 | 
				
			|||||||
    HeraldAdapter $adapter,
 | 
					    HeraldAdapter $adapter,
 | 
				
			||||||
    HeraldTranscript $transcript) {
 | 
					    HeraldTranscript $transcript) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    $xactions = array();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    $audit_phids = $adapter->getAuditMap();
 | 
					 | 
				
			||||||
    foreach ($audit_phids as $phid => $rule_ids) {
 | 
					 | 
				
			||||||
      foreach ($rule_ids as $rule_id) {
 | 
					 | 
				
			||||||
        $this->addAuditReason(
 | 
					 | 
				
			||||||
          $phid,
 | 
					 | 
				
			||||||
          pht(
 | 
					 | 
				
			||||||
            '%s Triggered Audit',
 | 
					 | 
				
			||||||
            "H{$rule_id}"));
 | 
					 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    if ($audit_phids) {
 | 
					 | 
				
			||||||
      $xactions[] = id(new PhabricatorAuditTransaction())
 | 
					 | 
				
			||||||
        ->setTransactionType(PhabricatorAuditActionConstants::ADD_AUDITORS)
 | 
					 | 
				
			||||||
        ->setNewValue(array_fuse(array_keys($audit_phids)))
 | 
					 | 
				
			||||||
        ->setMetadataValue(
 | 
					 | 
				
			||||||
          'auditStatus',
 | 
					 | 
				
			||||||
          PhabricatorAuditStatusConstants::AUDIT_REQUIRED)
 | 
					 | 
				
			||||||
        ->setMetadataValue(
 | 
					 | 
				
			||||||
          'auditReasonMap', $this->auditReasonMap);
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    $limit = self::MAX_FILES_SHOWN_IN_EMAIL;
 | 
					    $limit = self::MAX_FILES_SHOWN_IN_EMAIL;
 | 
				
			||||||
    $files = $adapter->loadAffectedPaths();
 | 
					    $files = $adapter->loadAffectedPaths();
 | 
				
			||||||
    sort($files);
 | 
					    sort($files);
 | 
				
			||||||
@@ -914,7 +890,7 @@ final class PhabricatorAuditEditor
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
    $this->affectedFiles = implode("\n", $files);
 | 
					    $this->affectedFiles = implode("\n", $files);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    return $xactions;
 | 
					    return array();
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  private function isCommitMostlyImported(PhabricatorLiskDAO $object) {
 | 
					  private function isCommitMostlyImported(PhabricatorLiskDAO $object) {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -200,7 +200,7 @@ abstract class DifferentialReviewersHeraldAction
 | 
				
			|||||||
    );
 | 
					    );
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  public function renderActionEffectDescription($type, $data) {
 | 
					  protected function renderActionEffectDescription($type, $data) {
 | 
				
			||||||
    switch ($type) {
 | 
					    switch ($type) {
 | 
				
			||||||
      case self::DO_NO_TARGETS:
 | 
					      case self::DO_NO_TARGETS:
 | 
				
			||||||
        return pht('Rule lists no targets.');
 | 
					        return pht('Rule lists no targets.');
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -0,0 +1,33 @@
 | 
				
			|||||||
 | 
					<?php
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					final class DiffusionAuditorsAddAuditorsHeraldAction
 | 
				
			||||||
 | 
					  extends DiffusionAuditorsHeraldAction {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  const ACTIONCONST = 'diffusion.auditors.add';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  public function getHeraldActionName() {
 | 
				
			||||||
 | 
					    return pht('Add auditors');
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  public function supportsRuleType($rule_type) {
 | 
				
			||||||
 | 
					    return ($rule_type != HeraldRuleTypeConfig::RULE_TYPE_PERSONAL);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  public function applyEffect($object, HeraldEffect $effect) {
 | 
				
			||||||
 | 
					    $rule = $effect->getRule();
 | 
				
			||||||
 | 
					    return $this->applyAuditors($effect->getTarget(), $rule);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  public function getHeraldActionStandardType() {
 | 
				
			||||||
 | 
					    return self::STANDARD_PHID_LIST;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  protected function getDatasource() {
 | 
				
			||||||
 | 
					    return new DiffusionAuditorDatasource();
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  public function renderActionDescription($value) {
 | 
				
			||||||
 | 
					    return pht('Add auditors: %s.', $this->renderHandleList($value));
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -0,0 +1,30 @@
 | 
				
			|||||||
 | 
					<?php
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					final class DiffusionAuditorsAddSelfHeraldAction
 | 
				
			||||||
 | 
					  extends DiffusionAuditorsHeraldAction {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  const ACTIONCONST = 'diffusion.auditors.self.add';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  public function getHeraldActionName() {
 | 
				
			||||||
 | 
					    return pht('Add me as an auditor');
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  public function supportsRuleType($rule_type) {
 | 
				
			||||||
 | 
					    return ($rule_type == HeraldRuleTypeConfig::RULE_TYPE_PERSONAL);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  public function applyEffect($object, HeraldEffect $effect) {
 | 
				
			||||||
 | 
					    $rule = $effect->getRule();
 | 
				
			||||||
 | 
					    $phid = $rule->getAuthorPHID();
 | 
				
			||||||
 | 
					    return $this->applyAuditors(array($phid), $rule);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  public function getHeraldActionStandardType() {
 | 
				
			||||||
 | 
					    return self::STANDARD_NONE;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  public function renderActionDescription($value) {
 | 
				
			||||||
 | 
					    return pht('Add rule author as auditor.');
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -0,0 +1,76 @@
 | 
				
			|||||||
 | 
					<?php
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					abstract class DiffusionAuditorsHeraldAction
 | 
				
			||||||
 | 
					  extends HeraldAction {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  const DO_ADD_AUDITORS = 'do.add-auditors';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  public function getActionGroupKey() {
 | 
				
			||||||
 | 
					    return HeraldApplicationActionGroup::ACTIONGROUPKEY;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  public function supportsObject($object) {
 | 
				
			||||||
 | 
					    return ($object instanceof PhabricatorRepositoryCommit);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  protected function applyAuditors(array $phids, HeraldRule $rule) {
 | 
				
			||||||
 | 
					    $adapter = $this->getAdapter();
 | 
				
			||||||
 | 
					    $object = $adapter->getObject();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    $auditors = $object->getAudits();
 | 
				
			||||||
 | 
					    $auditors = mpull($auditors, null, 'getAuditorPHID');
 | 
				
			||||||
 | 
					    $current = array_keys($auditors);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    $allowed_types = array(
 | 
				
			||||||
 | 
					      PhabricatorPeopleUserPHIDType::TYPECONST,
 | 
				
			||||||
 | 
					      PhabricatorProjectProjectPHIDType::TYPECONST,
 | 
				
			||||||
 | 
					      PhabricatorOwnersPackagePHIDType::TYPECONST,
 | 
				
			||||||
 | 
					    );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    $targets = $this->loadStandardTargets($phids, $allowed_types, $current);
 | 
				
			||||||
 | 
					    if (!$targets) {
 | 
				
			||||||
 | 
					      return;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    $phids = array_fuse(array_keys($targets));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // TODO: Convert this to be translatable, structured data eventually.
 | 
				
			||||||
 | 
					    $reason_map = array();
 | 
				
			||||||
 | 
					    foreach ($phids as $phid) {
 | 
				
			||||||
 | 
					      $reason_map[$phid][] = pht('%s Triggered Audit', $rule->getMonogram());
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    $xaction = $adapter->newTransaction()
 | 
				
			||||||
 | 
					      ->setTransactionType(PhabricatorAuditActionConstants::ADD_AUDITORS)
 | 
				
			||||||
 | 
					      ->setNewValue($phids)
 | 
				
			||||||
 | 
					      ->setMetadataValue(
 | 
				
			||||||
 | 
					        'auditStatus',
 | 
				
			||||||
 | 
					        PhabricatorAuditStatusConstants::AUDIT_REQUIRED)
 | 
				
			||||||
 | 
					      ->setMetadataValue('auditReasonMap', $reason_map);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    $adapter->queueTransaction($xaction);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    $this->logEffect(self::DO_ADD_AUDITORS, $phids);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  protected function getActionEffectMap() {
 | 
				
			||||||
 | 
					    return array(
 | 
				
			||||||
 | 
					      self::DO_ADD_AUDITORS => array(
 | 
				
			||||||
 | 
					        'icon' => 'fa-user',
 | 
				
			||||||
 | 
					        'color' => 'green',
 | 
				
			||||||
 | 
					        'name' => pht('Added Auditors'),
 | 
				
			||||||
 | 
					      ),
 | 
				
			||||||
 | 
					    );
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  protected function renderActionEffectDescription($type, $data) {
 | 
				
			||||||
 | 
					    switch ($type) {
 | 
				
			||||||
 | 
					      case self::DO_ADD_AUDITORS:
 | 
				
			||||||
 | 
					        return pht(
 | 
				
			||||||
 | 
					          'Added %s auditor(s): %s.',
 | 
				
			||||||
 | 
					          new PhutilNumber(count($data)),
 | 
				
			||||||
 | 
					          $this->renderHandleList($data));
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -12,8 +12,6 @@ final class HeraldCommitAdapter
 | 
				
			|||||||
  protected $commitData;
 | 
					  protected $commitData;
 | 
				
			||||||
  private $commitDiff;
 | 
					  private $commitDiff;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  protected $auditMap = array();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  protected $affectedPaths;
 | 
					  protected $affectedPaths;
 | 
				
			||||||
  protected $affectedRevision;
 | 
					  protected $affectedRevision;
 | 
				
			||||||
  protected $affectedPackages;
 | 
					  protected $affectedPackages;
 | 
				
			||||||
@@ -86,24 +84,6 @@ final class HeraldCommitAdapter
 | 
				
			|||||||
    return pht('This rule can trigger for **repositories** and **projects**.');
 | 
					    return pht('This rule can trigger for **repositories** and **projects**.');
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  public function getActions($rule_type) {
 | 
					 | 
				
			||||||
    switch ($rule_type) {
 | 
					 | 
				
			||||||
      case HeraldRuleTypeConfig::RULE_TYPE_GLOBAL:
 | 
					 | 
				
			||||||
      case HeraldRuleTypeConfig::RULE_TYPE_OBJECT:
 | 
					 | 
				
			||||||
        return array_merge(
 | 
					 | 
				
			||||||
          array(
 | 
					 | 
				
			||||||
            self::ACTION_AUDIT,
 | 
					 | 
				
			||||||
          ),
 | 
					 | 
				
			||||||
          parent::getActions($rule_type));
 | 
					 | 
				
			||||||
      case HeraldRuleTypeConfig::RULE_TYPE_PERSONAL:
 | 
					 | 
				
			||||||
        return array_merge(
 | 
					 | 
				
			||||||
          array(
 | 
					 | 
				
			||||||
            self::ACTION_AUDIT,
 | 
					 | 
				
			||||||
          ),
 | 
					 | 
				
			||||||
          parent::getActions($rule_type));
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  public static function newLegacyAdapter(
 | 
					  public static function newLegacyAdapter(
 | 
				
			||||||
    PhabricatorRepository $repository,
 | 
					    PhabricatorRepository $repository,
 | 
				
			||||||
    PhabricatorRepositoryCommit $commit,
 | 
					    PhabricatorRepositoryCommit $commit,
 | 
				
			||||||
@@ -149,10 +129,6 @@ final class HeraldCommitAdapter
 | 
				
			|||||||
    return $this;
 | 
					    return $this;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  public function getAuditMap() {
 | 
					 | 
				
			||||||
    return $this->auditMap;
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  public function getHeraldName() {
 | 
					  public function getHeraldName() {
 | 
				
			||||||
    return
 | 
					    return
 | 
				
			||||||
      'r'.
 | 
					      'r'.
 | 
				
			||||||
@@ -322,33 +298,6 @@ final class HeraldCommitAdapter
 | 
				
			|||||||
    return $result;
 | 
					    return $result;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  public function applyHeraldEffects(array $effects) {
 | 
					 | 
				
			||||||
    assert_instances_of($effects, 'HeraldEffect');
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    $result = array();
 | 
					 | 
				
			||||||
    foreach ($effects as $effect) {
 | 
					 | 
				
			||||||
      $action = $effect->getAction();
 | 
					 | 
				
			||||||
      switch ($action) {
 | 
					 | 
				
			||||||
        case self::ACTION_AUDIT:
 | 
					 | 
				
			||||||
          foreach ($effect->getTarget() as $phid) {
 | 
					 | 
				
			||||||
            if (empty($this->auditMap[$phid])) {
 | 
					 | 
				
			||||||
              $this->auditMap[$phid] = array();
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
            $this->auditMap[$phid][] = $effect->getRule()->getID();
 | 
					 | 
				
			||||||
          }
 | 
					 | 
				
			||||||
          $result[] = new HeraldApplyTranscript(
 | 
					 | 
				
			||||||
            $effect,
 | 
					 | 
				
			||||||
            true,
 | 
					 | 
				
			||||||
            pht('Triggered an audit.'));
 | 
					 | 
				
			||||||
          break;
 | 
					 | 
				
			||||||
        default:
 | 
					 | 
				
			||||||
          $result[] = $this->applyStandardEffect($effect);
 | 
					 | 
				
			||||||
          break;
 | 
					 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    return $result;
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* -(  HarbormasterBuildableAdapterInterface  )------------------------------ */
 | 
					/* -(  HarbormasterBuildableAdapterInterface  )------------------------------ */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -72,7 +72,7 @@ final class PhabricatorFlagAddFlagHeraldAction extends HeraldAction {
 | 
				
			|||||||
    return pht('Mark with %s flag.', $color);
 | 
					    return pht('Mark with %s flag.', $color);
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  public function renderActionEffectDescription($type, $data) {
 | 
					  protected function renderActionEffectDescription($type, $data) {
 | 
				
			||||||
    switch ($type) {
 | 
					    switch ($type) {
 | 
				
			||||||
      case self::DO_IGNORE:
 | 
					      case self::DO_IGNORE:
 | 
				
			||||||
        return pht(
 | 
					        return pht(
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -68,7 +68,7 @@ final class HarbormasterRunBuildPlansHeraldAction
 | 
				
			|||||||
        'color' => 'red',
 | 
					        'color' => 'red',
 | 
				
			||||||
        'name' => pht('Invalid Targets'),
 | 
					        'name' => pht('Invalid Targets'),
 | 
				
			||||||
      ),
 | 
					      ),
 | 
				
			||||||
      self::DO_ALREADY_REQUIRED => array(
 | 
					      self::DO_BUILD => array(
 | 
				
			||||||
        'icon' => 'fa-play',
 | 
					        'icon' => 'fa-play',
 | 
				
			||||||
        'color' => 'green',
 | 
					        'color' => 'green',
 | 
				
			||||||
        'name' => pht('Building'),
 | 
					        'name' => pht('Building'),
 | 
				
			||||||
@@ -76,7 +76,7 @@ final class HarbormasterRunBuildPlansHeraldAction
 | 
				
			|||||||
    );
 | 
					    );
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  public function renderActionEffectDescription($type, $data) {
 | 
					  protected function renderActionEffectDescription($type, $data) {
 | 
				
			||||||
    switch ($type) {
 | 
					    switch ($type) {
 | 
				
			||||||
      case self::DO_NO_TARGETS:
 | 
					      case self::DO_NO_TARGETS:
 | 
				
			||||||
        return pht('Rule lists no targets.');
 | 
					        return pht('Rule lists no targets.');
 | 
				
			||||||
@@ -85,7 +85,7 @@ final class HarbormasterRunBuildPlansHeraldAction
 | 
				
			|||||||
          '%s build plan(s) are not valid: %s.',
 | 
					          '%s build plan(s) are not valid: %s.',
 | 
				
			||||||
          new PhutilNumber(count($data)),
 | 
					          new PhutilNumber(count($data)),
 | 
				
			||||||
          $this->renderHandleList($data));
 | 
					          $this->renderHandleList($data));
 | 
				
			||||||
      case self::DO_REQUIRED:
 | 
					      case self::DO_BUILD:
 | 
				
			||||||
        return pht(
 | 
					        return pht(
 | 
				
			||||||
          'Started %s build(s): %s.',
 | 
					          'Started %s build(s): %s.',
 | 
				
			||||||
          new PhutilNumber(count($data)),
 | 
					          new PhutilNumber(count($data)),
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -9,11 +9,20 @@ abstract class HeraldAction extends Phobject {
 | 
				
			|||||||
  const STANDARD_NONE = 'standard.none';
 | 
					  const STANDARD_NONE = 'standard.none';
 | 
				
			||||||
  const STANDARD_PHID_LIST = 'standard.phid.list';
 | 
					  const STANDARD_PHID_LIST = 'standard.phid.list';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  const DO_STANDARD_EMPTY = 'do.standard.empty';
 | 
				
			||||||
 | 
					  const DO_STANDARD_NO_EFFECT = 'do.standard.no-effect';
 | 
				
			||||||
 | 
					  const DO_STANDARD_INVALID = 'do.standard.invalid';
 | 
				
			||||||
 | 
					  const DO_STANDARD_UNLOADABLE = 'do.standard.unloadable';
 | 
				
			||||||
 | 
					  const DO_STANDARD_PERMISSION = 'do.standard.permission';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  abstract public function getHeraldActionName();
 | 
					  abstract public function getHeraldActionName();
 | 
				
			||||||
  abstract public function supportsObject($object);
 | 
					  abstract public function supportsObject($object);
 | 
				
			||||||
  abstract public function supportsRuleType($rule_type);
 | 
					  abstract public function supportsRuleType($rule_type);
 | 
				
			||||||
  abstract public function applyEffect($object, HeraldEffect $effect);
 | 
					  abstract public function applyEffect($object, HeraldEffect $effect);
 | 
				
			||||||
  abstract public function renderActionEffectDescription($type, $data);
 | 
					
 | 
				
			||||||
 | 
					  protected function renderActionEffectDescription($type, $data) {
 | 
				
			||||||
 | 
					    return null;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  public function getActionGroupKey() {
 | 
					  public function getActionGroupKey() {
 | 
				
			||||||
    return null;
 | 
					    return null;
 | 
				
			||||||
@@ -154,21 +163,21 @@ abstract class HeraldAction extends Phobject {
 | 
				
			|||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  private function getActionEffectSpec($type) {
 | 
					  private function getActionEffectSpec($type) {
 | 
				
			||||||
    $map = $this->getActionEffectMap();
 | 
					    $map = $this->getActionEffectMap() + $this->getStandardEffectMap();
 | 
				
			||||||
    return idx($map, $type, array());
 | 
					    return idx($map, $type, array());
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  public function renderActionEffectIcon($type, $data) {
 | 
					  final public function renderActionEffectIcon($type, $data) {
 | 
				
			||||||
    $map = $this->getActionEffectSpec($type);
 | 
					    $map = $this->getActionEffectSpec($type);
 | 
				
			||||||
    return idx($map, 'icon');
 | 
					    return idx($map, 'icon');
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  public function renderActionEffectColor($type, $data) {
 | 
					  final public function renderActionEffectColor($type, $data) {
 | 
				
			||||||
    $map = $this->getActionEffectSpec($type);
 | 
					    $map = $this->getActionEffectSpec($type);
 | 
				
			||||||
    return idx($map, 'color');
 | 
					    return idx($map, 'color');
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  public function renderActionEffectName($type, $data) {
 | 
					  final public function renderActionEffectName($type, $data) {
 | 
				
			||||||
    $map = $this->getActionEffectSpec($type);
 | 
					    $map = $this->getActionEffectSpec($type);
 | 
				
			||||||
    return idx($map, 'name');
 | 
					    return idx($map, 'name');
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
@@ -184,4 +193,173 @@ abstract class HeraldAction extends Phobject {
 | 
				
			|||||||
      ->render();
 | 
					      ->render();
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  protected function loadStandardTargets(
 | 
				
			||||||
 | 
					    array $phids,
 | 
				
			||||||
 | 
					    array $allowed_types,
 | 
				
			||||||
 | 
					    array $current_value) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    $phids = array_fuse($phids);
 | 
				
			||||||
 | 
					    if (!$phids) {
 | 
				
			||||||
 | 
					      $this->logEffect(self::DO_STANDARD_EMPTY);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    $current_value = array_fuse($current_value);
 | 
				
			||||||
 | 
					    $no_effect = array();
 | 
				
			||||||
 | 
					    foreach ($phids as $phid) {
 | 
				
			||||||
 | 
					      if (isset($current_value[$phid])) {
 | 
				
			||||||
 | 
					        $no_effect[] = $phid;
 | 
				
			||||||
 | 
					        unset($phids[$phid]);
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if ($no_effect) {
 | 
				
			||||||
 | 
					      $this->logEffect(self::DO_STANDARD_NO_EFFECT, $no_effect);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (!$phids) {
 | 
				
			||||||
 | 
					      return;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    $allowed_types = array_fuse($allowed_types);
 | 
				
			||||||
 | 
					    $invalid = array();
 | 
				
			||||||
 | 
					    foreach ($phids as $phid) {
 | 
				
			||||||
 | 
					      $type = phid_get_type($phid);
 | 
				
			||||||
 | 
					      if ($type == PhabricatorPHIDConstants::PHID_TYPE_UNKNOWN) {
 | 
				
			||||||
 | 
					        $invalid[] = $phid;
 | 
				
			||||||
 | 
					        unset($phids[$phid]);
 | 
				
			||||||
 | 
					        continue;
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      if ($allowed_types && empty($allowed_types[$type])) {
 | 
				
			||||||
 | 
					        $invalid[] = $phid;
 | 
				
			||||||
 | 
					        unset($phids[$phid]);
 | 
				
			||||||
 | 
					        continue;
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if ($invalid) {
 | 
				
			||||||
 | 
					      $this->logEffect(self::DO_STANDARD_INVALID, $invalid);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (!$phids) {
 | 
				
			||||||
 | 
					      return;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    $targets = id(new PhabricatorObjectQuery())
 | 
				
			||||||
 | 
					      ->setViewer(PhabricatorUser::getOmnipotentUser())
 | 
				
			||||||
 | 
					      ->withPHIDs($phids)
 | 
				
			||||||
 | 
					      ->execute();
 | 
				
			||||||
 | 
					    $targets = mpull($targets, null, 'getPHID');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    $unloadable = array();
 | 
				
			||||||
 | 
					    foreach ($phids as $phid) {
 | 
				
			||||||
 | 
					      if (empty($targets[$phid])) {
 | 
				
			||||||
 | 
					        $unloadable[] = $phid;
 | 
				
			||||||
 | 
					        unset($phids[$phid]);
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if ($unloadable) {
 | 
				
			||||||
 | 
					      $this->logEffect(self::DO_STANDARD_UNLOADABLE, $unloadable);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (!$phids) {
 | 
				
			||||||
 | 
					      return;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    $adapter = $this->getAdapter();
 | 
				
			||||||
 | 
					    $object = $adapter->getObject();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if ($object instanceof PhabricatorPolicyInterface) {
 | 
				
			||||||
 | 
					      $no_permission = array();
 | 
				
			||||||
 | 
					      foreach ($targets as $phid => $target) {
 | 
				
			||||||
 | 
					        if (!($target instanceof PhabricatorUser)) {
 | 
				
			||||||
 | 
					          continue;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        $can_view = PhabricatorPolicyFilter::hasCapability(
 | 
				
			||||||
 | 
					          $target,
 | 
				
			||||||
 | 
					          $object,
 | 
				
			||||||
 | 
					          PhabricatorPolicyCapability::CAN_VIEW);
 | 
				
			||||||
 | 
					        if ($can_view) {
 | 
				
			||||||
 | 
					          continue;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        $no_permission[] = $phid;
 | 
				
			||||||
 | 
					        unset($targets[$phid]);
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if ($no_permission) {
 | 
				
			||||||
 | 
					      $this->logEffect(self::DO_STANDARD_PERMISSION, $no_permission);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return $targets;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  protected function getStandardEffectMap() {
 | 
				
			||||||
 | 
					    return array(
 | 
				
			||||||
 | 
					      self::DO_STANDARD_EMPTY => array(
 | 
				
			||||||
 | 
					        'icon' => 'fa-ban',
 | 
				
			||||||
 | 
					        'color' => 'grey',
 | 
				
			||||||
 | 
					        'name' => pht('No Targets'),
 | 
				
			||||||
 | 
					      ),
 | 
				
			||||||
 | 
					      self::DO_STANDARD_NO_EFFECT => array(
 | 
				
			||||||
 | 
					        'icon' => 'fa-circle-o',
 | 
				
			||||||
 | 
					        'color' => 'grey',
 | 
				
			||||||
 | 
					        'name' => pht('No Effect'),
 | 
				
			||||||
 | 
					      ),
 | 
				
			||||||
 | 
					      self::DO_STANDARD_INVALID => array(
 | 
				
			||||||
 | 
					        'icon' => 'fa-ban',
 | 
				
			||||||
 | 
					        'color' => 'red',
 | 
				
			||||||
 | 
					        'name' => pht('Invalid Targets'),
 | 
				
			||||||
 | 
					      ),
 | 
				
			||||||
 | 
					      self::DO_STANDARD_UNLOADABLE => array(
 | 
				
			||||||
 | 
					        'icon' => 'fa-ban',
 | 
				
			||||||
 | 
					        'color' => 'red',
 | 
				
			||||||
 | 
					        'name' => pht('Unloadable Targets'),
 | 
				
			||||||
 | 
					      ),
 | 
				
			||||||
 | 
					      self::DO_STANDARD_PERMISSION => array(
 | 
				
			||||||
 | 
					        'icon' => 'fa-lock',
 | 
				
			||||||
 | 
					        'color' => 'red',
 | 
				
			||||||
 | 
					        'name' => pht('No Permission'),
 | 
				
			||||||
 | 
					      ),
 | 
				
			||||||
 | 
					    );
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  final public function renderEffectDescription($type, $data) {
 | 
				
			||||||
 | 
					    $result = $this->renderActionEffectDescription($type, $data);
 | 
				
			||||||
 | 
					    if ($result !== null) {
 | 
				
			||||||
 | 
					      return $result;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    switch ($type) {
 | 
				
			||||||
 | 
					      case self::DO_STANDARD_EMPTY:
 | 
				
			||||||
 | 
					        return pht(
 | 
				
			||||||
 | 
					          'This action specifies no targets.');
 | 
				
			||||||
 | 
					      case self::DO_STANDARD_NO_EFFECT:
 | 
				
			||||||
 | 
					        return pht(
 | 
				
			||||||
 | 
					          'This action has no effect on %s target(s): %s.',
 | 
				
			||||||
 | 
					          new PhutilNumber(count($data)),
 | 
				
			||||||
 | 
					          $this->renderHandleList($data));
 | 
				
			||||||
 | 
					      case self::DO_STANDARD_INVALID:
 | 
				
			||||||
 | 
					        return pht(
 | 
				
			||||||
 | 
					          '%s target(s) are invalid or of the wrong type: %s.',
 | 
				
			||||||
 | 
					          new PhutilNumber(count($data)),
 | 
				
			||||||
 | 
					          $this->renderHandleList($data));
 | 
				
			||||||
 | 
					      case self::DO_STANDARD_UNLOADABLE:
 | 
				
			||||||
 | 
					        return pht(
 | 
				
			||||||
 | 
					          '%s target(s) could not be loaded: %s.',
 | 
				
			||||||
 | 
					          new PhutilNumber(count($data)),
 | 
				
			||||||
 | 
					          $this->renderHandleList($data));
 | 
				
			||||||
 | 
					      case self::DO_STANDARD_PERMISSION:
 | 
				
			||||||
 | 
					        return pht(
 | 
				
			||||||
 | 
					          '%s target(s) do not have permission to see this object: %s.',
 | 
				
			||||||
 | 
					          new PhutilNumber(count($data)),
 | 
				
			||||||
 | 
					          $this->renderHandleList($data));
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return null;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -43,7 +43,7 @@ final class HeraldDoNothingAction extends HeraldAction {
 | 
				
			|||||||
    return pht('Do nothing.');
 | 
					    return pht('Do nothing.');
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  public function renderActionEffectDescription($type, $data) {
 | 
					  protected function renderActionEffectDescription($type, $data) {
 | 
				
			||||||
    return pht('Did nothing.');
 | 
					    return pht('Did nothing.');
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -26,7 +26,6 @@ abstract class HeraldAdapter extends Phobject {
 | 
				
			|||||||
  const CONDITION_IS_TRUE         = 'true';
 | 
					  const CONDITION_IS_TRUE         = 'true';
 | 
				
			||||||
  const CONDITION_IS_FALSE        = 'false';
 | 
					  const CONDITION_IS_FALSE        = 'false';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  const ACTION_AUDIT        = 'audit';
 | 
					 | 
				
			||||||
  const ACTION_BLOCK = 'block';
 | 
					  const ACTION_BLOCK = 'block';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  private $contentSource;
 | 
					  private $contentSource;
 | 
				
			||||||
@@ -712,13 +711,11 @@ abstract class HeraldAdapter extends Phobject {
 | 
				
			|||||||
      case HeraldRuleTypeConfig::RULE_TYPE_GLOBAL:
 | 
					      case HeraldRuleTypeConfig::RULE_TYPE_GLOBAL:
 | 
				
			||||||
      case HeraldRuleTypeConfig::RULE_TYPE_OBJECT:
 | 
					      case HeraldRuleTypeConfig::RULE_TYPE_OBJECT:
 | 
				
			||||||
        $standard = array(
 | 
					        $standard = array(
 | 
				
			||||||
          self::ACTION_AUDIT        => pht('Trigger an Audit by'),
 | 
					 | 
				
			||||||
          self::ACTION_BLOCK => pht('Block change with message'),
 | 
					          self::ACTION_BLOCK => pht('Block change with message'),
 | 
				
			||||||
        );
 | 
					        );
 | 
				
			||||||
        break;
 | 
					        break;
 | 
				
			||||||
      case HeraldRuleTypeConfig::RULE_TYPE_PERSONAL:
 | 
					      case HeraldRuleTypeConfig::RULE_TYPE_PERSONAL:
 | 
				
			||||||
        $standard = array(
 | 
					        $standard = array(
 | 
				
			||||||
          self::ACTION_AUDIT        => pht('Trigger an Audit by me'),
 | 
					 | 
				
			||||||
        );
 | 
					        );
 | 
				
			||||||
        break;
 | 
					        break;
 | 
				
			||||||
      default:
 | 
					      default:
 | 
				
			||||||
@@ -757,8 +754,6 @@ abstract class HeraldAdapter extends Phobject {
 | 
				
			|||||||
    $rule_type = $rule->getRuleType();
 | 
					    $rule_type = $rule->getRuleType();
 | 
				
			||||||
    if ($rule_type == HeraldRuleTypeConfig::RULE_TYPE_PERSONAL) {
 | 
					    if ($rule_type == HeraldRuleTypeConfig::RULE_TYPE_PERSONAL) {
 | 
				
			||||||
      switch ($action->getAction()) {
 | 
					      switch ($action->getAction()) {
 | 
				
			||||||
        case self::ACTION_AUDIT:
 | 
					 | 
				
			||||||
          break;
 | 
					 | 
				
			||||||
        case self::ACTION_BLOCK:
 | 
					        case self::ACTION_BLOCK:
 | 
				
			||||||
          break;
 | 
					          break;
 | 
				
			||||||
        default:
 | 
					        default:
 | 
				
			||||||
@@ -790,14 +785,8 @@ abstract class HeraldAdapter extends Phobject {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    $is_personal = ($rule_type == HeraldRuleTypeConfig::RULE_TYPE_PERSONAL);
 | 
					    $is_personal = ($rule_type == HeraldRuleTypeConfig::RULE_TYPE_PERSONAL);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if ($is_personal) {
 | 
					    if (!$is_personal) {
 | 
				
			||||||
      switch ($action) {
 | 
					      switch ($action) {
 | 
				
			||||||
        case self::ACTION_AUDIT:
 | 
					 | 
				
			||||||
          return new HeraldEmptyFieldValue();
 | 
					 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
    } else {
 | 
					 | 
				
			||||||
      switch ($action) {
 | 
					 | 
				
			||||||
        case self::ACTION_AUDIT:
 | 
					 | 
				
			||||||
        case self::ACTION_BLOCK:
 | 
					        case self::ACTION_BLOCK:
 | 
				
			||||||
          return new HeraldTextFieldValue();
 | 
					          return new HeraldTextFieldValue();
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -376,7 +376,7 @@ final class HeraldTranscriptController extends HeraldController {
 | 
				
			|||||||
            $icon = $action->renderActionEffectIcon($type, $data);
 | 
					            $icon = $action->renderActionEffectIcon($type, $data);
 | 
				
			||||||
            $color = $action->renderActionEffectColor($type, $data);
 | 
					            $color = $action->renderActionEffectColor($type, $data);
 | 
				
			||||||
            $name = $action->renderActionEffectName($type, $data);
 | 
					            $name = $action->renderActionEffectName($type, $data);
 | 
				
			||||||
            $note = $action->renderActionEffectDescription($type, $data);
 | 
					            $note = $action->renderEffectDescription($type, $data);
 | 
				
			||||||
          } else {
 | 
					          } else {
 | 
				
			||||||
            $icon = 'fa-question-circle';
 | 
					            $icon = 'fa-question-circle';
 | 
				
			||||||
            $color = 'indigo';
 | 
					            $color = 'indigo';
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -142,7 +142,7 @@ final class LegalpadRequireSignatureHeraldAction
 | 
				
			|||||||
    );
 | 
					    );
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  public function renderActionEffectDescription($type, $data) {
 | 
					  protected function renderActionEffectDescription($type, $data) {
 | 
				
			||||||
    switch ($type) {
 | 
					    switch ($type) {
 | 
				
			||||||
      case self::DO_NO_TARGETS:
 | 
					      case self::DO_NO_TARGETS:
 | 
				
			||||||
        return pht('Rule lists no targets.');
 | 
					        return pht('Rule lists no targets.');
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -90,7 +90,7 @@ abstract class ManiphestTaskAssignHeraldAction
 | 
				
			|||||||
    );
 | 
					    );
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  public function renderActionEffectDescription($type, $data) {
 | 
					  protected function renderActionEffectDescription($type, $data) {
 | 
				
			||||||
    switch ($type) {
 | 
					    switch ($type) {
 | 
				
			||||||
      case self::DO_EMPTY:
 | 
					      case self::DO_EMPTY:
 | 
				
			||||||
        return pht('Action lists no user to assign.');
 | 
					        return pht('Action lists no user to assign.');
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -50,7 +50,7 @@ abstract class PhabricatorMetaMTAEmailHeraldAction
 | 
				
			|||||||
    );
 | 
					    );
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  public function renderActionEffectDescription($type, $data) {
 | 
					  protected function renderActionEffectDescription($type, $data) {
 | 
				
			||||||
    switch ($type) {
 | 
					    switch ($type) {
 | 
				
			||||||
      case self::DO_SEND:
 | 
					      case self::DO_SEND:
 | 
				
			||||||
        return pht(
 | 
					        return pht(
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -145,7 +145,7 @@ abstract class PhabricatorProjectHeraldAction
 | 
				
			|||||||
    );
 | 
					    );
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  public function renderActionEffectDescription($type, $data) {
 | 
					  protected function renderActionEffectDescription($type, $data) {
 | 
				
			||||||
    switch ($type) {
 | 
					    switch ($type) {
 | 
				
			||||||
      case self::DO_NO_TARGETS:
 | 
					      case self::DO_NO_TARGETS:
 | 
				
			||||||
        return pht('Rule lists no projects.');
 | 
					        return pht('Rule lists no projects.');
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -196,7 +196,7 @@ abstract class PhabricatorSubscriptionsHeraldAction
 | 
				
			|||||||
    );
 | 
					    );
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  public function renderActionEffectDescription($type, $data) {
 | 
					  protected function renderActionEffectDescription($type, $data) {
 | 
				
			||||||
    switch ($type) {
 | 
					    switch ($type) {
 | 
				
			||||||
      case self::DO_NO_TARGETS:
 | 
					      case self::DO_NO_TARGETS:
 | 
				
			||||||
        return pht('Rule lists no targets.');
 | 
					        return pht('Rule lists no targets.');
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1338,6 +1338,16 @@ final class PhabricatorUSEnglishTranslation
 | 
				
			|||||||
        'Required signatures: %2$s.',
 | 
					        'Required signatures: %2$s.',
 | 
				
			||||||
      ),
 | 
					      ),
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      'Started %s build(s): %s.' => array(
 | 
				
			||||||
 | 
					        'Started a build: %2$s.',
 | 
				
			||||||
 | 
					        'Started builds: %2$s.',
 | 
				
			||||||
 | 
					      ),
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      'Added %s auditor(s): %s.' => array(
 | 
				
			||||||
 | 
					        'Added an auditor: %2$s.',
 | 
				
			||||||
 | 
					        'Added auditors: %2$s.',
 | 
				
			||||||
 | 
					      ),
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    );
 | 
					    );
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user