1
0
Fork 0
mirror of https://we.phorge.it/source/phorge.git synced 2024-12-30 01:10:58 +01:00

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
This commit is contained in:
epriestley 2015-04-01 07:36:16 -07:00
parent 6f59b2ab87
commit 6f95b325c6
13 changed files with 260 additions and 2 deletions

View file

@ -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',

View file

@ -189,6 +189,10 @@ abstract class PhabricatorApplication implements PhabricatorPolicyInterface {
return array();
}
public function getMailCommandObjects() {
return array();
}
/* -( URI Routing )-------------------------------------------------------- */

View file

@ -186,4 +186,12 @@ EOTEXT
);
}
public function getMailCommandObjects() {
return array(
'revision' => array(
'object' => new DifferentialRevision(),
),
);
}
}

View file

@ -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;
}

View file

@ -143,4 +143,12 @@ final class PhabricatorManiphestApplication extends PhabricatorApplication {
);
}
public function getMailCommandObjects() {
return array(
'task' => array(
'object' => new ManiphestTask(),
),
);
}
}

View file

@ -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,

View file

@ -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,

View file

@ -7,6 +7,10 @@ final class ManiphestCloseEmailCommand
return 'close';
}
public function getCommandSummary() {
return pht('Close a task.');
}
public function buildTransactions(
PhabricatorUser $viewer,
PhabricatorApplicationTransactionInterface $object,

View file

@ -41,6 +41,8 @@ final class PhabricatorApplicationsApplication extends PhabricatorApplication {
=> 'PhabricatorApplicationDetailViewController',
'edit/(?P<application>\w+)/'
=> 'PhabricatorApplicationEditController',
'mailcommands/(?P<application>\w+)/(?P<type>\w+)/'
=> 'PhabricatorApplicationEmailCommandsController',
'(?P<application>\w+)/(?P<action>install|uninstall)/'
=> 'PhabricatorApplicationUninstallController',
'panel/(?P<application>\w+)/(?P<panel>\w+)/(?P<path>.*)'

View file

@ -0,0 +1,109 @@
<?php
final class PhabricatorApplicationEmailCommandsController
extends PhabricatorApplicationsController {
public function shouldAllowPublic() {
return true;
}
public function handleRequest(AphrontRequest $request) {
$viewer = $this->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',
));
}
}

View file

@ -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).'/');
}
}

View file

@ -1,10 +1,49 @@
<?php
/**
* @task docs Command Documentation
*/
abstract class MetaMTAEmailTransactionCommand extends Phobject {
abstract public function getCommand();
/**
* Return a brief human-readable description of the command effect.
*
* This should normally be one or two sentences briefly describing the
* command behavior.
*
* @return string Brief human-readable remarkup.
* @task docs
*/
abstract public function getCommandSummary();
/**
* Return a one-line Remarkup description of command syntax for documentation.
*
* @return string Brief human-readable remarkup.
* @task docs
*/
public function getCommandSyntax() {
return '**!'.$this->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,

View file

@ -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);