Page MenuHomePhabricator

D20161.diff
No OneTemporary

D20161.diff

diff --git a/src/applications/maniphest/config/PhabricatorManiphestConfigOptions.php b/src/applications/maniphest/config/PhabricatorManiphestConfigOptions.php
--- a/src/applications/maniphest/config/PhabricatorManiphestConfigOptions.php
+++ b/src/applications/maniphest/config/PhabricatorManiphestConfigOptions.php
@@ -342,6 +342,7 @@
- `icon` //Optional string.// Icon for the subtype.
- `children` //Optional map.// Configure options shown to the user when
they "Create Subtask". See below.
+ - `fields` //Optional map.// Configure field behaviors. See below.
Each subtype must have a unique key, and you must define a subtype with
the key "%s", which is used as a default subtype.
@@ -397,6 +398,28 @@
If only one option would be presented, the user will be taken directly to the
appropriate form instead of being prompted to choose a form.
+
+The `fields` key can configure the behavior of custom fields on specific
+task subtypes. For example:
+
+```
+{
+ ...
+ "fields": {
+ "custom.some-field": {
+ "disabled": true
+ }
+ }
+ ...
+}
+```
+
+Each field supports these options:
+
+ - `disabled` //Optional bool.// Allows you to disable fields on certain
+ subtypes.
+ - `name` //Optional string.// Custom name of this field for the subtype.
+
EOTEXT
,
$subtype_default_key));
diff --git a/src/applications/transactions/editengine/PhabricatorEditEngine.php b/src/applications/transactions/editengine/PhabricatorEditEngine.php
--- a/src/applications/transactions/editengine/PhabricatorEditEngine.php
+++ b/src/applications/transactions/editengine/PhabricatorEditEngine.php
@@ -165,14 +165,29 @@
$extensions = array();
}
+ // See T13248. Create a template object to provide to extensions. We
+ // adjust the template to have the intended subtype, so that extensions
+ // may change behavior based on the form subtype.
+
+ $template_object = clone $object;
+ if ($this->getIsCreate()) {
+ if ($this->supportsSubtypes()) {
+ $config = $this->getEditEngineConfiguration();
+ $subtype = $config->getSubtype();
+ $template_object->setSubtype($subtype);
+ }
+ }
+
foreach ($extensions as $extension) {
$extension->setViewer($viewer);
- if (!$extension->supportsObject($this, $object)) {
+ if (!$extension->supportsObject($this, $template_object)) {
continue;
}
- $extension_fields = $extension->buildCustomEditFields($this, $object);
+ $extension_fields = $extension->buildCustomEditFields(
+ $this,
+ $template_object);
// TODO: Validate this in more detail with a more tailored error.
assert_instances_of($extension_fields, 'PhabricatorEditField');
diff --git a/src/applications/transactions/editengine/PhabricatorEditEngineSubtype.php b/src/applications/transactions/editengine/PhabricatorEditEngineSubtype.php
--- a/src/applications/transactions/editengine/PhabricatorEditEngineSubtype.php
+++ b/src/applications/transactions/editengine/PhabricatorEditEngineSubtype.php
@@ -13,6 +13,7 @@
private $color;
private $childSubtypes = array();
private $childIdentifiers = array();
+ private $fieldConfiguration = array();
public function setKey($key) {
$this->key = $key;
@@ -94,6 +95,17 @@
return $view;
}
+ public function setSubtypeFieldConfiguration(
+ $subtype_key,
+ array $configuration) {
+ $this->fieldConfiguration[$subtype_key] = $configuration;
+ return $this;
+ }
+
+ public function getSubtypeFieldConfiguration($subtype_key) {
+ return idx($this->fieldConfiguration, $subtype_key);
+ }
+
public static function validateSubtypeKey($subtype) {
if (strlen($subtype) > 64) {
throw new Exception(
@@ -139,6 +151,7 @@
'color' => 'optional string',
'icon' => 'optional string',
'children' => 'optional map<string, wild>',
+ 'fields' => 'optional map<string, wild>',
));
$key = $value['key'];
@@ -183,6 +196,18 @@
'or the other, but not both.'));
}
}
+
+ $fields = idx($value, 'fields');
+ if ($fields) {
+ foreach ($fields as $field_key => $configuration) {
+ PhutilTypeSpec::checkMap(
+ $configuration,
+ array(
+ 'disabled' => 'optional bool',
+ 'name' => 'optional string',
+ ));
+ }
+ }
}
if (!isset($map[self::SUBTYPE_DEFAULT])) {
@@ -233,6 +258,15 @@
$subtype->setChildFormIdentifiers($child_forms);
}
+ $field_configurations = idx($entry, 'fields');
+ if ($field_configurations) {
+ foreach ($field_configurations as $field_key => $field_configuration) {
+ $subtype->setSubtypeFieldConfiguration(
+ $field_key,
+ $field_configuration);
+ }
+ }
+
$map[$key] = $subtype;
}
diff --git a/src/infrastructure/customfield/field/PhabricatorCustomField.php b/src/infrastructure/customfield/field/PhabricatorCustomField.php
--- a/src/infrastructure/customfield/field/PhabricatorCustomField.php
+++ b/src/infrastructure/customfield/field/PhabricatorCustomField.php
@@ -74,9 +74,22 @@
$spec,
$object);
+ $fields = self::adjustCustomFieldsForObjectSubtype(
+ $object,
+ $role,
+ $fields);
+
foreach ($fields as $key => $field) {
+ // NOTE: We perform this filtering in "buildFieldList()", but may need
+ // to filter again after subtype adjustment.
+ if (!$field->isFieldEnabled()) {
+ unset($fields[$key]);
+ continue;
+ }
+
if (!$field->shouldEnableForRole($role)) {
unset($fields[$key]);
+ continue;
}
}
@@ -1622,4 +1635,78 @@
return null;
}
+ private static function adjustCustomFieldsForObjectSubtype(
+ PhabricatorCustomFieldInterface $object,
+ $role,
+ array $fields) {
+ assert_instances_of($fields, __CLASS__);
+
+ // We only apply subtype adjustment for some roles. For example, when
+ // writing Herald rules or building a Search interface, we always want to
+ // show all the fields in their default state, so we do not apply any
+ // adjustments.
+ $subtype_roles = array(
+ self::ROLE_EDITENGINE,
+ self::ROLE_VIEW,
+ );
+
+ $subtype_roles = array_fuse($subtype_roles);
+ if (!isset($subtype_roles[$role])) {
+ return $fields;
+ }
+
+ // If the object doesn't support subtypes, we can't possibly make
+ // any adjustments based on subtype.
+ if (!($object instanceof PhabricatorEditEngineSubtypeInterface)) {
+ return $fields;
+ }
+
+ $subtype_map = $object->newEditEngineSubtypeMap();
+ $subtype_key = $object->getEditEngineSubtype();
+ $subtype_object = $subtype_map->getSubtype($subtype_key);
+
+ $map = array();
+ foreach ($fields as $field) {
+ $modern_key = $field->getModernFieldKey();
+ if (!strlen($modern_key)) {
+ continue;
+ }
+
+ $map[$modern_key] = $field;
+ }
+
+ foreach ($map as $field_key => $field) {
+ // For now, only support overriding standard custom fields. In the
+ // future there's no technical or product reason we couldn't let you
+ // override (some properites of) other fields like "Title", but they
+ // don't usually support appropriate "setX()" methods today.
+ if (!($field instanceof PhabricatorStandardCustomField)) {
+ // For fields that are proxies on top of StandardCustomField, which
+ // is how most application custom fields work today, we can reconfigure
+ // the proxied field instead.
+ $field = $field->getProxy();
+ if (!$field || !($field instanceof PhabricatorStandardCustomField)) {
+ continue;
+ }
+ }
+
+ $subtype_config = $subtype_object->getSubtypeFieldConfiguration(
+ $field_key);
+
+ if (!$subtype_config) {
+ continue;
+ }
+
+ if (isset($subtype_config['disabled'])) {
+ $field->setIsEnabled(!$subtype_config['disabled']);
+ }
+
+ if (isset($subtype_config['name'])) {
+ $field->setFieldName($subtype_config['name']);
+ }
+ }
+
+ return $fields;
+ }
+
}
diff --git a/src/infrastructure/customfield/standard/PhabricatorStandardCustomField.php b/src/infrastructure/customfield/standard/PhabricatorStandardCustomField.php
--- a/src/infrastructure/customfield/standard/PhabricatorStandardCustomField.php
+++ b/src/infrastructure/customfield/standard/PhabricatorStandardCustomField.php
@@ -18,6 +18,7 @@
private $isCopyable;
private $hasStorageValue;
private $isBuiltin;
+ private $isEnabled = true;
abstract public function getFieldType();
@@ -175,6 +176,19 @@
return $this->rawKey;
}
+ public function setIsEnabled($is_enabled) {
+ $this->isEnabled = $is_enabled;
+ return $this;
+ }
+
+ public function getIsEnabled() {
+ return $this->isEnabled;
+ }
+
+ public function isFieldEnabled() {
+ return $this->getIsEnabled();
+ }
+
/* -( PhabricatorCustomField )--------------------------------------------- */

File Metadata

Mime Type
text/plain
Expires
Fri, Nov 22, 8:25 AM (17 h, 19 m)
Storage Engine
blob
Storage Format
Encrypted (AES-256-CBC)
Storage Handle
6774039
Default Alt Text
D20161.diff (8 KB)

Event Timeline