Page MenuHomePhabricator

D20810.id49616.diff
No OneTemporary

D20810.id49616.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
@@ -344,6 +344,8 @@
- `children` //Optional map.// Configure options shown to the user when
they "Create Subtask". See below.
- `fields` //Optional map.// Configure field behaviors. See below.
+ - `mutations` //Optional list.// Configure which subtypes this subtype
+ can easily be converted to by using the "Change Subtype" action. 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.
@@ -404,15 +406,15 @@
task subtypes. For example:
```
-{
- ...
- "fields": {
- "custom.some-field": {
- "disabled": true
+ {
+ ...
+ "fields": {
+ "custom.some-field": {
+ "disabled": true
+ }
}
+ ...
}
- ...
-}
```
Each field supports these options:
@@ -421,6 +423,31 @@
subtypes.
- `name` //Optional string.// Custom name of this field for the subtype.
+
+The `mutations` key allows you to control the behavior of the "Change Subtype"
+action above the comment area. By default, this action allows users to change
+the task subtype into any other subtype.
+
+If you'd prefer to make it more difficult to change subtypes or offer only a
+subset of subtypes, you can specify the list of subtypes that "Change Subtypes"
+offers. For example, if you have several similar subtypes and want to allow
+tasks to be converted between them but not easily converted to other types,
+you can make the "Change Subtypes" control show only these options like this:
+
+```
+ {
+ ...
+ "mutations": ["bug", "issue", "defect"]
+ ...
+ }
+```
+
+If you specify an empty list, the "Change Subtypes" action will be completely
+hidden.
+
+This mutation list is advisory and only configures the UI. Tasks may still be
+converted across subtypes freely by using the Bulk Editor or API.
+
EOTEXT
,
$subtype_default_key));
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
@@ -14,6 +14,7 @@
private $childSubtypes = array();
private $childIdentifiers = array();
private $fieldConfiguration = array();
+ private $mutations;
public function setKey($key) {
$this->key = $key;
@@ -78,6 +79,15 @@
return $this->childIdentifiers;
}
+ public function setMutations($mutations) {
+ $this->mutations = $mutations;
+ return $this;
+ }
+
+ public function getMutations() {
+ return $this->mutations;
+ }
+
public function hasTagView() {
return (bool)strlen($this->getTagText());
}
@@ -152,6 +162,7 @@
'icon' => 'optional string',
'children' => 'optional map<string, wild>',
'fields' => 'optional map<string, wild>',
+ 'mutations' => 'optional list<string>',
));
$key = $value['key'];
@@ -217,6 +228,28 @@
'with key "%s". This subtype is required and must be defined.',
self::SUBTYPE_DEFAULT));
}
+
+ foreach ($config as $value) {
+ $key = idx($value, 'key');
+
+ $mutations = idx($value, 'mutations');
+ if (!$mutations) {
+ continue;
+ }
+
+ foreach ($mutations as $mutation) {
+ if (!isset($map[$mutation])) {
+ throw new Exception(
+ pht(
+ 'Subtype configuration is invalid: subtype with key "%s" '.
+ 'specifies that it can mutate into subtype "%s", but that is '.
+ 'not a valid subtype.',
+ $key,
+ $mutation));
+ }
+ }
+ }
+
}
public static function newSubtypeMap(array $config) {
@@ -267,6 +300,8 @@
}
}
+ $subtype->setMutations(idx($entry, 'mutations'));
+
$map[$key] = $subtype;
}
diff --git a/src/applications/transactions/editengine/PhabricatorEditEngineSubtypeMap.php b/src/applications/transactions/editengine/PhabricatorEditEngineSubtypeMap.php
--- a/src/applications/transactions/editengine/PhabricatorEditEngineSubtypeMap.php
+++ b/src/applications/transactions/editengine/PhabricatorEditEngineSubtypeMap.php
@@ -53,6 +53,44 @@
return clone($this->datasource);
}
+ public function getMutationMap($source_key) {
+ return mpull($this->getMutations($source_key), 'getName');
+ }
+
+ public function getMutations($source_key) {
+ $mutations = $this->subtypes;
+
+ $subtype = idx($this->subtypes, $source_key);
+ if ($subtype) {
+ $map = $subtype->getMutations();
+ if ($map !== null) {
+ $map = array_fuse($map);
+ foreach ($mutations as $key => $mutation) {
+ if ($key === $source_key) {
+ // This is the current subtype, so we always want to show it.
+ continue;
+ }
+
+ if (isset($map[$key])) {
+ // This is an allowed mutation, so keep it.
+ continue;
+ }
+
+ // Discard other subtypes as mutation options.
+ unset($mutations[$key]);
+ }
+ }
+ }
+
+ // If the only available mutation is the current subtype, treat this like
+ // no mutations are available.
+ if (array_keys($mutations) === array($source_key)) {
+ $mutations = array();
+ }
+
+ return $mutations;
+ }
+
public function getCreateFormsForSubtype(
PhabricatorEditEngine $edit_engine,
PhabricatorEditEngineSubtypeInterface $object) {
diff --git a/src/applications/transactions/engineextension/PhabricatorSubtypeEditEngineExtension.php b/src/applications/transactions/engineextension/PhabricatorSubtypeEditEngineExtension.php
--- a/src/applications/transactions/engineextension/PhabricatorSubtypeEditEngineExtension.php
+++ b/src/applications/transactions/engineextension/PhabricatorSubtypeEditEngineExtension.php
@@ -29,9 +29,17 @@
PhabricatorApplicationTransactionInterface $object) {
$subtype_type = PhabricatorTransactions::TYPE_SUBTYPE;
+ $subtype_value = $object->getEditEngineSubtype();
$map = $object->newEditEngineSubtypeMap();
- $options = $map->getDisplayMap();
+
+ if ($object->getID()) {
+ $options = $map->getMutationMap($subtype_value);
+ } else {
+ // NOTE: This is a crude proxy for "are we in the bulk edit workflow".
+ // We want to allow any mutation.
+ $options = $map->getDisplayMap();
+ }
$subtype_field = id(new PhabricatorSelectEditField())
->setKey(self::EDITKEY)
@@ -40,12 +48,12 @@
->setTransactionType($subtype_type)
->setConduitDescription(pht('Change the object subtype.'))
->setConduitTypeDescription(pht('New object subtype key.'))
- ->setValue($object->getEditEngineSubtype())
+ ->setValue($subtype_value)
->setOptions($options);
- // If subtypes are configured, enable changing them from the bulk editor
- // and comment action stack.
- if ($map->getCount() > 1) {
+ // If subtypes are configured, enable changing them from the bulk editor.
+ // Bulk editor
+ if ($options) {
$subtype_field
->setBulkEditLabel(pht('Change subtype to'))
->setCommentActionLabel(pht('Change Subtype'))

File Metadata

Mime Type
text/plain
Expires
Sat, May 11, 9:49 AM (4 w, 20 h ago)
Storage Engine
blob
Storage Format
Encrypted (AES-256-CBC)
Storage Handle
6285350
Default Alt Text
D20810.id49616.diff (7 KB)

Event Timeline