public function getActions($rule_type)
 {
     switch ($rule_type) {
         case HeraldRuleTypeConfig::RULE_TYPE_GLOBAL:
             return array_merge(array(self::ACTION_ADD_CC, self::ACTION_REMOVE_CC, self::ACTION_EMAIL, self::ACTION_NOTHING), parent::getActions($rule_type));
         case HeraldRuleTypeConfig::RULE_TYPE_PERSONAL:
             return array_merge(array(self::ACTION_ADD_CC, self::ACTION_REMOVE_CC, self::ACTION_EMAIL, self::ACTION_FLAG, self::ACTION_NOTHING), parent::getActions($rule_type));
     }
 }
 public function processRequest()
 {
     $request = $this->getRequest();
     $viewer = $request->getUser();
     $xscript = id(new HeraldTranscriptQuery())->setViewer($viewer)->withIDs(array($this->id))->executeOne();
     if (!$xscript) {
         return new Aphront404Response();
     }
     require_celerity_resource('herald-test-css');
     $nav = $this->buildSideNav();
     $object_xscript = $xscript->getObjectTranscript();
     if (!$object_xscript) {
         $notice = id(new PHUIInfoView())->setSeverity(PHUIInfoView::SEVERITY_NOTICE)->setTitle(pht('Old Transcript'))->appendChild(phutil_tag('p', array(), pht('Details of this transcript have been garbage collected.')));
         $nav->appendChild($notice);
     } else {
         $map = HeraldAdapter::getEnabledAdapterMap($viewer);
         $object_type = $object_xscript->getType();
         if (empty($map[$object_type])) {
             // TODO: We should filter these out in the Query, but we have to load
             // the objectTranscript right now, which is potentially enormous. We
             // should denormalize the object type, or move the data into a separate
             // table, and then filter this earlier (and thus raise a better error).
             // For now, just block access so we don't violate policies.
             throw new Exception(pht('This transcript has an invalid or inaccessible adapter.'));
         }
         $this->adapter = HeraldAdapter::getAdapterForContentType($object_type);
         $filter = $this->getFilterPHIDs();
         $this->filterTranscript($xscript, $filter);
         $phids = array_merge($filter, $this->getTranscriptPHIDs($xscript));
         $phids = array_unique($phids);
         $phids = array_filter($phids);
         $handles = $this->loadViewerHandles($phids);
         $this->handles = $handles;
         if ($xscript->getDryRun()) {
             $notice = new PHUIInfoView();
             $notice->setSeverity(PHUIInfoView::SEVERITY_NOTICE);
             $notice->setTitle(pht('Dry Run'));
             $notice->appendChild(pht('This was a dry run to test Herald rules, ' . 'no actions were executed.'));
             $nav->appendChild($notice);
         }
         $warning_panel = $this->buildWarningPanel($xscript);
         $nav->appendChild($warning_panel);
         $apply_xscript_panel = $this->buildApplyTranscriptPanel($xscript);
         $nav->appendChild($apply_xscript_panel);
         $action_xscript_panel = $this->buildActionTranscriptPanel($xscript);
         $nav->appendChild($action_xscript_panel);
         $object_xscript_panel = $this->buildObjectTranscriptPanel($xscript);
         $nav->appendChild($object_xscript_panel);
     }
     $crumbs = id($this->buildApplicationCrumbs())->addTextCrumb(pht('Transcripts'), $this->getApplicationURI('/transcript/'))->addTextCrumb($xscript->getID());
     $nav->setCrumbs($crumbs);
     return $this->buildApplicationPage($nav, array('title' => pht('Transcript')));
 }
 private function buildDescriptionView(HeraldRule $rule)
 {
     $viewer = $this->getRequest()->getUser();
     $view = id(new PHUIPropertyListView())->setUser($viewer);
     $adapter = HeraldAdapter::getAdapterForContentType($rule->getContentType());
     if ($adapter) {
         $handles = $viewer->loadHandles(HeraldAdapter::getHandlePHIDs($rule));
         $rule_text = $adapter->renderRuleAsText($rule, $handles, $viewer);
         $view->addTextContent($rule_text);
         return $view;
     }
     return null;
 }
 public function getHeraldField($field)
 {
     switch ($field) {
         case self::FIELD_TITLE:
             return $this->getDocument()->getContent()->getTitle();
         case self::FIELD_BODY:
             return $this->getDocument()->getContent()->getContent();
         case self::FIELD_AUTHOR:
             return $this->getDocument()->getContent()->getAuthorPHID();
         case self::FIELD_PATH:
             return $this->getDocument()->getContent()->getSlug();
     }
     return parent::getHeraldField($field);
 }
 public function getHeraldField($field)
 {
     switch ($field) {
         case self::FIELD_TITLE:
             return $this->getMock()->getName();
         case self::FIELD_BODY:
             return $this->getMock()->getDescription();
         case self::FIELD_AUTHOR:
             return $this->getMock()->getAuthorPHID();
         case self::FIELD_PROJECTS:
             return PhabricatorEdgeQuery::loadDestinationPHIDs($this->getMock()->getPHID(), PhabricatorProjectObjectHasProjectEdgeType::EDGECONST);
     }
     return parent::getHeraldField($field);
 }
 private function loadAdapter(AphrontRequest $request)
 {
     $viewer = $this->getViewer();
     $object = $this->getTestObject();
     $adapter_key = $request->getStr('adapter');
     $adapters = HeraldAdapter::getAllAdapters();
     $can_select = array();
     $display_adapters = array();
     foreach ($adapters as $key => $adapter) {
         if (!$adapter->isTestAdapterForObject($object)) {
             continue;
         }
         if (!$adapter->isAvailableToUser($viewer)) {
             continue;
         }
         $display_adapters[$key] = $adapter;
         if ($adapter->canCreateTestAdapterForObject($object)) {
             $can_select[$key] = $adapter;
         }
     }
     if ($request->isFormPost() && $adapter_key) {
         if (isset($can_select[$adapter_key])) {
             $adapter = $can_select[$adapter_key]->newTestAdapter($viewer, $object);
             $this->setTestAdapter($adapter);
             return null;
         }
     }
     $form = id(new AphrontFormView())->addHiddenInput('object_name', $request->getStr('object_name'))->setViewer($viewer);
     $cancel_uri = $this->getApplicationURI();
     if (!$display_adapters) {
         $form->appendRemarkupInstructions(pht('//There are no available Herald events for this object.//'))->appendControl(id(new AphrontFormSubmitControl())->addCancelButton($cancel_uri));
     } else {
         $adapter_control = id(new AphrontFormRadioButtonControl())->setLabel(pht('Event'))->setName('adapter')->setValue(head_key($can_select));
         foreach ($display_adapters as $adapter_key => $adapter) {
             $is_disabled = empty($can_select[$adapter_key]);
             $adapter_control->addButton($adapter_key, $adapter->getAdapterContentName(), $adapter->getAdapterTestDescription(), null, $is_disabled);
         }
         $form->appendControl($adapter_control)->appendControl(id(new AphrontFormSubmitControl())->setValue(pht('Run Test')));
     }
     return $this->buildTestConsoleResponse($form, array());
 }
 private function buildPropertyView(HeraldRule $rule, PhabricatorActionListView $actions)
 {
     $viewer = $this->getRequest()->getUser();
     $view = id(new PHUIPropertyListView())->setUser($viewer)->setObject($rule)->setActionList($actions);
     $view->addProperty(pht('Rule Type'), idx(HeraldRuleTypeConfig::getRuleTypeMap(), $rule->getRuleType()));
     if ($rule->isPersonalRule()) {
         $view->addProperty(pht('Author'), $viewer->renderHandle($rule->getAuthorPHID()));
     }
     $adapter = HeraldAdapter::getAdapterForContentType($rule->getContentType());
     if ($adapter) {
         $view->addProperty(pht('Applies To'), idx(HeraldAdapter::getEnabledAdapterMap($viewer), $rule->getContentType()));
         if ($rule->isObjectRule()) {
             $view->addProperty(pht('Trigger Object'), $viewer->renderHandle($rule->getTriggerObjectPHID()));
         }
         $view->invokeWillRenderEvent();
         $view->addSectionHeader(pht('Rule Description'), PHUIPropertyListView::ICON_SUMMARY);
         $handles = $viewer->loadHandles(HeraldAdapter::getHandlePHIDs($rule));
         $view->addTextContent($adapter->renderRuleAsText($rule, $handles));
     }
     return $view;
 }
 protected function willFilterPage(array $rules)
 {
     $rule_ids = mpull($rules, 'getID');
     // Filter out any rules that have invalid adapters, or have adapters the
     // viewer isn't permitted to see or use (for example, Differential rules
     // if the user can't use Differential or Differential is not installed).
     $types = HeraldAdapter::getEnabledAdapterMap($this->getViewer());
     foreach ($rules as $key => $rule) {
         if (empty($types[$rule->getContentType()])) {
             $this->didRejectResult($rule);
             unset($rules[$key]);
         }
     }
     if ($this->needValidateAuthors) {
         $this->validateRuleAuthors($rules);
     }
     if ($this->needConditionsAndActions) {
         $conditions = id(new HeraldCondition())->loadAllWhere('ruleID IN (%Ld)', $rule_ids);
         $conditions = mgroup($conditions, 'getRuleID');
         $actions = id(new HeraldAction())->loadAllWhere('ruleID IN (%Ld)', $rule_ids);
         $actions = mgroup($actions, 'getRuleID');
         foreach ($rules as $rule) {
             $rule->attachActions(idx($actions, $rule->getID(), array()));
             $rule->attachConditions(idx($conditions, $rule->getID(), array()));
         }
     }
     if ($this->needAppliedToPHIDs) {
         $conn_r = id(new HeraldRule())->establishConnection('r');
         $applied = queryfx_all($conn_r, 'SELECT * FROM %T WHERE ruleID IN (%Ld) AND phid IN (%Ls)', HeraldRule::TABLE_RULE_APPLIED, $rule_ids, $this->needAppliedToPHIDs);
         $map = array();
         foreach ($applied as $row) {
             $map[$row['ruleID']][$row['phid']] = true;
         }
         foreach ($rules as $rule) {
             foreach ($this->needAppliedToPHIDs as $phid) {
                 $rule->setRuleApplied($phid, isset($map[$rule->getID()][$phid]));
             }
         }
     }
     $object_phids = array();
     foreach ($rules as $rule) {
         if ($rule->isObjectRule()) {
             $object_phids[] = $rule->getTriggerObjectPHID();
         }
     }
     if ($object_phids) {
         $objects = id(new PhabricatorObjectQuery())->setParentQuery($this)->setViewer($this->getViewer())->withPHIDs($object_phids)->execute();
         $objects = mpull($objects, null, 'getPHID');
     } else {
         $objects = array();
     }
     foreach ($rules as $key => $rule) {
         if ($rule->isObjectRule()) {
             $object = idx($objects, $rule->getTriggerObjectPHID());
             if (!$object) {
                 unset($rules[$key]);
                 continue;
             }
             $rule->attachTriggerObject($object);
         }
     }
     return $rules;
 }
 protected function didApplyHeraldRules(PhabricatorLiskDAO $object, HeraldAdapter $adapter, HeraldTranscript $transcript)
 {
     // TODO: Convert this to be transaction-based.
     $cc_phids = $adapter->getCcPHIDs();
     if ($cc_phids) {
         id(new PhabricatorSubscriptionsEditor())->setObject($object)->setActor($this->requireActor())->subscribeImplicit($cc_phids)->save();
     }
     return array();
 }
