1
0
Fork 0
mirror of https://we.phorge.it/source/phorge.git synced 2024-12-19 12:00:55 +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:
epriestley 2015-04-23 06:47:30 -07:00
parent ccd6770a09
commit f64ca87bfe
9 changed files with 244 additions and 8 deletions

View file

@ -1045,6 +1045,7 @@ phutil_register_library_map(array(
'ManiphestStatusEmailCommand' => 'applications/maniphest/command/ManiphestStatusEmailCommand.php',
'ManiphestSubpriorityController' => 'applications/maniphest/controller/ManiphestSubpriorityController.php',
'ManiphestTask' => 'applications/maniphest/storage/ManiphestTask.php',
'ManiphestTaskClosedStatusDatasource' => 'applications/maniphest/typeahead/ManiphestTaskClosedStatusDatasource.php',
'ManiphestTaskDependedOnByTaskEdgeType' => 'applications/maniphest/edge/ManiphestTaskDependedOnByTaskEdgeType.php',
'ManiphestTaskDependsOnTaskEdgeType' => 'applications/maniphest/edge/ManiphestTaskDependsOnTaskEdgeType.php',
'ManiphestTaskDetailController' => 'applications/maniphest/controller/ManiphestTaskDetailController.php',
@ -1055,6 +1056,7 @@ phutil_register_library_map(array(
'ManiphestTaskListController' => 'applications/maniphest/controller/ManiphestTaskListController.php',
'ManiphestTaskListView' => 'applications/maniphest/view/ManiphestTaskListView.php',
'ManiphestTaskMailReceiver' => 'applications/maniphest/mail/ManiphestTaskMailReceiver.php',
'ManiphestTaskOpenStatusDatasource' => 'applications/maniphest/typeahead/ManiphestTaskOpenStatusDatasource.php',
'ManiphestTaskOwner' => 'applications/maniphest/constants/ManiphestTaskOwner.php',
'ManiphestTaskPHIDType' => 'applications/maniphest/phid/ManiphestTaskPHIDType.php',
'ManiphestTaskPriority' => 'applications/maniphest/constants/ManiphestTaskPriority.php',
@ -1064,6 +1066,7 @@ phutil_register_library_map(array(
'ManiphestTaskSearchEngine' => 'applications/maniphest/query/ManiphestTaskSearchEngine.php',
'ManiphestTaskStatus' => 'applications/maniphest/constants/ManiphestTaskStatus.php',
'ManiphestTaskStatusDatasource' => 'applications/maniphest/typeahead/ManiphestTaskStatusDatasource.php',
'ManiphestTaskStatusFunctionDatasource' => 'applications/maniphest/typeahead/ManiphestTaskStatusFunctionDatasource.php',
'ManiphestTaskStatusTestCase' => 'applications/maniphest/constants/__tests__/ManiphestTaskStatusTestCase.php',
'ManiphestTaskTestCase' => 'applications/maniphest/__tests__/ManiphestTaskTestCase.php',
'ManiphestTransaction' => 'applications/maniphest/storage/ManiphestTransaction.php',
@ -4335,6 +4338,7 @@ phutil_register_library_map(array(
'PhabricatorApplicationTransactionInterface',
'PhabricatorProjectInterface',
),
'ManiphestTaskClosedStatusDatasource' => 'PhabricatorTypeaheadDatasource',
'ManiphestTaskDependedOnByTaskEdgeType' => 'PhabricatorEdgeType',
'ManiphestTaskDependsOnTaskEdgeType' => 'PhabricatorEdgeType',
'ManiphestTaskDetailController' => 'ManiphestController',
@ -4345,6 +4349,7 @@ phutil_register_library_map(array(
'ManiphestTaskListController' => 'ManiphestController',
'ManiphestTaskListView' => 'ManiphestView',
'ManiphestTaskMailReceiver' => 'PhabricatorObjectMailReceiver',
'ManiphestTaskOpenStatusDatasource' => 'PhabricatorTypeaheadDatasource',
'ManiphestTaskOwner' => 'ManiphestConstants',
'ManiphestTaskPHIDType' => 'PhabricatorPHIDType',
'ManiphestTaskPriority' => 'ManiphestConstants',
@ -4354,6 +4359,7 @@ phutil_register_library_map(array(
'ManiphestTaskSearchEngine' => 'PhabricatorApplicationSearchEngine',
'ManiphestTaskStatus' => 'ManiphestConstants',
'ManiphestTaskStatusDatasource' => 'PhabricatorTypeaheadDatasource',
'ManiphestTaskStatusFunctionDatasource' => 'PhabricatorTypeaheadCompositeDatasource',
'ManiphestTaskStatusTestCase' => 'PhabricatorTestCase',
'ManiphestTaskTestCase' => 'PhabricatorTestCase',
'ManiphestTransaction' => 'PhabricatorApplicationTransaction',

View file

@ -139,7 +139,10 @@ final class ManiphestTaskSearchEngine
$query->withOwners($assigned_phids);
}
$datasource = id(new ManiphestTaskStatusFunctionDatasource())
->setViewer($this->requireViewer());
$statuses = $saved->getParameter('statuses');
$statuses = $datasource->evaluateTokens($statuses);
if ($statuses) {
$query->withStatuses($statuses);
}
@ -274,7 +277,7 @@ final class ManiphestTaskSearchEngine
->setValue($subscriber_phids))
->appendControl(
id(new AphrontFormTokenizerControl())
->setDatasource(new ManiphestTaskStatusDatasource())
->setDatasource(new ManiphestTaskStatusFunctionDatasource())
->setLabel(pht('Statuses'))
->setName('statuses')
->setValue($statuses))

View file

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

View file

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

View file

@ -20,7 +20,8 @@ final class ManiphestTaskStatusDatasource
return $this->filterResultsAgainstTokens($results);
}
public function renderTokens(array $values) {
protected function renderSpecialTokens(array $values) {
return $this->renderTokensFromResults($this->buildResults(), $values);
}

View file

@ -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(),
);
}
}

View file

@ -15,6 +15,26 @@ final class PhabricatorViewerDatasource
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() {
if ($this->getViewer()->getPHID()) {
$results = array($this->renderViewerFunctionToken());
@ -30,7 +50,7 @@ final class PhabricatorViewerDatasource
return false;
}
return ($function == 'viewer');
return parent::canEvaluateFunction($function);
}
protected function evaluateFunction($function, array $argv_list) {

View file

@ -162,5 +162,20 @@ abstract class PhabricatorTypeaheadCompositeDatasource
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;
}
}

View file

@ -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) {
$handles = $this->getViewer()->loadHandles($phids);
foreach ($phids as $key => $phid) {
@ -265,6 +283,10 @@ abstract class PhabricatorTypeaheadDatasource extends Phobject {
return array_select_keys($tokens, array_keys($values));
}
protected function renderSpecialTokens(array $values) {
return array();
}
/* -( Token Functions )---------------------------------------------------- */
@ -424,12 +446,13 @@ abstract class PhabricatorTypeaheadDatasource extends Phobject {
}
protected function renderTokensFromResults(array $results, array $values) {
$results = array_select_keys($results, $values);
$tokens = array();
foreach ($results as $result) {
$tokens[] = PhabricatorTypeaheadTokenView::newFromTypeaheadResult(
$result);
foreach ($values as $key => $value) {
if (empty($results[$value])) {
continue;
}
$tokens[$key] = PhabricatorTypeaheadTokenView::newFromTypeaheadResult(
$results[$value]);
}
return $tokens;