@recaptime-dev's working patches + fork for Phorge, a community fork of Phabricator. (Upstream dev and stable branches are at upstream/main and upstream/stable respectively.) hq.recaptime.dev/wiki/Phorge
phorge phabricator
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Add contextual typeahead function documentation

Summary: Ref T4100. This integration into the "Browse" dialog is probably a little more heavy-handed than we should shoot for.

Test Plan:
{F377131}

{F377132}

Reviewers: btrahan, chad

Reviewed By: chad

Subscribers: epriestley

Maniphest Tasks: T4100

Differential Revision: https://secure.phabricator.com/D12482

+292 -7
+2
src/__phutil_library_map__.php
··· 2639 2639 'PhabricatorTypeaheadCompositeDatasource' => 'applications/typeahead/datasource/PhabricatorTypeaheadCompositeDatasource.php', 2640 2640 'PhabricatorTypeaheadDatasource' => 'applications/typeahead/datasource/PhabricatorTypeaheadDatasource.php', 2641 2641 'PhabricatorTypeaheadDatasourceController' => 'applications/typeahead/controller/PhabricatorTypeaheadDatasourceController.php', 2642 + 'PhabricatorTypeaheadFunctionHelpController' => 'applications/typeahead/controller/PhabricatorTypeaheadFunctionHelpController.php', 2642 2643 'PhabricatorTypeaheadInvalidTokenException' => 'applications/typeahead/exception/PhabricatorTypeaheadInvalidTokenException.php', 2643 2644 'PhabricatorTypeaheadModularDatasourceController' => 'applications/typeahead/controller/PhabricatorTypeaheadModularDatasourceController.php', 2644 2645 'PhabricatorTypeaheadMonogramDatasource' => 'applications/typeahead/datasource/PhabricatorTypeaheadMonogramDatasource.php', ··· 6054 6055 'PhabricatorTypeaheadCompositeDatasource' => 'PhabricatorTypeaheadDatasource', 6055 6056 'PhabricatorTypeaheadDatasource' => 'Phobject', 6056 6057 'PhabricatorTypeaheadDatasourceController' => 'PhabricatorController', 6058 + 'PhabricatorTypeaheadFunctionHelpController' => 'PhabricatorTypeaheadDatasourceController', 6057 6059 'PhabricatorTypeaheadInvalidTokenException' => 'Exception', 6058 6060 'PhabricatorTypeaheadModularDatasourceController' => 'PhabricatorTypeaheadDatasourceController', 6059 6061 'PhabricatorTypeaheadMonogramDatasource' => 'PhabricatorTypeaheadDatasource',
+14 -1
src/applications/maniphest/typeahead/ManiphestNoOwnerDatasource.php
··· 20 20 public function getDatasourceFunctions() { 21 21 return array( 22 22 'none' => array( 23 - 'name' => pht('Find results which are not assigned.'), 23 + 'name' => pht('No Owner'), 24 + 'summary' => pht('Find results which are not assigned.'), 25 + 'description' => pht( 26 + 'This function includes results which have no owner. Use a query '. 27 + 'like this to find unassigned results:'. 28 + "\n\n". 29 + '> none()'. 30 + "\n\n". 31 + 'If you combine this function with other functions, the query will '. 32 + 'return results which match the other selectors //or// have no '. 33 + 'owner. For example, this query will find results which are owned '. 34 + 'by `alincoln`, and will also find results which have no owner:'. 35 + "\n\n". 36 + '> alincoln, none()'), 24 37 ), 25 38 ); 26 39 }
+46 -2
src/applications/project/typeahead/PhabricatorProjectLogicalOrNotDatasource.php
··· 24 24 public function getDatasourceFunctions() { 25 25 return array( 26 26 'any' => array( 27 - 'name' => pht('Find results in any of several projects.'), 27 + 'name' => pht('In Any: ...'), 28 + 'arguments' => pht('project'), 29 + 'summary' => pht('Find results in any of several projects.'), 30 + 'description' => pht( 31 + 'This function allows you to find results in one of several '. 32 + 'projects. Another way to think of this function is that it '. 33 + 'allows you to perform an "or" query.'. 34 + "\n\n". 35 + 'By default, if you enter several projects, results are returned '. 36 + 'only if they belong to all of the projects you enter. That is, '. 37 + 'this query will only return results in //both// projects:'. 38 + "\n\n". 39 + '> ios, android'. 40 + "\n\n". 41 + 'If you want to find results in any of several projects, you can '. 42 + 'use the `any()` function. For example, you can use this query to '. 43 + 'find results which are in //either// project:'. 44 + "\n\n". 45 + '> any(ios), any(android)'. 46 + "\n\n". 47 + 'You can combine the `any()` function with normal project tokens '. 48 + 'to refine results. For example, use this query to find bugs in '. 49 + '//either// iOS or Android:'. 50 + "\n\n". 51 + '> bug, any(ios), any(android)'), 28 52 ), 29 53 'not' => array( 30 - 'name' => pht('Find results not in specific projects.'), 54 + 'name' => pht('Not In: ...'), 55 + 'arguments' => pht('project'), 56 + 'summary' => pht('Find results not in specific projects.'), 57 + 'description' => pht( 58 + 'This function allows you to find results which are not in '. 59 + 'one or more projects. For example, use this query to find '. 60 + 'results which are not associated with a specific project:'. 61 + "\n\n". 62 + '> not(vanilla)'. 63 + "\n\n". 64 + 'You can exclude multiple projects. This will cause the query '. 65 + 'to return only results which are not in any of the excluded '. 66 + 'projects:'. 67 + "\n\n". 68 + '> not(vanilla), not(chocolate)'. 69 + "\n\n". 70 + 'You can combine this function with other functions to refine '. 71 + 'results. For example, use this query to find iOS results which '. 72 + 'are not bugs:'. 73 + "\n\n". 74 + '> ios, not(bug)'), 31 75 ), 32 76 ); 33 77 }
+11 -1
src/applications/project/typeahead/PhabricatorProjectLogicalUserDatasource.php
··· 24 24 public function getDatasourceFunctions() { 25 25 return array( 26 26 'projects' => array( 27 - 'name' => pht("Find results in any of a user's projects."), 27 + 'name' => pht('Projects: ...'), 28 + 'arguments' => pht('username'), 29 + 'summary' => pht("Find results in any of a user's projects."), 30 + 'description' => pht( 31 + 'This function allows you to find results associated with any '. 32 + 'of the projects a specified user is a member of. For example, '. 33 + 'this will find results associated with all of the projects '. 34 + '`alincoln` is a member of:'. 35 + "\n\n". 36 + '> projects(alincoln)'. 37 + "\n\n"), 28 38 ), 29 39 ); 30 40 }
+13 -1
src/applications/project/typeahead/PhabricatorProjectLogicalViewerDatasource.php
··· 18 18 public function getDatasourceFunctions() { 19 19 return array( 20 20 'viewerprojects' => array( 21 - 'name' => pht("Find results in any of the current viewer's projects."), 21 + 'name' => pht("Current Viewer's Projects"), 22 + 'summary' => pht( 23 + "Find results in any of the current viewer's projects."), 24 + 'description' => pht( 25 + "This function matches results in any of the current viewing ". 26 + "user's projects:". 27 + "\n\n". 28 + "> viewerprojects()". 29 + "\n\n". 30 + "This normally means //your// projects, but if you save a query ". 31 + "using this function and send it to someone else, it will mean ". 32 + "//their// projects when they run it (they become the currnet ". 33 + "viewer). This can be useful for building dashboard panels."), 22 34 ), 23 35 ); 24 36 }
+8 -1
src/applications/project/typeahead/PhabricatorProjectMembersDatasource.php
··· 24 24 public function getDatasourceFunctions() { 25 25 return array( 26 26 'members' => array( 27 - 'name' => pht('Find results for members of a project.'), 27 + 'name' => pht('Members: ...'), 28 + 'arguments' => pht('project'), 29 + 'summary' => pht('Find results for members of a project.'), 30 + 'description' => pht( 31 + 'This function allows you to find results for any of the members '. 32 + 'of a project:'. 33 + "\n\n". 34 + '> members(frontend)'), 28 35 ), 29 36 ); 30 37 }
+9 -1
src/applications/project/typeahead/PhabricatorProjectNoProjectsDatasource.php
··· 18 18 public function getDatasourceFunctions() { 19 19 return array( 20 20 'null' => array( 21 - 'name' => pht('Find results which are not in any projects.'), 21 + 'name' => pht('Not In Any Projects'), 22 + 'summary' => pht('Find results which are not in any projects.'), 23 + 'description' => pht( 24 + 'This function matches results which are not associated with any '. 25 + 'projects. It is usually most often used to find objects which '. 26 + 'might have slipped through the cracks and not been organized '. 27 + 'properly.'. 28 + "\n\n". 29 + "> null()"), 22 30 ), 23 31 ); 24 32 }
+2
src/applications/typeahead/application/PhabricatorTypeaheadApplication.php
··· 11 11 '/typeahead/' => array( 12 12 '(?P<action>browse|class)/(?:(?P<class>\w+)/)?' 13 13 => 'PhabricatorTypeaheadModularDatasourceController', 14 + 'help/(?P<class>\w+)/' 15 + => 'PhabricatorTypeaheadFunctionHelpController', 14 16 ), 15 17 ); 16 18 }
+150
src/applications/typeahead/controller/PhabricatorTypeaheadFunctionHelpController.php
··· 1 + <?php 2 + 3 + final class PhabricatorTypeaheadFunctionHelpController 4 + extends PhabricatorTypeaheadDatasourceController { 5 + 6 + public function shouldAllowPublic() { 7 + return true; 8 + } 9 + 10 + public function handleRequest(AphrontRequest $request) { 11 + $viewer = $this->getViewer(); 12 + $class = $request->getURIData('class'); 13 + 14 + $sources = id(new PhutilSymbolLoader()) 15 + ->setAncestorClass('PhabricatorTypeaheadDatasource') 16 + ->loadObjects(); 17 + if (!isset($sources[$class])) { 18 + return new Aphront404Response(); 19 + } 20 + 21 + $source = $sources[$class]; 22 + 23 + $application_class = $source->getDatasourceApplicationClass(); 24 + if ($application_class) { 25 + $result = id(new PhabricatorApplicationQuery()) 26 + ->setViewer($this->getViewer()) 27 + ->withClasses(array($application_class)) 28 + ->execute(); 29 + if (!$result) { 30 + return new Aphront404Response(); 31 + } 32 + } 33 + 34 + $source->setViewer($viewer); 35 + 36 + $title = pht('Typeahead Function Help'); 37 + 38 + $functions = $source->getAllDatasourceFunctions(); 39 + ksort($functions); 40 + 41 + $content = array(); 42 + 43 + $content[] = '= '.pht('Overview'); 44 + $content[] = pht( 45 + 'Typeahead functions are an advanced feature which allow you to build '. 46 + 'more powerful queries. This document explains functions available '. 47 + 'for the selected control.'. 48 + "\n\n". 49 + 'Note that different controls support //different// functions '. 50 + '(depending on what the control is doing), so these specific functions '. 51 + 'may not work everywhere. You can always check the help for a control '. 52 + 'to review which functions are available for that control.'); 53 + 54 + $table = array(); 55 + 56 + $table_header = array( 57 + pht('Function'), 58 + pht('Token Name'), 59 + pht('Summary'), 60 + ); 61 + $table[] = '| '.implode(' | ', $table_header).' |'; 62 + $table[] = '|---|---|---|'; 63 + 64 + foreach ($functions as $function => $spec) { 65 + $spec = $spec + array( 66 + 'summary' => null, 67 + 'arguments' => null, 68 + ); 69 + 70 + if (idx($spec, 'arguments')) { 71 + $signature = '**'.$function.'(**//'.$spec['arguments'].'//**)**'; 72 + } else { 73 + $signature = '**'.$function.'()**'; 74 + } 75 + 76 + $name = idx($spec, 'name', ''); 77 + $summary = idx($spec, 'summary', ''); 78 + 79 + $table[] = '| '.$signature.' | '.$name.' | '.$summary.' |'; 80 + } 81 + 82 + $table = implode("\n", $table); 83 + $content[] = '= '.pht('Function Quick Reference'); 84 + $content[] = pht( 85 + 'This table briefly describes available functions for this control. '. 86 + 'For details on a particular function, see the corresponding section '. 87 + 'below.'); 88 + $content[] = $table; 89 + 90 + $content[] = '= '.pht('Using Typeahead Functions'); 91 + $content[] = pht( 92 + 'In addition to typing user and project names to build queries, you can '. 93 + 'also type the names of special functions which give you more options '. 94 + 'and the ability to express more complex queries.'. 95 + "\n\n". 96 + 'Functions have an internal name (like `viewer()`) and a '. 97 + 'human-readable name, like `Current Viewer`. In general, you can type '. 98 + 'either one to select the function. You can also click the '. 99 + '{nav icon=search} button on any typeahead control to browse available '. 100 + 'functions and find this documentation.'. 101 + "\n\n". 102 + 'This documentation uses the internal names to make it clear where '. 103 + 'tokens begin and end. Specifically, you will find queries written '. 104 + 'out like this in the documentation: '. 105 + "\n\n". 106 + '> viewer(), alincoln'. 107 + "\n\n". 108 + 'When this query is actually shown in the control, it will look more '. 109 + 'like this:'. 110 + "\n\n". 111 + '> {nav Current Viewer} {nav alincoln (Abraham Lincoln)}'); 112 + 113 + 114 + $middot = "\xC2\xB7"; 115 + foreach ($functions as $function => $spec) { 116 + $arguments = idx($spec, 'arguments', ''); 117 + $name = idx($spec, 'name'); 118 + $content[] = '= '.$function.'('.$arguments.') '.$middot.' '.$name; 119 + $content[] = $spec['description']; 120 + } 121 + 122 + $content = implode("\n\n", $content); 123 + 124 + $content_box = PhabricatorMarkupEngine::renderOneObject( 125 + id(new PhabricatorMarkupOneOff())->setContent($content), 126 + 'default', 127 + $viewer); 128 + 129 + $header = id(new PHUIHeaderView()) 130 + ->setHeader($title); 131 + 132 + $document = id(new PHUIDocumentView()) 133 + ->setHeader($header) 134 + ->setFontKit(PHUIDocumentView::FONT_SOURCE_SANS) 135 + ->appendChild($content_box); 136 + 137 + $crumbs = $this->buildApplicationCrumbs(); 138 + $crumbs->addTextCrumb(pht('Function Help')); 139 + 140 + return $this->buildApplicationPage( 141 + array( 142 + $crumbs, 143 + $document, 144 + ), 145 + array( 146 + 'title' => $title, 147 + )); 148 + } 149 + 150 + }
+21
src/applications/typeahead/controller/PhabricatorTypeaheadModularDatasourceController.php
··· 222 222 $frame, 223 223 ); 224 224 225 + $function_help = null; 226 + if ($source->getAllDatasourceFunctions()) { 227 + $reference_uri = '/typeahead/help/'.get_class($source).'/'; 228 + 229 + $reference_link = phutil_tag( 230 + 'a', 231 + array( 232 + 'href' => $reference_uri, 233 + 'target' => '_blank', 234 + ), 235 + pht('Reference: Advanced Functions')); 236 + 237 + $function_help = array( 238 + id(new PHUIIconView()) 239 + ->setIconFont('fa-book'), 240 + ' ', 241 + $reference_link, 242 + ); 243 + } 244 + 225 245 return $this->newDialog() 226 246 ->setWidth(AphrontDialogView::WIDTH_FORM) 227 247 ->setRenderDialogAsDiv(true) 228 248 ->setTitle($source->getBrowseTitle()) 229 249 ->appendChild($browser) 250 + ->addFooter($function_help) 230 251 ->addCancelButton('/', pht('Close')); 231 252 } 232 253
+8
src/applications/typeahead/datasource/PhabricatorTypeaheadCompositeDatasource.php
··· 117 117 return $this->usable; 118 118 } 119 119 120 + public function getAllDatasourceFunctions() { 121 + $results = parent::getAllDatasourceFunctions(); 122 + foreach ($this->getUsableDatasources() as $source) { 123 + $results += $source->getAllDatasourceFunctions(); 124 + } 125 + return $results; 126 + } 127 + 120 128 protected function didEvaluateTokens(array $results) { 121 129 foreach ($this->getUsableDatasources() as $source) { 122 130 $results = $source->didEvaluateTokens($results);
+8
src/applications/typeahead/datasource/PhabricatorTypeaheadDatasource.php
··· 279 279 /** 280 280 * @task functions 281 281 */ 282 + public function getAllDatasourceFunctions() { 283 + return $this->getDatasourceFunctions(); 284 + } 285 + 286 + 287 + /** 288 + * @task functions 289 + */ 282 290 protected function canEvaluateFunction($function) { 283 291 return $this->shouldStripFunction($function); 284 292 }