Exemple #10
0
 public static function getEnabledAdapterMap(PhabricatorUser $viewer)
 {
     $map = array();
     $adapters = HeraldAdapter::getAllAdapters();
     foreach ($adapters as $adapter) {
         if (!$adapter->isAvailableToUser($viewer)) {
             continue;
         }
         $type = $adapter->getAdapterContentType();
         $name = $adapter->getAdapterContentName();
         $map[$type] = $name;
     }
     return $map;
 }
 /**
  * Render the selector for "Take these actions (every time | only the first
  * time) this rule matches..." element.
  */
 private function renderRepetitionSelector($rule, HeraldAdapter $adapter)
 {
     $repetition_policy = HeraldRepetitionPolicyConfig::toString($rule->getRepetitionPolicy());
     $repetition_options = $adapter->getRepetitionOptions();
     $repetition_names = HeraldRepetitionPolicyConfig::getMap();
     $repetition_map = array_select_keys($repetition_names, $repetition_options);
     if (count($repetition_map) < 2) {
         return head($repetition_names);
     } else {
         return AphrontFormSelectControl::renderSelectTag($repetition_policy, $repetition_map, array('name' => 'repetition_policy'));
     }
 }
 private function renderRuleTypeControl(array $rule_type_map, $e_rule)
 {
     $request = $this->getRequest();
     // Reorder array to put less powerful rules first.
     $rule_type_map = array_select_keys($rule_type_map, array(HeraldRuleTypeConfig::RULE_TYPE_PERSONAL, HeraldRuleTypeConfig::RULE_TYPE_OBJECT, HeraldRuleTypeConfig::RULE_TYPE_GLOBAL)) + $rule_type_map;
     list($can_global, $global_link) = $this->explainApplicationCapability(HeraldManageGlobalRulesCapability::CAPABILITY, pht('You have permission to create and manage global rules.'), pht('You do not have permission to create or manage global rules.'));
     $captions = array(HeraldRuleTypeConfig::RULE_TYPE_PERSONAL => pht('Personal rules notify you about events. You own them, but they can ' . 'only affect you. Personal rules only trigger for objects you have ' . 'permission to see.'), HeraldRuleTypeConfig::RULE_TYPE_OBJECT => pht('Object rules notify anyone about events. They are bound to an ' . 'object (like a repository) and can only act on that object. You ' . 'must be able to edit an object to create object rules for it. ' . 'Other users who can edit the object can edit its rules.'), HeraldRuleTypeConfig::RULE_TYPE_GLOBAL => array(pht('Global rules notify anyone about events. Global rules can ' . 'bypass access control policies and act on any object.'), $global_link));
     $radio = id(new AphrontFormRadioButtonControl())->setLabel(pht('Rule Type'))->setName('rule_type')->setValue($request->getStr('rule_type'))->setError($e_rule);
     $adapter = HeraldAdapter::getAdapterForContentType($request->getStr('content_type'));
     foreach ($rule_type_map as $value => $name) {
         $caption = idx($captions, $value);
         $disabled = $value == HeraldRuleTypeConfig::RULE_TYPE_GLOBAL && !$can_global;
         if (!$adapter->supportsRuleType($value)) {
             $disabled = true;
             $caption = array($caption, "\n\n", phutil_tag('em', array(), pht('This rule type is not supported by the selected content type.')));
         }
         $radio->addButton($value, $name, phutil_escape_html_newlines($caption), $disabled ? 'disabled' : null, $disabled);
     }
     return $radio;
 }
 protected function didApplyHeraldRules(PhabricatorLiskDAO $object, HeraldAdapter $adapter, HeraldTranscript $transcript)
 {
     $xactions = array();
     // Build a transaction to adjust reviewers.
     $reviewers = array(DifferentialReviewerStatus::STATUS_ADDED => array_keys($adapter->getReviewersAddedByHerald()), DifferentialReviewerStatus::STATUS_BLOCKING => array_keys($adapter->getBlockingReviewersAddedByHerald()));
     $old_reviewers = $object->getReviewerStatus();
     $old_reviewers = mpull($old_reviewers, null, 'getReviewerPHID');
     $value = array();
     foreach ($reviewers as $status => $phids) {
         foreach ($phids as $phid) {
             if ($phid == $object->getAuthorPHID()) {
                 // Don't try to add the revision's author as a reviewer, since this
                 // isn't valid and doesn't make sense.
                 continue;
             }
             // If the target is already a reviewer, don't try to change anything
             // if their current status is at least as strong as the new status.
             // For example, don't downgrade an "Accepted" to a "Blocking Reviewer".
             $old_reviewer = idx($old_reviewers, $phid);
             if ($old_reviewer) {
                 $old_status = $old_reviewer->getStatus();
                 $old_strength = DifferentialReviewerStatus::getStatusStrength($old_status);
                 $new_strength = DifferentialReviewerStatus::getStatusStrength($status);
                 if ($new_strength <= $old_strength) {
                     continue;
                 }
             }
             $value['+'][$phid] = array('data' => array('status' => $status));
         }
     }
     if ($value) {
         $edge_reviewer = DifferentialRevisionHasReviewerEdgeType::EDGECONST;
         $xactions[] = id(new DifferentialTransaction())->setTransactionType(PhabricatorTransactions::TYPE_EDGE)->setMetadataValue('edge:type', $edge_reviewer)->setNewValue($value);
     }
     // Require legalpad document signatures.
     $legal_phids = $adapter->getRequiredSignatureDocumentPHIDs();
     if ($legal_phids) {
         // We only require signatures of documents which have not already
         // been signed. In general, this reduces the amount of churn that
         // signature rules cause.
         $signatures = id(new LegalpadDocumentSignatureQuery())->setViewer(PhabricatorUser::getOmnipotentUser())->withDocumentPHIDs($legal_phids)->withSignerPHIDs(array($object->getAuthorPHID()))->execute();
         $signed_phids = mpull($signatures, 'getDocumentPHID');
         $legal_phids = array_diff($legal_phids, $signed_phids);
         // If we still have something to trigger, add the edges.
         if ($legal_phids) {
             $edge_legal = LegalpadObjectNeedsSignatureEdgeType::EDGECONST;
             $xactions[] = id(new DifferentialTransaction())->setTransactionType(PhabricatorTransactions::TYPE_EDGE)->setMetadataValue('edge:type', $edge_legal)->setNewValue(array('+' => array_fuse($legal_phids)));
         }
     }
     // Apply build plans.
     HarbormasterBuildable::applyBuildPlans($adapter->getDiff()->getPHID(), $adapter->getPHID(), $adapter->getBuildPlans());
     return $xactions;
 }
 private function getActionGroups(HeraldAdapter $adapter, array $action_map)
 {
     $group_map = array();
     foreach ($action_map as $action_key => $action_name) {
         $group_key = $adapter->getActionGroupKey($action_key);
         $group_map[$group_key][$action_key] = $action_name;
     }
     return $this->getGroups($group_map, HeraldActionGroup::getAllActionGroups());
 }
 protected function didApplyHeraldRules(PhabricatorLiskDAO $object, HeraldAdapter $adapter, HeraldTranscript $transcript)
 {
     $limit = self::MAX_FILES_SHOWN_IN_EMAIL;
     $files = $adapter->loadAffectedPaths();
     sort($files);
     if (count($files) > $limit) {
         array_splice($files, $limit);
         $files[] = pht('(This commit affected more than %d files. Only %d are shown here ' . 'and additional ones are truncated.)', $limit, $limit);
     }
     $this->affectedFiles = implode("\n", $files);
     return array();
 }
