1
0
Fork 0
mirror of https://we.phorge.it/source/phorge.git synced 2024-09-20 01:08:50 +02:00

Implement the "!priority" and "!status" mail commands

Summary: Ref T7199. Adds "!priority" and "!status".

Test Plan:
  - Used `!priority` and `!status` to adjust tasks.
  - Changed config and provided keywords.

{F355976}

Reviewers: btrahan

Reviewed By: btrahan

Subscribers: epriestley

Maniphest Tasks: T7199

Differential Revision: https://secure.phabricator.com/D12248
This commit is contained in:
epriestley 2015-04-01 10:09:47 -07:00
parent be1fbba698
commit 52eab87608
6 changed files with 220 additions and 0 deletions

View file

@ -1034,6 +1034,7 @@ phutil_register_library_map(array(
'ManiphestInfoConduitAPIMethod' => 'applications/maniphest/conduit/ManiphestInfoConduitAPIMethod.php', 'ManiphestInfoConduitAPIMethod' => 'applications/maniphest/conduit/ManiphestInfoConduitAPIMethod.php',
'ManiphestNameIndex' => 'applications/maniphest/storage/ManiphestNameIndex.php', 'ManiphestNameIndex' => 'applications/maniphest/storage/ManiphestNameIndex.php',
'ManiphestNameIndexEventListener' => 'applications/maniphest/event/ManiphestNameIndexEventListener.php', 'ManiphestNameIndexEventListener' => 'applications/maniphest/event/ManiphestNameIndexEventListener.php',
'ManiphestPriorityEmailCommand' => 'applications/maniphest/command/ManiphestPriorityEmailCommand.php',
'ManiphestQueryConduitAPIMethod' => 'applications/maniphest/conduit/ManiphestQueryConduitAPIMethod.php', 'ManiphestQueryConduitAPIMethod' => 'applications/maniphest/conduit/ManiphestQueryConduitAPIMethod.php',
'ManiphestQueryStatusesConduitAPIMethod' => 'applications/maniphest/conduit/ManiphestQueryStatusesConduitAPIMethod.php', 'ManiphestQueryStatusesConduitAPIMethod' => 'applications/maniphest/conduit/ManiphestQueryStatusesConduitAPIMethod.php',
'ManiphestRemarkupRule' => 'applications/maniphest/remarkup/ManiphestRemarkupRule.php', 'ManiphestRemarkupRule' => 'applications/maniphest/remarkup/ManiphestRemarkupRule.php',
@ -1042,6 +1043,7 @@ phutil_register_library_map(array(
'ManiphestSchemaSpec' => 'applications/maniphest/storage/ManiphestSchemaSpec.php', 'ManiphestSchemaSpec' => 'applications/maniphest/storage/ManiphestSchemaSpec.php',
'ManiphestSearchIndexer' => 'applications/maniphest/search/ManiphestSearchIndexer.php', 'ManiphestSearchIndexer' => 'applications/maniphest/search/ManiphestSearchIndexer.php',
'ManiphestStatusConfigOptionType' => 'applications/maniphest/config/ManiphestStatusConfigOptionType.php', 'ManiphestStatusConfigOptionType' => 'applications/maniphest/config/ManiphestStatusConfigOptionType.php',
'ManiphestStatusEmailCommand' => 'applications/maniphest/command/ManiphestStatusEmailCommand.php',
'ManiphestSubpriorityController' => 'applications/maniphest/controller/ManiphestSubpriorityController.php', 'ManiphestSubpriorityController' => 'applications/maniphest/controller/ManiphestSubpriorityController.php',
'ManiphestTask' => 'applications/maniphest/storage/ManiphestTask.php', 'ManiphestTask' => 'applications/maniphest/storage/ManiphestTask.php',
'ManiphestTaskDependedOnByTaskEdgeType' => 'applications/maniphest/edge/ManiphestTaskDependedOnByTaskEdgeType.php', 'ManiphestTaskDependedOnByTaskEdgeType' => 'applications/maniphest/edge/ManiphestTaskDependedOnByTaskEdgeType.php',
@ -4284,6 +4286,7 @@ phutil_register_library_map(array(
'ManiphestInfoConduitAPIMethod' => 'ManiphestConduitAPIMethod', 'ManiphestInfoConduitAPIMethod' => 'ManiphestConduitAPIMethod',
'ManiphestNameIndex' => 'ManiphestDAO', 'ManiphestNameIndex' => 'ManiphestDAO',
'ManiphestNameIndexEventListener' => 'PhabricatorEventListener', 'ManiphestNameIndexEventListener' => 'PhabricatorEventListener',
'ManiphestPriorityEmailCommand' => 'ManiphestEmailCommand',
'ManiphestQueryConduitAPIMethod' => 'ManiphestConduitAPIMethod', 'ManiphestQueryConduitAPIMethod' => 'ManiphestConduitAPIMethod',
'ManiphestQueryStatusesConduitAPIMethod' => 'ManiphestConduitAPIMethod', 'ManiphestQueryStatusesConduitAPIMethod' => 'ManiphestConduitAPIMethod',
'ManiphestRemarkupRule' => 'PhabricatorObjectRemarkupRule', 'ManiphestRemarkupRule' => 'PhabricatorObjectRemarkupRule',
@ -4292,6 +4295,7 @@ phutil_register_library_map(array(
'ManiphestSchemaSpec' => 'PhabricatorConfigSchemaSpec', 'ManiphestSchemaSpec' => 'PhabricatorConfigSchemaSpec',
'ManiphestSearchIndexer' => 'PhabricatorSearchDocumentIndexer', 'ManiphestSearchIndexer' => 'PhabricatorSearchDocumentIndexer',
'ManiphestStatusConfigOptionType' => 'PhabricatorConfigJSONOptionType', 'ManiphestStatusConfigOptionType' => 'PhabricatorConfigJSONOptionType',
'ManiphestStatusEmailCommand' => 'ManiphestEmailCommand',
'ManiphestSubpriorityController' => 'ManiphestController', 'ManiphestSubpriorityController' => 'ManiphestController',
'ManiphestTask' => array( 'ManiphestTask' => array(
'ManiphestDAO', 'ManiphestDAO',

View file

@ -0,0 +1,73 @@
<?php
final class ManiphestPriorityEmailCommand
extends ManiphestEmailCommand {
public function getCommand() {
return 'priority';
}
public function getCommandSyntax() {
return '**!priority** //priority//';
}
public function getCommandSummary() {
return pht('Change the priority of a task.');
}
public function getCommandDescription() {
$names = ManiphestTaskPriority::getTaskPriorityMap();
$keywords = ManiphestTaskPriority::getTaskPriorityKeywordsMap();
$table = array();
$table[] = '| '.pht('Priority').' | '.pht('Keywords');
$table[] = '|---|---|';
foreach ($keywords as $priority => $words) {
$words = implode(', ', $words);
$table[] = '| '.$names[$priority].' | '.$words;
}
$table = implode("\n", $table);
return pht(
'To change the priority of a task, specify the desired priority, like '.
'`!priority high`. This table shows the configured names for priority '.
'levels.'.
"\n\n%s\n\n".
'If you specify an invalid priority, the command is ignored. This '.
'command has no effect if you do not specify a priority.',
$table);
}
public function buildTransactions(
PhabricatorUser $viewer,
PhabricatorApplicationTransactionInterface $object,
PhabricatorMetaMTAReceivedMail $mail,
$command,
array $argv) {
$xactions = array();
$target = phutil_utf8_strtolower(head($argv));
$priority = null;
$keywords = ManiphestTaskPriority::getTaskPriorityKeywordsMap();
foreach ($keywords as $key => $words) {
foreach ($words as $word) {
if ($word == $target) {
$priority = $key;
break;
}
}
}
if ($priority === null) {
return array();
}
$xactions[] = $object->getApplicationTransactionTemplate()
->setTransactionType(ManiphestTransaction::TYPE_PRIORITY)
->setNewValue($priority);
return $xactions;
}
}

View file

@ -0,0 +1,72 @@
<?php
final class ManiphestStatusEmailCommand
extends ManiphestEmailCommand {
public function getCommand() {
return 'status';
}
public function getCommandSyntax() {
return '**!status** //status//';
}
public function getCommandSummary() {
return pht('Change the status of a task.');
}
public function getCommandDescription() {
$names = ManiphestTaskStatus::getTaskStatusMap();
$keywords = ManiphestTaskStatus::getTaskStatusKeywordsMap();
$table = array();
$table[] = '| '.pht('Status').' | '.pht('Keywords');
$table[] = '|---|---|';
foreach ($keywords as $status => $words) {
$words = implode(', ', $words);
$table[] = '| '.$names[$status].' | '.$words;
}
$table = implode("\n", $table);
return pht(
'To change the status of a task, specify the desired status, like '.
'`!status invalid`. This table shows the configured names for statuses.'.
"\n\n%s\n\n".
'If you specify an invalid status, the command is ignored. This '.
'command has no effect if you do not specify a status.',
$table);
}
public function buildTransactions(
PhabricatorUser $viewer,
PhabricatorApplicationTransactionInterface $object,
PhabricatorMetaMTAReceivedMail $mail,
$command,
array $argv) {
$xactions = array();
$target = phutil_utf8_strtolower(head($argv));
$status = null;
$keywords = ManiphestTaskStatus::getTaskStatusKeywordsMap();
foreach ($keywords as $key => $words) {
foreach ($words as $word) {
if ($word == $target) {
$status = $key;
break;
}
}
}
if ($status === null) {
return array();
}
$xactions[] = $object->getApplicationTransactionTemplate()
->setTransactionType(ManiphestTransaction::TYPE_STATUS)
->setNewValue($status);
return $xactions;
}
}

View file

@ -26,31 +26,37 @@ final class PhabricatorManiphestConfigOptions
'name' => pht('Unbreak Now!'), 'name' => pht('Unbreak Now!'),
'short' => pht('Unbreak!'), 'short' => pht('Unbreak!'),
'color' => 'indigo', 'color' => 'indigo',
'keywords' => array('unbreak'),
), ),
90 => array( 90 => array(
'name' => pht('Needs Triage'), 'name' => pht('Needs Triage'),
'short' => pht('Triage'), 'short' => pht('Triage'),
'color' => 'violet', 'color' => 'violet',
'keywords' => array('triage'),
), ),
80 => array( 80 => array(
'name' => pht('High'), 'name' => pht('High'),
'short' => pht('High'), 'short' => pht('High'),
'color' => 'red', 'color' => 'red',
'keywords' => array('high'),
), ),
50 => array( 50 => array(
'name' => pht('Normal'), 'name' => pht('Normal'),
'short' => pht('Normal'), 'short' => pht('Normal'),
'color' => 'orange', 'color' => 'orange',
'keywords' => array('normal'),
), ),
25 => array( 25 => array(
'name' => pht('Low'), 'name' => pht('Low'),
'short' => pht('Low'), 'short' => pht('Low'),
'color' => 'yellow', 'color' => 'yellow',
'keywords' => array('low'),
), ),
0 => array( 0 => array(
'name' => pht('Wishlist'), 'name' => pht('Wishlist'),
'short' => pht('Wish'), 'short' => pht('Wish'),
'color' => 'sky', 'color' => 'sky',
'keywords' => array('wish', 'wishlist'),
), ),
); );
@ -80,6 +86,7 @@ final class PhabricatorManiphestConfigOptions
'as resolved', 'as resolved',
'as fixed', 'as fixed',
), ),
'keywords' => array('closed', 'fixed', 'resolved'),
), ),
'wontfix' => array( 'wontfix' => array(
'name' => pht('Wontfix'), 'name' => pht('Wontfix'),
@ -182,6 +189,9 @@ The keys you can provide in a specification are:
providing "as invalid" here will allow users to move tasks providing "as invalid" here will allow users to move tasks
to this status by writing `Closes T123 as invalid`, even if another status to this status by writing `Closes T123 as invalid`, even if another status
is selected by the "Closes" prefix. is selected by the "Closes" prefix.
- `keywords` //Optional list<string>.// Allows you to specify a list
of keywords which can be used with `!status` commands in email to select
this status.
Statuses will appear in the UI in the order specified. Note the status marked Statuses will appear in the UI in the order specified. Note the status marked
`special` as `duplicate` is not settable directly and will not appear in UI `special` as `duplicate` is not settable directly and will not appear in UI
@ -257,6 +267,9 @@ EOTEXT
' - `short` Alternate shorter name, used in UIs where there is '. ' - `short` Alternate shorter name, used in UIs where there is '.
' not much space available.'."\n". ' not much space available.'."\n".
' - `color` A color for this priority, like "red" or "blue".'. ' - `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\n". "\n\n".
'You can choose which priority is the default for newly created '. 'You can choose which priority is the default for newly created '.
'tasks with `maniphest.default-priority`.')), 'tasks with `maniphest.default-priority`.')),

