Path: blob/master/src/applications/herald/controller/HeraldNewController.php
12256 views
<?php12final class HeraldNewController extends HeraldController {34public function handleRequest(AphrontRequest $request) {5$viewer = $this->getViewer();67$adapter_type_map = HeraldAdapter::getEnabledAdapterMap($viewer);8$adapter_type = $request->getStr('adapter');910if (!isset($adapter_type_map[$adapter_type])) {11$title = pht('Create Herald Rule');12$content = $this->newAdapterMenu($title);13} else {14$adapter = HeraldAdapter::getAdapterForContentType($adapter_type);1516$rule_type_map = HeraldRuleTypeConfig::getRuleTypeMap();17$rule_type = $request->getStr('type');1819if (!isset($rule_type_map[$rule_type])) {20$title = pht(21'Create Herald Rule: %s',22$adapter->getAdapterContentName());2324$content = $this->newTypeMenu($adapter, $title);25} else {26if ($rule_type !== HeraldRuleTypeConfig::RULE_TYPE_OBJECT) {27$target_phid = null;28$target_okay = true;29} else {30$object_name = $request->getStr('objectName');31$target_okay = false;3233$errors = array();34$e_object = null;3536if ($request->isFormPost()) {37if (strlen($object_name)) {38$target_object = id(new PhabricatorObjectQuery())39->setViewer($viewer)40->withNames(array($object_name))41->executeOne();42if ($target_object) {43$can_edit = PhabricatorPolicyFilter::hasCapability(44$viewer,45$target_object,46PhabricatorPolicyCapability::CAN_EDIT);47if (!$can_edit) {48$errors[] = pht(49'You can not create a rule for that object, because you '.50'do not have permission to edit it. You can only create '.51'rules for objects you can edit.');52$e_object = pht('Not Editable');53} else {54if (!$adapter->canTriggerOnObject($target_object)) {55$errors[] = pht(56'This object is not of an allowed type for the rule. '.57'Rules can only trigger on certain objects.');58$e_object = pht('Invalid');59} else {60$target_phid = $target_object->getPHID();61}62}63} else {64$errors[] = pht('No object exists by that name.');65$e_object = pht('Invalid');66}67} else {68$errors[] = pht(69'You must choose an object to associate this rule with.');70$e_object = pht('Required');71}7273$target_okay = !$errors;74}75}7677if (!$target_okay) {78$title = pht('Choose Object');79$content = $this->newTargetForm(80$adapter,81$rule_type,82$object_name,83$errors,84$e_object,85$title);86} else {87$params = array(88'content_type' => $adapter_type,89'rule_type' => $rule_type,90'targetPHID' => $target_phid,91);9293$edit_uri = $this->getApplicationURI('edit/');94$edit_uri = new PhutilURI($edit_uri, $params);9596return id(new AphrontRedirectResponse())97->setURI($edit_uri);98}99}100}101102$crumbs = $this103->buildApplicationCrumbs()104->addTextCrumb(pht('Create Rule'))105->setBorder(true);106107$view = id(new PHUITwoColumnView())108->setFooter($content);109110return $this->newPage()111->setTitle($title)112->setCrumbs($crumbs)113->appendChild($view);114}115116private function newAdapterMenu($title) {117$viewer = $this->getViewer();118119$types = HeraldAdapter::getEnabledAdapterMap($viewer);120121foreach ($types as $key => $type) {122$types[$key] = HeraldAdapter::getAdapterForContentType($key);123}124125$types = msort($types, 'getAdapterContentName');126127$base_uri = $this->getApplicationURI('create/');128129$menu = id(new PHUIObjectItemListView())130->setViewer($viewer)131->setBig(true);132133foreach ($types as $key => $adapter) {134$adapter_uri = id(new PhutilURI($base_uri))135->replaceQueryParam('adapter', $key);136137$description = $adapter->getAdapterContentDescription();138$description = phutil_escape_html_newlines($description);139140$item = id(new PHUIObjectItemView())141->setHeader($adapter->getAdapterContentName())142->setImageIcon($adapter->getAdapterContentIcon())143->addAttribute($description)144->setHref($adapter_uri)145->setClickable(true);146147$menu->addItem($item);148}149150$box = id(new PHUIObjectBoxView())151->setHeaderText($title)152->setBackground(PHUIObjectBoxView::WHITE_CONFIG)153->setObjectList($menu);154155return id(new PHUILauncherView())156->appendChild($box);157}158159private function newTypeMenu(HeraldAdapter $adapter, $title) {160$viewer = $this->getViewer();161162$global_capability = HeraldManageGlobalRulesCapability::CAPABILITY;163$can_global = $this->hasApplicationCapability($global_capability);164165if ($can_global) {166$global_note = pht(167'You have permission to create and manage global rules.');168} else {169$global_note = pht(170'You do not have permission to create or manage global rules.');171}172$global_note = phutil_tag('em', array(), $global_note);173174$specs = array(175HeraldRuleTypeConfig::RULE_TYPE_PERSONAL => array(176'name' => pht('Personal Rule'),177'icon' => 'fa-user',178'help' => pht(179'Personal rules notify you about events. You own them, but they can '.180'only affect you. Personal rules only trigger for objects you have '.181'permission to see.'),182'enabled' => true,183),184HeraldRuleTypeConfig::RULE_TYPE_OBJECT => array(185'name' => pht('Object Rule'),186'icon' => 'fa-cube',187'help' => pht(188'Object rules notify anyone about events. They are bound to an '.189'object (like a repository) and can only act on that object. You '.190'must be able to edit an object to create object rules for it. '.191'Other users who can edit the object can edit its rules.'),192'enabled' => true,193),194HeraldRuleTypeConfig::RULE_TYPE_GLOBAL => array(195'name' => pht('Global Rule'),196'icon' => 'fa-globe',197'help' => array(198pht(199'Global rules notify anyone about events. Global rules can '.200'bypass access control policies and act on any object.'),201$global_note,202),203'enabled' => $can_global,204),205);206207$adapter_type = $adapter->getAdapterContentType();208209$base_uri = new PhutilURI($this->getApplicationURI('create/'));210211$adapter_uri = id(clone $base_uri)212->replaceQueryParam('adapter', $adapter_type);213214$menu = id(new PHUIObjectItemListView())215->setUser($viewer)216->setBig(true);217218foreach ($specs as $rule_type => $spec) {219$type_uri = id(clone $adapter_uri)220->replaceQueryParam('type', $rule_type);221222$name = $spec['name'];223$icon = $spec['icon'];224225$description = $spec['help'];226$description = (array)$description;227228$enabled = $spec['enabled'];229if ($enabled) {230$enabled = $adapter->supportsRuleType($rule_type);231if (!$enabled) {232$description[] = phutil_tag(233'em',234array(),235pht(236'This rule type is not supported by the selected '.237'content type.'));238}239}240241$description = phutil_implode_html(242array(243phutil_tag('br'),244phutil_tag('br'),245),246$description);247248$item = id(new PHUIObjectItemView())249->setHeader($name)250->setImageIcon($icon)251->addAttribute($description);252253if ($enabled) {254$item255->setHref($type_uri)256->setClickable(true);257} else {258$item->setDisabled(true);259}260261$menu->addItem($item);262}263264$box = id(new PHUIObjectBoxView())265->setHeaderText($title)266->setBackground(PHUIObjectBoxView::WHITE_CONFIG)267->setObjectList($menu);268269$box->newTailButton()270->setText(pht('Back to Content Types'))271->setIcon('fa-chevron-left')272->setHref($base_uri);273274return id(new PHUILauncherView())275->appendChild($box);276}277278279private function newTargetForm(280HeraldAdapter $adapter,281$rule_type,282$object_name,283$errors,284$e_object,285$title) {286287$viewer = $this->getViewer();288$content_type = $adapter->getAdapterContentType();289$rule_type_map = HeraldRuleTypeConfig::getRuleTypeMap();290291$params = array(292'adapter' => $content_type,293'type' => $rule_type,294);295296$form = id(new AphrontFormView())297->setViewer($viewer)298->appendChild(299id(new AphrontFormStaticControl())300->setLabel(pht('Rule for'))301->setValue(302phutil_tag(303'strong',304array(),305$adapter->getAdapterContentName())))306->appendChild(307id(new AphrontFormStaticControl())308->setLabel(pht('Rule Type'))309->setValue(310phutil_tag(311'strong',312array(),313idx($rule_type_map, $rule_type))))314->appendRemarkupInstructions(315pht(316'Choose the object this rule will act on (for example, enter '.317'`rX` to act on the `rX` repository, or `#project` to act on '.318'a project).'))319->appendRemarkupInstructions(320$adapter->explainValidTriggerObjects())321->appendChild(322id(new AphrontFormTextControl())323->setName('objectName')324->setError($e_object)325->setValue($object_name)326->setLabel(pht('Object')));327328foreach ($params as $key => $value) {329$form->addHiddenInput($key, $value);330}331332$cancel_params = $params;333unset($cancel_params['type']);334335$cancel_uri = $this->getApplicationURI('new/');336$cancel_uri = new PhutilURI($cancel_uri, $params);337338$form->appendChild(339id(new AphrontFormSubmitControl())340->setValue(pht('Continue'))341->addCancelButton($cancel_uri, pht('Back')));342343$form_box = id(new PHUIObjectBoxView())344->setHeaderText($title)345->setFormErrors($errors)346->setBackground(PHUIObjectBoxView::WHITE_CONFIG)347->setForm($form);348349return $form_box;350}351352}353354355