2011-03-22 23:27:52 +01:00
|
|
|
<?php
|
|
|
|
|
2012-03-10 00:46:25 +01:00
|
|
|
final class HeraldRuleController extends HeraldController {
|
2011-03-22 23:27:52 +01:00
|
|
|
|
|
|
|
private $id;
|
2011-12-16 22:29:32 +01:00
|
|
|
private $filter;
|
|
|
|
|
2011-03-22 23:27:52 +01:00
|
|
|
public function willProcessRequest(array $data) {
|
|
|
|
$this->id = (int)idx($data, 'id');
|
|
|
|
}
|
|
|
|
|
|
|
|
public function processRequest() {
|
|
|
|
|
|
|
|
$request = $this->getRequest();
|
|
|
|
$user = $request->getUser();
|
|
|
|
|
2013-10-05 00:15:48 +02:00
|
|
|
$content_type_map = HeraldAdapter::getEnabledAdapterMap($user);
|
2012-01-14 00:24:56 +01:00
|
|
|
$rule_type_map = HeraldRuleTypeConfig::getRuleTypeMap();
|
2011-03-22 23:27:52 +01:00
|
|
|
|
|
|
|
if ($this->id) {
|
2013-08-06 22:43:45 +02:00
|
|
|
$id = $this->id;
|
2013-08-02 19:25:45 +02:00
|
|
|
$rule = id(new HeraldRuleQuery())
|
|
|
|
->setViewer($user)
|
2013-08-06 22:43:45 +02:00
|
|
|
->withIDs(array($id))
|
2013-08-02 19:25:45 +02:00
|
|
|
->requireCapabilities(
|
|
|
|
array(
|
|
|
|
PhabricatorPolicyCapability::CAN_VIEW,
|
|
|
|
PhabricatorPolicyCapability::CAN_EDIT,
|
|
|
|
))
|
|
|
|
->executeOne();
|
2011-03-22 23:27:52 +01:00
|
|
|
if (!$rule) {
|
|
|
|
return new Aphront404Response();
|
|
|
|
}
|
2013-08-06 22:43:45 +02:00
|
|
|
$cancel_uri = $this->getApplicationURI("rule/{$id}/");
|
2011-03-22 23:27:52 +01:00
|
|
|
} else {
|
|
|
|
$rule = new HeraldRule();
|
|
|
|
$rule->setAuthorPHID($user->getPHID());
|
2013-09-04 21:07:26 +02:00
|
|
|
$rule->setMustMatchAll(1);
|
2011-03-22 23:27:52 +01:00
|
|
|
|
2012-01-14 00:24:56 +01:00
|
|
|
$content_type = $request->getStr('content_type');
|
|
|
|
$rule->setContentType($content_type);
|
|
|
|
|
|
|
|
$rule_type = $request->getStr('rule_type');
|
|
|
|
if (!isset($rule_type_map[$rule_type])) {
|
2013-10-05 00:15:48 +02:00
|
|
|
$rule_type = HeraldRuleTypeConfig::RULE_TYPE_PERSONAL;
|
2012-01-14 00:24:56 +01:00
|
|
|
}
|
|
|
|
$rule->setRuleType($rule_type);
|
2013-08-06 22:43:45 +02:00
|
|
|
|
2013-12-31 01:48:14 +01:00
|
|
|
$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!'));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-08-06 22:43:45 +02:00
|
|
|
$cancel_uri = $this->getApplicationURI();
|
2013-10-05 00:15:48 +02:00
|
|
|
}
|
|
|
|
|
2013-12-27 22:17:10 +01:00
|
|
|
if ($rule->isGlobalRule()) {
|
2013-10-05 00:15:48 +02:00
|
|
|
$this->requireApplicationCapability(
|
2013-10-09 22:44:41 +02:00
|
|
|
HeraldCapabilityManageGlobalRules::CAPABILITY);
|
2011-03-22 23:27:52 +01:00
|
|
|
}
|
|
|
|
|
2013-08-02 19:25:45 +02:00
|
|
|
$adapter = HeraldAdapter::getAdapterForContentType($rule->getContentType());
|
|
|
|
|
2011-03-22 23:27:52 +01:00
|
|
|
$local_version = id(new HeraldRule())->getConfigVersion();
|
|
|
|
if ($rule->getConfigVersion() > $local_version) {
|
|
|
|
throw new Exception(
|
2013-12-31 01:48:07 +01:00
|
|
|
pht(
|
2014-06-09 20:36:49 +02:00
|
|
|
'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.'));
|
2013-12-31 01:48:07 +01:00
|
|
|
}
|
|
|
|
|
2011-03-22 23:27:52 +01:00
|
|
|
// 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')) {
|
2013-08-05 19:02:40 +02:00
|
|
|
list($e_name, $errors) = $this->saveRule($adapter, $rule, $request);
|
2011-03-22 23:27:52 +01:00
|
|
|
if (!$errors) {
|
2013-08-06 22:43:45 +02:00
|
|
|
$id = $rule->getID();
|
|
|
|
$uri = $this->getApplicationURI("rule/{$id}/");
|
General Herald refactoring pass
Summary:
**Who can delete global rules?**: I discussed this with @jungejason. The current behavior is that the rule author or any administrator can delete a global rule, but this
isn't consistent with who can edit a rule (anyone) and doesn't really make much sense (it's an artifact of the global/personal split). I proposed that anyone can delete a
rule but we don't actually delete them, and log the deletion. However, when it came time to actually write the code for this I backed off a bit and continued actually
deleting the rules -- I think this does a reasonable job of balancing accountability with complexity. So the new impelmentation is:
- Personal rules can be deleted only by their owners.
- Global rules can be deleted by any user.
- All deletes are logged.
- Logs are more detailed.
- All logged actions can be viewed in aggregate.
**Minor Cleanup**
- Merged `HomeController` and `AllController`.
- Moved most queries to Query classes.
- Use AphrontFormSelectControl::renderSelectTag() where appropriate (this is a fairly recent addition).
- Use an AphrontErrorView to render the dry run notice (this didn't exist when I ported).
- Reenable some transaction code (this works again now).
- Removed the ability for admins to change rule authors (this was a little buggy, messy, and doesn't make tons of sense after the personal/global rule split).
- Rules which depend on other rules now display the right options (all global rules, all your personal rules for personal rules).
- Fix a bug in AphrontTableView where the "no data" cell would be rendered too wide if some columns are not visible.
- Allow selectFilter() in AphrontNavFilterView to be called without a 'default' argument.
Test Plan:
- Browsed, created, edited, deleted personal and gules.
- Verified generated logs.
- Did some dry runs.
- Verified transcript list and transcript details.
- Created/edited all/any rules; created/edited once/every time rules.
- Filtered admin views by users.
Reviewers: jungejason, btrahan
Reviewed By: btrahan
CC: aran, epriestley
Differential Revision: https://secure.phabricator.com/D2040
2012-03-30 19:49:55 +02:00
|
|
|
return id(new AphrontRedirectResponse())->setURI($uri);
|
2011-03-22 23:27:52 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
General Herald refactoring pass
Summary:
**Who can delete global rules?**: I discussed this with @jungejason. The current behavior is that the rule author or any administrator can delete a global rule, but this
isn't consistent with who can edit a rule (anyone) and doesn't really make much sense (it's an artifact of the global/personal split). I proposed that anyone can delete a
rule but we don't actually delete them, and log the deletion. However, when it came time to actually write the code for this I backed off a bit and continued actually
deleting the rules -- I think this does a reasonable job of balancing accountability with complexity. So the new impelmentation is:
- Personal rules can be deleted only by their owners.
- Global rules can be deleted by any user.
- All deletes are logged.
- Logs are more detailed.
- All logged actions can be viewed in aggregate.
**Minor Cleanup**
- Merged `HomeController` and `AllController`.
- Moved most queries to Query classes.
- Use AphrontFormSelectControl::renderSelectTag() where appropriate (this is a fairly recent addition).
- Use an AphrontErrorView to render the dry run notice (this didn't exist when I ported).
- Reenable some transaction code (this works again now).
- Removed the ability for admins to change rule authors (this was a little buggy, messy, and doesn't make tons of sense after the personal/global rule split).
- Rules which depend on other rules now display the right options (all global rules, all your personal rules for personal rules).
- Fix a bug in AphrontTableView where the "no data" cell would be rendered too wide if some columns are not visible.
- Allow selectFilter() in AphrontNavFilterView to be called without a 'default' argument.
Test Plan:
- Browsed, created, edited, deleted personal and gules.
- Verified generated logs.
- Did some dry runs.
- Verified transcript list and transcript details.
- Created/edited all/any rules; created/edited once/every time rules.
- Filtered admin views by users.
Reviewers: jungejason, btrahan
Reviewed By: btrahan
CC: aran, epriestley
Differential Revision: https://secure.phabricator.com/D2040
2012-03-30 19:49:55 +02:00
|
|
|
$must_match_selector = $this->renderMustMatchSelector($rule);
|
2013-08-02 21:35:33 +02:00
|
|
|
$repetition_selector = $this->renderRepetitionSelector($rule, $adapter);
|
2011-03-22 23:27:52 +01:00
|
|
|
|
2012-08-15 23:11:40 +02:00
|
|
|
$handles = $this->loadHandlesForRule($rule);
|
2011-05-28 00:52:26 +02:00
|
|
|
|
2011-03-24 19:07:36 +01:00
|
|
|
require_celerity_resource('herald-css');
|
|
|
|
|
2012-01-14 00:24:56 +01:00
|
|
|
$content_type_name = $content_type_map[$rule->getContentType()];
|
|
|
|
$rule_type_name = $rule_type_map[$rule->getRuleType()];
|
2011-03-22 23:27:52 +01:00
|
|
|
|
|
|
|
$form = id(new AphrontFormView())
|
|
|
|
->setUser($user)
|
2011-03-23 01:08:08 +01:00
|
|
|
->setID('herald-rule-edit-form')
|
2012-01-14 00:24:56 +01:00
|
|
|
->addHiddenInput('content_type', $rule->getContentType())
|
|
|
|
->addHiddenInput('rule_type', $rule->getRuleType())
|
2011-03-24 19:07:36 +01:00
|
|
|
->addHiddenInput('save', 1)
|
|
|
|
->appendChild(
|
General Herald refactoring pass
Summary:
**Who can delete global rules?**: I discussed this with @jungejason. The current behavior is that the rule author or any administrator can delete a global rule, but this
isn't consistent with who can edit a rule (anyone) and doesn't really make much sense (it's an artifact of the global/personal split). I proposed that anyone can delete a
rule but we don't actually delete them, and log the deletion. However, when it came time to actually write the code for this I backed off a bit and continued actually
deleting the rules -- I think this does a reasonable job of balancing accountability with complexity. So the new impelmentation is:
- Personal rules can be deleted only by their owners.
- Global rules can be deleted by any user.
- All deletes are logged.
- Logs are more detailed.
- All logged actions can be viewed in aggregate.
**Minor Cleanup**
- Merged `HomeController` and `AllController`.
- Moved most queries to Query classes.
- Use AphrontFormSelectControl::renderSelectTag() where appropriate (this is a fairly recent addition).
- Use an AphrontErrorView to render the dry run notice (this didn't exist when I ported).
- Reenable some transaction code (this works again now).
- Removed the ability for admins to change rule authors (this was a little buggy, messy, and doesn't make tons of sense after the personal/global rule split).
- Rules which depend on other rules now display the right options (all global rules, all your personal rules for personal rules).
- Fix a bug in AphrontTableView where the "no data" cell would be rendered too wide if some columns are not visible.
- Allow selectFilter() in AphrontNavFilterView to be called without a 'default' argument.
Test Plan:
- Browsed, created, edited, deleted personal and gules.
- Verified generated logs.
- Did some dry runs.
- Verified transcript list and transcript details.
- Created/edited all/any rules; created/edited once/every time rules.
- Filtered admin views by users.
Reviewers: jungejason, btrahan
Reviewed By: btrahan
CC: aran, epriestley
Differential Revision: https://secure.phabricator.com/D2040
2012-03-30 19:49:55 +02:00
|
|
|
// Build this explicitly (instead of using addHiddenInput())
|
|
|
|
// so we can add a sigil to it.
|
2013-01-25 21:57:17 +01:00
|
|
|
javelin_tag(
|
2011-03-24 19:07:36 +01:00
|
|
|
'input',
|
|
|
|
array(
|
|
|
|
'type' => 'hidden',
|
|
|
|
'name' => 'rule',
|
|
|
|
'sigil' => 'rule',
|
|
|
|
)))
|
2011-03-22 23:27:52 +01:00
|
|
|
->appendChild(
|
|
|
|
id(new AphrontFormTextControl())
|
2013-05-20 17:24:07 +02:00
|
|
|
->setLabel(pht('Rule Name'))
|
2011-03-24 19:07:36 +01:00
|
|
|
->setName('name')
|
2011-03-22 23:27:52 +01:00
|
|
|
->setError($e_name)
|
Improve Herald personal/global UI/UX
Summary:
- Default "personal" vs "global" choice to "personal".
- Don't show global rules under "My Rules".
- After editing or creating a global rule, redirect back to global rule list.
- Use radio buttons for "personal" vs "global" and add captions explaining the
difference.
- For "global" rules, don't show the owner/author in the rule detail view --
they effectively have no owner (see also D1387).
- For "global" rules, don't show the owner/author in the rule list view, as
above.
- For admin views, show rule type (global vs personal).
Test Plan:
- Created and edited new global and personal rules.
- Viewed "my", "global" and "admin" views.
Reviewers: btrahan, jungejason, nh, xela
Reviewed By: btrahan
CC: aran, epriestley
Differential Revision: https://secure.phabricator.com/D1518
2012-01-31 21:09:29 +01:00
|
|
|
->setValue($rule->getName()));
|
|
|
|
|
2013-12-31 01:48:14 +01:00
|
|
|
$trigger_object_control = false;
|
|
|
|
if ($rule->isObjectRule()) {
|
|
|
|
$trigger_object_control = id(new AphrontFormStaticControl())
|
|
|
|
->setValue(
|
|
|
|
pht(
|
|
|
|
'This rule triggers for %s.',
|
|
|
|
$handles[$rule->getTriggerObjectPHID()]->renderLink()));
|
|
|
|
}
|
|
|
|
|
|
|
|
|
Improve Herald personal/global UI/UX
Summary:
- Default "personal" vs "global" choice to "personal".
- Don't show global rules under "My Rules".
- After editing or creating a global rule, redirect back to global rule list.
- Use radio buttons for "personal" vs "global" and add captions explaining the
difference.
- For "global" rules, don't show the owner/author in the rule detail view --
they effectively have no owner (see also D1387).
- For "global" rules, don't show the owner/author in the rule list view, as
above.
- For admin views, show rule type (global vs personal).
Test Plan:
- Created and edited new global and personal rules.
- Viewed "my", "global" and "admin" views.
Reviewers: btrahan, jungejason, nh, xela
Reviewed By: btrahan
CC: aran, epriestley
Differential Revision: https://secure.phabricator.com/D1518
2012-01-31 21:09:29 +01:00
|
|
|
$form
|
2011-03-22 23:27:52 +01:00
|
|
|
->appendChild(
|
|
|
|
id(new AphrontFormMarkupControl())
|
2013-05-20 17:24:07 +02:00
|
|
|
->setValue(pht(
|
2014-06-09 20:36:49 +02:00
|
|
|
'This %s rule triggers for %s.',
|
2013-05-20 17:24:07 +02:00
|
|
|
phutil_tag('strong', array(), $rule_type_name),
|
|
|
|
phutil_tag('strong', array(), $content_type_name))))
|
2013-12-31 01:48:14 +01:00
|
|
|
->appendChild($trigger_object_control)
|
2011-03-22 23:27:52 +01:00
|
|
|
->appendChild(
|
2012-03-16 01:10:19 +01:00
|
|
|
id(new AphrontFormInsetView())
|
2013-05-20 17:24:07 +02:00
|
|
|
->setTitle(pht('Conditions'))
|
2013-01-25 21:57:17 +01:00
|
|
|
->setRightButton(javelin_tag(
|
2012-03-16 01:10:19 +01:00
|
|
|
'a',
|
|
|
|
array(
|
|
|
|
'href' => '#',
|
|
|
|
'class' => 'button green',
|
|
|
|
'sigil' => 'create-condition',
|
|
|
|
'mustcapture' => true
|
|
|
|
),
|
2013-05-20 17:24:07 +02:00
|
|
|
pht('New Condition')))
|
2012-03-16 01:10:19 +01:00
|
|
|
->setDescription(
|
2013-05-20 17:24:07 +02:00
|
|
|
pht('When %s these conditions are met:', $must_match_selector))
|
2013-01-25 21:57:17 +01:00
|
|
|
->setContent(javelin_tag(
|
2011-03-23 01:08:08 +01:00
|
|
|
'table',
|
|
|
|
array(
|
|
|
|
'sigil' => 'rule-conditions',
|
2012-03-16 01:10:19 +01:00
|
|
|
'class' => 'herald-condition-table'
|
2011-03-23 01:08:08 +01:00
|
|
|
),
|
2012-03-16 01:10:19 +01:00
|
|
|
'')))
|
2011-03-22 23:27:52 +01:00
|
|
|
->appendChild(
|
2012-03-16 01:10:19 +01:00
|
|
|
id(new AphrontFormInsetView())
|
2013-05-20 17:24:07 +02:00
|
|
|
->setTitle(pht('Action'))
|
2013-01-25 21:57:17 +01:00
|
|
|
->setRightButton(javelin_tag(
|
2011-03-23 04:41:02 +01:00
|
|
|
'a',
|
|
|
|
array(
|
|
|
|
'href' => '#',
|
|
|
|
'class' => 'button green',
|
|
|
|
'sigil' => 'create-action',
|
|
|
|
'mustcapture' => true,
|
|
|
|
),
|
2013-05-20 17:24:07 +02:00
|
|
|
pht('New Action')))
|
|
|
|
->setDescription(pht(
|
2013-02-05 23:30:29 +01:00
|
|
|
'Take these actions %s this rule matches:',
|
|
|
|
$repetition_selector))
|
2013-01-25 21:57:17 +01:00
|
|
|
->setContent(javelin_tag(
|
2012-03-16 01:10:19 +01:00
|
|
|
'table',
|
|
|
|
array(
|
|
|
|
'sigil' => 'rule-actions',
|
|
|
|
'class' => 'herald-action-table',
|
|
|
|
),
|
|
|
|
'')))
|
2011-03-22 23:27:52 +01:00
|
|
|
->appendChild(
|
|
|
|
id(new AphrontFormSubmitControl())
|
2013-05-20 17:24:07 +02:00
|
|
|
->setValue(pht('Save Rule'))
|
2013-08-06 22:43:45 +02:00
|
|
|
->addCancelButton($cancel_uri));
|
2011-03-22 23:27:52 +01:00
|
|
|
|
2013-08-02 19:25:45 +02:00
|
|
|
$this->setupEditorBehavior($rule, $handles, $adapter);
|
2011-10-22 03:34:38 +02:00
|
|
|
|
2013-05-20 17:24:07 +02:00
|
|
|
$title = $rule->getID()
|
2013-01-19 21:15:41 +01:00
|
|
|
? pht('Edit Herald Rule')
|
2013-05-20 17:24:07 +02:00
|
|
|
: pht('Create Herald Rule');
|
|
|
|
|
2013-09-25 20:23:29 +02:00
|
|
|
$form_box = id(new PHUIObjectBoxView())
|
2013-08-26 20:53:11 +02:00
|
|
|
->setHeaderText($title)
|
2014-01-10 18:17:37 +01:00
|
|
|
->setFormErrors($errors)
|
2013-08-26 20:53:11 +02:00
|
|
|
->setForm($form);
|
|
|
|
|
2013-05-20 17:24:07 +02:00
|
|
|
$crumbs = $this
|
|
|
|
->buildApplicationCrumbs()
|
2013-12-19 02:47:34 +01:00
|
|
|
->addTextCrumb($title);
|
2013-08-02 15:58:31 +02:00
|
|
|
|
|
|
|
return $this->buildApplicationPage(
|
2011-10-22 03:34:38 +02:00
|
|
|
array(
|
2013-08-02 15:58:31 +02:00
|
|
|
$crumbs,
|
2013-08-26 20:53:11 +02:00
|
|
|
$form_box,
|
2013-08-02 15:58:31 +02:00
|
|
|
),
|
2011-10-22 03:34:38 +02:00
|
|
|
array(
|
Update form styles, implement in many places
Summary:
This creates a common form look and feel across the site. I spent a bit of time working out a number of kinks in our various renderings. Some things:
- Font Styles are correctly applied for form elements now.
- Everything lines up!
- Selects are larger, easier to read, interact.
- Inputs have been squared.
- Consistant CSS applied glow (try it!)
- Improved Mobile Responsiveness
- CSS applied to all form elements, not just Aphront
- Many other minor tweaks.
I tried to hit as many high profile forms as possible in an effort to increase consistency. Stopped for now and will follow up after this lands. I know Evan is not a super fan of the glow, but after working with it for a week, it's way cleaner and responsive than the OS controls. Give it a try.
Test Plan: Tested many applications, forms, mobile and tablet.
Reviewers: epriestley, btrahan
Reviewed By: epriestley
CC: aran, Korvin
Differential Revision: https://secure.phabricator.com/D5860
2013-05-07 23:07:06 +02:00
|
|
|
'title' => pht('Edit Rule'),
|
2011-10-22 03:34:38 +02:00
|
|
|
));
|
|
|
|
}
|
|
|
|
|
2013-08-05 19:02:40 +02:00
|
|
|
private function saveRule(HeraldAdapter $adapter, $rule, $request) {
|
2011-10-22 03:34:38 +02:00
|
|
|
$rule->setName($request->getStr('name'));
|
2013-09-04 21:07:26 +02:00
|
|
|
$match_all = ($request->getStr('must_match') == 'all');
|
|
|
|
$rule->setMustMatchAll((int)$match_all);
|
2011-10-22 03:34:38 +02:00
|
|
|
|
|
|
|
$repetition_policy_param = $request->getStr('repetition_policy');
|
|
|
|
$rule->setRepetitionPolicy(
|
2013-02-19 22:33:10 +01:00
|
|
|
HeraldRepetitionPolicyConfig::toInt($repetition_policy_param));
|
2011-10-22 03:34:38 +02:00
|
|
|
|
|
|
|
$e_name = true;
|
|
|
|
$errors = array();
|
|
|
|
|
|
|
|
if (!strlen($rule->getName())) {
|
2014-06-09 20:36:49 +02:00
|
|
|
$e_name = pht('Required');
|
|
|
|
$errors[] = pht('Rule must have a name.');
|
2011-10-22 03:34:38 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
$data = json_decode($request->getStr('rule'), true);
|
|
|
|
if (!is_array($data) ||
|
|
|
|
!$data['conditions'] ||
|
|
|
|
!$data['actions']) {
|
2014-06-09 20:36:49 +02:00
|
|
|
throw new Exception('Failed to decode rule data.');
|
2011-10-22 03:34:38 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
$conditions = array();
|
|
|
|
foreach ($data['conditions'] as $condition) {
|
|
|
|
if ($condition === null) {
|
|
|
|
// We manage this as a sparse array on the client, so may receive
|
|
|
|
// NULL if conditions have been removed.
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
$obj = new HeraldCondition();
|
|
|
|
$obj->setFieldName($condition[0]);
|
|
|
|
$obj->setFieldCondition($condition[1]);
|
|
|
|
|
|
|
|
if (is_array($condition[2])) {
|
|
|
|
$obj->setValue(array_keys($condition[2]));
|
|
|
|
} else {
|
|
|
|
$obj->setValue($condition[2]);
|
|
|
|
}
|
|
|
|
|
2013-08-05 19:02:40 +02:00
|
|
|
try {
|
|
|
|
$adapter->willSaveCondition($obj);
|
|
|
|
} catch (HeraldInvalidConditionException $ex) {
|
|
|
|
$errors[] = $ex->getMessage();
|
2011-10-22 03:34:38 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
$conditions[] = $obj;
|
|
|
|
}
|
|
|
|
|
|
|
|
$actions = array();
|
|
|
|
foreach ($data['actions'] as $action) {
|
|
|
|
if ($action === null) {
|
|
|
|
// Sparse on the client; removals can give us NULLs.
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!isset($action[1])) {
|
|
|
|
// Legitimate for any action which doesn't need a target, like
|
|
|
|
// "Do nothing".
|
|
|
|
$action[1] = null;
|
|
|
|
}
|
|
|
|
|
2013-08-06 20:23:01 +02:00
|
|
|
$obj = new HeraldAction();
|
|
|
|
$obj->setAction($action[0]);
|
|
|
|
$obj->setTarget($action[1]);
|
|
|
|
|
|
|
|
try {
|
|
|
|
$adapter->willSaveAction($rule, $obj);
|
|
|
|
} catch (HeraldInvalidActionException $ex) {
|
|
|
|
$errors[] = $ex;
|
|
|
|
}
|
|
|
|
|
|
|
|
$actions[] = $obj;
|
2012-01-05 22:07:08 +01:00
|
|
|
}
|
|
|
|
|
2011-10-22 03:34:38 +02:00
|
|
|
$rule->attachConditions($conditions);
|
|
|
|
$rule->attachActions($actions);
|
|
|
|
|
|
|
|
if (!$errors) {
|
|
|
|
try {
|
|
|
|
|
General Herald refactoring pass
Summary:
**Who can delete global rules?**: I discussed this with @jungejason. The current behavior is that the rule author or any administrator can delete a global rule, but this
isn't consistent with who can edit a rule (anyone) and doesn't really make much sense (it's an artifact of the global/personal split). I proposed that anyone can delete a
rule but we don't actually delete them, and log the deletion. However, when it came time to actually write the code for this I backed off a bit and continued actually
deleting the rules -- I think this does a reasonable job of balancing accountability with complexity. So the new impelmentation is:
- Personal rules can be deleted only by their owners.
- Global rules can be deleted by any user.
- All deletes are logged.
- Logs are more detailed.
- All logged actions can be viewed in aggregate.
**Minor Cleanup**
- Merged `HomeController` and `AllController`.
- Moved most queries to Query classes.
- Use AphrontFormSelectControl::renderSelectTag() where appropriate (this is a fairly recent addition).
- Use an AphrontErrorView to render the dry run notice (this didn't exist when I ported).
- Reenable some transaction code (this works again now).
- Removed the ability for admins to change rule authors (this was a little buggy, messy, and doesn't make tons of sense after the personal/global rule split).
- Rules which depend on other rules now display the right options (all global rules, all your personal rules for personal rules).
- Fix a bug in AphrontTableView where the "no data" cell would be rendered too wide if some columns are not visible.
- Allow selectFilter() in AphrontNavFilterView to be called without a 'default' argument.
Test Plan:
- Browsed, created, edited, deleted personal and gules.
- Verified generated logs.
- Did some dry runs.
- Verified transcript list and transcript details.
- Created/edited all/any rules; created/edited once/every time rules.
- Filtered admin views by users.
Reviewers: jungejason, btrahan
Reviewed By: btrahan
CC: aran, epriestley
Differential Revision: https://secure.phabricator.com/D2040
2012-03-30 19:49:55 +02:00
|
|
|
$edit_action = $rule->getID() ? 'edit' : 'create';
|
|
|
|
|
|
|
|
$rule->openTransaction();
|
2011-10-22 03:34:38 +02:00
|
|
|
$rule->save();
|
|
|
|
$rule->saveConditions($conditions);
|
|
|
|
$rule->saveActions($actions);
|
General Herald refactoring pass
Summary:
**Who can delete global rules?**: I discussed this with @jungejason. The current behavior is that the rule author or any administrator can delete a global rule, but this
isn't consistent with who can edit a rule (anyone) and doesn't really make much sense (it's an artifact of the global/personal split). I proposed that anyone can delete a
rule but we don't actually delete them, and log the deletion. However, when it came time to actually write the code for this I backed off a bit and continued actually
deleting the rules -- I think this does a reasonable job of balancing accountability with complexity. So the new impelmentation is:
- Personal rules can be deleted only by their owners.
- Global rules can be deleted by any user.
- All deletes are logged.
- Logs are more detailed.
- All logged actions can be viewed in aggregate.
**Minor Cleanup**
- Merged `HomeController` and `AllController`.
- Moved most queries to Query classes.
- Use AphrontFormSelectControl::renderSelectTag() where appropriate (this is a fairly recent addition).
- Use an AphrontErrorView to render the dry run notice (this didn't exist when I ported).
- Reenable some transaction code (this works again now).
- Removed the ability for admins to change rule authors (this was a little buggy, messy, and doesn't make tons of sense after the personal/global rule split).
- Rules which depend on other rules now display the right options (all global rules, all your personal rules for personal rules).
- Fix a bug in AphrontTableView where the "no data" cell would be rendered too wide if some columns are not visible.
- Allow selectFilter() in AphrontNavFilterView to be called without a 'default' argument.
Test Plan:
- Browsed, created, edited, deleted personal and gules.
- Verified generated logs.
- Did some dry runs.
- Verified transcript list and transcript details.
- Created/edited all/any rules; created/edited once/every time rules.
- Filtered admin views by users.
Reviewers: jungejason, btrahan
Reviewed By: btrahan
CC: aran, epriestley
Differential Revision: https://secure.phabricator.com/D2040
2012-03-30 19:49:55 +02:00
|
|
|
$rule->logEdit($request->getUser()->getPHID(), $edit_action);
|
|
|
|
$rule->saveTransaction();
|
2011-10-22 03:34:38 +02:00
|
|
|
|
|
|
|
} catch (AphrontQueryDuplicateKeyException $ex) {
|
2014-06-09 20:36:49 +02:00
|
|
|
$e_name = pht('Not Unique');
|
|
|
|
$errors[] = pht('Rule name is not unique. Choose a unique name.');
|
2011-10-22 03:34:38 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return array($e_name, $errors);
|
|
|
|
}
|
|
|
|
|
2013-08-02 19:25:45 +02:00
|
|
|
private function setupEditorBehavior(
|
|
|
|
HeraldRule $rule,
|
|
|
|
array $handles,
|
|
|
|
HeraldAdapter $adapter) {
|
|
|
|
|
2011-03-22 23:27:52 +01:00
|
|
|
$serial_conditions = array(
|
|
|
|
array('default', 'default', ''),
|
|
|
|
);
|
2011-03-24 19:07:36 +01:00
|
|
|
|
2011-03-22 23:27:52 +01:00
|
|
|
if ($rule->getConditions()) {
|
|
|
|
$serial_conditions = array();
|
|
|
|
foreach ($rule->getConditions() as $condition) {
|
|
|
|
|
|
|
|
$value = $condition->getValue();
|
2014-02-06 20:42:31 +01:00
|
|
|
switch ($condition->getFieldName()) {
|
|
|
|
case HeraldAdapter::FIELD_TASK_PRIORITY:
|
|
|
|
$value_map = array();
|
|
|
|
$priority_map = ManiphestTaskPriority::getTaskPriorityMap();
|
|
|
|
foreach ($value as $priority) {
|
|
|
|
$value_map[$priority] = idx($priority_map, $priority);
|
|
|
|
}
|
|
|
|
$value = $value_map;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
if (is_array($value)) {
|
|
|
|
$value_map = array();
|
|
|
|
foreach ($value as $k => $fbid) {
|
|
|
|
$value_map[$fbid] = $handles[$fbid]->getName();
|
|
|
|
}
|
|
|
|
$value = $value_map;
|
|
|
|
}
|
|
|
|
break;
|
2011-03-22 23:27:52 +01:00
|
|
|
}
|
|
|
|
$serial_conditions[] = array(
|
|
|
|
$condition->getFieldName(),
|
2011-03-24 19:07:36 +01:00
|
|
|
$condition->getFieldCondition(),
|
2011-03-22 23:27:52 +01:00
|
|
|
$value,
|
|
|
|
);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
$serial_actions = array(
|
|
|
|
array('default', ''),
|
|
|
|
);
|
|
|
|
if ($rule->getActions()) {
|
|
|
|
$serial_actions = array();
|
|
|
|
foreach ($rule->getActions() as $action) {
|
|
|
|
|
2012-03-30 22:51:54 +02:00
|
|
|
switch ($action->getAction()) {
|
2013-08-06 20:23:01 +02:00
|
|
|
case HeraldAdapter::ACTION_FLAG:
|
Add Herald support for blocking ref changes
Summary: Ref T4195. Allows users to write Herald rules which block ref changes. For example, you can write a rule like `alincoln can not create branches`, or `no one can push to the branch "frozen"`.
Test Plan:
This covers a lot of ground. I created and pushed a bunch of rules, then looked at transcripts, in general. Here are some bits in detail:
Here's a hook-based reject message:
>>> orbital ~/repos/POEMS $ git push
Counting objects: 5, done.
Delta compression using up to 8 threads.
Compressing objects: 100% (3/3), done.
Writing objects: 100% (3/3), 274 bytes, done.
Total 3 (delta 2), reused 0 (delta 0)
remote: +---------------------------------------------------------------+
remote: | * * * PUSH REJECTED BY EVIL DRAGON BUREAUCRATS * * * |
remote: +---------------------------------------------------------------+
remote: \
remote: \ ^ /^
remote: \ / \ // \
remote: \ |\___/| / \// .\
remote: \ /V V \__ / // | \ \ *----*
remote: / / \/_/ // | \ \ \ |
remote: @___@` \/_ // | \ \ \/\ \
remote: 0/0/| \/_ // | \ \ \ \
remote: 0/0/0/0/| \/// | \ \ | |
remote: 0/0/0/0/0/_|_ / ( // | \ _\ | /
remote: 0/0/0/0/0/0/`/,_ _ _/ ) ; -. | _ _\.-~ / /
remote: ,-} _ *-.|.-~-. .~ ~
remote: \ \__/ `/\ / ~-. _ .-~ /
remote: \____(Oo) *. } { /
remote: ( (--) .----~-.\ \-` .~
remote: //__\\ \ DENIED! ///.----..< \ _ -~
remote: // \\ ///-._ _ _ _ _ _ _{^ - - - - ~
remote:
remote:
remote: This commit was rejected by Herald pre-commit rule H24.
remote: Rule: No Branches Called Blarp
remote: Reason: "blarp" is a bad branch name
remote:
To ssh://dweller@localhost/diffusion/POEMS/
! [remote rejected] blarp -> blarp (pre-receive hook declined)
error: failed to push some refs to 'ssh://dweller@localhost/diffusion/POEMS/'
Here's a transcript, showing that all the field values populate sensibly:
{F90453}
Here's a rule:
{F90454}
Reviewers: btrahan
Reviewed By: btrahan
CC: aran
Maniphest Tasks: T4195
Differential Revision: https://secure.phabricator.com/D7782
2013-12-18 00:23:55 +01:00
|
|
|
case HeraldAdapter::ACTION_BLOCK:
|
2012-03-30 22:51:54 +02:00
|
|
|
$current_value = $action->getTarget();
|
|
|
|
break;
|
|
|
|
default:
|
Support custom actions in Herald
Summary:
This was significantly easier than expected. Here's an example of what an extension class might look like:
```
<?php
final class AddRiskReviewHeraldCustomAction extends HeraldCustomAction {
public function appliesToAdapter(HeraldAdapter $adapter) {
return $adapter instanceof HeraldDifferentialRevisionAdapter;
}
public function appliesToRuleType($rule_type) {
return $rule_type == HeraldRuleTypeConfig::RULE_TYPE_GLOBAL ||
$rule_type == HeraldRuleTypeConfig::RULE_TYPE_OBJECT;
}
public function getActionKey() {
return 'custom:add-risk';
}
public function getActionName() {
return 'Add risk rating (JSON)';
}
public function getActionType() {
return HeraldAdapter::VALUE_TEXT;
}
public function applyEffect(
HeraldAdapter $adapter,
$object,
HeraldEffect $effect) {
$key = "phragile:risk-rating";
// Read existing value.
$field_list = PhabricatorCustomField::getObjectFields(
$object,
PhabricatorCustomField::ROLE_VIEW);
$field_list->readFieldsFromStorage($object);
$field_list = mpull($field_list->getFields(), null, 'getFieldKey');
$field = $field_list[$key];
$field->setObject($object);
$field->setViewer(PhabricatorUser::getOmnipotentUser());
$risk = $field->getValue();
$old_risk = $risk; // PHP copies arrays by default!
// Add new value to array.
$herald_args = phutil_json_decode($effect->getTarget());
$risk[$herald_args['key']] = array(
'value' => $herald_args['value'],
'reason' => $herald_args['reason']);
$risk_key = $herald_args['key'];
// Set new value.
$adapter->queueTransaction(
id(new DifferentialTransaction())
->setTransactionType(PhabricatorTransactions::TYPE_CUSTOMFIELD)
->setMetadataValue('customfield:key', $key)
->setOldValue($old_risk)
->setNewValue($risk));
return new HeraldApplyTranscript(
$effect,
true,
pht(
'Modifying automatic risk ratings (key: %s)!',
$risk_key));
}
}
```
Test Plan: Created a custom action for differential revisions, set up a Herald rule to match and trigger the custom action, did 'arc diff' and saw the action trigger in the transcripts.
Reviewers: epriestley, #blessed_reviewers
Reviewed By: epriestley, #blessed_reviewers
Subscribers: locutus, edutibau, ite-klass, epriestley, Korvin
Maniphest Tasks: T4884
Differential Revision: https://secure.phabricator.com/D8784
2014-07-02 06:29:46 +02:00
|
|
|
if (is_array($action->getTarget())) {
|
|
|
|
$target_map = array();
|
|
|
|
foreach ((array)$action->getTarget() as $fbid) {
|
|
|
|
$target_map[$fbid] = $handles[$fbid]->getName();
|
|
|
|
}
|
|
|
|
$current_value = $target_map;
|
|
|
|
} else {
|
|
|
|
$current_value = $action->getTarget();
|
2012-03-30 22:51:54 +02:00
|
|
|
}
|
|
|
|
break;
|
2011-03-22 23:27:52 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
$serial_actions[] = array(
|
|
|
|
$action->getAction(),
|
2012-03-30 22:51:54 +02:00
|
|
|
$current_value,
|
2011-03-22 23:27:52 +01:00
|
|
|
);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
General Herald refactoring pass
Summary:
**Who can delete global rules?**: I discussed this with @jungejason. The current behavior is that the rule author or any administrator can delete a global rule, but this
isn't consistent with who can edit a rule (anyone) and doesn't really make much sense (it's an artifact of the global/personal split). I proposed that anyone can delete a
rule but we don't actually delete them, and log the deletion. However, when it came time to actually write the code for this I backed off a bit and continued actually
deleting the rules -- I think this does a reasonable job of balancing accountability with complexity. So the new impelmentation is:
- Personal rules can be deleted only by their owners.
- Global rules can be deleted by any user.
- All deletes are logged.
- Logs are more detailed.
- All logged actions can be viewed in aggregate.
**Minor Cleanup**
- Merged `HomeController` and `AllController`.
- Moved most queries to Query classes.
- Use AphrontFormSelectControl::renderSelectTag() where appropriate (this is a fairly recent addition).
- Use an AphrontErrorView to render the dry run notice (this didn't exist when I ported).
- Reenable some transaction code (this works again now).
- Removed the ability for admins to change rule authors (this was a little buggy, messy, and doesn't make tons of sense after the personal/global rule split).
- Rules which depend on other rules now display the right options (all global rules, all your personal rules for personal rules).
- Fix a bug in AphrontTableView where the "no data" cell would be rendered too wide if some columns are not visible.
- Allow selectFilter() in AphrontNavFilterView to be called without a 'default' argument.
Test Plan:
- Browsed, created, edited, deleted personal and gules.
- Verified generated logs.
- Did some dry runs.
- Verified transcript list and transcript details.
- Created/edited all/any rules; created/edited once/every time rules.
- Filtered admin views by users.
Reviewers: jungejason, btrahan
Reviewed By: btrahan
CC: aran, epriestley
Differential Revision: https://secure.phabricator.com/D2040
2012-03-30 19:49:55 +02:00
|
|
|
$all_rules = $this->loadRulesThisRuleMayDependUpon($rule);
|
2014-02-10 23:40:09 +01:00
|
|
|
$all_rules = mpull($all_rules, 'getName', 'getPHID');
|
2011-03-22 23:27:52 +01:00
|
|
|
asort($all_rules);
|
|
|
|
|
2013-08-02 19:54:19 +02:00
|
|
|
$all_fields = $adapter->getFieldNameMap();
|
|
|
|
$all_conditions = $adapter->getConditionNameMap();
|
2013-08-02 20:32:50 +02:00
|
|
|
$all_actions = $adapter->getActionNameMap($rule->getRuleType());
|
2013-08-02 19:54:19 +02:00
|
|
|
|
2013-08-02 19:25:45 +02:00
|
|
|
$fields = $adapter->getFields();
|
2013-08-02 19:54:19 +02:00
|
|
|
$field_map = array_select_keys($all_fields, $fields);
|
2013-08-02 19:25:45 +02:00
|
|
|
|
2014-04-04 03:43:49 +02:00
|
|
|
// Populate any fields which exist in the rule but which we don't know the
|
|
|
|
// names of, so that saving a rule without touching anything doesn't change
|
|
|
|
// it.
|
|
|
|
foreach ($rule->getConditions() as $condition) {
|
|
|
|
if (empty($field_map[$condition->getFieldName()])) {
|
|
|
|
$field_map[$condition->getFieldName()] = pht('<Unknown Field>');
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-08-02 20:32:50 +02:00
|
|
|
$actions = $adapter->getActions($rule->getRuleType());
|
|
|
|
$action_map = array_select_keys($all_actions, $actions);
|
|
|
|
|
2011-03-22 23:27:52 +01:00
|
|
|
$config_info = array();
|
2013-08-02 19:25:45 +02:00
|
|
|
$config_info['fields'] = $field_map;
|
2013-08-02 19:54:19 +02:00
|
|
|
$config_info['conditions'] = $all_conditions;
|
2013-08-02 20:32:50 +02:00
|
|
|
$config_info['actions'] = $action_map;
|
|
|
|
|
2011-03-22 23:27:52 +01:00
|
|
|
foreach ($config_info['fields'] as $field => $name) {
|
2013-08-02 19:54:19 +02:00
|
|
|
$field_conditions = $adapter->getConditionsForField($field);
|
|
|
|
$config_info['conditionMap'][$field] = $field_conditions;
|
2011-03-22 23:27:52 +01:00
|
|
|
}
|
2013-08-02 19:54:19 +02:00
|
|
|
|
2011-03-22 23:27:52 +01:00
|
|
|
foreach ($config_info['fields'] as $field => $fname) {
|
2013-08-02 19:54:19 +02:00
|
|
|
foreach ($config_info['conditionMap'][$field] as $condition) {
|
2013-08-02 20:32:50 +02:00
|
|
|
$value_type = $adapter->getValueTypeForFieldAndCondition(
|
|
|
|
$field,
|
|
|
|
$condition);
|
|
|
|
$config_info['values'][$field][$condition] = $value_type;
|
2011-03-22 23:27:52 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-01-14 00:24:56 +01:00
|
|
|
$config_info['rule_type'] = $rule->getRuleType();
|
2011-03-22 23:27:52 +01:00
|
|
|
|
|
|
|
foreach ($config_info['actions'] as $action => $name) {
|
2013-08-02 20:32:50 +02:00
|
|
|
$config_info['targets'][$action] = $adapter->getValueTypeForAction(
|
|
|
|
$action,
|
|
|
|
$rule->getRuleType());
|
2011-03-22 23:27:52 +01:00
|
|
|
}
|
|
|
|
|
2014-04-08 20:58:28 +02:00
|
|
|
$changeflag_options =
|
2014-04-20 17:02:55 +02:00
|
|
|
PhabricatorRepositoryPushLog::getHeraldChangeFlagConditionOptions();
|
2011-03-22 23:27:52 +01:00
|
|
|
Javelin::initBehavior(
|
|
|
|
'herald-rule-editor',
|
|
|
|
array(
|
2011-03-23 01:08:08 +01:00
|
|
|
'root' => 'herald-rule-edit-form',
|
2011-10-22 03:34:38 +02:00
|
|
|
'conditions' => (object)$serial_conditions,
|
|
|
|
'actions' => (object)$serial_actions,
|
Add Herald support for blocking ref changes
Summary: Ref T4195. Allows users to write Herald rules which block ref changes. For example, you can write a rule like `alincoln can not create branches`, or `no one can push to the branch "frozen"`.
Test Plan:
This covers a lot of ground. I created and pushed a bunch of rules, then looked at transcripts, in general. Here are some bits in detail:
Here's a hook-based reject message:
>>> orbital ~/repos/POEMS $ git push
Counting objects: 5, done.
Delta compression using up to 8 threads.
Compressing objects: 100% (3/3), done.
Writing objects: 100% (3/3), 274 bytes, done.
Total 3 (delta 2), reused 0 (delta 0)
remote: +---------------------------------------------------------------+
remote: | * * * PUSH REJECTED BY EVIL DRAGON BUREAUCRATS * * * |
remote: +---------------------------------------------------------------+
remote: \
remote: \ ^ /^
remote: \ / \ // \
remote: \ |\___/| / \// .\
remote: \ /V V \__ / // | \ \ *----*
remote: / / \/_/ // | \ \ \ |
remote: @___@` \/_ // | \ \ \/\ \
remote: 0/0/| \/_ // | \ \ \ \
remote: 0/0/0/0/| \/// | \ \ | |
remote: 0/0/0/0/0/_|_ / ( // | \ _\ | /
remote: 0/0/0/0/0/0/`/,_ _ _/ ) ; -. | _ _\.-~ / /
remote: ,-} _ *-.|.-~-. .~ ~
remote: \ \__/ `/\ / ~-. _ .-~ /
remote: \____(Oo) *. } { /
remote: ( (--) .----~-.\ \-` .~
remote: //__\\ \ DENIED! ///.----..< \ _ -~
remote: // \\ ///-._ _ _ _ _ _ _{^ - - - - ~
remote:
remote:
remote: This commit was rejected by Herald pre-commit rule H24.
remote: Rule: No Branches Called Blarp
remote: Reason: "blarp" is a bad branch name
remote:
To ssh://dweller@localhost/diffusion/POEMS/
! [remote rejected] blarp -> blarp (pre-receive hook declined)
error: failed to push some refs to 'ssh://dweller@localhost/diffusion/POEMS/'
Here's a transcript, showing that all the field values populate sensibly:
{F90453}
Here's a rule:
{F90454}
Reviewers: btrahan
Reviewed By: btrahan
CC: aran
Maniphest Tasks: T4195
Differential Revision: https://secure.phabricator.com/D7782
2013-12-18 00:23:55 +01:00
|
|
|
'select' => array(
|
|
|
|
HeraldAdapter::VALUE_CONTENT_SOURCE => array(
|
|
|
|
'options' => PhabricatorContentSource::getSourceNameMap(),
|
|
|
|
'default' => PhabricatorContentSource::SOURCE_WEB,
|
|
|
|
),
|
|
|
|
HeraldAdapter::VALUE_FLAG_COLOR => array(
|
|
|
|
'options' => PhabricatorFlagColor::getColorNameMap(),
|
|
|
|
'default' => PhabricatorFlagColor::COLOR_BLUE,
|
|
|
|
),
|
|
|
|
HeraldPreCommitRefAdapter::VALUE_REF_TYPE => array(
|
|
|
|
'options' => array(
|
|
|
|
PhabricatorRepositoryPushLog::REFTYPE_BRANCH
|
|
|
|
=> pht('branch (git/hg)'),
|
|
|
|
PhabricatorRepositoryPushLog::REFTYPE_TAG
|
|
|
|
=> pht('tag (git)'),
|
|
|
|
PhabricatorRepositoryPushLog::REFTYPE_BOOKMARK
|
|
|
|
=> pht('bookmark (hg)'),
|
|
|
|
),
|
|
|
|
'default' => PhabricatorRepositoryPushLog::REFTYPE_BRANCH,
|
|
|
|
),
|
|
|
|
HeraldPreCommitRefAdapter::VALUE_REF_CHANGE => array(
|
2014-04-08 20:58:28 +02:00
|
|
|
'options' => $changeflag_options,
|
Add Herald support for blocking ref changes
Summary: Ref T4195. Allows users to write Herald rules which block ref changes. For example, you can write a rule like `alincoln can not create branches`, or `no one can push to the branch "frozen"`.
Test Plan:
This covers a lot of ground. I created and pushed a bunch of rules, then looked at transcripts, in general. Here are some bits in detail:
Here's a hook-based reject message:
>>> orbital ~/repos/POEMS $ git push
Counting objects: 5, done.
Delta compression using up to 8 threads.
Compressing objects: 100% (3/3), done.
Writing objects: 100% (3/3), 274 bytes, done.
Total 3 (delta 2), reused 0 (delta 0)
remote: +---------------------------------------------------------------+
remote: | * * * PUSH REJECTED BY EVIL DRAGON BUREAUCRATS * * * |
remote: +---------------------------------------------------------------+
remote: \
remote: \ ^ /^
remote: \ / \ // \
remote: \ |\___/| / \// .\
remote: \ /V V \__ / // | \ \ *----*
remote: / / \/_/ // | \ \ \ |
remote: @___@` \/_ // | \ \ \/\ \
remote: 0/0/| \/_ // | \ \ \ \
remote: 0/0/0/0/| \/// | \ \ | |
remote: 0/0/0/0/0/_|_ / ( // | \ _\ | /
remote: 0/0/0/0/0/0/`/,_ _ _/ ) ; -. | _ _\.-~ / /
remote: ,-} _ *-.|.-~-. .~ ~
remote: \ \__/ `/\ / ~-. _ .-~ /
remote: \____(Oo) *. } { /
remote: ( (--) .----~-.\ \-` .~
remote: //__\\ \ DENIED! ///.----..< \ _ -~
remote: // \\ ///-._ _ _ _ _ _ _{^ - - - - ~
remote:
remote:
remote: This commit was rejected by Herald pre-commit rule H24.
remote: Rule: No Branches Called Blarp
remote: Reason: "blarp" is a bad branch name
remote:
To ssh://dweller@localhost/diffusion/POEMS/
! [remote rejected] blarp -> blarp (pre-receive hook declined)
error: failed to push some refs to 'ssh://dweller@localhost/diffusion/POEMS/'
Here's a transcript, showing that all the field values populate sensibly:
{F90453}
Here's a rule:
{F90454}
Reviewers: btrahan
Reviewed By: btrahan
CC: aran
Maniphest Tasks: T4195
Differential Revision: https://secure.phabricator.com/D7782
2013-12-18 00:23:55 +01:00
|
|
|
'default' => PhabricatorRepositoryPushLog::CHANGEFLAG_ADD,
|
|
|
|
),
|
|
|
|
),
|
2014-04-10 21:38:15 +02:00
|
|
|
'template' => $this->buildTokenizerTemplates($handles) + array(
|
2011-03-22 23:27:52 +01:00
|
|
|
'rules' => $all_rules,
|
|
|
|
),
|
2012-01-05 22:07:08 +01:00
|
|
|
'author' => array($rule->getAuthorPHID() =>
|
|
|
|
$handles[$rule->getAuthorPHID()]->getName()),
|
2011-03-22 23:27:52 +01:00
|
|
|
'info' => $config_info,
|
|
|
|
));
|
2011-10-22 03:34:38 +02:00
|
|
|
}
|
2011-03-22 23:27:52 +01:00
|
|
|
|
2012-08-15 23:11:40 +02:00
|
|
|
private function loadHandlesForRule($rule) {
|
2011-10-22 03:34:38 +02:00
|
|
|
$phids = array();
|
2011-03-22 23:27:52 +01:00
|
|
|
|
2011-10-22 03:34:38 +02:00
|
|
|
foreach ($rule->getActions() as $action) {
|
|
|
|
if (!is_array($action->getTarget())) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
foreach ($action->getTarget() as $target) {
|
|
|
|
$target = (array)$target;
|
|
|
|
foreach ($target as $phid) {
|
|
|
|
$phids[] = $phid;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
foreach ($rule->getConditions() as $condition) {
|
|
|
|
$value = $condition->getValue();
|
|
|
|
if (is_array($value)) {
|
|
|
|
foreach ($value as $phid) {
|
|
|
|
$phids[] = $phid;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
General Herald refactoring pass
Summary:
**Who can delete global rules?**: I discussed this with @jungejason. The current behavior is that the rule author or any administrator can delete a global rule, but this
isn't consistent with who can edit a rule (anyone) and doesn't really make much sense (it's an artifact of the global/personal split). I proposed that anyone can delete a
rule but we don't actually delete them, and log the deletion. However, when it came time to actually write the code for this I backed off a bit and continued actually
deleting the rules -- I think this does a reasonable job of balancing accountability with complexity. So the new impelmentation is:
- Personal rules can be deleted only by their owners.
- Global rules can be deleted by any user.
- All deletes are logged.
- Logs are more detailed.
- All logged actions can be viewed in aggregate.
**Minor Cleanup**
- Merged `HomeController` and `AllController`.
- Moved most queries to Query classes.
- Use AphrontFormSelectControl::renderSelectTag() where appropriate (this is a fairly recent addition).
- Use an AphrontErrorView to render the dry run notice (this didn't exist when I ported).
- Reenable some transaction code (this works again now).
- Removed the ability for admins to change rule authors (this was a little buggy, messy, and doesn't make tons of sense after the personal/global rule split).
- Rules which depend on other rules now display the right options (all global rules, all your personal rules for personal rules).
- Fix a bug in AphrontTableView where the "no data" cell would be rendered too wide if some columns are not visible.
- Allow selectFilter() in AphrontNavFilterView to be called without a 'default' argument.
Test Plan:
- Browsed, created, edited, deleted personal and gules.
- Verified generated logs.
- Did some dry runs.
- Verified transcript list and transcript details.
- Created/edited all/any rules; created/edited once/every time rules.
- Filtered admin views by users.
Reviewers: jungejason, btrahan
Reviewed By: btrahan
CC: aran, epriestley
Differential Revision: https://secure.phabricator.com/D2040
2012-03-30 19:49:55 +02:00
|
|
|
$phids[] = $rule->getAuthorPHID();
|
2011-10-22 03:34:38 +02:00
|
|
|
|
2013-12-31 01:48:14 +01:00
|
|
|
if ($rule->isObjectRule()) {
|
|
|
|
$phids[] = $rule->getTriggerObjectPHID();
|
|
|
|
}
|
|
|
|
|
2012-09-05 04:02:56 +02:00
|
|
|
return $this->loadViewerHandles($phids);
|
General Herald refactoring pass
Summary:
**Who can delete global rules?**: I discussed this with @jungejason. The current behavior is that the rule author or any administrator can delete a global rule, but this
isn't consistent with who can edit a rule (anyone) and doesn't really make much sense (it's an artifact of the global/personal split). I proposed that anyone can delete a
rule but we don't actually delete them, and log the deletion. However, when it came time to actually write the code for this I backed off a bit and continued actually
deleting the rules -- I think this does a reasonable job of balancing accountability with complexity. So the new impelmentation is:
- Personal rules can be deleted only by their owners.
- Global rules can be deleted by any user.
- All deletes are logged.
- Logs are more detailed.
- All logged actions can be viewed in aggregate.
**Minor Cleanup**
- Merged `HomeController` and `AllController`.
- Moved most queries to Query classes.
- Use AphrontFormSelectControl::renderSelectTag() where appropriate (this is a fairly recent addition).
- Use an AphrontErrorView to render the dry run notice (this didn't exist when I ported).
- Reenable some transaction code (this works again now).
- Removed the ability for admins to change rule authors (this was a little buggy, messy, and doesn't make tons of sense after the personal/global rule split).
- Rules which depend on other rules now display the right options (all global rules, all your personal rules for personal rules).
- Fix a bug in AphrontTableView where the "no data" cell would be rendered too wide if some columns are not visible.
- Allow selectFilter() in AphrontNavFilterView to be called without a 'default' argument.
Test Plan:
- Browsed, created, edited, deleted personal and gules.
- Verified generated logs.
- Did some dry runs.
- Verified transcript list and transcript details.
- Created/edited all/any rules; created/edited once/every time rules.
- Filtered admin views by users.
Reviewers: jungejason, btrahan
Reviewed By: btrahan
CC: aran, epriestley
Differential Revision: https://secure.phabricator.com/D2040
2012-03-30 19:49:55 +02:00
|
|
|
}
|
2011-10-22 03:34:38 +02:00
|
|
|
|
|
|
|
|
General Herald refactoring pass
Summary:
**Who can delete global rules?**: I discussed this with @jungejason. The current behavior is that the rule author or any administrator can delete a global rule, but this
isn't consistent with who can edit a rule (anyone) and doesn't really make much sense (it's an artifact of the global/personal split). I proposed that anyone can delete a
rule but we don't actually delete them, and log the deletion. However, when it came time to actually write the code for this I backed off a bit and continued actually
deleting the rules -- I think this does a reasonable job of balancing accountability with complexity. So the new impelmentation is:
- Personal rules can be deleted only by their owners.
- Global rules can be deleted by any user.
- All deletes are logged.
- Logs are more detailed.
- All logged actions can be viewed in aggregate.
**Minor Cleanup**
- Merged `HomeController` and `AllController`.
- Moved most queries to Query classes.
- Use AphrontFormSelectControl::renderSelectTag() where appropriate (this is a fairly recent addition).
- Use an AphrontErrorView to render the dry run notice (this didn't exist when I ported).
- Reenable some transaction code (this works again now).
- Removed the ability for admins to change rule authors (this was a little buggy, messy, and doesn't make tons of sense after the personal/global rule split).
- Rules which depend on other rules now display the right options (all global rules, all your personal rules for personal rules).
- Fix a bug in AphrontTableView where the "no data" cell would be rendered too wide if some columns are not visible.
- Allow selectFilter() in AphrontNavFilterView to be called without a 'default' argument.
Test Plan:
- Browsed, created, edited, deleted personal and gules.
- Verified generated logs.
- Did some dry runs.
- Verified transcript list and transcript details.
- Created/edited all/any rules; created/edited once/every time rules.
- Filtered admin views by users.
Reviewers: jungejason, btrahan
Reviewed By: btrahan
CC: aran, epriestley
Differential Revision: https://secure.phabricator.com/D2040
2012-03-30 19:49:55 +02:00
|
|
|
/**
|
|
|
|
* Render the selector for the "When (all of | any of) these conditions are
|
|
|
|
* met:" element.
|
|
|
|
*/
|
|
|
|
private function renderMustMatchSelector($rule) {
|
|
|
|
return AphrontFormSelectControl::renderSelectTag(
|
|
|
|
$rule->getMustMatchAll() ? 'all' : 'any',
|
|
|
|
array(
|
2013-05-20 17:24:07 +02:00
|
|
|
'all' => pht('all of'),
|
|
|
|
'any' => pht('any of'),
|
General Herald refactoring pass
Summary:
**Who can delete global rules?**: I discussed this with @jungejason. The current behavior is that the rule author or any administrator can delete a global rule, but this
isn't consistent with who can edit a rule (anyone) and doesn't really make much sense (it's an artifact of the global/personal split). I proposed that anyone can delete a
rule but we don't actually delete them, and log the deletion. However, when it came time to actually write the code for this I backed off a bit and continued actually
deleting the rules -- I think this does a reasonable job of balancing accountability with complexity. So the new impelmentation is:
- Personal rules can be deleted only by their owners.
- Global rules can be deleted by any user.
- All deletes are logged.
- Logs are more detailed.
- All logged actions can be viewed in aggregate.
**Minor Cleanup**
- Merged `HomeController` and `AllController`.
- Moved most queries to Query classes.
- Use AphrontFormSelectControl::renderSelectTag() where appropriate (this is a fairly recent addition).
- Use an AphrontErrorView to render the dry run notice (this didn't exist when I ported).
- Reenable some transaction code (this works again now).
- Removed the ability for admins to change rule authors (this was a little buggy, messy, and doesn't make tons of sense after the personal/global rule split).
- Rules which depend on other rules now display the right options (all global rules, all your personal rules for personal rules).
- Fix a bug in AphrontTableView where the "no data" cell would be rendered too wide if some columns are not visible.
- Allow selectFilter() in AphrontNavFilterView to be called without a 'default' argument.
Test Plan:
- Browsed, created, edited, deleted personal and gules.
- Verified generated logs.
- Did some dry runs.
- Verified transcript list and transcript details.
- Created/edited all/any rules; created/edited once/every time rules.
- Filtered admin views by users.
Reviewers: jungejason, btrahan
Reviewed By: btrahan
CC: aran, epriestley
Differential Revision: https://secure.phabricator.com/D2040
2012-03-30 19:49:55 +02:00
|
|
|
),
|
|
|
|
array(
|
|
|
|
'name' => 'must_match',
|
|
|
|
));
|
2011-10-22 03:34:38 +02:00
|
|
|
}
|
|
|
|
|
General Herald refactoring pass
Summary:
**Who can delete global rules?**: I discussed this with @jungejason. The current behavior is that the rule author or any administrator can delete a global rule, but this
isn't consistent with who can edit a rule (anyone) and doesn't really make much sense (it's an artifact of the global/personal split). I proposed that anyone can delete a
rule but we don't actually delete them, and log the deletion. However, when it came time to actually write the code for this I backed off a bit and continued actually
deleting the rules -- I think this does a reasonable job of balancing accountability with complexity. So the new impelmentation is:
- Personal rules can be deleted only by their owners.
- Global rules can be deleted by any user.
- All deletes are logged.
- Logs are more detailed.
- All logged actions can be viewed in aggregate.
**Minor Cleanup**
- Merged `HomeController` and `AllController`.
- Moved most queries to Query classes.
- Use AphrontFormSelectControl::renderSelectTag() where appropriate (this is a fairly recent addition).
- Use an AphrontErrorView to render the dry run notice (this didn't exist when I ported).
- Reenable some transaction code (this works again now).
- Removed the ability for admins to change rule authors (this was a little buggy, messy, and doesn't make tons of sense after the personal/global rule split).
- Rules which depend on other rules now display the right options (all global rules, all your personal rules for personal rules).
- Fix a bug in AphrontTableView where the "no data" cell would be rendered too wide if some columns are not visible.
- Allow selectFilter() in AphrontNavFilterView to be called without a 'default' argument.
Test Plan:
- Browsed, created, edited, deleted personal and gules.
- Verified generated logs.
- Did some dry runs.
- Verified transcript list and transcript details.
- Created/edited all/any rules; created/edited once/every time rules.
- Filtered admin views by users.
Reviewers: jungejason, btrahan
Reviewed By: btrahan
CC: aran, epriestley
Differential Revision: https://secure.phabricator.com/D2040
2012-03-30 19:49:55 +02:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Render the selector for "Take these actions (every time | only the first
|
|
|
|
* time) this rule matches..." element.
|
|
|
|
*/
|
2013-08-02 21:35:33 +02:00
|
|
|
private function renderRepetitionSelector($rule, HeraldAdapter $adapter) {
|
2011-10-22 03:34:38 +02:00
|
|
|
$repetition_policy = HeraldRepetitionPolicyConfig::toString(
|
General Herald refactoring pass
Summary:
**Who can delete global rules?**: I discussed this with @jungejason. The current behavior is that the rule author or any administrator can delete a global rule, but this
isn't consistent with who can edit a rule (anyone) and doesn't really make much sense (it's an artifact of the global/personal split). I proposed that anyone can delete a
rule but we don't actually delete them, and log the deletion. However, when it came time to actually write the code for this I backed off a bit and continued actually
deleting the rules -- I think this does a reasonable job of balancing accountability with complexity. So the new impelmentation is:
- Personal rules can be deleted only by their owners.
- Global rules can be deleted by any user.
- All deletes are logged.
- Logs are more detailed.
- All logged actions can be viewed in aggregate.
**Minor Cleanup**
- Merged `HomeController` and `AllController`.
- Moved most queries to Query classes.
- Use AphrontFormSelectControl::renderSelectTag() where appropriate (this is a fairly recent addition).
- Use an AphrontErrorView to render the dry run notice (this didn't exist when I ported).
- Reenable some transaction code (this works again now).
- Removed the ability for admins to change rule authors (this was a little buggy, messy, and doesn't make tons of sense after the personal/global rule split).
- Rules which depend on other rules now display the right options (all global rules, all your personal rules for personal rules).
- Fix a bug in AphrontTableView where the "no data" cell would be rendered too wide if some columns are not visible.
- Allow selectFilter() in AphrontNavFilterView to be called without a 'default' argument.
Test Plan:
- Browsed, created, edited, deleted personal and gules.
- Verified generated logs.
- Did some dry runs.
- Verified transcript list and transcript details.
- Created/edited all/any rules; created/edited once/every time rules.
- Filtered admin views by users.
Reviewers: jungejason, btrahan
Reviewed By: btrahan
CC: aran, epriestley
Differential Revision: https://secure.phabricator.com/D2040
2012-03-30 19:49:55 +02:00
|
|
|
$rule->getRepetitionPolicy());
|
2013-08-02 21:35:33 +02:00
|
|
|
|
|
|
|
$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);
|
2011-10-22 03:34:38 +02:00
|
|
|
} else {
|
General Herald refactoring pass
Summary:
**Who can delete global rules?**: I discussed this with @jungejason. The current behavior is that the rule author or any administrator can delete a global rule, but this
isn't consistent with who can edit a rule (anyone) and doesn't really make much sense (it's an artifact of the global/personal split). I proposed that anyone can delete a
rule but we don't actually delete them, and log the deletion. However, when it came time to actually write the code for this I backed off a bit and continued actually
deleting the rules -- I think this does a reasonable job of balancing accountability with complexity. So the new impelmentation is:
- Personal rules can be deleted only by their owners.
- Global rules can be deleted by any user.
- All deletes are logged.
- Logs are more detailed.
- All logged actions can be viewed in aggregate.
**Minor Cleanup**
- Merged `HomeController` and `AllController`.
- Moved most queries to Query classes.
- Use AphrontFormSelectControl::renderSelectTag() where appropriate (this is a fairly recent addition).
- Use an AphrontErrorView to render the dry run notice (this didn't exist when I ported).
- Reenable some transaction code (this works again now).
- Removed the ability for admins to change rule authors (this was a little buggy, messy, and doesn't make tons of sense after the personal/global rule split).
- Rules which depend on other rules now display the right options (all global rules, all your personal rules for personal rules).
- Fix a bug in AphrontTableView where the "no data" cell would be rendered too wide if some columns are not visible.
- Allow selectFilter() in AphrontNavFilterView to be called without a 'default' argument.
Test Plan:
- Browsed, created, edited, deleted personal and gules.
- Verified generated logs.
- Did some dry runs.
- Verified transcript list and transcript details.
- Created/edited all/any rules; created/edited once/every time rules.
- Filtered admin views by users.
Reviewers: jungejason, btrahan
Reviewed By: btrahan
CC: aran, epriestley
Differential Revision: https://secure.phabricator.com/D2040
2012-03-30 19:49:55 +02:00
|
|
|
return AphrontFormSelectControl::renderSelectTag(
|
|
|
|
$repetition_policy,
|
2013-08-02 21:35:33 +02:00
|
|
|
$repetition_map,
|
General Herald refactoring pass
Summary:
**Who can delete global rules?**: I discussed this with @jungejason. The current behavior is that the rule author or any administrator can delete a global rule, but this
isn't consistent with who can edit a rule (anyone) and doesn't really make much sense (it's an artifact of the global/personal split). I proposed that anyone can delete a
rule but we don't actually delete them, and log the deletion. However, when it came time to actually write the code for this I backed off a bit and continued actually
deleting the rules -- I think this does a reasonable job of balancing accountability with complexity. So the new impelmentation is:
- Personal rules can be deleted only by their owners.
- Global rules can be deleted by any user.
- All deletes are logged.
- Logs are more detailed.
- All logged actions can be viewed in aggregate.
**Minor Cleanup**
- Merged `HomeController` and `AllController`.
- Moved most queries to Query classes.
- Use AphrontFormSelectControl::renderSelectTag() where appropriate (this is a fairly recent addition).
- Use an AphrontErrorView to render the dry run notice (this didn't exist when I ported).
- Reenable some transaction code (this works again now).
- Removed the ability for admins to change rule authors (this was a little buggy, messy, and doesn't make tons of sense after the personal/global rule split).
- Rules which depend on other rules now display the right options (all global rules, all your personal rules for personal rules).
- Fix a bug in AphrontTableView where the "no data" cell would be rendered too wide if some columns are not visible.
- Allow selectFilter() in AphrontNavFilterView to be called without a 'default' argument.
Test Plan:
- Browsed, created, edited, deleted personal and gules.
- Verified generated logs.
- Did some dry runs.
- Verified transcript list and transcript details.
- Created/edited all/any rules; created/edited once/every time rules.
- Filtered admin views by users.
Reviewers: jungejason, btrahan
Reviewed By: btrahan
CC: aran, epriestley
Differential Revision: https://secure.phabricator.com/D2040
2012-03-30 19:49:55 +02:00
|
|
|
array(
|
|
|
|
'name' => 'repetition_policy',
|
|
|
|
));
|
2011-10-22 03:34:38 +02:00
|
|
|
}
|
2011-03-22 23:27:52 +01:00
|
|
|
}
|
|
|
|
|
General Herald refactoring pass
Summary:
**Who can delete global rules?**: I discussed this with @jungejason. The current behavior is that the rule author or any administrator can delete a global rule, but this
isn't consistent with who can edit a rule (anyone) and doesn't really make much sense (it's an artifact of the global/personal split). I proposed that anyone can delete a
rule but we don't actually delete them, and log the deletion. However, when it came time to actually write the code for this I backed off a bit and continued actually
deleting the rules -- I think this does a reasonable job of balancing accountability with complexity. So the new impelmentation is:
- Personal rules can be deleted only by their owners.
- Global rules can be deleted by any user.
- All deletes are logged.
- Logs are more detailed.
- All logged actions can be viewed in aggregate.
**Minor Cleanup**
- Merged `HomeController` and `AllController`.
- Moved most queries to Query classes.
- Use AphrontFormSelectControl::renderSelectTag() where appropriate (this is a fairly recent addition).
- Use an AphrontErrorView to render the dry run notice (this didn't exist when I ported).
- Reenable some transaction code (this works again now).
- Removed the ability for admins to change rule authors (this was a little buggy, messy, and doesn't make tons of sense after the personal/global rule split).
- Rules which depend on other rules now display the right options (all global rules, all your personal rules for personal rules).
- Fix a bug in AphrontTableView where the "no data" cell would be rendered too wide if some columns are not visible.
- Allow selectFilter() in AphrontNavFilterView to be called without a 'default' argument.
Test Plan:
- Browsed, created, edited, deleted personal and gules.
- Verified generated logs.
- Did some dry runs.
- Verified transcript list and transcript details.
- Created/edited all/any rules; created/edited once/every time rules.
- Filtered admin views by users.
Reviewers: jungejason, btrahan
Reviewed By: btrahan
CC: aran, epriestley
Differential Revision: https://secure.phabricator.com/D2040
2012-03-30 19:49:55 +02:00
|
|
|
|
2014-04-10 21:38:15 +02:00
|
|
|
protected function buildTokenizerTemplates(array $handles) {
|
2011-03-23 04:41:02 +01:00
|
|
|
$template = new AphrontTokenizerTemplateView();
|
|
|
|
$template = $template->render();
|
|
|
|
|
2011-03-22 23:27:52 +01:00
|
|
|
return array(
|
|
|
|
'source' => array(
|
2014-02-06 20:42:31 +01:00
|
|
|
'email' => '/typeahead/common/mailable/',
|
|
|
|
'user' => '/typeahead/common/accounts/',
|
|
|
|
'repository' => '/typeahead/common/repositories/',
|
|
|
|
'package' => '/typeahead/common/packages/',
|
|
|
|
'project' => '/typeahead/common/projects/',
|
2013-10-15 04:38:35 +02:00
|
|
|
'userorproject' => '/typeahead/common/accountsorprojects/',
|
2014-02-06 20:42:31 +01:00
|
|
|
'buildplan' => '/typeahead/common/buildplans/',
|
|
|
|
'taskpriority' => '/typeahead/common/taskpriority/',
|
2014-03-11 21:15:01 +01:00
|
|
|
'arcanistprojects' => '/typeahead/common/arcanistprojects/',
|
Allow Herald to "Require legal signatures" for reviews
Summary:
Ref T3116. Add a Herald action "Require legal signatures" which requires revision authors to accept legal agreements before their revisions can be accepted.
- Herald will check which documents the author has signed, and trigger a "you have to sign X, Y, Z" for other documents.
- If the author has already signed everything, we don't spam the revision -- basically, this only triggers when signatures are missing.
- The UI will show which documents must be signed and warn that the revision can't be accepted until they're completed.
- Users aren't allowed to "Accept" the revision until documents are cleared.
Fixes T1157. The original install making the request (Hive) no longer uses Phabricator, and this satisfies our requirements.
Test Plan:
- Added a Herald rule.
- Created a revision, saw the rule trigger.
- Viewed as author and non-author, saw field UI (generic for non-author, specific for author), transaction UI, and accept-warning UI.
- Tried to accept revision.
- Signed document, saw UI update. Note that signatures don't currently //push// an update to the revision, but could eventually (like blocking tasks work).
- Accepted revision.
- Created another revision, saw rules not add the document (since it's already signed, this is the "no spam" case).
Reviewers: btrahan, chad
Reviewed By: chad
Subscribers: asherkin, epriestley
Maniphest Tasks: T1157, T3116
Differential Revision: https://secure.phabricator.com/D9771
2014-06-29 16:53:53 +02:00
|
|
|
'legaldocuments' => '/typeahead/common/legalpaddocuments/',
|
2011-03-22 23:27:52 +01:00
|
|
|
),
|
2014-04-10 21:38:15 +02:00
|
|
|
'username' => $this->getRequest()->getUser()->getUserName(),
|
|
|
|
'icons' => mpull($handles, 'getTypeIcon', 'getPHID'),
|
2011-03-23 04:41:02 +01:00
|
|
|
'markup' => $template,
|
2011-03-22 23:27:52 +01:00
|
|
|
);
|
|
|
|
}
|
General Herald refactoring pass
Summary:
**Who can delete global rules?**: I discussed this with @jungejason. The current behavior is that the rule author or any administrator can delete a global rule, but this
isn't consistent with who can edit a rule (anyone) and doesn't really make much sense (it's an artifact of the global/personal split). I proposed that anyone can delete a
rule but we don't actually delete them, and log the deletion. However, when it came time to actually write the code for this I backed off a bit and continued actually
deleting the rules -- I think this does a reasonable job of balancing accountability with complexity. So the new impelmentation is:
- Personal rules can be deleted only by their owners.
- Global rules can be deleted by any user.
- All deletes are logged.
- Logs are more detailed.
- All logged actions can be viewed in aggregate.
**Minor Cleanup**
- Merged `HomeController` and `AllController`.
- Moved most queries to Query classes.
- Use AphrontFormSelectControl::renderSelectTag() where appropriate (this is a fairly recent addition).
- Use an AphrontErrorView to render the dry run notice (this didn't exist when I ported).
- Reenable some transaction code (this works again now).
- Removed the ability for admins to change rule authors (this was a little buggy, messy, and doesn't make tons of sense after the personal/global rule split).
- Rules which depend on other rules now display the right options (all global rules, all your personal rules for personal rules).
- Fix a bug in AphrontTableView where the "no data" cell would be rendered too wide if some columns are not visible.
- Allow selectFilter() in AphrontNavFilterView to be called without a 'default' argument.
Test Plan:
- Browsed, created, edited, deleted personal and gules.
- Verified generated logs.
- Did some dry runs.
- Verified transcript list and transcript details.
- Created/edited all/any rules; created/edited once/every time rules.
- Filtered admin views by users.
Reviewers: jungejason, btrahan
Reviewed By: btrahan
CC: aran, epriestley
Differential Revision: https://secure.phabricator.com/D2040
2012-03-30 19:49:55 +02:00
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Load rules for the "Another Herald rule..." condition dropdown, which
|
|
|
|
* allows one rule to depend upon the success or failure of another rule.
|
|
|
|
*/
|
|
|
|
private function loadRulesThisRuleMayDependUpon(HeraldRule $rule) {
|
2013-08-02 15:38:17 +02:00
|
|
|
$viewer = $this->getRequest()->getUser();
|
|
|
|
|
General Herald refactoring pass
Summary:
**Who can delete global rules?**: I discussed this with @jungejason. The current behavior is that the rule author or any administrator can delete a global rule, but this
isn't consistent with who can edit a rule (anyone) and doesn't really make much sense (it's an artifact of the global/personal split). I proposed that anyone can delete a
rule but we don't actually delete them, and log the deletion. However, when it came time to actually write the code for this I backed off a bit and continued actually
deleting the rules -- I think this does a reasonable job of balancing accountability with complexity. So the new impelmentation is:
- Personal rules can be deleted only by their owners.
- Global rules can be deleted by any user.
- All deletes are logged.
- Logs are more detailed.
- All logged actions can be viewed in aggregate.
**Minor Cleanup**
- Merged `HomeController` and `AllController`.
- Moved most queries to Query classes.
- Use AphrontFormSelectControl::renderSelectTag() where appropriate (this is a fairly recent addition).
- Use an AphrontErrorView to render the dry run notice (this didn't exist when I ported).
- Reenable some transaction code (this works again now).
- Removed the ability for admins to change rule authors (this was a little buggy, messy, and doesn't make tons of sense after the personal/global rule split).
- Rules which depend on other rules now display the right options (all global rules, all your personal rules for personal rules).
- Fix a bug in AphrontTableView where the "no data" cell would be rendered too wide if some columns are not visible.
- Allow selectFilter() in AphrontNavFilterView to be called without a 'default' argument.
Test Plan:
- Browsed, created, edited, deleted personal and gules.
- Verified generated logs.
- Did some dry runs.
- Verified transcript list and transcript details.
- Created/edited all/any rules; created/edited once/every time rules.
- Filtered admin views by users.
Reviewers: jungejason, btrahan
Reviewed By: btrahan
CC: aran, epriestley
Differential Revision: https://secure.phabricator.com/D2040
2012-03-30 19:49:55 +02:00
|
|
|
// Any rule can depend on a global rule.
|
|
|
|
$all_rules = id(new HeraldRuleQuery())
|
2013-08-02 15:38:17 +02:00
|
|
|
->setViewer($viewer)
|
General Herald refactoring pass
Summary:
**Who can delete global rules?**: I discussed this with @jungejason. The current behavior is that the rule author or any administrator can delete a global rule, but this
isn't consistent with who can edit a rule (anyone) and doesn't really make much sense (it's an artifact of the global/personal split). I proposed that anyone can delete a
rule but we don't actually delete them, and log the deletion. However, when it came time to actually write the code for this I backed off a bit and continued actually
deleting the rules -- I think this does a reasonable job of balancing accountability with complexity. So the new impelmentation is:
- Personal rules can be deleted only by their owners.
- Global rules can be deleted by any user.
- All deletes are logged.
- Logs are more detailed.
- All logged actions can be viewed in aggregate.
**Minor Cleanup**
- Merged `HomeController` and `AllController`.
- Moved most queries to Query classes.
- Use AphrontFormSelectControl::renderSelectTag() where appropriate (this is a fairly recent addition).
- Use an AphrontErrorView to render the dry run notice (this didn't exist when I ported).
- Reenable some transaction code (this works again now).
- Removed the ability for admins to change rule authors (this was a little buggy, messy, and doesn't make tons of sense after the personal/global rule split).
- Rules which depend on other rules now display the right options (all global rules, all your personal rules for personal rules).
- Fix a bug in AphrontTableView where the "no data" cell would be rendered too wide if some columns are not visible.
- Allow selectFilter() in AphrontNavFilterView to be called without a 'default' argument.
Test Plan:
- Browsed, created, edited, deleted personal and gules.
- Verified generated logs.
- Did some dry runs.
- Verified transcript list and transcript details.
- Created/edited all/any rules; created/edited once/every time rules.
- Filtered admin views by users.
Reviewers: jungejason, btrahan
Reviewed By: btrahan
CC: aran, epriestley
Differential Revision: https://secure.phabricator.com/D2040
2012-03-30 19:49:55 +02:00
|
|
|
->withRuleTypes(array(HeraldRuleTypeConfig::RULE_TYPE_GLOBAL))
|
|
|
|
->withContentTypes(array($rule->getContentType()))
|
|
|
|
->execute();
|
|
|
|
|
2013-12-27 22:17:10 +01:00
|
|
|
if ($rule->isObjectRule()) {
|
|
|
|
// Object rules may depend on other rules for the same object.
|
|
|
|
$all_rules += id(new HeraldRuleQuery())
|
|
|
|
->setViewer($viewer)
|
|
|
|
->withRuleTypes(array(HeraldRuleTypeConfig::RULE_TYPE_OBJECT))
|
|
|
|
->withContentTypes(array($rule->getContentType()))
|
|
|
|
->withTriggerObjectPHIDs(array($rule->getTriggerObjectPHID()))
|
|
|
|
->execute();
|
|
|
|
}
|
|
|
|
|
|
|
|
if ($rule->isPersonalRule()) {
|
General Herald refactoring pass
Summary:
**Who can delete global rules?**: I discussed this with @jungejason. The current behavior is that the rule author or any administrator can delete a global rule, but this
isn't consistent with who can edit a rule (anyone) and doesn't really make much sense (it's an artifact of the global/personal split). I proposed that anyone can delete a
rule but we don't actually delete them, and log the deletion. However, when it came time to actually write the code for this I backed off a bit and continued actually
deleting the rules -- I think this does a reasonable job of balancing accountability with complexity. So the new impelmentation is:
- Personal rules can be deleted only by their owners.
- Global rules can be deleted by any user.
- All deletes are logged.
- Logs are more detailed.
- All logged actions can be viewed in aggregate.
**Minor Cleanup**
- Merged `HomeController` and `AllController`.
- Moved most queries to Query classes.
- Use AphrontFormSelectControl::renderSelectTag() where appropriate (this is a fairly recent addition).
- Use an AphrontErrorView to render the dry run notice (this didn't exist when I ported).
- Reenable some transaction code (this works again now).
- Removed the ability for admins to change rule authors (this was a little buggy, messy, and doesn't make tons of sense after the personal/global rule split).
- Rules which depend on other rules now display the right options (all global rules, all your personal rules for personal rules).
- Fix a bug in AphrontTableView where the "no data" cell would be rendered too wide if some columns are not visible.
- Allow selectFilter() in AphrontNavFilterView to be called without a 'default' argument.
Test Plan:
- Browsed, created, edited, deleted personal and gules.
- Verified generated logs.
- Did some dry runs.
- Verified transcript list and transcript details.
- Created/edited all/any rules; created/edited once/every time rules.
- Filtered admin views by users.
Reviewers: jungejason, btrahan
Reviewed By: btrahan
CC: aran, epriestley
Differential Revision: https://secure.phabricator.com/D2040
2012-03-30 19:49:55 +02:00
|
|
|
// Personal rules may depend upon your other personal rules.
|
|
|
|
$all_rules += id(new HeraldRuleQuery())
|
2013-08-02 15:38:17 +02:00
|
|
|
->setViewer($viewer)
|
General Herald refactoring pass
Summary:
**Who can delete global rules?**: I discussed this with @jungejason. The current behavior is that the rule author or any administrator can delete a global rule, but this
isn't consistent with who can edit a rule (anyone) and doesn't really make much sense (it's an artifact of the global/personal split). I proposed that anyone can delete a
rule but we don't actually delete them, and log the deletion. However, when it came time to actually write the code for this I backed off a bit and continued actually
deleting the rules -- I think this does a reasonable job of balancing accountability with complexity. So the new impelmentation is:
- Personal rules can be deleted only by their owners.
- Global rules can be deleted by any user.
- All deletes are logged.
- Logs are more detailed.
- All logged actions can be viewed in aggregate.
**Minor Cleanup**
- Merged `HomeController` and `AllController`.
- Moved most queries to Query classes.
- Use AphrontFormSelectControl::renderSelectTag() where appropriate (this is a fairly recent addition).
- Use an AphrontErrorView to render the dry run notice (this didn't exist when I ported).
- Reenable some transaction code (this works again now).
- Removed the ability for admins to change rule authors (this was a little buggy, messy, and doesn't make tons of sense after the personal/global rule split).
- Rules which depend on other rules now display the right options (all global rules, all your personal rules for personal rules).
- Fix a bug in AphrontTableView where the "no data" cell would be rendered too wide if some columns are not visible.
- Allow selectFilter() in AphrontNavFilterView to be called without a 'default' argument.
Test Plan:
- Browsed, created, edited, deleted personal and gules.
- Verified generated logs.
- Did some dry runs.
- Verified transcript list and transcript details.
- Created/edited all/any rules; created/edited once/every time rules.
- Filtered admin views by users.
Reviewers: jungejason, btrahan
Reviewed By: btrahan
CC: aran, epriestley
Differential Revision: https://secure.phabricator.com/D2040
2012-03-30 19:49:55 +02:00
|
|
|
->withRuleTypes(array(HeraldRuleTypeConfig::RULE_TYPE_PERSONAL))
|
|
|
|
->withContentTypes(array($rule->getContentType()))
|
|
|
|
->withAuthorPHIDs(array($rule->getAuthorPHID()))
|
|
|
|
->execute();
|
|
|
|
}
|
|
|
|
|
2014-02-10 23:40:09 +01:00
|
|
|
// mark disabled rules as disabled since they are not useful as such;
|
|
|
|
// don't filter though to keep edit cases sane / expected
|
|
|
|
foreach ($all_rules as $current_rule) {
|
|
|
|
if ($current_rule->getIsDisabled()) {
|
|
|
|
$current_rule->makeEphemeral();
|
2014-06-10 01:03:58 +02:00
|
|
|
$current_rule->setName($rule->getName().' '.pht('(Disabled)'));
|
2014-02-10 23:40:09 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
General Herald refactoring pass
Summary:
**Who can delete global rules?**: I discussed this with @jungejason. The current behavior is that the rule author or any administrator can delete a global rule, but this
isn't consistent with who can edit a rule (anyone) and doesn't really make much sense (it's an artifact of the global/personal split). I proposed that anyone can delete a
rule but we don't actually delete them, and log the deletion. However, when it came time to actually write the code for this I backed off a bit and continued actually
deleting the rules -- I think this does a reasonable job of balancing accountability with complexity. So the new impelmentation is:
- Personal rules can be deleted only by their owners.
- Global rules can be deleted by any user.
- All deletes are logged.
- Logs are more detailed.
- All logged actions can be viewed in aggregate.
**Minor Cleanup**
- Merged `HomeController` and `AllController`.
- Moved most queries to Query classes.
- Use AphrontFormSelectControl::renderSelectTag() where appropriate (this is a fairly recent addition).
- Use an AphrontErrorView to render the dry run notice (this didn't exist when I ported).
- Reenable some transaction code (this works again now).
- Removed the ability for admins to change rule authors (this was a little buggy, messy, and doesn't make tons of sense after the personal/global rule split).
- Rules which depend on other rules now display the right options (all global rules, all your personal rules for personal rules).
- Fix a bug in AphrontTableView where the "no data" cell would be rendered too wide if some columns are not visible.
- Allow selectFilter() in AphrontNavFilterView to be called without a 'default' argument.
Test Plan:
- Browsed, created, edited, deleted personal and gules.
- Verified generated logs.
- Did some dry runs.
- Verified transcript list and transcript details.
- Created/edited all/any rules; created/edited once/every time rules.
- Filtered admin views by users.
Reviewers: jungejason, btrahan
Reviewed By: btrahan
CC: aran, epriestley
Differential Revision: https://secure.phabricator.com/D2040
2012-03-30 19:49:55 +02:00
|
|
|
// A rule can not depend upon itself.
|
|
|
|
unset($all_rules[$rule->getID()]);
|
|
|
|
|
|
|
|
return $all_rules;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2011-03-22 23:27:52 +01:00
|
|
|
}
|