Exemple #16
0
 private function canRuleApplyToObject(HeraldRule $rule, HeraldAdapter $adapter)
 {
     // Rules which are not object rules can apply to anything.
     if (!$rule->isObjectRule()) {
         return true;
     }
     $trigger_phid = $rule->getTriggerObjectPHID();
     $object_phids = $adapter->getTriggerObjectPHIDs();
     if ($object_phids) {
         if (in_array($trigger_phid, $object_phids)) {
             return true;
         }
     }
     return false;
 }
 public function applyHeraldEffects(array $effects)
 {
     assert_instances_of($effects, 'HeraldEffect');
     $result = array();
     foreach ($effects as $effect) {
         $action = $effect->getAction();
         switch ($action) {
             case self::ACTION_NOTHING:
                 $result[] = new HeraldApplyTranscript($effect, true, pht('Great success at doing nothing.'));
                 break;
             case self::ACTION_EMAIL:
                 foreach ($effect->getTarget() as $phid) {
                     $this->emailPHIDs[$phid] = true;
                 }
                 $result[] = new HeraldApplyTranscript($effect, true, pht('Added address to email targets.'));
                 break;
             case self::ACTION_ADD_CC:
                 foreach ($effect->getTarget() as $phid) {
                     if (empty($this->addCCPHIDs[$phid])) {
                         $this->addCCPHIDs[$phid] = array();
                     }
                     $this->addCCPHIDs[$phid][] = $effect->getRuleID();
                 }
                 $result[] = new HeraldApplyTranscript($effect, true, pht('Added address to CC.'));
                 break;
             case self::ACTION_AUDIT:
                 foreach ($effect->getTarget() as $phid) {
                     if (empty($this->auditMap[$phid])) {
                         $this->auditMap[$phid] = array();
                     }
                     $this->auditMap[$phid][] = $effect->getRuleID();
                 }
                 $result[] = new HeraldApplyTranscript($effect, true, pht('Triggered an audit.'));
                 break;
             case self::ACTION_APPLY_BUILD_PLANS:
                 foreach ($effect->getTarget() as $phid) {
                     $this->buildPlans[] = $phid;
                 }
                 $result[] = new HeraldApplyTranscript($effect, true, pht('Applied build plans.'));
                 break;
             case self::ACTION_FLAG:
                 $result[] = parent::applyFlagEffect($effect, $this->commit->getPHID());
                 break;
             default:
                 $custom_result = parent::handleCustomHeraldEffect($effect);
                 if ($custom_result === null) {
                     throw new Exception(pht("No rules to handle action '%s'.", $action));
                 }
                 $result[] = $custom_result;
                 break;
         }
     }
     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_NOTHING:
                 $result[] = new HeraldApplyTranscript($effect, true, pht('Did nothing.'));
                 break;
             case self::ACTION_EMAIL:
                 foreach ($effect->getTarget() as $phid) {
                     $this->emailPHIDs[$phid] = $phid;
                 }
                 $result[] = new HeraldApplyTranscript($effect, true, pht('Added mailable to mail targets.'));
                 break;
             case self::ACTION_BLOCK:
                 $result[] = new HeraldApplyTranscript($effect, true, pht('Blocked push.'));
                 break;
             default:
                 $custom_result = parent::handleCustomHeraldEffect($effect);
                 if ($custom_result === null) {
                     throw new Exception(pht("No rules to handle action '%s'.", $action));
                 }
                 $result[] = $custom_result;
                 break;
         }
     }
     return $result;
 }
 protected function didApplyHeraldRules(PhabricatorLiskDAO $object, HeraldAdapter $adapter, HeraldTranscript $transcript)
 {
     // TODO: Convert these to transactions. The way Maniphest deals with these
     // transactions is currently unconventional and messy.
     $save_again = false;
     $cc_phids = $adapter->getCcPHIDs();
     if ($cc_phids) {
         $existing_cc = $object->getCCPHIDs();
         $new_cc = array_unique(array_merge($cc_phids, $existing_cc));
         $object->setCCPHIDs($new_cc);
         $object->save();
     }
     $this->heraldEmailPHIDs = $adapter->getEmailPHIDs();
     $xactions = array();
     $assign_phid = $adapter->getAssignPHID();
     if ($assign_phid) {
         $xactions[] = id(new ManiphestTransaction())->setTransactionType(ManiphestTransaction::TYPE_OWNER)->setNewValue($assign_phid);
     }
     $project_phids = $adapter->getProjectPHIDs();
     if ($project_phids) {
         $project_type = PhabricatorProjectObjectHasProjectEdgeType::EDGECONST;
         $xactions[] = id(new ManiphestTransaction())->setTransactionType(PhabricatorTransactions::TYPE_EDGE)->setMetadataValue('edge:type', $project_type)->setNewValue(array('+' => array_fuse($project_phids)));
     }
     return $xactions;
 }
 protected function didApplyHeraldRules(PhabricatorLiskDAO $object, HeraldAdapter $adapter, 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);
     }
     HarbormasterBuildable::applyBuildPlans($object->getPHID(), $object->getRepository()->getPHID(), $adapter->getBuildPlans());
     $limit = self::MAX_FILES_SHOWN_IN_EMAIL;
     $files = $adapter->loadAffectedPaths();
     sort($files);
     if (count($files) > $limit) {
         array_splice($files, $limit);
         $files[] = pht('(This commit affected more than %d files. Only %d are shown here ' . 'and additional ones are truncated.)', $limit, $limit);
     }
     $this->affectedFiles = implode("\n", $files);
     return $xactions;
 }
 public function getHeraldField($field)
 {
     switch ($field) {
         case self::FIELD_TITLE:
             return $this->getTask()->getTitle();
         case self::FIELD_BODY:
             return $this->getTask()->getDescription();
         case self::FIELD_AUTHOR:
             return $this->getTask()->getAuthorPHID();
         case self::FIELD_ASSIGNEE:
             return $this->getTask()->getOwnerPHID();
         case self::FIELD_PROJECTS:
             return PhabricatorEdgeQuery::loadDestinationPHIDs($this->getTask()->getPHID(), PhabricatorProjectObjectHasProjectEdgeType::EDGECONST);
         case self::FIELD_TASK_PRIORITY:
             return $this->getTask()->getPriority();
         case self::FIELD_TASK_STATUS:
             return $this->getTask()->getStatus();
     }
     return parent::getHeraldField($field);
 }
 protected function renderResultList(array $rules, PhabricatorSavedQuery $query, array $handles)
 {
     assert_instances_of($rules, 'HeraldRule');
     $viewer = $this->requireViewer();
     $content_type_map = HeraldAdapter::getEnabledAdapterMap($viewer);
     $list = id(new PHUIObjectItemListView())->setUser($viewer);
     foreach ($rules as $rule) {
         $id = $rule->getID();
         $item = id(new PHUIObjectItemView())->setObjectName("H{$id}")->setHeader($rule->getName())->setHref($this->getApplicationURI("rule/{$id}/"));
         if ($rule->isPersonalRule()) {
             $item->addIcon('fa-user', pht('Personal Rule'));
             $item->addByline(pht('Authored by %s', $handles[$rule->getAuthorPHID()]->renderLink()));
         } else {
             if ($rule->isObjectRule()) {
                 $item->addIcon('fa-briefcase', pht('Object Rule'));
             } else {
                 $item->addIcon('fa-globe', pht('Global Rule'));
             }
         }
         if ($rule->getIsDisabled()) {
             $item->setDisabled(true);
             $item->addIcon('fa-lock grey', pht('Disabled'));
         }
         $item->addAction(id(new PHUIListItemView())->setHref($this->getApplicationURI("history/{$id}/"))->setIcon('fa-file-text-o')->setName(pht('Edit Log')));
         $content_type_name = idx($content_type_map, $rule->getContentType());
         $item->addAttribute(pht('Affects: %s', $content_type_name));
         $list->addItem($item);
     }
     $result = new PhabricatorApplicationSearchResultView();
     $result->setObjectList($list);
     $result->setNoDataString(pht('No rules found.'));
     return $result;
 }
 private function applyHeraldRules(array $updates, HeraldAdapter $adapter_template, array $all_updates)
 {
     if (!$updates) {
         return;
     }
     $adapter_template->setHookEngine($this);
     $engine = new HeraldEngine();
     $rules = null;
     $blocking_effect = null;
     $blocked_update = null;
     $blocking_xscript = null;
     foreach ($updates as $update) {
         $adapter = id(clone $adapter_template)->setPushLog($update);
         if ($rules === null) {
             $rules = $engine->loadRulesForAdapter($adapter);
         }
         $effects = $engine->applyRules($rules, $adapter);
         $engine->applyEffects($effects, $adapter, $rules);
         $xscript = $engine->getTranscript();
         // Store any PHIDs we want to send email to for later.
         foreach ($adapter->getEmailPHIDs() as $email_phid) {
             $this->emailPHIDs[$email_phid] = $email_phid;
         }
         $block_action = DiffusionBlockHeraldAction::ACTIONCONST;
         if ($blocking_effect === null) {
             foreach ($effects as $effect) {
                 if ($effect->getAction() == $block_action) {
                     $blocking_effect = $effect;
                     $blocked_update = $update;
                     $blocking_xscript = $xscript;
                     break;
                 }
             }
         }
     }
     if ($blocking_effect) {
         $rule = $blocking_effect->getRule();
         $this->rejectCode = PhabricatorRepositoryPushLog::REJECT_HERALD;
         $this->rejectDetails = $rule->getPHID();
         $message = $blocking_effect->getTarget();
         if (!strlen($message)) {
             $message = pht('(None.)');
         }
         $blocked_ref_name = coalesce($blocked_update->getRefName(), $blocked_update->getRefNewShort());
         $blocked_name = $blocked_update->getRefType() . '/' . $blocked_ref_name;
         throw new DiffusionCommitHookRejectException(pht("This push was rejected by Herald push rule %s.\n" . "    Change: %s\n" . "      Rule: %s\n" . "    Reason: %s\n" . "Transcript: %s", $rule->getMonogram(), $blocked_name, $rule->getName(), $message, PhabricatorEnv::getProductionURI('/herald/transcript/' . $blocking_xscript->getID() . '/')));
     }
 }
 public function getHeraldField($field)
 {
     $data = $this->commitData;
     switch ($field) {
         case self::FIELD_BODY:
             return $data->getCommitMessage();
         case self::FIELD_AUTHOR:
             return $data->getCommitDetail('authorPHID');
         case self::FIELD_COMMITTER:
             return $data->getCommitDetail('committerPHID');
         case self::FIELD_REVIEWER:
             return $data->getCommitDetail('reviewerPHID');
         case self::FIELD_DIFF_FILE:
             return $this->loadAffectedPaths();
         case self::FIELD_REPOSITORY:
             return $this->repository->getPHID();
         case self::FIELD_REPOSITORY_PROJECTS:
             return $this->repository->getProjectPHIDs();
         case self::FIELD_DIFF_CONTENT:
             return $this->getDiffContent('*');
         case self::FIELD_DIFF_ADDED_CONTENT:
             return $this->getDiffContent('+');
         case self::FIELD_DIFF_REMOVED_CONTENT:
             return $this->getDiffContent('-');
         case self::FIELD_DIFF_ENORMOUS:
             $this->getDiffContent('*');
             return $this->commitDiff instanceof Exception;
         case self::FIELD_AFFECTED_PACKAGE:
             $packages = $this->loadAffectedPackages();
             return mpull($packages, 'getPHID');
         case self::FIELD_AFFECTED_PACKAGE_OWNER:
             $packages = $this->loadAffectedPackages();
             $owners = PhabricatorOwnersOwner::loadAllForPackages($packages);
             return mpull($owners, 'getUserPHID');
         case self::FIELD_NEED_AUDIT_FOR_PACKAGE:
             return $this->loadAuditNeededPackage();
         case self::FIELD_DIFFERENTIAL_REVISION:
             $revision = $this->loadDifferentialRevision();
             if (!$revision) {
                 return null;
             }
             return $revision->getID();
         case self::FIELD_DIFFERENTIAL_ACCEPTED:
             $revision = $this->loadDifferentialRevision();
             if (!$revision) {
                 return null;
             }
             $status = $data->getCommitDetail('precommitRevisionStatus', $revision->getStatus());
             switch ($status) {
                 case ArcanistDifferentialRevisionStatus::ACCEPTED:
                 case ArcanistDifferentialRevisionStatus::CLOSED:
                     return $revision->getPHID();
             }
             return null;
         case self::FIELD_DIFFERENTIAL_REVIEWERS:
             $revision = $this->loadDifferentialRevision();
             if (!$revision) {
                 return array();
             }
             return $revision->getReviewers();
         case self::FIELD_DIFFERENTIAL_CCS:
             $revision = $this->loadDifferentialRevision();
             if (!$revision) {
                 return array();
             }
             return $revision->getCCPHIDs();
         case self::FIELD_BRANCHES:
             $params = array('callsign' => $this->repository->getCallsign(), 'contains' => $this->commit->getCommitIdentifier());
             $result = id(new ConduitCall('diffusion.branchquery', $params))->setUser(PhabricatorUser::getOmnipotentUser())->execute();
             $refs = DiffusionRepositoryRef::loadAllFromDictionaries($result);
             return mpull($refs, 'getShortName');
         case self::FIELD_REPOSITORY_AUTOCLOSE_BRANCH:
             return $this->repository->shouldAutocloseCommit($this->commit);
     }
     return parent::getHeraldField($field);
 }
 public function applyHeraldEffects(array $effects)
 {
     assert_instances_of($effects, 'HeraldEffect');
     $result = array();
     foreach ($effects as $effect) {
         $action = $effect->getAction();
         switch ($action) {
             case self::ACTION_NOTHING:
                 $result[] = new HeraldApplyTranscript($effect, true, pht('Great success at doing nothing.'));
                 break;
             case self::ACTION_ADD_CC:
                 foreach ($effect->getTarget() as $phid) {
                     $this->ccPHIDs[] = $phid;
                 }
                 $result[] = new HeraldApplyTranscript($effect, true, pht('Added address to cc list.'));
                 break;
             case self::ACTION_FLAG:
                 $result[] = parent::applyFlagEffect($effect, $this->getMock()->getPHID());
                 break;
             default:
                 $custom_result = parent::handleCustomHeraldEffect($effect);
                 if ($custom_result === null) {
                     throw new Exception(pht("No rules to handle action '%s'.", $action));
                 }
                 $result[] = $custom_result;
                 break;
         }
     }
     return $result;
 }
 protected function didApplyHeraldRules(PhabricatorLiskDAO $object, HeraldAdapter $adapter, HeraldTranscript $transcript)
 {
     $xactions = array();
     $assign_phid = $adapter->getAssignPHID();
     if ($assign_phid) {
         $xactions[] = id(new ManiphestTransaction())->setTransactionType(ManiphestTransaction::TYPE_OWNER)->setNewValue($assign_phid);
     }
     return $xactions;
 }