From 6f95b325c6b315f2d92a2549428273e6297c9b5c Mon Sep 17 00:00:00 2001 From: epriestley Date: Wed, 1 Apr 2015 07:36:16 -0700 Subject: [PATCH] Generate mail command documentation from active commands Summary: Ref T7199. This needs some polish and isn't reachable from the UI, but technically has all of the information. Test Plan: {F355899} {F355900} Reviewers: btrahan Reviewed By: btrahan Subscribers: epriestley Maniphest Tasks: T7199 Differential Revision: https://secure.phabricator.com/D12241 --- src/__phutil_library_map__.php | 2 + .../base/PhabricatorApplication.php | 4 + .../PhabricatorDifferentialApplication.php | 8 ++ .../DifferentialActionEmailCommand.php | 52 ++++++++- .../PhabricatorManiphestApplication.php | 8 ++ .../command/ManiphestAssignEmailCommand.php | 17 +++ .../command/ManiphestClaimEmailCommand.php | 4 + .../command/ManiphestCloseEmailCommand.php | 4 + .../PhabricatorApplicationsApplication.php | 2 + ...atorApplicationEmailCommandsController.php | 109 ++++++++++++++++++ .../PhabricatorApplicationsController.php | 9 ++ .../MetaMTAEmailTransactionCommand.php | 39 +++++++ ...orSubscriptionsUnsubscribeEmailCommand.php | 4 + 13 files changed, 260 insertions(+), 2 deletions(-) create mode 100644 src/applications/meta/controller/PhabricatorApplicationEmailCommandsController.php diff --git a/src/__phutil_library_map__.php b/src/__phutil_library_map__.php index 5ac246867d..1b80afbdaa 100644 --- a/src/__phutil_library_map__.php +++ b/src/__phutil_library_map__.php @@ -1291,6 +1291,7 @@ phutil_register_library_map(array( 'PhabricatorApplicationDatasource' => 'applications/meta/typeahead/PhabricatorApplicationDatasource.php', 'PhabricatorApplicationDetailViewController' => 'applications/meta/controller/PhabricatorApplicationDetailViewController.php', 'PhabricatorApplicationEditController' => 'applications/meta/controller/PhabricatorApplicationEditController.php', + 'PhabricatorApplicationEmailCommandsController' => 'applications/meta/controller/PhabricatorApplicationEmailCommandsController.php', 'PhabricatorApplicationLaunchView' => 'applications/meta/view/PhabricatorApplicationLaunchView.php', 'PhabricatorApplicationPanelController' => 'applications/meta/controller/PhabricatorApplicationPanelController.php', 'PhabricatorApplicationQuery' => 'applications/meta/query/PhabricatorApplicationQuery.php', @@ -4562,6 +4563,7 @@ phutil_register_library_map(array( 'PhabricatorApplicationDatasource' => 'PhabricatorTypeaheadDatasource', 'PhabricatorApplicationDetailViewController' => 'PhabricatorApplicationsController', 'PhabricatorApplicationEditController' => 'PhabricatorApplicationsController', + 'PhabricatorApplicationEmailCommandsController' => 'PhabricatorApplicationsController', 'PhabricatorApplicationLaunchView' => 'AphrontTagView', 'PhabricatorApplicationPanelController' => 'PhabricatorApplicationsController', 'PhabricatorApplicationQuery' => 'PhabricatorCursorPagedPolicyAwareQuery', diff --git a/src/applications/base/PhabricatorApplication.php b/src/applications/base/PhabricatorApplication.php index 5f550cc11c..a01d50a03f 100644 --- a/src/applications/base/PhabricatorApplication.php +++ b/src/applications/base/PhabricatorApplication.php @@ -189,6 +189,10 @@ abstract class PhabricatorApplication implements PhabricatorPolicyInterface { return array(); } + public function getMailCommandObjects() { + return array(); + } + /* -( URI Routing )-------------------------------------------------------- */ diff --git a/src/applications/differential/application/PhabricatorDifferentialApplication.php b/src/applications/differential/application/PhabricatorDifferentialApplication.php index be0ee46ac9..5a7eb82d1c 100644 --- a/src/applications/differential/application/PhabricatorDifferentialApplication.php +++ b/src/applications/differential/application/PhabricatorDifferentialApplication.php @@ -186,4 +186,12 @@ EOTEXT ); } + public function getMailCommandObjects() { + return array( + 'revision' => array( + 'object' => new DifferentialRevision(), + ), + ); + } + } diff --git a/src/applications/differential/command/DifferentialActionEmailCommand.php b/src/applications/differential/command/DifferentialActionEmailCommand.php index 896daa4287..a761339141 100644 --- a/src/applications/differential/command/DifferentialActionEmailCommand.php +++ b/src/applications/differential/command/DifferentialActionEmailCommand.php @@ -6,6 +6,8 @@ final class DifferentialActionEmailCommand private $command; private $action; private $aliases; + private $commandSummary; + private $commandDescription; public function getCommand() { return $this->command; @@ -34,13 +36,31 @@ final class DifferentialActionEmailCommand return $this->aliases; } + public function setCommandSummary($command_summary) { + $this->commandSummary = $command_summary; + return $this; + } + + public function getCommandSummary() { + return $this->commandSummary; + } + + public function setCommandDescription($command_description) { + $this->commandDescription = $command_description; + return $this; + } + + public function getCommandDescription() { + return $this->commandDescription; + } + public function getCommandObjects() { $actions = array( DifferentialAction::ACTION_REJECT => 'request', DifferentialAction::ACTION_ABANDON => 'abandon', DifferentialAction::ACTION_RECLAIM => 'reclaim', DifferentialAction::ACTION_RESIGN => 'resign', - DifferentialAction::ACTION_RETHINK => 'rethink', + DifferentialAction::ACTION_RETHINK => 'planchanges', DifferentialAction::ACTION_CLAIM => 'commandeer', ); @@ -51,21 +71,49 @@ final class DifferentialActionEmailCommand $aliases = array( DifferentialAction::ACTION_REJECT => array('reject'), DifferentialAction::ACTION_CLAIM => array('claim'), + DifferentialAction::ACTION_RETHINK => array('rethink'), + ); + + $summaries = array( + DifferentialAction::ACTION_REJECT => + pht('Request changes to a revision.'), + DifferentialAction::ACTION_ABANDON => + pht('Abandon a revision.'), + DifferentialAction::ACTION_RECLAIM => + pht('Reclaim a revision.'), + DifferentialAction::ACTION_RESIGN => + pht('Resign from a revision.'), + DifferentialAction::ACTION_RETHINK => + pht('Plan changes to a revision.'), + DifferentialAction::ACTION_CLAIM => + pht('Commandeer a revision.'), + DifferentialAction::ACTION_ACCEPT => + pht('Accept a revision.'), + ); + + $descriptions = array( + ); $objects = array(); foreach ($actions as $action => $keyword) { $object = id(new DifferentialActionEmailCommand()) ->setCommand($keyword) - ->setAction($action); + ->setAction($action) + ->setCommandSummary($summaries[$action]); if (isset($aliases[$action])) { $object->setCommandAliases($aliases[$action]); } + if (isset($descriptions[$action])) { + $object->setCommandDescription($descriptions[$action]); + } + $objects[] = $object; } + return $objects; } diff --git a/src/applications/maniphest/application/PhabricatorManiphestApplication.php b/src/applications/maniphest/application/PhabricatorManiphestApplication.php index 3f0ebb7674..2405e446f0 100644 --- a/src/applications/maniphest/application/PhabricatorManiphestApplication.php +++ b/src/applications/maniphest/application/PhabricatorManiphestApplication.php @@ -143,4 +143,12 @@ final class PhabricatorManiphestApplication extends PhabricatorApplication { ); } + public function getMailCommandObjects() { + return array( + 'task' => array( + 'object' => new ManiphestTask(), + ), + ); + } + } diff --git a/src/applications/maniphest/command/ManiphestAssignEmailCommand.php b/src/applications/maniphest/command/ManiphestAssignEmailCommand.php index 9721a4ea36..7d98bb003f 100644 --- a/src/applications/maniphest/command/ManiphestAssignEmailCommand.php +++ b/src/applications/maniphest/command/ManiphestAssignEmailCommand.php @@ -7,6 +7,23 @@ final class ManiphestAssignEmailCommand return 'assign'; } + public function getCommandSyntax() { + return '**!assign** //username//'; + } + + public function getCommandSummary() { + return pht('Assign a task to a specific user.'); + } + + public function getCommandDescription() { + return pht( + 'To assign a task to another user, provide their username. For example, '. + 'to assign a task to `alincoln`, write `!assign alincoln`.'. + "\n\n". + 'If you omit the username or the username is not valid, this behaves '. + 'like `!claim` and assigns the task to you instead.'); + } + public function buildTransactions( PhabricatorUser $viewer, PhabricatorApplicationTransactionInterface $object, diff --git a/src/applications/maniphest/command/ManiphestClaimEmailCommand.php b/src/applications/maniphest/command/ManiphestClaimEmailCommand.php index 759c5835d1..38919617c6 100644 --- a/src/applications/maniphest/command/ManiphestClaimEmailCommand.php +++ b/src/applications/maniphest/command/ManiphestClaimEmailCommand.php @@ -7,6 +7,10 @@ final class ManiphestClaimEmailCommand return 'claim'; } + public function getCommandSummary() { + return pht('Assign yourself as the owner of a task.'); + } + public function buildTransactions( PhabricatorUser $viewer, PhabricatorApplicationTransactionInterface $object, diff --git a/src/applications/maniphest/command/ManiphestCloseEmailCommand.php b/src/applications/maniphest/command/ManiphestCloseEmailCommand.php index 2750dcadbb..a30f3a35f0 100644 --- a/src/applications/maniphest/command/ManiphestCloseEmailCommand.php +++ b/src/applications/maniphest/command/ManiphestCloseEmailCommand.php @@ -7,6 +7,10 @@ final class ManiphestCloseEmailCommand return 'close'; } + public function getCommandSummary() { + return pht('Close a task.'); + } + public function buildTransactions( PhabricatorUser $viewer, PhabricatorApplicationTransactionInterface $object, diff --git a/src/applications/meta/application/PhabricatorApplicationsApplication.php b/src/applications/meta/application/PhabricatorApplicationsApplication.php index dc774fdb7a..1b354213be 100644 --- a/src/applications/meta/application/PhabricatorApplicationsApplication.php +++ b/src/applications/meta/application/PhabricatorApplicationsApplication.php @@ -41,6 +41,8 @@ final class PhabricatorApplicationsApplication extends PhabricatorApplication { => 'PhabricatorApplicationDetailViewController', 'edit/(?P\w+)/' => 'PhabricatorApplicationEditController', + 'mailcommands/(?P\w+)/(?P\w+)/' + => 'PhabricatorApplicationEmailCommandsController', '(?P\w+)/(?Pinstall|uninstall)/' => 'PhabricatorApplicationUninstallController', 'panel/(?P\w+)/(?P\w+)/(?P.*)' diff --git a/src/applications/meta/controller/PhabricatorApplicationEmailCommandsController.php b/src/applications/meta/controller/PhabricatorApplicationEmailCommandsController.php new file mode 100644 index 0000000000..fe89672fd2 --- /dev/null +++ b/src/applications/meta/controller/PhabricatorApplicationEmailCommandsController.php @@ -0,0 +1,109 @@ +getViewer(); + $application = $request->getURIData('application'); + + $selected = id(new PhabricatorApplicationQuery()) + ->setViewer($viewer) + ->withClasses(array($application)) + ->executeOne(); + if (!$selected) { + return new Aphront404Response(); + } + + $specs = $selected->getMailCommandObjects(); + $type = $request->getURIData('type'); + if (empty($specs[$type])) { + return new Aphront404Response(); + } + + $spec = $specs[$type]; + $commands = MetaMTAEmailTransactionCommand::getAllCommandsForObject( + $spec['object']); + + $commands = msort($commands, 'getCommand'); + + $content = array(); + + $content[] = '= '.pht('Quick Reference'); + $table = array(); + $table[] = '| '.pht('Command').' | '.pht('Summary').' |'; + $table[] = '|---|---|'; + foreach ($commands as $command) { + $summary = $command->getCommandSummary(); + $table[] = '| '.$command->getCommandSyntax().' | '.$summary; + } + $table = implode("\n", $table); + $content[] = $table; + + foreach ($commands as $command) { + $content[] = '== !'.$command->getCommand().' =='; + $content[] = $command->getCommandSummary(); + + $aliases = $command->getCommandAliases(); + if ($aliases) { + foreach ($aliases as $key => $alias) { + $aliases[$key] = '!'.$alias; + } + $aliases = implode(', ', $aliases); + } else { + $aliases = '//None//'; + } + + $syntax = $command->getCommandSyntax(); + + $table = array(); + $table[] = '| '.pht('Property').' | '.pht('Value'); + $table[] = '|---|---|'; + $table[] = '| **'.pht('Syntax').'** | '.$syntax; + $table[] = '| **'.pht('Aliases').'** | '.$aliases; + $table[] = '| **'.pht('Class').'** | `'.get_class($command).'`'; + $table = implode("\n", $table); + + $content[] = $table; + + $description = $command->getCommandDescription(); + if ($description) { + $content[] = $description; + } + } + + $content = implode("\n\n", $content); + + $crumbs = $this->buildApplicationCrumbs(); + $this->addApplicationCrumb($crumbs, $selected); + $crumbs->addTextCrumb(pht('Mail Commands')); + + $content_box = id(new PHUIBoxView()) + ->addMargin(PHUI::MARGIN_LARGE) + ->appendChild( + PhabricatorMarkupEngine::renderOneObject( + id(new PhabricatorMarkupOneOff())->setContent($content), + 'default', + $viewer)); + + $box = id(new PHUIObjectBoxView()) + ->setHeaderText(pht('Mail Commands')) + ->appendChild($content_box); + + return $this->buildApplicationPage( + array( + $crumbs, + $box, + ), + array( + 'title' => 'asdf', + )); + + } + + +} diff --git a/src/applications/meta/controller/PhabricatorApplicationsController.php b/src/applications/meta/controller/PhabricatorApplicationsController.php index e5b035bab4..7751e102be 100644 --- a/src/applications/meta/controller/PhabricatorApplicationsController.php +++ b/src/applications/meta/controller/PhabricatorApplicationsController.php @@ -21,4 +21,13 @@ abstract class PhabricatorApplicationsController extends PhabricatorController { return $this->buildSideNavView(true)->getMenu(); } + protected function addApplicationCrumb( + PHUICrumbsView $crumbs, + PhabricatorApplication $application) { + + $crumbs->addTextCrumb( + $application->getName(), + '/applications/view/'.get_class($application).'/'); + } + } diff --git a/src/applications/metamta/command/MetaMTAEmailTransactionCommand.php b/src/applications/metamta/command/MetaMTAEmailTransactionCommand.php index 9e20ef43e1..e6011768df 100644 --- a/src/applications/metamta/command/MetaMTAEmailTransactionCommand.php +++ b/src/applications/metamta/command/MetaMTAEmailTransactionCommand.php @@ -1,10 +1,49 @@ getCommand().'**'; + } + + /** + * Return a longer human-readable description of the command effect. + * + * This can be as long as necessary to explain the command. + * + * @return string Human-readable remarkup of whatever length is desired. + * @task docs + */ + public function getCommandDescription() { + return null; + } + abstract public function isCommandSupportedForObject( PhabricatorApplicationTransactionInterface $object); + abstract public function buildTransactions( PhabricatorUser $viewer, PhabricatorApplicationTransactionInterface $object, diff --git a/src/applications/subscriptions/command/PhabricatorSubscriptionsUnsubscribeEmailCommand.php b/src/applications/subscriptions/command/PhabricatorSubscriptionsUnsubscribeEmailCommand.php index 124ba9605a..24b3f85674 100644 --- a/src/applications/subscriptions/command/PhabricatorSubscriptionsUnsubscribeEmailCommand.php +++ b/src/applications/subscriptions/command/PhabricatorSubscriptionsUnsubscribeEmailCommand.php @@ -7,6 +7,10 @@ final class PhabricatorSubscriptionsUnsubscribeEmailCommand return 'unsubscribe'; } + public function getCommandSummary() { + return pht('Remove yourself as a subscriber.'); + } + public function isCommandSupportedForObject( PhabricatorApplicationTransactionInterface $object) { return ($object instanceof PhabricatorSubscribableInterface);