public function processRequest()
 {
     $request = $this->getRequest();
     $user = $request->getUser();
     $content_type_map = HeraldContentTypeConfig::getContentTypeMap();
     if (empty($content_type_map[$this->contentType])) {
         $this->contentType = head_key($content_type_map);
     }
     $rule_type_map = HeraldRuleTypeConfig::getRuleTypeMap();
     if (empty($rule_type_map[$this->ruleType])) {
         $this->ruleType = HeraldRuleTypeConfig::RULE_TYPE_PERSONAL;
     }
     // Reorder array to put "personal" first.
     $rule_type_map = array_select_keys($rule_type_map, array(HeraldRuleTypeConfig::RULE_TYPE_PERSONAL)) + $rule_type_map;
     $captions = array(HeraldRuleTypeConfig::RULE_TYPE_PERSONAL => 'Personal rules notify you about events. You own them, but they can ' . 'only affect you.', HeraldRuleTypeConfig::RULE_TYPE_GLOBAL => 'Global rules notify anyone about events. No one owns them, and ' . 'anyone can edit them. Usually, Global rules are used to notify ' . 'mailing lists.');
     $radio = id(new AphrontFormRadioButtonControl())->setLabel('Type')->setName('rule_type')->setValue($this->ruleType);
     foreach ($rule_type_map as $value => $name) {
         $radio->addButton($value, $name, idx($captions, $value));
     }
     $form = id(new AphrontFormView())->setUser($user)->setAction('/herald/rule/')->appendChild(id(new AphrontFormSelectControl())->setLabel('New rule for')->setName('content_type')->setValue($this->contentType)->setOptions($content_type_map))->appendChild($radio)->appendChild(id(new AphrontFormSubmitControl())->setValue('Create Rule')->addCancelButton('/herald/view/' . $this->contentType . '/'));
     $panel = new AphrontPanelView();
     $panel->setHeader('Create New Herald Rule');
     $panel->setWidth(AphrontPanelView::WIDTH_FULL);
     $panel->appendChild($form);
     $nav = $this->renderNav();
     $nav->selectFilter('new');
     $nav->appendChild($panel);
     return $this->buildStandardPageResponse($nav, array('title' => 'Create Herald Rule'));
 }
 private function buildPropertySectionView(HeraldRule $rule)
 {
     $viewer = $this->getRequest()->getUser();
     $view = id(new PHUIPropertyListView())->setUser($viewer);
     $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()));
         }
     }
     return $view;
 }
 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;
 }
 public function render()
 {
     $type_map = HeraldRuleTypeConfig::getRuleTypeMap();
     $rows = array();
     foreach ($this->rules as $rule) {
         if ($rule->getRuleType() == HeraldRuleTypeConfig::RULE_TYPE_GLOBAL) {
             $author = null;
         } else {
             $author = $this->handles[$rule->getAuthorPHID()]->renderLink();
         }
         $name = phutil_render_tag('a', array('href' => '/herald/rule/' . $rule->getID() . '/'), phutil_escape_html($rule->getName()));
         $edit_log = phutil_render_tag('a', array('href' => '/herald/history/' . $rule->getID() . '/'), 'View Edit Log');
         $delete = javelin_render_tag('a', array('href' => '/herald/delete/' . $rule->getID() . '/', 'sigil' => 'workflow', 'class' => 'button small grey'), 'Delete');
         $rows[] = array($type_map[$rule->getRuleType()], $author, $name, $edit_log, $delete);
     }
     $table = new AphrontTableView($rows);
     $table->setNoDataString("No matching rules.");
     $table->setHeaders(array('Rule Type', 'Author', 'Rule Name', 'Edit Log', ''));
     $table->setColumnClasses(array('', '', 'wide pri', '', 'action'));
     $table->setColumnVisibility(array($this->showRuleType, $this->showAuthor, true, true, true));
     return $table->render();
 }
 public function processRequest()
 {
     $request = $this->getRequest();
     $user = $request->getUser();
     $content_type_map = HeraldAdapter::getEnabledAdapterMap($user);
     $rule_type_map = HeraldRuleTypeConfig::getRuleTypeMap();
     if ($this->id) {
         $id = $this->id;
         $rule = id(new HeraldRuleQuery())->setViewer($user)->withIDs(array($id))->requireCapabilities(array(PhabricatorPolicyCapability::CAN_VIEW, PhabricatorPolicyCapability::CAN_EDIT))->executeOne();
         if (!$rule) {
             return new Aphront404Response();
         }
         $cancel_uri = $this->getApplicationURI("rule/{$id}/");
     } else {
         $rule = new HeraldRule();
         $rule->setAuthorPHID($user->getPHID());
         $rule->setMustMatchAll(1);
         $content_type = $request->getStr('content_type');
         $rule->setContentType($content_type);
         $rule_type = $request->getStr('rule_type');
         if (!isset($rule_type_map[$rule_type])) {
             $rule_type = HeraldRuleTypeConfig::RULE_TYPE_PERSONAL;
         }
         $rule->setRuleType($rule_type);
         $adapter = HeraldAdapter::getAdapterForContentType($rule->getContentType());
         if (!$adapter->supportsRuleType($rule->getRuleType())) {
             throw new Exception(pht("This rule's content type does not support the selected rule " . "type."));
         }
         if ($rule->isObjectRule()) {
             $rule->setTriggerObjectPHID($request->getStr('targetPHID'));
             $object = id(new PhabricatorObjectQuery())->setViewer($user)->withPHIDs(array($rule->getTriggerObjectPHID()))->requireCapabilities(array(PhabricatorPolicyCapability::CAN_VIEW, PhabricatorPolicyCapability::CAN_EDIT))->executeOne();
             if (!$object) {
                 throw new Exception(pht('No valid object provided for object rule!'));
             }
             if (!$adapter->canTriggerOnObject($object)) {
                 throw new Exception(pht('Object is of wrong type for adapter!'));
             }
         }
         $cancel_uri = $this->getApplicationURI();
     }
     if ($rule->isGlobalRule()) {
         $this->requireApplicationCapability(HeraldManageGlobalRulesCapability::CAPABILITY);
     }
     $adapter = HeraldAdapter::getAdapterForContentType($rule->getContentType());
     $local_version = id(new HeraldRule())->getConfigVersion();
     if ($rule->getConfigVersion() > $local_version) {
         throw new Exception(pht('This rule was created with a newer version of Herald. You can not ' . 'view or edit it in this older version. Upgrade your Phabricator ' . 'deployment.'));
     }
     // Upgrade rule version to our version, since we might add newly-defined
     // conditions, etc.
     $rule->setConfigVersion($local_version);
     $rule_conditions = $rule->loadConditions();
     $rule_actions = $rule->loadActions();
     $rule->attachConditions($rule_conditions);
     $rule->attachActions($rule_actions);
     $e_name = true;
     $errors = array();
     if ($request->isFormPost() && $request->getStr('save')) {
         list($e_name, $errors) = $this->saveRule($adapter, $rule, $request);
         if (!$errors) {
             $id = $rule->getID();
             $uri = $this->getApplicationURI("rule/{$id}/");
             return id(new AphrontRedirectResponse())->setURI($uri);
         }
     }
     $must_match_selector = $this->renderMustMatchSelector($rule);
     $repetition_selector = $this->renderRepetitionSelector($rule, $adapter);
     $handles = $this->loadHandlesForRule($rule);
     require_celerity_resource('herald-css');
     $content_type_name = $content_type_map[$rule->getContentType()];
     $rule_type_name = $rule_type_map[$rule->getRuleType()];
     $form = id(new AphrontFormView())->setUser($user)->setID('herald-rule-edit-form')->addHiddenInput('content_type', $rule->getContentType())->addHiddenInput('rule_type', $rule->getRuleType())->addHiddenInput('save', 1)->appendChild(javelin_tag('input', array('type' => 'hidden', 'name' => 'rule', 'sigil' => 'rule')))->appendChild(id(new AphrontFormTextControl())->setLabel(pht('Rule Name'))->setName('name')->setError($e_name)->setValue($rule->getName()));
     $trigger_object_control = false;
     if ($rule->isObjectRule()) {
         $trigger_object_control = id(new AphrontFormStaticControl())->setValue(pht('This rule triggers for %s.', $handles[$rule->getTriggerObjectPHID()]->renderLink()));
     }
     $form->appendChild(id(new AphrontFormMarkupControl())->setValue(pht('This %s rule triggers for %s.', phutil_tag('strong', array(), $rule_type_name), phutil_tag('strong', array(), $content_type_name))))->appendChild($trigger_object_control)->appendChild(id(new PHUIFormInsetView())->setTitle(pht('Conditions'))->setRightButton(javelin_tag('a', array('href' => '#', 'class' => 'button green', 'sigil' => 'create-condition', 'mustcapture' => true), pht('New Condition')))->setDescription(pht('When %s these conditions are met:', $must_match_selector))->setContent(javelin_tag('table', array('sigil' => 'rule-conditions', 'class' => 'herald-condition-table'), '')))->appendChild(id(new PHUIFormInsetView())->setTitle(pht('Action'))->setRightButton(javelin_tag('a', array('href' => '#', 'class' => 'button green', 'sigil' => 'create-action', 'mustcapture' => true), pht('New Action')))->setDescription(pht('Take these actions %s this rule matches:', $repetition_selector))->setContent(javelin_tag('table', array('sigil' => 'rule-actions', 'class' => 'herald-action-table'), '')))->appendChild(id(new AphrontFormSubmitControl())->setValue(pht('Save Rule'))->addCancelButton($cancel_uri));
     $this->setupEditorBehavior($rule, $handles, $adapter);
     $title = $rule->getID() ? pht('Edit Herald Rule') : pht('Create Herald Rule');
     $form_box = id(new PHUIObjectBoxView())->setHeaderText($title)->setFormErrors($errors)->setForm($form);
     $crumbs = $this->buildApplicationCrumbs()->addTextCrumb($title);
     return $this->buildApplicationPage(array($crumbs, $form_box), array('title' => pht('Edit Rule')));
 }
 public function handleRequest(AphrontRequest $request)
 {
     $viewer = $request->getViewer();
     $content_type_map = HeraldAdapter::getEnabledAdapterMap($viewer);
     $rule_type_map = HeraldRuleTypeConfig::getRuleTypeMap();
     $errors = array();
     $e_type = null;
     $e_rule = null;
     $e_object = null;
     $step = $request->getInt('step');
     if ($request->isFormPost()) {
         $content_type = $request->getStr('content_type');
         if (empty($content_type_map[$content_type])) {
             $errors[] = pht('You must choose a content type for this rule.');
             $e_type = pht('Required');
             $step = 0;
         }
         if (!$errors && $step > 1) {
             $rule_type = $request->getStr('rule_type');
             if (empty($rule_type_map[$rule_type])) {
                 $errors[] = pht('You must choose a rule type for this rule.');
                 $e_rule = pht('Required');
                 $step = 1;
             }
         }
         if (!$errors && $step >= 2) {
             $target_phid = null;
             $object_name = $request->getStr('objectName');
             $done = false;
             if ($rule_type != HeraldRuleTypeConfig::RULE_TYPE_OBJECT) {
                 $done = true;
             } else {
                 if (strlen($object_name)) {
                     $target_object = id(new PhabricatorObjectQuery())->setViewer($viewer)->withNames(array($object_name))->executeOne();
                     if ($target_object) {
                         $can_edit = PhabricatorPolicyFilter::hasCapability($viewer, $target_object, PhabricatorPolicyCapability::CAN_EDIT);
                         if (!$can_edit) {
                             $errors[] = pht('You can not create a rule for that object, because you do ' . 'not have permission to edit it. You can only create rules ' . 'for objects you can edit.');
                             $e_object = pht('Not Editable');
                             $step = 2;
                         } else {
                             $adapter = HeraldAdapter::getAdapterForContentType($content_type);
                             if (!$adapter->canTriggerOnObject($target_object)) {
                                 $errors[] = pht('This object is not of an allowed type for the rule. ' . 'Rules can only trigger on certain objects.');
                                 $e_object = pht('Invalid');
                                 $step = 2;
                             } else {
                                 $target_phid = $target_object->getPHID();
                                 $done = true;
                             }
                         }
                     } else {
                         $errors[] = pht('No object exists by that name.');
                         $e_object = pht('Invalid');
                         $step = 2;
                     }
                 } else {
                     if ($step > 2) {
                         $errors[] = pht('You must choose an object to associate this rule with.');
                         $e_object = pht('Required');
                         $step = 2;
                     }
                 }
             }
             if (!$errors && $done) {
                 $uri = id(new PhutilURI('edit/'))->setQueryParams(array('content_type' => $content_type, 'rule_type' => $rule_type, 'targetPHID' => $target_phid));
                 $uri = $this->getApplicationURI($uri);
                 return id(new AphrontRedirectResponse())->setURI($uri);
             }
         }
     }
     $content_type = $request->getStr('content_type');
     $rule_type = $request->getStr('rule_type');
     $form = id(new AphrontFormView())->setUser($viewer)->setAction($this->getApplicationURI('new/'));
     switch ($step) {
         case 0:
         default:
             $content_types = $this->renderContentTypeControl($content_type_map, $e_type);
             $form->addHiddenInput('step', 1)->appendChild($content_types);
             $cancel_text = null;
             $cancel_uri = $this->getApplicationURI();
             break;
         case 1:
             $rule_types = $this->renderRuleTypeControl($rule_type_map, $e_rule);
             $form->addHiddenInput('content_type', $content_type)->addHiddenInput('step', 2)->appendChild(id(new AphrontFormStaticControl())->setLabel(pht('Rule for'))->setValue(phutil_tag('strong', array(), idx($content_type_map, $content_type))))->appendChild($rule_types);
             $cancel_text = pht('Back');
             $cancel_uri = id(new PhutilURI('new/'))->setQueryParams(array('content_type' => $content_type, 'step' => 0));
             $cancel_uri = $this->getApplicationURI($cancel_uri);
             break;
         case 2:
             $adapter = HeraldAdapter::getAdapterForContentType($content_type);
             $form->addHiddenInput('content_type', $content_type)->addHiddenInput('rule_type', $rule_type)->addHiddenInput('step', 3)->appendChild(id(new AphrontFormStaticControl())->setLabel(pht('Rule for'))->setValue(phutil_tag('strong', array(), idx($content_type_map, $content_type))))->appendChild(id(new AphrontFormStaticControl())->setLabel(pht('Rule Type'))->setValue(phutil_tag('strong', array(), idx($rule_type_map, $rule_type))))->appendRemarkupInstructions(pht('Choose the object this rule will act on (for example, enter ' . '`rX` to act on the `rX` repository, or `#project` to act on ' . 'a project).'))->appendRemarkupInstructions($adapter->explainValidTriggerObjects())->appendChild(id(new AphrontFormTextControl())->setName('objectName')->setError($e_object)->setValue($request->getStr('objectName'))->setLabel(pht('Object')));
             $cancel_text = pht('Back');
             $cancel_uri = id(new PhutilURI('new/'))->setQueryParams(array('content_type' => $content_type, 'rule_type' => $rule_type, 'step' => 1));
             $cancel_uri = $this->getApplicationURI($cancel_uri);
             break;
     }
     $form->appendChild(id(new AphrontFormSubmitControl())->setValue(pht('Continue'))->addCancelButton($cancel_uri, $cancel_text));
     $form_box = id(new PHUIObjectBoxView())->setFormErrors($errors)->setHeaderText(pht('Create Herald Rule'))->setForm($form);
     $crumbs = $this->buildApplicationCrumbs()->addTextCrumb(pht('Create Rule'));
     return $this->buildApplicationPage(array($crumbs, $form_box), array('title' => pht('Create Herald Rule')));
 }
 private function getRuleTypeValues()
 {
     return array_fuse(array_keys(HeraldRuleTypeConfig::getRuleTypeMap()));
 }
 public function processRequest()
 {
     $request = $this->getRequest();
     $user = $request->getUser();
     $content_type_map = HeraldContentTypeConfig::getContentTypeMap();
     $rule_type_map = HeraldRuleTypeConfig::getRuleTypeMap();
     if ($this->id) {
         $rule = id(new HeraldRule())->load($this->id);
         if (!$rule) {
             return new Aphront404Response();
         }
         if (!$this->canEditRule($rule, $user)) {
             throw new Exception("You don't own this rule and can't edit it.");
         }
     } else {
         $rule = new HeraldRule();
         $rule->setAuthorPHID($user->getPHID());
         $rule->setMustMatchAll(true);
         $content_type = $request->getStr('content_type');
         if (!isset($content_type_map[$content_type])) {
             $content_type = HeraldContentTypeConfig::CONTENT_TYPE_DIFFERENTIAL;
         }
         $rule->setContentType($content_type);
         $rule_type = $request->getStr('rule_type');
         if (!isset($rule_type_map[$rule_type])) {
             $rule_type = HeraldRuleTypeConfig::RULE_TYPE_GLOBAL;
         }
         $rule->setRuleType($rule_type);
     }
     $local_version = id(new HeraldRule())->getConfigVersion();
     if ($rule->getConfigVersion() > $local_version) {
         throw new Exception("This rule was created with a newer version of Herald. You can not " . "view or edit it in this older version. Upgrade your Phabricator " . "deployment.");
     }
     // Upgrade rule version to our version, since we might add newly-defined
     // conditions, etc.
     $rule->setConfigVersion($local_version);
     $rule_conditions = $rule->loadConditions();
     $rule_actions = $rule->loadActions();
     $rule->attachConditions($rule_conditions);
     $rule->attachActions($rule_actions);
     $e_name = true;
     $errors = array();
     if ($request->isFormPost() && $request->getStr('save')) {
         list($e_name, $errors) = $this->saveRule($rule, $request);
         if (!$errors) {
             $uri = '/herald/view/' . $rule->getContentType() . '/' . $rule->getRuleType() . '/';
             return id(new AphrontRedirectResponse())->setURI($uri);
         }
     }
     if ($errors) {
         $error_view = new AphrontErrorView();
         $error_view->setTitle('Form Errors');
         $error_view->setErrors($errors);
     } else {
         $error_view = null;
     }
     $must_match_selector = $this->renderMustMatchSelector($rule);
     $repetition_selector = $this->renderRepetitionSelector($rule);
     $handles = $this->loadHandlesForRule($rule);
     require_celerity_resource('herald-css');
     $content_type_name = $content_type_map[$rule->getContentType()];
     $rule_type_name = $rule_type_map[$rule->getRuleType()];
     $form = id(new AphrontFormView())->setUser($user)->setID('herald-rule-edit-form')->addHiddenInput('content_type', $rule->getContentType())->addHiddenInput('rule_type', $rule->getRuleType())->addHiddenInput('save', 1)->appendChild(javelin_render_tag('input', array('type' => 'hidden', 'name' => 'rule', 'sigil' => 'rule')))->appendChild(id(new AphrontFormTextControl())->setLabel('Rule Name')->setName('name')->setError($e_name)->setValue($rule->getName()));
     $form->appendChild(id(new AphrontFormMarkupControl())->setValue("This <strong>{$rule_type_name}</strong> rule triggers for " . "<strong>{$content_type_name}</strong>."))->appendChild(id(new AphrontFormInsetView())->setTitle('Conditions')->setRightButton(javelin_render_tag('a', array('href' => '#', 'class' => 'button green', 'sigil' => 'create-condition', 'mustcapture' => true), 'Create New Condition'))->setDescription('When ' . $must_match_selector . ' these conditions are met:')->setContent(javelin_render_tag('table', array('sigil' => 'rule-conditions', 'class' => 'herald-condition-table'), '')))->appendChild(id(new AphrontFormInsetView())->setTitle('Action')->setRightButton(javelin_render_tag('a', array('href' => '#', 'class' => 'button green', 'sigil' => 'create-action', 'mustcapture' => true), 'Create New Action'))->setDescription('Take these actions ' . $repetition_selector . ' this rule matches:')->setContent(javelin_render_tag('table', array('sigil' => 'rule-actions', 'class' => 'herald-action-table'), '')))->appendChild(id(new AphrontFormSubmitControl())->setValue('Save Rule')->addCancelButton('/herald/view/' . $rule->getContentType() . '/'));
     $this->setupEditorBehavior($rule, $handles);
     $panel = new AphrontPanelView();
     $panel->setHeader($rule->getID() ? 'Edit Herald Rule' : 'Create Herald Rule');
     $panel->setWidth(AphrontPanelView::WIDTH_WIDE);
     $panel->appendChild($form);
     $nav = $this->renderNav();
     $nav->selectFilter('view/' . $rule->getContentType() . '/' . $rule->getRuleType());
     $nav->appendChild(array($error_view, $panel));
     return $this->buildStandardPageResponse($nav, array('title' => 'Edit Rule'));
 }