View file

@ -16,6 +16,32 @@ final class ManiphestTaskPriority extends ManiphestConstants {
} }
/**
* Get the priorities and their command keywords.
*
* @return map Priorities to lists of command keywords.
*/
public static function getTaskPriorityKeywordsMap() {
$map = self::getConfig();
foreach ($map as $key => $spec) {
$words = idx($spec, 'keywords', array());
if (!is_array($words)) {
$words = array($words);
}
foreach ($words as $word_key => $word) {
$words[$word_key] = phutil_utf8_strtolower($word);
}
$words = array_unique($words);
$map[$key] = $words;
}
return $map;
}
/** /**
* Get the priorities and their related short (one-word) descriptions. * Get the priorities and their related short (one-word) descriptions.
* *

View file

@ -38,6 +38,37 @@ final class ManiphestTaskStatus extends ManiphestConstants {
return ipull(self::getEnabledStatusMap(), 'name'); return ipull(self::getEnabledStatusMap(), 'name');
} }
/**
* Get the statuses and their command keywords.
*
* @return map Statuses to lists of command keywords.
*/
public static function getTaskStatusKeywordsMap() {
$map = self::getEnabledStatusMap();
foreach ($map as $key => $spec) {
$words = idx($spec, 'keywords', array());
if (!is_array($words)) {
$words = array($words);
}
// For statuses, we include the status name because it's usually
// at least somewhat meaningful.
$words[] = $key;
foreach ($words as $word_key => $word) {
$words[$word_key] = phutil_utf8_strtolower($word);
}
$words = array_unique($words);
$map[$key] = $words;
}
return $map;
}
public static function getTaskStatusName($status) { public static function getTaskStatusName($status) {
return self::getStatusAttribute($status, 'name', pht('Unknown Status')); return self::getStatusAttribute($status, 'name', pht('Unknown Status'));
} }
@ -231,6 +262,7 @@ final class ManiphestTaskStatus extends ManiphestConstants {
'silly' => 'optional bool', 'silly' => 'optional bool',
'prefixes' => 'optional list<string>', 'prefixes' => 'optional list<string>',
'suffixes' => 'optional list<string>', 'suffixes' => 'optional list<string>',
'keywords' => 'optional list<string>',
)); ));
} }