Page MenuHomePhabricator

D7300.diff

diff --git a/src/__celerity_resource_map__.php b/src/__celerity_resource_map__.php
--- a/src/__celerity_resource_map__.php
+++ b/src/__celerity_resource_map__.php
@@ -2295,15 +2295,16 @@
),
'javelin-behavior-policy-control' =>
array(
- 'uri' => '/res/f43ba427/rsrc/js/application/policy/behavior-policy-control.js',
+ 'uri' => '/res/ce9f54c8/rsrc/js/application/policy/behavior-policy-control.js',
'type' => 'js',
'requires' =>
array(
0 => 'javelin-behavior',
1 => 'javelin-dom',
2 => 'javelin-util',
3 => 'phabricator-dropdown-menu',
4 => 'phabricator-menu-item',
+ 5 => 'javelin-workflow',
),
'disk' => '/rsrc/js/application/policy/behavior-policy-control.js',
),
diff --git a/src/applications/meta/controller/PhabricatorApplicationEditController.php b/src/applications/meta/controller/PhabricatorApplicationEditController.php
--- a/src/applications/meta/controller/PhabricatorApplicationEditController.php
+++ b/src/applications/meta/controller/PhabricatorApplicationEditController.php
@@ -47,8 +47,16 @@
}
if (empty($policies[$new])) {
- // Can't set the policy to something invalid.
- continue;
+ // Not a standard policy, check for a custom policy.
+ $policy = id(new PhabricatorPolicyQuery())
+ ->setViewer($user)
+ ->withPHIDs(array($new))
+ ->executeOne();
+ if (!$policy) {
+ // Not a custom policy either. Can't set the policy to something
+ // invalid, so skip this.
+ continue;
+ }
}
if ($new == PhabricatorPolicies::POLICY_PUBLIC) {
diff --git a/src/applications/policy/rule/PhabricatorPolicyRuleProjects.php b/src/applications/policy/rule/PhabricatorPolicyRuleProjects.php
--- a/src/applications/policy/rule/PhabricatorPolicyRuleProjects.php
+++ b/src/applications/policy/rule/PhabricatorPolicyRuleProjects.php
@@ -10,7 +10,7 @@
}
public function willApplyRules(PhabricatorUser $viewer, array $values) {
- $values = array_unique(array_filter($values));
+ $values = array_unique(array_filter(array_mergev($values)));
if (!$values) {
return;
}
diff --git a/src/view/form/control/AphrontFormPolicyControl.php b/src/view/form/control/AphrontFormPolicyControl.php
--- a/src/view/form/control/AphrontFormPolicyControl.php
+++ b/src/view/form/control/AphrontFormPolicyControl.php
@@ -54,6 +54,48 @@
'icon' => $policy->getIcon(),
);
}
+
+ // If we were passed several custom policy options, throw away the ones
+ // which aren't the value for this capability. For example, an object might
+ // have a custom view pollicy and a custom edit policy. When we render
+ // the selector for "Can View", we don't want to show the "Can Edit"
+ // custom policy -- if we did, the menu would look like this:
+ //
+ // Custom
+ // Custom Policy
+ // Custom Policy
+ //
+ // ...where one is the "view" custom policy, and one is the "edit" custom
+ // policy.
+
+ $type_custom = PhabricatorPolicyType::TYPE_CUSTOM;
+ if (!empty($options[$type_custom])) {
+ $options[$type_custom] = array_select_keys(
+ $options[$type_custom],
+ array($this->getValue()));
+ }
+
+ // If there aren't any custom policies, add a placeholder policy so we
+ // render a menu item. This allows the user to switch to a custom policy.
+
+ if (empty($options[$type_custom])) {
+ $placeholder = new PhabricatorPolicy();
+ $placeholder->setName(pht('Custom Policy...'));
+ $options[$type_custom][$this->getCustomPolicyPlaceholder()] = array(
+ 'name' => $placeholder->getName(),
+ 'full' => $placeholder->getName(),
+ 'icon' => $placeholder->getIcon(),
+ );
+ }
+
+ $options = array_select_keys(
+ $options,
+ array(
+ PhabricatorPolicyType::TYPE_GLOBAL,
+ PhabricatorPolicyType::TYPE_CUSTOM,
+ PhabricatorPolicyType::TYPE_PROJECT,
+ ));
+
return $options;
}
@@ -121,6 +163,7 @@
'icons' => $icons,
'labels' => $labels,
'value' => $this->getValue(),
+ 'customPlaceholder' => $this->getCustomPolicyPlaceholder(),
));
$selected = $flat_options[$this->getValue()];
@@ -165,5 +208,8 @@
));
}
+ private function getCustomPolicyPlaceholder() {
+ return 'custom:placeholder';
+ }
}
diff --git a/webroot/rsrc/js/application/policy/behavior-policy-control.js b/webroot/rsrc/js/application/policy/behavior-policy-control.js
--- a/webroot/rsrc/js/application/policy/behavior-policy-control.js
+++ b/webroot/rsrc/js/application/policy/behavior-policy-control.js
@@ -5,6 +5,7 @@
* javelin-util
* phabricator-dropdown-menu
* phabricator-menu-item
+ * javelin-workflow
* @javelin
*/
JX.behavior('policy-control', function(config) {
@@ -23,25 +24,37 @@
for (var ii = 0; ii < config.groups.length; ii++) {
var group = config.groups[ii];
- var header = new JX.PhabricatorMenuItem(config.labels[group]);
+ var header = new JX.PhabricatorMenuItem(config.labels[group], JX.bag);
header.setDisabled(true);
menu.addItem(header);
for (var jj = 0; jj < config.order[group].length; jj++) {
var phid = config.order[group][jj];
- var option = config.options[phid];
- var render = [JX.$H(config.icons[option.icon]), option.name];
+ var onselect;
+ if (group == 'custom') {
+ onselect = JX.bind(null, function(phid) {
+ var uri = get_custom_uri(phid);
+
+ new JX.Workflow(uri)
+ .setHandler(function(response) {
+ if (!response.phid) {
+ return;
+ }
+
+ replace_policy(phid, response.phid, response.info);
+ select_policy(response.phid);
+ })
+ .start();
+
+ }, phid);
+ } else {
+ onselect = JX.bind(null, select_policy, phid);
+ }
var item = new JX.PhabricatorMenuItem(
- render,
- JX.bind(null, function(phid, render) {
- JX.DOM.setContent(
- JX.DOM.find(control, 'span', 'policy-label'),
- render);
- input.value = phid;
- value = phid;
- }, phid, render));
+ render_option(phid, true),
+ onselect);
if (phid == value) {
item.setSelected(true);
@@ -53,4 +66,56 @@
});
+
+ var select_policy = function(phid) {
+ JX.DOM.setContent(
+ JX.DOM.find(control, 'span', 'policy-label'),
+ render_option(phid));
+
+ input.value = phid;
+ value = phid;
+ };
+
+
+ var render_option = function(phid, with_title) {
+ var option = config.options[phid];
+
+ var name = option.name;
+ if (with_title && (option.full != option.name)) {
+ name = JX.$N('span', {title: option.full}, name);
+ }
+
+ return [JX.$H(config.icons[option.icon]), name];
+ };
+
+
+ /**
+ * Get the workflow URI to create or edit a policy with a given PHID.
+ */
+ var get_custom_uri = function(phid) {
+ var uri = '/policy/edit/';
+ if (phid != config.customPlaceholder) {
+ uri += phid + '/';
+ }
+ return uri;
+ };
+
+
+ /**
+ * Replace an existing policy option with a new one. Used to swap out custom
+ * policies after the user edits them.
+ */
+ var replace_policy = function(old_phid, new_phid, info) {
+ config.options[new_phid] = info;
+ for (var k in config.order) {
+ for (var ii = 0; ii < config.order[k].length; ii++) {
+ if (config.order[k][ii] == old_phid) {
+ config.order[k][ii] = new_phid;
+ return;
+ }
+ }
+ }
+ };
+
+
});

File Metadata

Mime Type
text/x-diff
Storage Engine
amazon-s3
Storage Format
Raw Data
Storage Handle
phabricator/ld/xt/bdgbarpyrjeuprjm
Default Alt Text
D7300.diff (7 KB)

Event Timeline