Page MenuHomePhorge

No OneTemporary

diff --git a/src/applications/herald/controller/HeraldRuleViewController.php b/src/applications/herald/controller/HeraldRuleViewController.php
index 818eb7560f..9e696c23c4 100644
--- a/src/applications/herald/controller/HeraldRuleViewController.php
+++ b/src/applications/herald/controller/HeraldRuleViewController.php
@@ -1,158 +1,162 @@
<?php
final class HeraldRuleViewController extends HeraldController {
+ public function shouldAllowPublic() {
+ return true;
+ }
+
public function handleRequest(AphrontRequest $request) {
$viewer = $request->getViewer();
$id = $request->getURIData('id');
$rule = id(new HeraldRuleQuery())
->setViewer($viewer)
->withIDs(array($id))
->needConditionsAndActions(true)
->executeOne();
if (!$rule) {
return new Aphront404Response();
}
$header = id(new PHUIHeaderView())
->setUser($viewer)
->setHeader($rule->getName())
->setPolicyObject($rule)
->setHeaderIcon('fa-bullhorn');
if ($rule->getIsDisabled()) {
$header->setStatus(
'fa-ban',
'red',
pht('Archived'));
} else {
$header->setStatus(
'fa-check',
'bluegrey',
pht('Active'));
}
$curtain = $this->buildCurtain($rule);
$details = $this->buildPropertySectionView($rule);
$description = $this->buildDescriptionView($rule);
$id = $rule->getID();
$crumbs = $this->buildApplicationCrumbs();
$crumbs->addTextCrumb("H{$id}");
$crumbs->setBorder(true);
$timeline = $this->buildTransactionTimeline(
$rule,
new HeraldTransactionQuery());
$timeline->setShouldTerminate(true);
$title = $rule->getName();
$view = id(new PHUITwoColumnView())
->setHeader($header)
->setCurtain($curtain)
->setMainColumn($timeline)
->addPropertySection(pht('Details'), $details)
->addPropertySection(pht('Description'), $description);
return $this->newPage()
->setTitle($title)
->setCrumbs($crumbs)
->appendChild($view);
}
private function buildCurtain(HeraldRule $rule) {
$viewer = $this->getViewer();
$id = $rule->getID();
$can_edit = PhabricatorPolicyFilter::hasCapability(
$viewer,
$rule,
PhabricatorPolicyCapability::CAN_EDIT);
$curtain = $this->newCurtainView($rule);
$curtain->addAction(
id(new PhabricatorActionView())
->setName(pht('Edit Rule'))
->setHref($this->getApplicationURI("edit/{$id}/"))
->setIcon('fa-pencil')
->setDisabled(!$can_edit)
->setWorkflow(!$can_edit));
if ($rule->getIsDisabled()) {
$disable_uri = "disable/{$id}/enable/";
$disable_icon = 'fa-check';
$disable_name = pht('Activate Rule');
} else {
$disable_uri = "disable/{$id}/disable/";
$disable_icon = 'fa-ban';
$disable_name = pht('Archive Rule');
}
$curtain->addAction(
id(new PhabricatorActionView())
->setName(pht('Disable Rule'))
->setHref($this->getApplicationURI($disable_uri))
->setIcon($disable_icon)
->setName($disable_name)
->setDisabled(!$can_edit)
->setWorkflow(true));
return $curtain;
}
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 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;
}
}
diff --git a/src/applications/herald/storage/HeraldRule.php b/src/applications/herald/storage/HeraldRule.php
index 19f9b95507..cf00e046b7 100644
--- a/src/applications/herald/storage/HeraldRule.php
+++ b/src/applications/herald/storage/HeraldRule.php
@@ -1,346 +1,347 @@
<?php
final class HeraldRule extends HeraldDAO
implements
PhabricatorApplicationTransactionInterface,
PhabricatorFlaggableInterface,
PhabricatorPolicyInterface,
PhabricatorDestructibleInterface,
PhabricatorSubscribableInterface {
const TABLE_RULE_APPLIED = 'herald_ruleapplied';
protected $name;
protected $authorPHID;
protected $contentType;
protected $mustMatchAll;
protected $repetitionPolicy;
protected $ruleType;
protected $isDisabled = 0;
protected $triggerObjectPHID;
protected $configVersion = 38;
// PHIDs for which this rule has been applied
private $ruleApplied = self::ATTACHABLE;
private $validAuthor = self::ATTACHABLE;
private $author = self::ATTACHABLE;
private $conditions;
private $actions;
private $triggerObject = self::ATTACHABLE;
protected function getConfiguration() {
return array(
self::CONFIG_AUX_PHID => true,
self::CONFIG_COLUMN_SCHEMA => array(
'name' => 'sort255',
'contentType' => 'text255',
'mustMatchAll' => 'bool',
'configVersion' => 'uint32',
'ruleType' => 'text32',
'isDisabled' => 'uint32',
'triggerObjectPHID' => 'phid?',
// T6203/NULLABILITY
// This should not be nullable.
'repetitionPolicy' => 'uint32?',
),
self::CONFIG_KEY_SCHEMA => array(
'key_name' => array(
'columns' => array('name(128)'),
),
'key_author' => array(
'columns' => array('authorPHID'),
),
'key_ruletype' => array(
'columns' => array('ruleType'),
),
'key_trigger' => array(
'columns' => array('triggerObjectPHID'),
),
),
) + parent::getConfiguration();
}
public function generatePHID() {
return PhabricatorPHID::generateNewPHID(HeraldRulePHIDType::TYPECONST);
}
public function getRuleApplied($phid) {
return $this->assertAttachedKey($this->ruleApplied, $phid);
}
public function setRuleApplied($phid, $applied) {
if ($this->ruleApplied === self::ATTACHABLE) {
$this->ruleApplied = array();
}
$this->ruleApplied[$phid] = $applied;
return $this;
}
public function loadConditions() {
if (!$this->getID()) {
return array();
}
return id(new HeraldCondition())->loadAllWhere(
'ruleID = %d',
$this->getID());
}
public function attachConditions(array $conditions) {
assert_instances_of($conditions, 'HeraldCondition');
$this->conditions = $conditions;
return $this;
}
public function getConditions() {
// TODO: validate conditions have been attached.
return $this->conditions;
}
public function loadActions() {
if (!$this->getID()) {
return array();
}
return id(new HeraldActionRecord())->loadAllWhere(
'ruleID = %d',
$this->getID());
}
public function attachActions(array $actions) {
// TODO: validate actions have been attached.
assert_instances_of($actions, 'HeraldActionRecord');
$this->actions = $actions;
return $this;
}
public function getActions() {
return $this->actions;
}
public function saveConditions(array $conditions) {
assert_instances_of($conditions, 'HeraldCondition');
return $this->saveChildren(
id(new HeraldCondition())->getTableName(),
$conditions);
}
public function saveActions(array $actions) {
assert_instances_of($actions, 'HeraldActionRecord');
return $this->saveChildren(
id(new HeraldActionRecord())->getTableName(),
$actions);
}
protected function saveChildren($table_name, array $children) {
assert_instances_of($children, 'HeraldDAO');
if (!$this->getID()) {
throw new PhutilInvalidStateException('save');
}
foreach ($children as $child) {
$child->setRuleID($this->getID());
}
$this->openTransaction();
queryfx(
$this->establishConnection('w'),
'DELETE FROM %T WHERE ruleID = %d',
$table_name,
$this->getID());
foreach ($children as $child) {
$child->save();
}
$this->saveTransaction();
}
public function delete() {
$this->openTransaction();
queryfx(
$this->establishConnection('w'),
'DELETE FROM %T WHERE ruleID = %d',
id(new HeraldCondition())->getTableName(),
$this->getID());
queryfx(
$this->establishConnection('w'),
'DELETE FROM %T WHERE ruleID = %d',
id(new HeraldActionRecord())->getTableName(),
$this->getID());
$result = parent::delete();
$this->saveTransaction();
return $result;
}
public function hasValidAuthor() {
return $this->assertAttached($this->validAuthor);
}
public function attachValidAuthor($valid) {
$this->validAuthor = $valid;
return $this;
}
public function getAuthor() {
return $this->assertAttached($this->author);
}
public function attachAuthor(PhabricatorUser $user) {
$this->author = $user;
return $this;
}
public function isGlobalRule() {
return ($this->getRuleType() === HeraldRuleTypeConfig::RULE_TYPE_GLOBAL);
}
public function isPersonalRule() {
return ($this->getRuleType() === HeraldRuleTypeConfig::RULE_TYPE_PERSONAL);
}
public function isObjectRule() {
return ($this->getRuleType() == HeraldRuleTypeConfig::RULE_TYPE_OBJECT);
}
public function attachTriggerObject($trigger_object) {
$this->triggerObject = $trigger_object;
return $this;
}
public function getTriggerObject() {
return $this->assertAttached($this->triggerObject);
}
/**
* Get a sortable key for rule execution order.
*
* Rules execute in a well-defined order: personal rules first, then object
* rules, then global rules. Within each rule type, rules execute from lowest
* ID to highest ID.
*
* This ordering allows more powerful rules (like global rules) to override
* weaker rules (like personal rules) when multiple rules exist which try to
* affect the same field. Executing from low IDs to high IDs makes
* interactions easier to understand when adding new rules, because the newest
* rules always happen last.
*
* @return string A sortable key for this rule.
*/
public function getRuleExecutionOrderSortKey() {
$rule_type = $this->getRuleType();
switch ($rule_type) {
case HeraldRuleTypeConfig::RULE_TYPE_PERSONAL:
$type_order = 1;
break;
case HeraldRuleTypeConfig::RULE_TYPE_OBJECT:
$type_order = 2;
break;
case HeraldRuleTypeConfig::RULE_TYPE_GLOBAL:
$type_order = 3;
break;
default:
throw new Exception(pht('Unknown rule type "%s"!', $rule_type));
}
return sprintf('~%d%010d', $type_order, $this->getID());
}
public function getMonogram() {
return 'H'.$this->getID();
}
/* -( PhabricatorApplicationTransactionInterface )------------------------- */
public function getApplicationTransactionEditor() {
return new HeraldRuleEditor();
}
public function getApplicationTransactionObject() {
return $this;
}
public function getApplicationTransactionTemplate() {
return new HeraldRuleTransaction();
}
public function willRenderTimeline(
PhabricatorApplicationTransactionView $timeline,
AphrontRequest $request) {
return $timeline;
}
/* -( PhabricatorPolicyInterface )----------------------------------------- */
public function getCapabilities() {
return array(
PhabricatorPolicyCapability::CAN_VIEW,
PhabricatorPolicyCapability::CAN_EDIT,
);
}
public function getPolicy($capability) {
+ if ($capability == PhabricatorPolicyCapability::CAN_VIEW) {
+ return PhabricatorPolicies::getMostOpenPolicy();
+ }
+
if ($this->isGlobalRule()) {
- switch ($capability) {
- case PhabricatorPolicyCapability::CAN_VIEW:
- return PhabricatorPolicies::POLICY_USER;
- case PhabricatorPolicyCapability::CAN_EDIT:
- $app = 'PhabricatorHeraldApplication';
- $herald = PhabricatorApplication::getByClass($app);
- $global = HeraldManageGlobalRulesCapability::CAPABILITY;
- return $herald->getPolicy($global);
- }
+ $app = 'PhabricatorHeraldApplication';
+ $herald = PhabricatorApplication::getByClass($app);
+ $global = HeraldManageGlobalRulesCapability::CAPABILITY;
+ return $herald->getPolicy($global);
} else if ($this->isObjectRule()) {
return $this->getTriggerObject()->getPolicy($capability);
} else {
- return PhabricatorPolicies::POLICY_NOONE;
+ return $this->getAuthorPHID();
}
}
public function hasAutomaticCapability($capability, PhabricatorUser $viewer) {
- if ($this->isPersonalRule()) {
- return ($viewer->getPHID() == $this->getAuthorPHID());
- } else {
- return false;
- }
+ return false;
}
public function describeAutomaticCapability($capability) {
- if ($this->isPersonalRule()) {
- return pht("A personal rule's owner can always view and edit it.");
- } else if ($this->isObjectRule()) {
- return pht('Object rules inherit the policies of their objects.');
+ if ($capability == PhabricatorPolicyCapability::CAN_VIEW) {
+ return null;
}
- return null;
+ if ($this->isGlobalRule()) {
+ return pht(
+ 'Global Herald rules can be edited by users with the "Can Manage '.
+ 'Global Rules" Herald application permission.');
+ } else if ($this->isObjectRule()) {
+ return pht('Object rules inherit the edit policies of their objects.');
+ } else {
+ return pht('A personal rule can only be edited by its owner.');
+ }
}
/* -( PhabricatorSubscribableInterface )----------------------------------- */
public function isAutomaticallySubscribed($phid) {
return $this->isPersonalRule() && $phid == $this->getAuthorPHID();
}
/* -( PhabricatorDestructibleInterface )----------------------------------- */
public function destroyObjectPermanently(
PhabricatorDestructionEngine $engine) {
$this->openTransaction();
$this->delete();
$this->saveTransaction();
}
}

File Metadata

Mime Type
text/x-diff
Expires
Sun, Jan 19, 14:52 (3 w, 2 d ago)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
1125687
Default Alt Text
(15 KB)

Event Timeline