Path: blob/master/src/applications/maniphest/config/PhabricatorManiphestConfigOptions.php
12256 views
<?php12final class PhabricatorManiphestConfigOptions3extends PhabricatorApplicationConfigOptions {45public function getName() {6return pht('Maniphest');7}89public function getDescription() {10return pht('Configure Maniphest.');11}1213public function getIcon() {14return 'fa-anchor';15}1617public function getGroup() {18return 'apps';19}2021public function getOptions() {22$priority_type = 'maniphest.priorities';23$priority_defaults = array(24100 => array(25'name' => pht('Unbreak Now!'),26'keywords' => array('unbreak'),27'short' => pht('Unbreak!'),28'color' => 'pink',29),3090 => array(31'name' => pht('Needs Triage'),32'keywords' => array('triage'),33'short' => pht('Triage'),34'color' => 'violet',35),3680 => array(37'name' => pht('High'),38'keywords' => array('high'),39'short' => pht('High'),40'color' => 'red',41),4250 => array(43'name' => pht('Normal'),44'keywords' => array('normal'),45'short' => pht('Normal'),46'color' => 'orange',47),4825 => array(49'name' => pht('Low'),50'keywords' => array('low'),51'short' => pht('Low'),52'color' => 'yellow',53),540 => array(55'name' => pht('Wishlist'),56'keywords' => array('wish', 'wishlist'),57'short' => pht('Wish'),58'color' => 'sky',59),60);6162$status_type = 'maniphest.statuses';63$status_defaults = array(64'open' => array(65'name' => pht('Open'),66'special' => ManiphestTaskStatus::SPECIAL_DEFAULT,67'prefixes' => array(68'open',69'opens',70'reopen',71'reopens',72),73),74'resolved' => array(75'name' => pht('Resolved'),76'name.full' => pht('Closed, Resolved'),77'closed' => true,78'special' => ManiphestTaskStatus::SPECIAL_CLOSED,79'transaction.icon' => 'fa-check-circle',80'prefixes' => array(81'closed',82'closes',83'close',84'fix',85'fixes',86'fixed',87'resolve',88'resolves',89'resolved',90),91'suffixes' => array(92'as resolved',93'as fixed',94),95'keywords' => array('closed', 'fixed', 'resolved'),96),97'wontfix' => array(98'name' => pht('Wontfix'),99'name.full' => pht('Closed, Wontfix'),100'transaction.icon' => 'fa-ban',101'closed' => true,102'prefixes' => array(103'wontfix',104'wontfixes',105'wontfixed',106),107'suffixes' => array(108'as wontfix',109),110),111'invalid' => array(112'name' => pht('Invalid'),113'name.full' => pht('Closed, Invalid'),114'transaction.icon' => 'fa-minus-circle',115'closed' => true,116'claim' => false,117'prefixes' => array(118'invalidate',119'invalidates',120'invalidated',121),122'suffixes' => array(123'as invalid',124),125),126'duplicate' => array(127'name' => pht('Duplicate'),128'name.full' => pht('Closed, Duplicate'),129'transaction.icon' => 'fa-files-o',130'special' => ManiphestTaskStatus::SPECIAL_DUPLICATE,131'closed' => true,132'claim' => false,133),134'spite' => array(135'name' => pht('Spite'),136'name.full' => pht('Closed, Spite'),137'name.action' => pht('Spited'),138'transaction.icon' => 'fa-thumbs-o-down',139'silly' => true,140'closed' => true,141'prefixes' => array(142'spite',143'spites',144'spited',145),146'suffixes' => array(147'out of spite',148'as spite',149),150),151);152153$status_description = $this->deformat(pht(<<<EOTEXT154Allows you to edit, add, or remove the task statuses available in Maniphest,155like "Open", "Resolved" and "Invalid". The configuration should contain a map156of status constants to status specifications (see defaults below for examples).157158The constant for each status should be 1-12 characters long and contain only159lowercase letters and digits. Valid examples are "open", "closed", and160"invalid". Users will not normally see these values.161162The keys you can provide in a specification are:163164- `name` //Required string.// Name of the status, like "Invalid".165- `name.full` //Optional string.// Longer name, like "Closed, Invalid". This166appears on the task detail view in the header.167- `name.action` //Optional string.// Action name for email subjects, like168"Marked Invalid".169- `closed` //Optional bool.// Statuses are either "open" or "closed".170Specifying `true` here will mark the status as closed (like "Resolved" or171"Invalid"). By default, statuses are open.172- `special` //Optional string.// Mark this status as special. The special173statuses are:174- `default` This is the default status for newly created tasks. You must175designate one status as default, and it must be an open status.176- `closed` This is the default status for closed tasks (for example, tasks177closed via the "!close" action in email or via the quick close button in178Maniphest). You must designate one status as the default closed status,179and it must be a closed status.180- `duplicate` This is the status used when tasks are merged into one181another as duplicates. You must designate one status for duplicates,182and it must be a closed status.183- `transaction.icon` //Optional string.// Allows you to choose a different184icon to use for this status when showing status changes in the transaction185log. Please see UIExamples, Icons and Images for a list.186- `transaction.color` //Optional string.// Allows you to choose a different187color to use for this status when showing status changes in the transaction188log.189- `silly` //Optional bool.// Marks this status as silly, and thus wholly190inappropriate for use by serious businesses.191- `prefixes` //Optional list<string>.// Allows you to specify a list of192text prefixes which will trigger a task transition into this status193when mentioned in a commit message. For example, providing "closes" here194will allow users to move tasks to this status by writing `Closes T123` in195commit messages.196- `suffixes` //Optional list<string>.// Allows you to specify a list of197text suffixes which will trigger a task transition into this status198when mentioned in a commit message, after a valid prefix. For example,199providing "as invalid" here will allow users to move tasks200to this status by writing `Closes T123 as invalid`, even if another status201is selected by the "Closes" prefix.202- `keywords` //Optional list<string>.// Allows you to specify a list203of keywords which can be used with `!status` commands in email to select204this status.205- `disabled` //Optional bool.// Marks this status as no longer in use so206tasks can not be created or edited to have this status. Existing tasks with207this status will not be affected, but you can batch edit them or let them208die out on their own.209- `claim` //Optional bool.// By default, closing an unassigned task claims210it. You can set this to `false` to disable this behavior for a particular211status.212- `locked` //Optional string.// Lock tasks in this status. Specify "comments"213to lock comments (users who can edit the task may override this lock).214Specify "edits" to prevent anyone except the task owner from making edits.215- `mfa` //Optional bool.// Require all edits to this task to be signed with216multi-factor authentication.217218Statuses will appear in the UI in the order specified. Note the status marked219`special` as `duplicate` is not settable directly and will not appear in UI220elements, and that any status marked `silly` does not appear if the software221is configured with `phabricator.serious-business` set to true.222223Examining the default configuration and examples below will probably be helpful224in understanding these options.225226EOTEXT227));228229$status_example = array(230'open' => array(231'name' => pht('Open'),232'special' => 'default',233),234'closed' => array(235'name' => pht('Closed'),236'special' => 'closed',237'closed' => true,238),239'duplicate' => array(240'name' => pht('Duplicate'),241'special' => 'duplicate',242'closed' => true,243),244);245246$json = new PhutilJSON();247$status_example = $json->encodeFormatted($status_example);248249// This is intentionally blank for now, until we can move more Maniphest250// logic to custom fields.251$default_fields = array();252253foreach ($default_fields as $key => $enabled) {254$default_fields[$key] = array(255'disabled' => !$enabled,256);257}258259$custom_field_type = 'custom:PhabricatorCustomFieldConfigOptionType';260261$fields_example = array(262'mycompany.estimated-hours' => array(263'name' => pht('Estimated Hours'),264'type' => 'int',265'caption' => pht('Estimated number of hours this will take.'),266),267);268$fields_json = id(new PhutilJSON())->encodeFormatted($fields_example);269270$points_type = 'maniphest.points';271272$points_example_1 = array(273'enabled' => true,274'label' => pht('Story Points'),275'action' => pht('Change Story Points'),276);277$points_json_1 = id(new PhutilJSON())->encodeFormatted($points_example_1);278279$points_example_2 = array(280'enabled' => true,281'label' => pht('Estimated Hours'),282'action' => pht('Change Estimate'),283);284$points_json_2 = id(new PhutilJSON())->encodeFormatted($points_example_2);285286$points_description = $this->deformat(pht(<<<EOTEXT287Activates a points field on tasks. You can use points for estimation or288planning. If configured, points will appear on workboards.289290To activate points, set this value to a map with these keys:291292- `enabled` //Optional bool.// Use `true` to enable points, or293`false` to disable them.294- `label` //Optional string.// Label for points, like "Story Points" or295"Estimated Hours". If omitted, points will be called "Points".296- `action` //Optional string.// Label for the action which changes points297in Maniphest, like "Change Estimate". If omitted, the action will298be called "Change Points".299300See the example below for a starting point.301EOTEXT302));303304$subtype_type = 'maniphest.subtypes';305$subtype_default_key = PhabricatorEditEngineSubtype::SUBTYPE_DEFAULT;306$subtype_example = array(307array(308'key' => $subtype_default_key,309'name' => pht('Task'),310),311array(312'key' => 'bug',313'name' => pht('Bug'),314),315array(316'key' => 'feature',317'name' => pht('Feature Request'),318),319);320$subtype_example = id(new PhutilJSON())->encodeAsList($subtype_example);321322$subtype_default = array(323array(324'key' => $subtype_default_key,325'name' => pht('Task'),326),327);328329$subtype_description = $this->deformat(pht(<<<EOTEXT330Allows you to define task subtypes. Subtypes let you hide fields you don't331need to simplify the workflows for editing tasks.332333To define subtypes, provide a list of subtypes. Each subtype should be a334dictionary with these keys:335336- `key` //Required string.// Internal identifier for the subtype, like337"task", "feature", or "bug".338- `name` //Required string.// Human-readable name for this subtype, like339"Task", "Feature Request" or "Bug Report".340- `tag` //Optional string.// Tag text for this subtype.341- `color` //Optional string.// Display color for this subtype.342- `icon` //Optional string.// Icon for the subtype.343- `children` //Optional map.// Configure options shown to the user when344they "Create Subtask". See below.345- `fields` //Optional map.// Configure field behaviors. See below.346- `mutations` //Optional list.// Configure which subtypes this subtype347can easily be converted to by using the "Change Subtype" action. See below.348349Each subtype must have a unique key, and you must define a subtype with350the key "%s", which is used as a default subtype.351352The tag text (`tag`) is used to set the text shown in the subtype tag on list353views and workboards. If you do not configure it, the default subtype will have354no subtype tag and other subtypes will use their name as tag text.355356The `children` key allows you to configure which options are presented to the357user when they "Create Subtask" from a task of this subtype. You can specify358these keys:359360- `subtypes`: //Optional list<string>.// Show users creation forms for these361task subtypes.362- `forms`: //Optional list<string|int>.// Show users these specific forms,363in order.364365If you don't specify either constraint, users will be shown creation forms366for the same subtype.367368For example, if you have a "quest" subtype and do not configure `children`,369users who click "Create Subtask" will be presented with all create forms for370"quest" tasks.371372If you want to present them with forms for a different task subtype or set of373subtypes instead, use `subtypes`:374375```376{377...378"children": {379"subtypes": ["objective", "boss", "reward"]380}381...382}383```384385If you want to present them with specific forms, use `forms` and specify form386IDs:387388```389{390...391"children": {392"forms": [12, 16]393}394...395}396```397398When specifying forms by ID explicitly, the order you specify the forms in will399be used when presenting options to the user.400401If only one option would be presented, the user will be taken directly to the402appropriate form instead of being prompted to choose a form.403404The `fields` key can configure the behavior of custom fields on specific405task subtypes. For example:406407```408{409...410"fields": {411"custom.some-field": {412"disabled": true413}414}415...416}417```418419Each field supports these options:420421- `disabled` //Optional bool.// Allows you to disable fields on certain422subtypes.423- `name` //Optional string.// Custom name of this field for the subtype.424425426The `mutations` key allows you to control the behavior of the "Change Subtype"427action above the comment area. By default, this action allows users to change428the task subtype into any other subtype.429430If you'd prefer to make it more difficult to change subtypes or offer only a431subset of subtypes, you can specify the list of subtypes that "Change Subtypes"432offers. For example, if you have several similar subtypes and want to allow433tasks to be converted between them but not easily converted to other types,434you can make the "Change Subtypes" control show only these options like this:435436```437{438...439"mutations": ["bug", "issue", "defect"]440...441}442```443444If you specify an empty list, the "Change Subtypes" action will be completely445hidden.446447This mutation list is advisory and only configures the UI. Tasks may still be448converted across subtypes freely by using the Bulk Editor or API.449450EOTEXT451,452$subtype_default_key));453454$priorities_description = $this->deformat(pht(<<<EOTEXT455Allows you to edit or override the default priorities available in Maniphest,456like "High", "Normal" and "Low". The configuration should contain a map of457numeric priority values (where larger numbers correspond to higher priorities)458to priority specifications (see defaults below for examples).459460The keys you can define for a priority are:461462- `name` //Required string.// Name of the priority.463- `keywords` //Required list<string>.// List of unique keywords which identify464this priority, like "high" or "low". Each priority must have at least one465keyword and two priorities may not share the same keyword.466- `short` //Optional string.// Alternate shorter name, used in UIs where467there is less space available.468- `color` //Optional string.// Color for this priority, like "red" or469"blue".470- `disabled` //Optional bool.// Set to true to prevent users from choosing471this priority when creating or editing tasks. Existing tasks will not be472affected, and can be batch edited to a different priority or left to473eventually die out.474475You can choose the default priority for newly created tasks with476"maniphest.default-priority".477EOTEXT478));479480$fields_description = $this->deformat(pht(<<<EOTEXT481List of custom fields for Maniphest tasks.482483For details on adding custom fields to Maniphest, see [[ %s | %s ]] in the484documentation.485EOTEXT486,487PhabricatorEnv::getDoclink('Configuring Custom Fields'),488pht('Configuring Custom Fields')));489490return array(491$this->newOption('maniphest.custom-field-definitions', 'wild', array())492->setSummary(pht('Custom Maniphest fields.'))493->setDescription($fields_description)494->addExample($fields_json, pht('Valid setting')),495$this->newOption('maniphest.fields', $custom_field_type, $default_fields)496->setCustomData(id(new ManiphestTask())->getCustomFieldBaseClass())497->setDescription(pht('Select and reorder task fields.')),498$this->newOption(499'maniphest.priorities',500$priority_type,501$priority_defaults)502->setSummary(pht('Configure Maniphest priority names.'))503->setDescription($priorities_description),504$this->newOption('maniphest.statuses', $status_type, $status_defaults)505->setSummary(pht('Configure Maniphest task statuses.'))506->setDescription($status_description)507->addExample($status_example, pht('Minimal Valid Config')),508$this->newOption('maniphest.default-priority', 'int', 90)509->setSummary(pht('Default task priority for create flows.'))510->setDescription(511pht(512'Choose a default priority for newly created tasks. You can '.513'review and adjust available priorities by using the '.514'%s configuration option. The default value (`90`) '.515'corresponds to the default "Needs Triage" priority.',516'maniphest.priorities')),517$this->newOption('maniphest.points', $points_type, array())518->setSummary(pht('Configure point values for tasks.'))519->setDescription($points_description)520->addExample($points_json_1, pht('Points Config'))521->addExample($points_json_2, pht('Hours Config')),522$this->newOption('maniphest.subtypes', $subtype_type, $subtype_default)523->setSummary(pht('Define task subtypes.'))524->setDescription($subtype_description)525->addExample($subtype_example, pht('Simple Subtypes')),526);527}528529}530531532