1
0
Fork 0
mirror of https://we.phorge.it/source/phorge.git synced 2024-11-26 16:52:41 +01:00

Convert Maniphest custom config to new config types

Summary:
Fixes T12870. Ref T12845.

Technically, this addresses the core issue in T12845 too, but I'm going to convert the rest of the `custom:...` types before closing that.

In particular, for T12870:

  - Validates that keywords are unique across priorities.
  - Fixes missing newline in documentation.
  - Updates documentation to note that keywords are now mandatory and must be unique across priorities.

Test Plan: Edited, deleted and mangled all the Maniphest custom options (priorities, statuses, points, subtypes).

Reviewers: chad, amckinley

Reviewed By: amckinley

Maniphest Tasks: T12870, T12845

Differential Revision: https://secure.phabricator.com/D18165
This commit is contained in:
epriestley 2017-06-27 07:05:58 -07:00
parent a14b82d4f4
commit 6984d239b0
12 changed files with 120 additions and 83 deletions

View file

@ -1488,8 +1488,8 @@ phutil_register_library_map(array(
'ManiphestHovercardEngineExtension' => 'applications/maniphest/engineextension/ManiphestHovercardEngineExtension.php', 'ManiphestHovercardEngineExtension' => 'applications/maniphest/engineextension/ManiphestHovercardEngineExtension.php',
'ManiphestInfoConduitAPIMethod' => 'applications/maniphest/conduit/ManiphestInfoConduitAPIMethod.php', 'ManiphestInfoConduitAPIMethod' => 'applications/maniphest/conduit/ManiphestInfoConduitAPIMethod.php',
'ManiphestNameIndex' => 'applications/maniphest/storage/ManiphestNameIndex.php', 'ManiphestNameIndex' => 'applications/maniphest/storage/ManiphestNameIndex.php',
'ManiphestPointsConfigOptionType' => 'applications/maniphest/config/ManiphestPointsConfigOptionType.php', 'ManiphestPointsConfigType' => 'applications/maniphest/config/ManiphestPointsConfigType.php',
'ManiphestPriorityConfigOptionType' => 'applications/maniphest/config/ManiphestPriorityConfigOptionType.php', 'ManiphestPrioritiesConfigType' => 'applications/maniphest/config/ManiphestPrioritiesConfigType.php',
'ManiphestPriorityEmailCommand' => 'applications/maniphest/command/ManiphestPriorityEmailCommand.php', 'ManiphestPriorityEmailCommand' => 'applications/maniphest/command/ManiphestPriorityEmailCommand.php',
'ManiphestPrioritySearchConduitAPIMethod' => 'applications/maniphest/conduit/ManiphestPrioritySearchConduitAPIMethod.php', 'ManiphestPrioritySearchConduitAPIMethod' => 'applications/maniphest/conduit/ManiphestPrioritySearchConduitAPIMethod.php',
'ManiphestProjectNameFulltextEngineExtension' => 'applications/maniphest/engineextension/ManiphestProjectNameFulltextEngineExtension.php', 'ManiphestProjectNameFulltextEngineExtension' => 'applications/maniphest/engineextension/ManiphestProjectNameFulltextEngineExtension.php',
@ -1500,11 +1500,11 @@ phutil_register_library_map(array(
'ManiphestReportController' => 'applications/maniphest/controller/ManiphestReportController.php', 'ManiphestReportController' => 'applications/maniphest/controller/ManiphestReportController.php',
'ManiphestSchemaSpec' => 'applications/maniphest/storage/ManiphestSchemaSpec.php', 'ManiphestSchemaSpec' => 'applications/maniphest/storage/ManiphestSchemaSpec.php',
'ManiphestSearchConduitAPIMethod' => 'applications/maniphest/conduit/ManiphestSearchConduitAPIMethod.php', 'ManiphestSearchConduitAPIMethod' => 'applications/maniphest/conduit/ManiphestSearchConduitAPIMethod.php',
'ManiphestStatusConfigOptionType' => 'applications/maniphest/config/ManiphestStatusConfigOptionType.php',
'ManiphestStatusEmailCommand' => 'applications/maniphest/command/ManiphestStatusEmailCommand.php', 'ManiphestStatusEmailCommand' => 'applications/maniphest/command/ManiphestStatusEmailCommand.php',
'ManiphestStatusSearchConduitAPIMethod' => 'applications/maniphest/conduit/ManiphestStatusSearchConduitAPIMethod.php', 'ManiphestStatusSearchConduitAPIMethod' => 'applications/maniphest/conduit/ManiphestStatusSearchConduitAPIMethod.php',
'ManiphestStatusesConfigType' => 'applications/maniphest/config/ManiphestStatusesConfigType.php',
'ManiphestSubpriorityController' => 'applications/maniphest/controller/ManiphestSubpriorityController.php', 'ManiphestSubpriorityController' => 'applications/maniphest/controller/ManiphestSubpriorityController.php',
'ManiphestSubtypesConfigOptionsType' => 'applications/maniphest/config/ManiphestSubtypesConfigOptionsType.php', 'ManiphestSubtypesConfigType' => 'applications/maniphest/config/ManiphestSubtypesConfigType.php',
'ManiphestTask' => 'applications/maniphest/storage/ManiphestTask.php', 'ManiphestTask' => 'applications/maniphest/storage/ManiphestTask.php',
'ManiphestTaskAssignHeraldAction' => 'applications/maniphest/herald/ManiphestTaskAssignHeraldAction.php', 'ManiphestTaskAssignHeraldAction' => 'applications/maniphest/herald/ManiphestTaskAssignHeraldAction.php',
'ManiphestTaskAssignOtherHeraldAction' => 'applications/maniphest/herald/ManiphestTaskAssignOtherHeraldAction.php', 'ManiphestTaskAssignOtherHeraldAction' => 'applications/maniphest/herald/ManiphestTaskAssignOtherHeraldAction.php',
@ -6603,8 +6603,8 @@ phutil_register_library_map(array(
'ManiphestHovercardEngineExtension' => 'PhabricatorHovercardEngineExtension', 'ManiphestHovercardEngineExtension' => 'PhabricatorHovercardEngineExtension',
'ManiphestInfoConduitAPIMethod' => 'ManiphestConduitAPIMethod', 'ManiphestInfoConduitAPIMethod' => 'ManiphestConduitAPIMethod',
'ManiphestNameIndex' => 'ManiphestDAO', 'ManiphestNameIndex' => 'ManiphestDAO',
'ManiphestPointsConfigOptionType' => 'PhabricatorConfigJSONOptionType', 'ManiphestPointsConfigType' => 'PhabricatorJSONConfigType',
'ManiphestPriorityConfigOptionType' => 'PhabricatorConfigJSONOptionType', 'ManiphestPrioritiesConfigType' => 'PhabricatorJSONConfigType',
'ManiphestPriorityEmailCommand' => 'ManiphestEmailCommand', 'ManiphestPriorityEmailCommand' => 'ManiphestEmailCommand',
'ManiphestPrioritySearchConduitAPIMethod' => 'ManiphestConduitAPIMethod', 'ManiphestPrioritySearchConduitAPIMethod' => 'ManiphestConduitAPIMethod',
'ManiphestProjectNameFulltextEngineExtension' => 'PhabricatorFulltextEngineExtension', 'ManiphestProjectNameFulltextEngineExtension' => 'PhabricatorFulltextEngineExtension',
@ -6615,11 +6615,11 @@ phutil_register_library_map(array(
'ManiphestReportController' => 'ManiphestController', 'ManiphestReportController' => 'ManiphestController',
'ManiphestSchemaSpec' => 'PhabricatorConfigSchemaSpec', 'ManiphestSchemaSpec' => 'PhabricatorConfigSchemaSpec',
'ManiphestSearchConduitAPIMethod' => 'PhabricatorSearchEngineAPIMethod', 'ManiphestSearchConduitAPIMethod' => 'PhabricatorSearchEngineAPIMethod',
'ManiphestStatusConfigOptionType' => 'PhabricatorConfigJSONOptionType',
'ManiphestStatusEmailCommand' => 'ManiphestEmailCommand', 'ManiphestStatusEmailCommand' => 'ManiphestEmailCommand',
'ManiphestStatusSearchConduitAPIMethod' => 'ManiphestConduitAPIMethod', 'ManiphestStatusSearchConduitAPIMethod' => 'ManiphestConduitAPIMethod',
'ManiphestStatusesConfigType' => 'PhabricatorJSONConfigType',
'ManiphestSubpriorityController' => 'ManiphestController', 'ManiphestSubpriorityController' => 'ManiphestController',
'ManiphestSubtypesConfigOptionsType' => 'PhabricatorConfigJSONOptionType', 'ManiphestSubtypesConfigType' => 'PhabricatorJSONConfigType',
'ManiphestTask' => array( 'ManiphestTask' => array(
'ManiphestDAO', 'ManiphestDAO',
'PhabricatorSubscribableInterface', 'PhabricatorSubscribableInterface',

View file

@ -290,6 +290,11 @@ final class PhabricatorConfigEditController
} catch (PhabricatorConfigValidationException $ex) { } catch (PhabricatorConfigValidationException $ex) {
$errors[] = $ex->getMessage(); $errors[] = $ex->getMessage();
$xaction = null; $xaction = null;
} catch (Exception $ex) {
// NOTE: Some older validators throw bare exceptions. Purely in good
// taste, it would be nice to convert these at some point.
$errors[] = $ex->getMessage();
$xaction = null;
} }
return array( return array(

View file

@ -1,10 +0,0 @@
<?php
final class ManiphestPointsConfigOptionType
extends PhabricatorConfigJSONOptionType {
public function validateOption(PhabricatorConfigOption $option, $value) {
ManiphestTaskPoints::validateConfiguration($value);
}
}

View file

@ -0,0 +1,14 @@
<?php
final class ManiphestPointsConfigType
extends PhabricatorJSONConfigType {
const TYPEKEY = 'maniphest.points';
public function validateStoredValue(
PhabricatorConfigOption $option,
$value) {
ManiphestTaskPoints::validateConfiguration($value);
}
}

View file

@ -0,0 +1,14 @@
<?php
final class ManiphestPrioritiesConfigType
extends PhabricatorJSONConfigType {
const TYPEKEY = 'maniphest.priorities';
public function validateStoredValue(
PhabricatorConfigOption $option,
$value) {
ManiphestTaskPriority::validateConfiguration($value);
}
}

View file

@ -1,10 +0,0 @@
<?php
final class ManiphestPriorityConfigOptionType
extends PhabricatorConfigJSONOptionType {
public function validateOption(PhabricatorConfigOption $option, $value) {
ManiphestTaskPriority::validateConfiguration($value);
}
}

View file

@ -1,10 +0,0 @@
<?php
final class ManiphestStatusConfigOptionType
extends PhabricatorConfigJSONOptionType {
public function validateOption(PhabricatorConfigOption $option, $value) {
ManiphestTaskStatus::validateConfiguration($value);
}
}

View file

@ -0,0 +1,14 @@
<?php
final class ManiphestStatusesConfigType
extends PhabricatorJSONConfigType {
const TYPEKEY = 'maniphest.statuses';
public function validateStoredValue(
PhabricatorConfigOption $option,
$value) {
ManiphestTaskStatus::validateConfiguration($value);
}
}

View file

@ -1,10 +0,0 @@
<?php
final class ManiphestSubtypesConfigOptionsType
extends PhabricatorConfigJSONOptionType {
public function validateOption(PhabricatorConfigOption $option, $value) {
PhabricatorEditEngineSubtype::validateConfiguration($value);
}
}

View file

@ -0,0 +1,14 @@
<?php
final class ManiphestSubtypesConfigType
extends PhabricatorJSONConfigType {
const TYPEKEY = 'maniphest.subtypes';
public function validateStoredValue(
PhabricatorConfigOption $option,
$value) {
PhabricatorEditEngineSubtype::validateConfiguration($value);
}
}

View file

@ -20,47 +20,47 @@ final class PhabricatorManiphestConfigOptions
} }
public function getOptions() { public function getOptions() {
$priority_type = 'custom:ManiphestPriorityConfigOptionType'; $priority_type = 'maniphest.priorities';
$priority_defaults = array( $priority_defaults = array(
100 => array( 100 => array(
'name' => pht('Unbreak Now!'), 'name' => pht('Unbreak Now!'),
'keywords' => array('unbreak'),
'short' => pht('Unbreak!'), 'short' => pht('Unbreak!'),
'color' => 'pink', 'color' => 'pink',
'keywords' => array('unbreak'),
), ),
90 => array( 90 => array(
'name' => pht('Needs Triage'), 'name' => pht('Needs Triage'),
'keywords' => array('triage'),
'short' => pht('Triage'), 'short' => pht('Triage'),
'color' => 'violet', 'color' => 'violet',
'keywords' => array('triage'),
), ),
80 => array( 80 => array(
'name' => pht('High'), 'name' => pht('High'),
'keywords' => array('high'),
'short' => pht('High'), 'short' => pht('High'),
'color' => 'red', 'color' => 'red',
'keywords' => array('high'),
), ),
50 => array( 50 => array(
'name' => pht('Normal'), 'name' => pht('Normal'),
'keywords' => array('normal'),
'short' => pht('Normal'), 'short' => pht('Normal'),
'color' => 'orange', 'color' => 'orange',
'keywords' => array('normal'),
), ),
25 => array( 25 => array(
'name' => pht('Low'), 'name' => pht('Low'),
'keywords' => array('low'),
'short' => pht('Low'), 'short' => pht('Low'),
'color' => 'yellow', 'color' => 'yellow',
'keywords' => array('low'),
), ),
0 => array( 0 => array(
'name' => pht('Wishlist'), 'name' => pht('Wishlist'),
'keywords' => array('wish', 'wishlist'),
'short' => pht('Wish'), 'short' => pht('Wish'),
'color' => 'sky', 'color' => 'sky',
'keywords' => array('wish', 'wishlist'),
), ),
); );
$status_type = 'custom:ManiphestStatusConfigOptionType'; $status_type = 'maniphest.statuses';
$status_defaults = array( $status_defaults = array(
'open' => array( 'open' => array(
'name' => pht('Open'), 'name' => pht('Open'),
@ -265,7 +265,7 @@ EOTEXT
); );
$fields_json = id(new PhutilJSON())->encodeFormatted($fields_example); $fields_json = id(new PhutilJSON())->encodeFormatted($fields_example);
$points_type = 'custom:ManiphestPointsConfigOptionType'; $points_type = 'maniphest.points';
$points_example_1 = array( $points_example_1 = array(
'enabled' => true, 'enabled' => true,
@ -299,7 +299,7 @@ See the example below for a starting point.
EOTEXT EOTEXT
)); ));
$subtype_type = 'custom:ManiphestSubtypesConfigOptionsType'; $subtype_type = 'maniphest.subtypes';
$subtype_default_key = PhabricatorEditEngineSubtype::SUBTYPE_DEFAULT; $subtype_default_key = PhabricatorEditEngineSubtype::SUBTYPE_DEFAULT;
$subtype_example = array( $subtype_example = array(
array( array(
@ -349,6 +349,32 @@ EOTEXT
, ,
$subtype_default_key)); $subtype_default_key));
$priorities_description = $this->deformat(pht(<<<EOTEXT
Allows you to edit or override the default priorities available in Maniphest,
like "High", "Normal" and "Low". The configuration should contain a map of
numeric priority values (where larger numbers correspond to higher priorities)
to priority specifications (see defaults below for examples).
The keys you can define for a priority are:
- `name` //Required string.// Name of the priority.
- `keywords` //Required list<string>.// List of unique keywords which identify
this priority, like "high" or "low". Each priority must have at least one
keyword and two priorities may not share the same keyword.
- `short` //Optional string.// Alternate shorter name, used in UIs where
there is less space available.
- `color` //Optional string.// Color for this priority, like "red" or
"blue".
- `disabled` //Optional bool.// Set to true to prevent users from choosing
this priority when creating or editing tasks. Existing tasks will not be
affected, and can be batch edited to a different priority or left to
eventually die out.
You can choose the default priority for newly created tasks with
"maniphest.default-priority".
EOTEXT
));
return array( return array(
$this->newOption('maniphest.custom-field-definitions', 'wild', array()) $this->newOption('maniphest.custom-field-definitions', 'wild', array())
@ -367,30 +393,7 @@ EOTEXT
$priority_type, $priority_type,
$priority_defaults) $priority_defaults)
->setSummary(pht('Configure Maniphest priority names.')) ->setSummary(pht('Configure Maniphest priority names.'))
->setDescription( ->setDescription($priorities_description),
pht(
'Allows you to edit or override the default priorities available '.
'in Maniphest, like "High", "Normal" and "Low". The configuration '.
'should contain a map of priority constants to priority '.
'specifications (see defaults below for examples).'.
"\n\n".
'The keys you can define for a priority are:'.
"\n\n".
' - `name` Name of the priority.'."\n".
' - `short` Alternate shorter name, used in UIs where there is '.
' not much space available.'."\n".
' - `color` A color for this priority, like "red" or "blue".'.
' - `keywords` An optional list of keywords which can '.
' be used to select this priority when using `!priority` '.
' commands in email.'."\n".
' - `disabled` Optional boolean to prevent users from choosing '.
' this priority when creating or editing tasks. Existing '.
' tasks will be unaffected, and can be batch edited to a '.
' different priority or left to eventually die out.'.
"\n\n".
'You can choose which priority is the default for newly created '.
'tasks with `%s`.',
'maniphest.default-priority')),
$this->newOption('maniphest.statuses', $status_type, $status_defaults) $this->newOption('maniphest.statuses', $status_type, $status_defaults)
->setSummary(pht('Configure Maniphest task statuses.')) ->setSummary(pht('Configure Maniphest task statuses.'))
->setDescription($status_description) ->setDescription($status_description)

View file

@ -203,6 +203,7 @@ final class ManiphestTaskPriority extends ManiphestConstants {
$config)); $config));
} }
$all_keywords = array();
foreach ($config as $key => $value) { foreach ($config as $key => $value) {
if (!ctype_digit((string)$key)) { if (!ctype_digit((string)$key)) {
throw new Exception( throw new Exception(
@ -223,9 +224,9 @@ final class ManiphestTaskPriority extends ManiphestConstants {
$value, $value,
array( array(
'name' => 'string', 'name' => 'string',
'keywords' => 'list<string>',
'short' => 'optional string', 'short' => 'optional string',
'color' => 'optional string', 'color' => 'optional string',
'keywords' => 'list<string>',
'disabled' => 'optional bool', 'disabled' => 'optional bool',
)); ));
@ -242,6 +243,18 @@ final class ManiphestTaskPriority extends ManiphestConstants {
'low', 'low',
'critical')); 'critical'));
} }
if (isset($all_keywords[$keyword])) {
throw new Exception(
pht(
'Two different task priorities ("%s" and "%s") have the same '.
'keyword ("%s"). Keywords must uniquely identify priorities.',
$value['name'],
$all_keywords[$keyword],
$keyword));
}
$all_keywords[$keyword] = $value['name'];
} }
} }
} }