mirror of
https://we.phorge.it/source/phorge.git
synced 2024-11-19 05:12:41 +01:00
Implement open() and closed() Maniphest tokenizer status functions, plus cleanup
Summary: Ref T4100. - Make it easy to choose all open or closed tasks. - Make "special" tokenizers composable. - Get `viewer()` generating documentation properly. Test Plan: - Ran queries with new tokens. - Browsed new tokens. - Viewed docs on new tokens. - Used plain status tokens. Reviewers: btrahan Reviewed By: btrahan Subscribers: chad, epriestley Maniphest Tasks: T4100 Differential Revision: https://secure.phabricator.com/D12530
This commit is contained in:
parent
ccd6770a09
commit
f64ca87bfe
9 changed files with 244 additions and 8 deletions
|
@ -1045,6 +1045,7 @@ phutil_register_library_map(array(
|
||||||
'ManiphestStatusEmailCommand' => 'applications/maniphest/command/ManiphestStatusEmailCommand.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',
|
||||||
|
'ManiphestTaskClosedStatusDatasource' => 'applications/maniphest/typeahead/ManiphestTaskClosedStatusDatasource.php',
|
||||||
'ManiphestTaskDependedOnByTaskEdgeType' => 'applications/maniphest/edge/ManiphestTaskDependedOnByTaskEdgeType.php',
|
'ManiphestTaskDependedOnByTaskEdgeType' => 'applications/maniphest/edge/ManiphestTaskDependedOnByTaskEdgeType.php',
|
||||||
'ManiphestTaskDependsOnTaskEdgeType' => 'applications/maniphest/edge/ManiphestTaskDependsOnTaskEdgeType.php',
|
'ManiphestTaskDependsOnTaskEdgeType' => 'applications/maniphest/edge/ManiphestTaskDependsOnTaskEdgeType.php',
|
||||||
'ManiphestTaskDetailController' => 'applications/maniphest/controller/ManiphestTaskDetailController.php',
|
'ManiphestTaskDetailController' => 'applications/maniphest/controller/ManiphestTaskDetailController.php',
|
||||||
|
@ -1055,6 +1056,7 @@ phutil_register_library_map(array(
|
||||||
'ManiphestTaskListController' => 'applications/maniphest/controller/ManiphestTaskListController.php',
|
'ManiphestTaskListController' => 'applications/maniphest/controller/ManiphestTaskListController.php',
|
||||||
'ManiphestTaskListView' => 'applications/maniphest/view/ManiphestTaskListView.php',
|
'ManiphestTaskListView' => 'applications/maniphest/view/ManiphestTaskListView.php',
|
||||||
'ManiphestTaskMailReceiver' => 'applications/maniphest/mail/ManiphestTaskMailReceiver.php',
|
'ManiphestTaskMailReceiver' => 'applications/maniphest/mail/ManiphestTaskMailReceiver.php',
|
||||||
|
'ManiphestTaskOpenStatusDatasource' => 'applications/maniphest/typeahead/ManiphestTaskOpenStatusDatasource.php',
|
||||||
'ManiphestTaskOwner' => 'applications/maniphest/constants/ManiphestTaskOwner.php',
|
'ManiphestTaskOwner' => 'applications/maniphest/constants/ManiphestTaskOwner.php',
|
||||||
'ManiphestTaskPHIDType' => 'applications/maniphest/phid/ManiphestTaskPHIDType.php',
|
'ManiphestTaskPHIDType' => 'applications/maniphest/phid/ManiphestTaskPHIDType.php',
|
||||||
'ManiphestTaskPriority' => 'applications/maniphest/constants/ManiphestTaskPriority.php',
|
'ManiphestTaskPriority' => 'applications/maniphest/constants/ManiphestTaskPriority.php',
|
||||||
|
@ -1064,6 +1066,7 @@ phutil_register_library_map(array(
|
||||||
'ManiphestTaskSearchEngine' => 'applications/maniphest/query/ManiphestTaskSearchEngine.php',
|
'ManiphestTaskSearchEngine' => 'applications/maniphest/query/ManiphestTaskSearchEngine.php',
|
||||||
'ManiphestTaskStatus' => 'applications/maniphest/constants/ManiphestTaskStatus.php',
|
'ManiphestTaskStatus' => 'applications/maniphest/constants/ManiphestTaskStatus.php',
|
||||||
'ManiphestTaskStatusDatasource' => 'applications/maniphest/typeahead/ManiphestTaskStatusDatasource.php',
|
'ManiphestTaskStatusDatasource' => 'applications/maniphest/typeahead/ManiphestTaskStatusDatasource.php',
|
||||||
|
'ManiphestTaskStatusFunctionDatasource' => 'applications/maniphest/typeahead/ManiphestTaskStatusFunctionDatasource.php',
|
||||||
'ManiphestTaskStatusTestCase' => 'applications/maniphest/constants/__tests__/ManiphestTaskStatusTestCase.php',
|
'ManiphestTaskStatusTestCase' => 'applications/maniphest/constants/__tests__/ManiphestTaskStatusTestCase.php',
|
||||||
'ManiphestTaskTestCase' => 'applications/maniphest/__tests__/ManiphestTaskTestCase.php',
|
'ManiphestTaskTestCase' => 'applications/maniphest/__tests__/ManiphestTaskTestCase.php',
|
||||||
'ManiphestTransaction' => 'applications/maniphest/storage/ManiphestTransaction.php',
|
'ManiphestTransaction' => 'applications/maniphest/storage/ManiphestTransaction.php',
|
||||||
|
@ -4335,6 +4338,7 @@ phutil_register_library_map(array(
|
||||||
'PhabricatorApplicationTransactionInterface',
|
'PhabricatorApplicationTransactionInterface',
|
||||||
'PhabricatorProjectInterface',
|
'PhabricatorProjectInterface',
|
||||||
),
|
),
|
||||||
|
'ManiphestTaskClosedStatusDatasource' => 'PhabricatorTypeaheadDatasource',
|
||||||
'ManiphestTaskDependedOnByTaskEdgeType' => 'PhabricatorEdgeType',
|
'ManiphestTaskDependedOnByTaskEdgeType' => 'PhabricatorEdgeType',
|
||||||
'ManiphestTaskDependsOnTaskEdgeType' => 'PhabricatorEdgeType',
|
'ManiphestTaskDependsOnTaskEdgeType' => 'PhabricatorEdgeType',
|
||||||
'ManiphestTaskDetailController' => 'ManiphestController',
|
'ManiphestTaskDetailController' => 'ManiphestController',
|
||||||
|
@ -4345,6 +4349,7 @@ phutil_register_library_map(array(
|
||||||
'ManiphestTaskListController' => 'ManiphestController',
|
'ManiphestTaskListController' => 'ManiphestController',
|
||||||
'ManiphestTaskListView' => 'ManiphestView',
|
'ManiphestTaskListView' => 'ManiphestView',
|
||||||
'ManiphestTaskMailReceiver' => 'PhabricatorObjectMailReceiver',
|
'ManiphestTaskMailReceiver' => 'PhabricatorObjectMailReceiver',
|
||||||
|
'ManiphestTaskOpenStatusDatasource' => 'PhabricatorTypeaheadDatasource',
|
||||||
'ManiphestTaskOwner' => 'ManiphestConstants',
|
'ManiphestTaskOwner' => 'ManiphestConstants',
|
||||||
'ManiphestTaskPHIDType' => 'PhabricatorPHIDType',
|
'ManiphestTaskPHIDType' => 'PhabricatorPHIDType',
|
||||||
'ManiphestTaskPriority' => 'ManiphestConstants',
|
'ManiphestTaskPriority' => 'ManiphestConstants',
|
||||||
|
@ -4354,6 +4359,7 @@ phutil_register_library_map(array(
|
||||||
'ManiphestTaskSearchEngine' => 'PhabricatorApplicationSearchEngine',
|
'ManiphestTaskSearchEngine' => 'PhabricatorApplicationSearchEngine',
|
||||||
'ManiphestTaskStatus' => 'ManiphestConstants',
|
'ManiphestTaskStatus' => 'ManiphestConstants',
|
||||||
'ManiphestTaskStatusDatasource' => 'PhabricatorTypeaheadDatasource',
|
'ManiphestTaskStatusDatasource' => 'PhabricatorTypeaheadDatasource',
|
||||||
|
'ManiphestTaskStatusFunctionDatasource' => 'PhabricatorTypeaheadCompositeDatasource',
|
||||||
'ManiphestTaskStatusTestCase' => 'PhabricatorTestCase',
|
'ManiphestTaskStatusTestCase' => 'PhabricatorTestCase',
|
||||||
'ManiphestTaskTestCase' => 'PhabricatorTestCase',
|
'ManiphestTaskTestCase' => 'PhabricatorTestCase',
|
||||||
'ManiphestTransaction' => 'PhabricatorApplicationTransaction',
|
'ManiphestTransaction' => 'PhabricatorApplicationTransaction',
|
||||||
|
|
|
@ -139,7 +139,10 @@ final class ManiphestTaskSearchEngine
|
||||||
$query->withOwners($assigned_phids);
|
$query->withOwners($assigned_phids);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$datasource = id(new ManiphestTaskStatusFunctionDatasource())
|
||||||
|
->setViewer($this->requireViewer());
|
||||||
$statuses = $saved->getParameter('statuses');
|
$statuses = $saved->getParameter('statuses');
|
||||||
|
$statuses = $datasource->evaluateTokens($statuses);
|
||||||
if ($statuses) {
|
if ($statuses) {
|
||||||
$query->withStatuses($statuses);
|
$query->withStatuses($statuses);
|
||||||
}
|
}
|
||||||
|
@ -274,7 +277,7 @@ final class ManiphestTaskSearchEngine
|
||||||
->setValue($subscriber_phids))
|
->setValue($subscriber_phids))
|
||||||
->appendControl(
|
->appendControl(
|
||||||
id(new AphrontFormTokenizerControl())
|
id(new AphrontFormTokenizerControl())
|
||||||
->setDatasource(new ManiphestTaskStatusDatasource())
|
->setDatasource(new ManiphestTaskStatusFunctionDatasource())
|
||||||
->setLabel(pht('Statuses'))
|
->setLabel(pht('Statuses'))
|
||||||
->setName('statuses')
|
->setName('statuses')
|
||||||
->setValue($statuses))
|
->setValue($statuses))
|
||||||
|
|
|
@ -0,0 +1,73 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
final class ManiphestTaskClosedStatusDatasource
|
||||||
|
extends PhabricatorTypeaheadDatasource {
|
||||||
|
|
||||||
|
const FUNCTION_TOKEN = 'closed()';
|
||||||
|
|
||||||
|
public function getBrowseTitle() {
|
||||||
|
return pht('Browse Any Closed Status');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getPlaceholderText() {
|
||||||
|
return pht('Type closed()...');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getDatasourceApplicationClass() {
|
||||||
|
return 'PhabricatorManiphestApplication';
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getDatasourceFunctions() {
|
||||||
|
return array(
|
||||||
|
'closed' => array(
|
||||||
|
'name' => pht('Any Closed Status'),
|
||||||
|
'summary' => pht('Find results with any closed status.'),
|
||||||
|
'description' => pht(
|
||||||
|
'This function includes results which have any closed status.'),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function loadResults() {
|
||||||
|
$results = array(
|
||||||
|
$this->buildClosedResult(),
|
||||||
|
);
|
||||||
|
return $this->filterResultsAgainstTokens($results);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function evaluateFunction($function, array $argv_list) {
|
||||||
|
$results = array();
|
||||||
|
|
||||||
|
$map = ManiphestTaskStatus::getTaskStatusMap();
|
||||||
|
foreach ($argv_list as $argv) {
|
||||||
|
foreach ($map as $status => $name) {
|
||||||
|
if (!ManiphestTaskStatus::isOpenStatus($status)) {
|
||||||
|
$results[] = $status;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $results;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function renderFunctionTokens($function, array $argv_list) {
|
||||||
|
$results = array();
|
||||||
|
|
||||||
|
foreach ($argv_list as $argv) {
|
||||||
|
$results[] = PhabricatorTypeaheadTokenView::newFromTypeaheadResult(
|
||||||
|
$this->buildClosedResult());
|
||||||
|
}
|
||||||
|
|
||||||
|
return $results;
|
||||||
|
}
|
||||||
|
|
||||||
|
private function buildClosedResult() {
|
||||||
|
$name = pht('Any Closed Status');
|
||||||
|
return $this->newFunctionResult()
|
||||||
|
->setName($name.' closed')
|
||||||
|
->setDisplayName($name)
|
||||||
|
->setPHID(self::FUNCTION_TOKEN)
|
||||||
|
->setUnique(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,73 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
final class ManiphestTaskOpenStatusDatasource
|
||||||
|
extends PhabricatorTypeaheadDatasource {
|
||||||
|
|
||||||
|
const FUNCTION_TOKEN = 'open()';
|
||||||
|
|
||||||
|
public function getBrowseTitle() {
|
||||||
|
return pht('Browse Any Open Status');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getPlaceholderText() {
|
||||||
|
return pht('Type open()...');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getDatasourceApplicationClass() {
|
||||||
|
return 'PhabricatorManiphestApplication';
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getDatasourceFunctions() {
|
||||||
|
return array(
|
||||||
|
'open' => array(
|
||||||
|
'name' => pht('Any Open Status'),
|
||||||
|
'summary' => pht('Find results with any open status.'),
|
||||||
|
'description' => pht(
|
||||||
|
'This function includes results which have any open status.'),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function loadResults() {
|
||||||
|
$results = array(
|
||||||
|
$this->buildOpenResult(),
|
||||||
|
);
|
||||||
|
return $this->filterResultsAgainstTokens($results);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function evaluateFunction($function, array $argv_list) {
|
||||||
|
$results = array();
|
||||||
|
|
||||||
|
$map = ManiphestTaskStatus::getTaskStatusMap();
|
||||||
|
foreach ($argv_list as $argv) {
|
||||||
|
foreach ($map as $status => $name) {
|
||||||
|
if (ManiphestTaskStatus::isOpenStatus($status)) {
|
||||||
|
$results[] = $status;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $results;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function renderFunctionTokens($function, array $argv_list) {
|
||||||
|
$results = array();
|
||||||
|
|
||||||
|
foreach ($argv_list as $argv) {
|
||||||
|
$results[] = PhabricatorTypeaheadTokenView::newFromTypeaheadResult(
|
||||||
|
$this->buildOpenResult());
|
||||||
|
}
|
||||||
|
|
||||||
|
return $results;
|
||||||
|
}
|
||||||
|
|
||||||
|
private function buildOpenResult() {
|
||||||
|
$name = pht('Any Open Status');
|
||||||
|
return $this->newFunctionResult()
|
||||||
|
->setName($name.' open')
|
||||||
|
->setDisplayName($name)
|
||||||
|
->setPHID(self::FUNCTION_TOKEN)
|
||||||
|
->setUnique(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -20,7 +20,8 @@ final class ManiphestTaskStatusDatasource
|
||||||
return $this->filterResultsAgainstTokens($results);
|
return $this->filterResultsAgainstTokens($results);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function renderTokens(array $values) {
|
|
||||||
|
protected function renderSpecialTokens(array $values) {
|
||||||
return $this->renderTokensFromResults($this->buildResults(), $values);
|
return $this->renderTokensFromResults($this->buildResults(), $values);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,22 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
final class ManiphestTaskStatusFunctionDatasource
|
||||||
|
extends PhabricatorTypeaheadCompositeDatasource {
|
||||||
|
|
||||||
|
public function getBrowseTitle() {
|
||||||
|
return pht('Browse Statuses');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getPlaceholderText() {
|
||||||
|
return pht('Type a task status name or function...');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getComponentDatasources() {
|
||||||
|
return array(
|
||||||
|
new ManiphestTaskStatusDatasource(),
|
||||||
|
new ManiphestTaskClosedStatusDatasource(),
|
||||||
|
new ManiphestTaskOpenStatusDatasource(),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -15,6 +15,26 @@ final class PhabricatorViewerDatasource
|
||||||
return 'PhabricatorPeopleApplication';
|
return 'PhabricatorPeopleApplication';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function getDatasourceFunctions() {
|
||||||
|
return array(
|
||||||
|
'viewer' => array(
|
||||||
|
'name' => pht('Current Viewer'),
|
||||||
|
'summary' => pht('Use the current viewing user.'),
|
||||||
|
'description' => pht(
|
||||||
|
'This function allows you to change the behavior of a query '.
|
||||||
|
'based on who is running it. When you use this function, you will '.
|
||||||
|
'be the current viewer, so it works like you typed your own '.
|
||||||
|
'username.'.
|
||||||
|
"\n\n".
|
||||||
|
'However, if you save a query using this function and send it '.
|
||||||
|
'to someone else, it will work like //their// username was the '.
|
||||||
|
'one that was typed. This can be useful for building dashboard '.
|
||||||
|
'panels that always show relevant information to the user who '.
|
||||||
|
'is looking at them.'),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
public function loadResults() {
|
public function loadResults() {
|
||||||
if ($this->getViewer()->getPHID()) {
|
if ($this->getViewer()->getPHID()) {
|
||||||
$results = array($this->renderViewerFunctionToken());
|
$results = array($this->renderViewerFunctionToken());
|
||||||
|
@ -30,7 +50,7 @@ final class PhabricatorViewerDatasource
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return ($function == 'viewer');
|
return parent::canEvaluateFunction($function);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function evaluateFunction($function, array $argv_list) {
|
protected function evaluateFunction($function, array $argv_list) {
|
||||||
|
|
|
@ -162,5 +162,20 @@ abstract class PhabricatorTypeaheadCompositeDatasource
|
||||||
return parent::renderFunctionTokens($function, $argv_list);
|
return parent::renderFunctionTokens($function, $argv_list);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected function renderSpecialTokens(array $values) {
|
||||||
|
$result = array();
|
||||||
|
foreach ($this->getUsableDatasources() as $source) {
|
||||||
|
$special = $source->renderSpecialTokens($values);
|
||||||
|
foreach ($special as $key => $token) {
|
||||||
|
$result[$key] = $token;
|
||||||
|
unset($values[$key]);
|
||||||
|
}
|
||||||
|
if (!$values) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return $result;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -229,6 +229,24 @@ abstract class PhabricatorTypeaheadDatasource extends Phobject {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Give special non-function tokens which are also not PHIDs (like statuses
|
||||||
|
// and priorities) an opportunity to render.
|
||||||
|
$type_unknown = PhabricatorPHIDConstants::PHID_TYPE_UNKNOWN;
|
||||||
|
$special = array();
|
||||||
|
foreach ($values as $key => $value) {
|
||||||
|
if (phid_get_type($value) == $type_unknown) {
|
||||||
|
$special[$key] = $value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($special) {
|
||||||
|
$special_tokens = $this->renderSpecialTokens($special);
|
||||||
|
foreach ($special_tokens as $key => $token) {
|
||||||
|
$tokens[$key] = $token;
|
||||||
|
unset($phids[$key]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if ($phids) {
|
if ($phids) {
|
||||||
$handles = $this->getViewer()->loadHandles($phids);
|
$handles = $this->getViewer()->loadHandles($phids);
|
||||||
foreach ($phids as $key => $phid) {
|
foreach ($phids as $key => $phid) {
|
||||||
|
@ -265,6 +283,10 @@ abstract class PhabricatorTypeaheadDatasource extends Phobject {
|
||||||
return array_select_keys($tokens, array_keys($values));
|
return array_select_keys($tokens, array_keys($values));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected function renderSpecialTokens(array $values) {
|
||||||
|
return array();
|
||||||
|
}
|
||||||
|
|
||||||
/* -( Token Functions )---------------------------------------------------- */
|
/* -( Token Functions )---------------------------------------------------- */
|
||||||
|
|
||||||
|
|
||||||
|
@ -424,12 +446,13 @@ abstract class PhabricatorTypeaheadDatasource extends Phobject {
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function renderTokensFromResults(array $results, array $values) {
|
protected function renderTokensFromResults(array $results, array $values) {
|
||||||
$results = array_select_keys($results, $values);
|
|
||||||
|
|
||||||
$tokens = array();
|
$tokens = array();
|
||||||
foreach ($results as $result) {
|
foreach ($values as $key => $value) {
|
||||||
$tokens[] = PhabricatorTypeaheadTokenView::newFromTypeaheadResult(
|
if (empty($results[$value])) {
|
||||||
$result);
|
continue;
|
||||||
|
}
|
||||||
|
$tokens[$key] = PhabricatorTypeaheadTokenView::newFromTypeaheadResult(
|
||||||
|
$results[$value]);
|
||||||
}
|
}
|
||||||
|
|
||||||
return $tokens;
|
return $tokens;
|
||||||
|
|
Loading…
Reference in a new issue