diff --git a/src/__phutil_library_map__.php b/src/__phutil_library_map__.php --- a/src/__phutil_library_map__.php +++ b/src/__phutil_library_map__.php @@ -4202,6 +4202,7 @@ 'PhabricatorProjectTriggerEditor' => 'applications/project/editor/PhabricatorProjectTriggerEditor.php', 'PhabricatorProjectTriggerInvalidRule' => 'applications/project/trigger/PhabricatorProjectTriggerInvalidRule.php', 'PhabricatorProjectTriggerListController' => 'applications/project/controller/trigger/PhabricatorProjectTriggerListController.php', + 'PhabricatorProjectTriggerManiphestOwnerRule' => 'applications/project/trigger/PhabricatorProjectTriggerManiphestOwnerRule.php', 'PhabricatorProjectTriggerManiphestPriorityRule' => 'applications/project/trigger/PhabricatorProjectTriggerManiphestPriorityRule.php', 'PhabricatorProjectTriggerManiphestStatusRule' => 'applications/project/trigger/PhabricatorProjectTriggerManiphestStatusRule.php', 'PhabricatorProjectTriggerNameTransaction' => 'applications/project/xaction/trigger/PhabricatorProjectTriggerNameTransaction.php', @@ -10368,6 +10369,7 @@ 'PhabricatorProjectTriggerEditor' => 'PhabricatorApplicationTransactionEditor', 'PhabricatorProjectTriggerInvalidRule' => 'PhabricatorProjectTriggerRule', 'PhabricatorProjectTriggerListController' => 'PhabricatorProjectTriggerController', + 'PhabricatorProjectTriggerManiphestOwnerRule' => 'PhabricatorProjectTriggerRule', 'PhabricatorProjectTriggerManiphestPriorityRule' => 'PhabricatorProjectTriggerRule', 'PhabricatorProjectTriggerManiphestStatusRule' => 'PhabricatorProjectTriggerRule', 'PhabricatorProjectTriggerNameTransaction' => 'PhabricatorProjectTriggerTransactionType', diff --git a/src/applications/project/controller/PhabricatorProjectBoardViewController.php b/src/applications/project/controller/PhabricatorProjectBoardViewController.php --- a/src/applications/project/controller/PhabricatorProjectBoardViewController.php +++ b/src/applications/project/controller/PhabricatorProjectBoardViewController.php @@ -577,6 +577,11 @@ $panel->addHeaderAction($column_menu); if ($column->canHaveTrigger()) { + $trigger = $column->getTrigger(); + if ($trigger) { + $trigger->setViewer($viewer); + } + $trigger_menu = $this->buildTriggerMenu($column); $panel->addHeaderAction($trigger_menu); } diff --git a/src/applications/project/controller/trigger/PhabricatorProjectTriggerEditController.php b/src/applications/project/controller/trigger/PhabricatorProjectTriggerEditController.php --- a/src/applications/project/controller/trigger/PhabricatorProjectTriggerEditController.php +++ b/src/applications/project/controller/trigger/PhabricatorProjectTriggerEditController.php @@ -25,6 +25,8 @@ $trigger = PhabricatorProjectTrigger::initializeNewTrigger(); } + $trigger->setViewer($viewer); + $column_phid = $request->getStr('columnPHID'); if ($column_phid) { $column = id(new PhabricatorProjectColumnQuery()) @@ -272,6 +274,10 @@ $rule_list = array_values($rule_list); $type_list = PhabricatorProjectTriggerRule::getAllTriggerRules(); + + foreach ($type_list as $rule) { + $rule->setViewer($this->getViewer()); + } $type_list = mpull($type_list, 'newTemplate'); $type_list = array_values($type_list); diff --git a/src/applications/project/controller/trigger/PhabricatorProjectTriggerViewController.php b/src/applications/project/controller/trigger/PhabricatorProjectTriggerViewController.php --- a/src/applications/project/controller/trigger/PhabricatorProjectTriggerViewController.php +++ b/src/applications/project/controller/trigger/PhabricatorProjectTriggerViewController.php @@ -20,6 +20,7 @@ if (!$trigger) { return new Aphront404Response(); } + $trigger->setViewer($viewer); $rules_view = $this->newRulesView($trigger); $columns_view = $this->newColumnsView($trigger); diff --git a/src/applications/project/storage/PhabricatorProjectTrigger.php b/src/applications/project/storage/PhabricatorProjectTrigger.php --- a/src/applications/project/storage/PhabricatorProjectTrigger.php +++ b/src/applications/project/storage/PhabricatorProjectTrigger.php @@ -13,6 +13,7 @@ protected $editPolicy; private $triggerRules; + private $viewer; private $usage = self::ATTACHABLE; public static function initializeNewTrigger() { @@ -41,6 +42,15 @@ return PhabricatorProjectTriggerPHIDType::TYPECONST; } + public function getViewer() { + return $this->viewer; + } + + public function setViewer(PhabricatorUser $user) { + $this->viewer = $user; + return $this; + } + public function getDisplayName() { $name = $this->getName(); if (strlen($name)) { @@ -72,11 +82,16 @@ parent::setRuleset($ruleset); } - public function getTriggerRules() { + public function getTriggerRules($viewer = null) { if ($this->triggerRules === null) { + if (!$viewer) { + $viewer = $this->getViewer(); + } + $trigger_rules = self::newTriggerRulesFromRuleSpecifications( $this->getRuleset(), - $allow_invalid = true); + $allow_invalid = true, + $viewer); $this->triggerRules = $trigger_rules; } @@ -86,7 +101,8 @@ public static function newTriggerRulesFromRuleSpecifications( array $list, - $allow_invalid) { + $allow_invalid, + PhabricatorUser $viewer) { // NOTE: With "$allow_invalid" set, we're trying to preserve the database // state in the rule structure, even if it includes rule types we don't @@ -124,7 +140,7 @@ if (!is_array($rule)) { throw new PhabricatorProjectTriggerCorruptionException( pht( - 'Trigger ruleset is corrupt: rule (with key "%s") should be a '. + 'Trigger ruleset is corrupt: rule (at index "%s") should be a '. 'rule specification, but is actually "%s".', $key, phutil_describe_type($rule))); @@ -140,7 +156,7 @@ } catch (PhutilTypeCheckException $ex) { throw new PhabricatorProjectTriggerCorruptionException( pht( - 'Trigger ruleset is corrupt: rule (with key "%s") is not a '. + 'Trigger ruleset is corrupt: rule (at index "%s") is not a '. 'valid rule specification: %s', $key, $ex->getMessage())); @@ -179,6 +195,7 @@ ->setRecord($record) ->setException($ex); } + $rule->setViewer($viewer); $trigger_rules[] = $rule; } @@ -206,9 +223,8 @@ $object) { $trigger_xactions = array(); - foreach ($this->getTriggerRules() as $rule) { + foreach ($this->getTriggerRules($viewer) as $rule) { $rule - ->setViewer($viewer) ->setTrigger($this) ->setColumn($column) ->setObject($object); diff --git a/src/applications/project/trigger/PhabricatorProjectTriggerManiphestOwnerRule.php b/src/applications/project/trigger/PhabricatorProjectTriggerManiphestOwnerRule.php new file mode 100644 --- /dev/null +++ b/src/applications/project/trigger/PhabricatorProjectTriggerManiphestOwnerRule.php @@ -0,0 +1,126 @@ +getDatasource()->getWireTokens($this->getValue()); + } + + private function convertTokenizerValueToOwner($value) { + $value = head($value); + if ($value === PhabricatorPeopleNoOwnerDatasource::FUNCTION_TOKEN) { + $value = null; + } + return $value; + } + + protected function assertValidRuleValue($value) { + if (!is_array($value)) { + throw new Exception( + pht( + 'Owner rule value should be a list, but is not (value is "%s").', + phutil_describe_type($value))); + } + + if (count($value) != 1) { + throw new Exception( + pht( + 'Owner rule value should be a list of exactly one user PHID, or the '. + 'token "none()" (value is "%s").', + implode(', ', $value))); + } + } + + protected function newDropTransactions($object, $value) { + $value = $this->convertTokenizerValueToOwner($value); + return array( + $this->newTransaction() + ->setTransactionType(ManiphestTaskOwnerTransaction::TRANSACTIONTYPE) + ->setNewValue($value), + ); + } + + protected function newDropEffects($value) { + $owner_value = $this->convertTokenizerValueToOwner($value); + + return array( + $this->newEffect() + ->setIcon('fa-user') + ->setContent($this->getRuleViewDescription($value)) + ->addCondition('owner', '!=', $owner_value), + ); + } + + protected function getDefaultValue() { + return null; + } + + protected function getPHUIXControlType() { + return 'tokenizer'; + } + + protected function getDatasource() { + $datasource = id(new ManiphestAssigneeDatasource()) + ->setLimit(1); + + if ($this->getViewer()) { + $datasource->setViewer($this->getViewer()); + } + + return $datasource; + } + + protected function getPHUIXControlSpecification() { + $template = id(new AphrontTokenizerTemplateView()) + ->setViewer($this->getViewer()); + + $template_markup = $template->render(); + $datasource = $this->getDatasource(); + + return array( + 'markup' => (string)hsprintf('%s', $template_markup), + 'config' => array( + 'src' => $datasource->getDatasourceURI(), + 'browseURI' => $datasource->getBrowseURI(), + 'placeholder' => $datasource->getPlaceholderText(), + 'limit' => $datasource->getLimit(), + ), + 'value' => null, + ); + } + + public function getRuleViewLabel() { + return pht('Change Owner'); + } + + public function getRuleViewDescription($value) { + $value = $this->convertTokenizerValueToOwner($value); + + if (!$value) { + return pht('Unassign task.'); + } else { + return pht( + 'Assign task to %s.', + phutil_tag( + 'strong', + array(), + $this->getViewer() + ->renderHandle($value) + ->render())); + } + } + + public function getRuleViewIcon($value) { + return id(new PHUIIconView()) + ->setIcon('fa-user', 'green'); + } + + +} diff --git a/src/applications/project/trigger/PhabricatorProjectTriggerRule.php b/src/applications/project/trigger/PhabricatorProjectTriggerRule.php --- a/src/applications/project/trigger/PhabricatorProjectTriggerRule.php +++ b/src/applications/project/trigger/PhabricatorProjectTriggerRule.php @@ -37,6 +37,10 @@ return $this->getRecord()->getValue(); } + protected function getValueForEditorField() { + return $this->getValue(); + } + abstract public function getSelectControlName(); abstract public function getRuleViewLabel(); abstract public function getRuleViewDescription($value); @@ -130,7 +134,7 @@ return array( 'type' => $record->getType(), - 'value' => $record->getValue(), + 'value' => $this->getValueForEditorField(), 'isValidRule' => $is_valid, 'invalidView' => $invalid_view, ); diff --git a/src/applications/project/xaction/trigger/PhabricatorProjectTriggerRulesetTransaction.php b/src/applications/project/xaction/trigger/PhabricatorProjectTriggerRulesetTransaction.php --- a/src/applications/project/xaction/trigger/PhabricatorProjectTriggerRulesetTransaction.php +++ b/src/applications/project/xaction/trigger/PhabricatorProjectTriggerRulesetTransaction.php @@ -28,7 +28,8 @@ try { PhabricatorProjectTrigger::newTriggerRulesFromRuleSpecifications( $ruleset, - $allow_invalid = false); + $allow_invalid = false, + $xaction->getViewer()); } catch (PhabricatorProjectTriggerCorruptionException $ex) { $errors[] = $this->newInvalidError( pht(