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

Modernize most Conduit console interfaces

Summary:
Ref T603. Ref T2625.

Long chain of "doing the right thing" here: I want to clean this up, so I can clean up the Conduit logs, so I can add a setup issue for deprecated method calls, so I can remove deprecated methods, so I can get rid of `DifferentialRevisionListData`, so I can make Differntial policy-aware.

Adds modern infrastructure and UI to all of the Conduit interfaces (except only partially for the logs, that will be the next diff).

Test Plan:
{F48201}
{F48202}
{F48203}
{F48204}
{F48206}

This will get further updates in the next diff:

{F48205}

Reviewers: btrahan, chad

Reviewed By: chad

CC: aran

Maniphest Tasks: T603, T2625

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

+510 -224
+14 -1
src/__phutil_library_map__.php
··· 921 921 'PhabricatorConduitListController' => 'applications/conduit/controller/PhabricatorConduitListController.php', 922 922 'PhabricatorConduitLogController' => 'applications/conduit/controller/PhabricatorConduitLogController.php', 923 923 'PhabricatorConduitMethodCallLog' => 'applications/conduit/storage/PhabricatorConduitMethodCallLog.php', 924 + 'PhabricatorConduitMethodQuery' => 'applications/conduit/query/PhabricatorConduitMethodQuery.php', 925 + 'PhabricatorConduitSearchEngine' => 'applications/conduit/query/PhabricatorConduitSearchEngine.php', 924 926 'PhabricatorConduitTokenController' => 'applications/conduit/controller/PhabricatorConduitTokenController.php', 925 927 'PhabricatorConfigAllController' => 'applications/config/controller/PhabricatorConfigAllController.php', 926 928 'PhabricatorConfigController' => 'applications/config/controller/PhabricatorConfigController.php', ··· 2009 2011 'CelerityResourceController' => 'PhabricatorController', 2010 2012 'CelerityResourceGraph' => 'AbstractDirectedGraph', 2011 2013 'CelerityResourceTransformerTestCase' => 'PhabricatorTestCase', 2014 + 'ConduitAPIMethod' => 2015 + array( 2016 + 0 => 'Phobject', 2017 + 1 => 'PhabricatorPolicyInterface', 2018 + ), 2012 2019 'ConduitAPI_arcanist_Method' => 'ConduitAPIMethod', 2013 2020 'ConduitAPI_arcanist_projectinfo_Method' => 'ConduitAPI_arcanist_Method', 2014 2021 'ConduitAPI_audit_Method' => 'ConduitAPIMethod', ··· 2807 2814 'PhabricatorConduitConsoleController' => 'PhabricatorConduitController', 2808 2815 'PhabricatorConduitController' => 'PhabricatorController', 2809 2816 'PhabricatorConduitDAO' => 'PhabricatorLiskDAO', 2810 - 'PhabricatorConduitListController' => 'PhabricatorConduitController', 2817 + 'PhabricatorConduitListController' => 2818 + array( 2819 + 0 => 'PhabricatorConduitController', 2820 + 1 => 'PhabricatorApplicationSearchResultsControllerInterface', 2821 + ), 2811 2822 'PhabricatorConduitLogController' => 'PhabricatorConduitController', 2812 2823 'PhabricatorConduitMethodCallLog' => 'PhabricatorConduitDAO', 2824 + 'PhabricatorConduitMethodQuery' => 'PhabricatorCursorPagedPolicyAwareQuery', 2825 + 'PhabricatorConduitSearchEngine' => 'PhabricatorApplicationSearchEngine', 2813 2826 'PhabricatorConduitTokenController' => 'PhabricatorConduitController', 2814 2827 'PhabricatorConfigAllController' => 'PhabricatorConfigController', 2815 2828 'PhabricatorConfigController' => 'PhabricatorController',
+1 -1
src/applications/conduit/application/PhabricatorApplicationConduit.php
··· 38 38 public function getRoutes() { 39 39 return array( 40 40 '/conduit/' => array( 41 - '' => 'PhabricatorConduitListController', 41 + '(?:query/(?P<queryKey>[^/]+)/)?' => 'PhabricatorConduitListController', 42 42 'method/(?P<method>[^/]+)/' => 'PhabricatorConduitConsoleController', 43 43 'log/' => 'PhabricatorConduitLogController', 44 44 'log/view/(?P<view>[^/]+)/' => 'PhabricatorConduitLogController',
+28 -3
src/applications/conduit/controller/PhabricatorConduitAPIController.php
··· 354 354 } 355 355 356 356 $param_table = new AphrontTableView($param_rows); 357 + $param_table->setDeviceReadyTable(true); 357 358 $param_table->setColumnClasses( 358 359 array( 359 360 'header', ··· 369 370 } 370 371 371 372 $result_table = new AphrontTableView($result_rows); 373 + $result_table->setDeviceReadyTable(true); 372 374 $result_table->setColumnClasses( 373 375 array( 374 376 'header', ··· 383 385 $result_panel->setHeader('Method Result'); 384 386 $result_panel->appendChild($result_table); 385 387 386 - return $this->buildStandardPageResponse( 388 + $param_head = id(new PhabricatorHeaderView()) 389 + ->setHeader(pht('Method Parameters')); 390 + 391 + $result_head = id(new PhabricatorHeaderView()) 392 + ->setHeader(pht('Method Result')); 393 + 394 + $method_uri = $this->getApplicationURI('method/'.$method.'/'); 395 + 396 + $crumbs = $this->buildApplicationCrumbs(); 397 + $crumbs 398 + ->addCrumb( 399 + id(new PhabricatorCrumbView()) 400 + ->setName($method) 401 + ->setHref($method_uri)) 402 + ->addCrumb( 403 + id(new PhabricatorCrumbView()) 404 + ->setName(pht('Call'))); 405 + 406 + return $this->buildApplicationPage( 387 407 array( 388 - $param_panel, 389 - $result_panel, 408 + $crumbs, 409 + $param_head, 410 + $param_table, 411 + $result_head, 412 + $result_table, 390 413 ), 391 414 array( 392 415 'title' => 'Method Call Result', 416 + 'device' => true, 417 + 'dust' => true, 393 418 )); 394 419 } 395 420
+25 -28
src/applications/conduit/controller/PhabricatorConduitConsoleController.php
··· 15 15 public function processRequest() { 16 16 17 17 $request = $this->getRequest(); 18 + $viewer = $request->getUser(); 18 19 19 - $methods = $this->getAllMethods(); 20 - if (empty($methods[$this->method])) { 20 + $method = id(new PhabricatorConduitMethodQuery()) 21 + ->setViewer($viewer) 22 + ->withMethods(array($this->method)) 23 + ->executeOne(); 24 + 25 + if (!$method) { 21 26 return new Aphront404Response(); 22 27 } 23 - $this->setFilter('method/'.$this->method); 24 28 25 - $method_class = $methods[$this->method]; 26 - $method_object = newv($method_class, array()); 27 - 28 - $status = $method_object->getMethodStatus(); 29 - $reason = $method_object->getMethodStatusDescription(); 29 + $status = $method->getMethodStatus(); 30 + $reason = $method->getMethodStatusDescription(); 30 31 31 32 $status_view = null; 32 33 if ($status != ConduitAPIMethod::METHOD_STATUS_STABLE) { ··· 49 50 } 50 51 } 51 52 52 - $error_types = $method_object->defineErrorTypes(); 53 + $error_types = $method->defineErrorTypes(); 53 54 if ($error_types) { 54 55 $error_description = array(); 55 56 foreach ($error_types as $error => $meaning) { ··· 68 69 ->setUser($request->getUser()) 69 70 ->setAction('/api/'.$this->method) 70 71 ->addHiddenInput('allowEmptyParams', 1) 72 + ->setFlexible(true) 71 73 ->appendChild( 72 74 id(new AphrontFormStaticControl()) 73 75 ->setLabel('Description') 74 - ->setValue($method_object->getMethodDescription())) 76 + ->setValue($method->getMethodDescription())) 75 77 ->appendChild( 76 78 id(new AphrontFormStaticControl()) 77 79 ->setLabel('Returns') 78 - ->setValue($method_object->defineReturnType())) 80 + ->setValue($method->defineReturnType())) 79 81 ->appendChild( 80 82 id(new AphrontFormMarkupControl()) 81 83 ->setLabel('Errors') ··· 85 87 '<strong>JSON</strong>. For instance, to enter a list, type: '. 86 88 '<tt>["apple", "banana", "cherry"]</tt>')); 87 89 88 - $params = $method_object->defineParamTypes(); 90 + $params = $method->defineParamTypes(); 89 91 foreach ($params as $param => $desc) { 90 92 $form->appendChild( 91 93 id(new AphrontFormTextControl()) ··· 106 108 ))) 107 109 ->appendChild( 108 110 id(new AphrontFormSubmitControl()) 111 + ->addCancelButton($this->getApplicationURI()) 109 112 ->setValue('Call Method')); 110 113 111 - $panel = new AphrontPanelView(); 112 - $panel->setHeader('Conduit API: '.$this->method); 113 - $panel->appendChild($form); 114 - $panel->setWidth(AphrontPanelView::WIDTH_FULL); 114 + $crumbs = $this->buildApplicationCrumbs(); 115 + $crumbs->addCrumb( 116 + id(new PhabricatorCrumbView()) 117 + ->setName($method->getAPIMethodName())); 115 118 116 - return $this->buildStandardPageResponse( 119 + return $this->buildApplicationPage( 117 120 array( 121 + $crumbs, 118 122 $status_view, 119 - $panel, 123 + $form, 120 124 ), 121 125 array( 122 - 'title' => 'Conduit Console - '.$this->method, 126 + 'title' => $method->getAPIMethodName(), 127 + 'device' => true, 128 + 'dust' => true, 123 129 )); 124 130 } 125 131 126 - private function getAllMethods() { 127 - $classes = $this->getAllMethodImplementationClasses(); 128 - $methods = array(); 129 - foreach ($classes as $class) { 130 - $name = ConduitAPIMethod::getAPIMethodNameFromClassName($class); 131 - $methods[$name] = $class; 132 - } 133 - return $methods; 134 - } 135 132 }
+13 -108
src/applications/conduit/controller/PhabricatorConduitController.php
··· 5 5 */ 6 6 abstract class PhabricatorConduitController extends PhabricatorController { 7 7 8 - private $filter; 9 - protected $showSideNav; 8 + protected function buildSideNavView() { 9 + $viewer = $this->getRequest()->getUser(); 10 10 11 - public function buildStandardPageResponse($view, array $data) { 12 - $page = $this->buildStandardPageView(); 11 + $nav = new AphrontSideNavFilterView(); 12 + $nav->setBaseURI(new PhutilURI($this->getApplicationURI())); 13 13 14 - $page->setApplicationName('Conduit'); 15 - $page->setBaseURI('/conduit/'); 16 - $page->setTitle(idx($data, 'title')); 17 - $page->setGlyph("\xE2\x87\xB5"); 14 + id(new PhabricatorConduitSearchEngine()) 15 + ->setViewer($viewer) 16 + ->addNavigationItems($nav->getMenu()); 18 17 19 - if ($this->showSideNav()) { 18 + $nav->addLabel('Logs'); 19 + $nav->addFilter('log', pht('Call Logs')); 20 20 21 - $nav = new AphrontSideNavFilterView(); 22 - $nav->setBaseURI(new PhutilURI('/conduit/')); 23 - $method_filters = $this->getMethodFilters(); 24 - foreach ($method_filters as $group => $methods) { 25 - $nav->addLabel($group); 26 - foreach ($methods as $method) { 27 - $method_name = $method['full_name']; 21 + $nav->selectFilter(null); 28 22 29 - $display_name = $method_name; 30 - switch ($method['status']) { 31 - case ConduitAPIMethod::METHOD_STATUS_DEPRECATED: 32 - $display_name = '('.$display_name.')'; 33 - break; 34 - } 35 - 36 - $nav->addFilter('method/'.$method_name, 37 - $display_name); 38 - } 39 - } 40 - $nav->selectFilter($this->getFilter()); 41 - $nav->appendChild($view); 42 - $body = $nav; 43 - } else { 44 - $body = $view; 45 - } 46 - $page->appendChild($body); 47 - 48 - $response = new AphrontWebpageResponse(); 49 - return $response->setContent($page->render()); 23 + return $nav; 50 24 } 51 25 52 - private function getFilter() { 53 - return $this->filter; 54 - } 55 - 56 - protected function setFilter($filter) { 57 - $this->filter = $filter; 58 - return $this; 59 - } 60 - 61 - private function showSideNav() { 62 - return $this->showSideNav !== false; 26 + protected function buildApplicationMenu() { 27 + return $this->buildSideNavView()->getMenu(); 63 28 } 64 29 65 - protected function setShowSideNav($show_side_nav) { 66 - $this->showSideNav = $show_side_nav; 67 - return $this; 68 - } 69 - 70 - protected function getAllMethodImplementationClasses() { 71 - $classes = id(new PhutilSymbolLoader()) 72 - ->setAncestorClass('ConduitAPIMethod') 73 - ->setType('class') 74 - ->setConcreteOnly(true) 75 - ->selectSymbolsWithoutLoading(); 76 - 77 - return array_values(ipull($classes, 'name')); 78 - } 79 - 80 - protected function getMethodFilters() { 81 - $classes = $this->getAllMethodImplementationClasses(); 82 - $method_names = array(); 83 - foreach ($classes as $method_class) { 84 - $method_name = ConduitAPIMethod::getAPIMethodNameFromClassName( 85 - $method_class); 86 - $group_name = head(explode('.', $method_name)); 87 - 88 - $method_object = newv($method_class, array()); 89 - 90 - $application = $method_object->getApplication(); 91 - if ($application && !$application->isInstalled()) { 92 - continue; 93 - } 94 - 95 - $status = $method_object->getMethodStatus(); 96 - 97 - $key = sprintf( 98 - '%02d %s %s', 99 - $this->getOrderForMethodStatus($status), 100 - $group_name, 101 - $method_name); 102 - 103 - $method_names[$key] = array( 104 - 'full_name' => $method_name, 105 - 'group_name' => $group_name, 106 - 'status' => $status, 107 - 'description' => $method_object->getMethodDescription(), 108 - ); 109 - } 110 - ksort($method_names); 111 - $method_names = igroup($method_names, 'group_name'); 112 - ksort($method_names); 113 - 114 - return $method_names; 115 - } 116 - 117 - private function getOrderForMethodStatus($status) { 118 - $map = array( 119 - ConduitAPIMethod::METHOD_STATUS_STABLE => 0, 120 - ConduitAPIMethod::METHOD_STATUS_UNSTABLE => 1, 121 - ConduitAPIMethod::METHOD_STATUS_DEPRECATED => 2, 122 - ); 123 - return idx($map, $status, 0); 124 - } 125 30 126 31 }
+62 -62
src/applications/conduit/controller/PhabricatorConduitListController.php
··· 4 4 * @group conduit 5 5 */ 6 6 final class PhabricatorConduitListController 7 - extends PhabricatorConduitController { 7 + extends PhabricatorConduitController 8 + implements PhabricatorApplicationSearchResultsControllerInterface { 9 + 10 + private $queryKey; 11 + 12 + public function willProcessRequest(array $data) { 13 + $this->queryKey = idx($data, 'queryKey'); 14 + } 8 15 9 16 public function processRequest() { 10 - $method_groups = $this->getMethodFilters(); 11 - $rows = array(); 12 - foreach ($method_groups as $group => $methods) { 13 - foreach ($methods as $info) { 14 - switch ($info['status']) { 15 - case ConduitAPIMethod::METHOD_STATUS_DEPRECATED: 16 - $status = 'Deprecated'; 17 - break; 18 - case ConduitAPIMethod::METHOD_STATUS_UNSTABLE: 19 - $status = 'Unstable'; 20 - break; 21 - default: 22 - $status = null; 23 - break; 17 + $request = $this->getRequest(); 18 + $controller = id(new PhabricatorApplicationSearchController($request)) 19 + ->setQueryKey($this->queryKey) 20 + ->setSearchEngine(new PhabricatorConduitSearchEngine()) 21 + ->setNavigation($this->buildSideNavView()); 22 + return $this->delegateToController($controller); 23 + } 24 + 25 + public function renderResultsList(array $methods) { 26 + assert_instances_of($methods, 'ConduitAPIMethod'); 27 + 28 + $viewer = $this->getRequest()->getUser(); 29 + 30 + $out = array(); 31 + 32 + $last = null; 33 + $list = null; 34 + foreach ($methods as $method) { 35 + $app = $method->getApplicationName(); 36 + if ($app !== $last) { 37 + $last = $app; 38 + if ($list) { 39 + $out[] = $list; 24 40 } 41 + $list = id(new PhabricatorObjectItemListView()); 25 42 26 - $rows[] = array( 27 - $group, 28 - phutil_tag( 29 - 'a', 30 - array( 31 - 'href' => '/conduit/method/'.$info['full_name'], 32 - ), 33 - $info['full_name']), 34 - $info['description'], 35 - $status, 36 - ); 37 - $group = null; 43 + $app_object = $method->getApplication(); 44 + if ($app_object) { 45 + $app_name = $app_object->getName(); 46 + } else { 47 + $app_name = $app; 48 + } 38 49 } 39 - } 40 50 41 - $table = new AphrontTableView($rows); 42 - $table->setHeaders(array( 43 - 'Group', 44 - 'Name', 45 - 'Description', 46 - 'Status', 47 - )); 48 - $table->setColumnClasses(array( 49 - 'pri', 50 - 'pri', 51 - 'wide', 52 - null, 53 - )); 51 + $method_name = $method->getAPIMethodName(); 54 52 55 - $panel = new AphrontPanelView(); 56 - $panel->setHeader('Conduit Methods'); 57 - $panel->appendChild($table); 58 - $panel->setWidth(AphrontPanelView::WIDTH_FULL); 53 + $item = id(new PhabricatorObjectItemView()) 54 + ->setHeader($method_name) 55 + ->setHref($this->getApplicationURI('method/'.$method_name.'/')) 56 + ->addAttribute($method->getMethodDescription()); 59 57 60 - $utils = new AphrontPanelView(); 61 - $utils->setHeader('Utilities'); 62 - $utils->appendChild(hsprintf( 63 - '<ul>'. 64 - '<li><a href="/conduit/log/">Log</a> - Conduit Method Calls</li>'. 65 - '<li><a href="/conduit/token/">Token</a> - Certificate Install</li>'. 66 - '</ul>')); 67 - $utils->setWidth(AphrontPanelView::WIDTH_FULL); 58 + switch ($method->getMethodStatus()) { 59 + case ConduitAPIMethod::METHOD_STATUS_STABLE: 60 + break; 61 + case ConduitAPIMethod::METHOD_STATUS_UNSTABLE: 62 + $item->addIcon('warning-grey', pht('Unstable')); 63 + $item->setBarColor('yellow'); 64 + break; 65 + case ConduitAPIMethod::METHOD_STATUS_DEPRECATED: 66 + $item->addIcon('warning', pht('Deprecated')); 67 + $item->setBarColor('red'); 68 + break; 69 + } 70 + 71 + $list->addItem($item); 72 + } 68 73 69 - $this->setShowSideNav(false); 74 + if ($list) { 75 + $out[] = $list; 76 + } 70 77 71 - return $this->buildStandardPageResponse( 72 - array( 73 - $panel, 74 - $utils, 75 - ), 76 - array( 77 - 'title' => 'Conduit Console', 78 - )); 78 + return $out; 79 79 } 80 80 81 81 }
+9 -3
src/applications/conduit/controller/PhabricatorConduitLogController.php
··· 41 41 $panel->appendChild($table); 42 42 $panel->appendChild($pager); 43 43 44 - $this->setShowSideNav(false); 44 + $crumbs = $this->buildApplicationCrumbs(); 45 + $crumbs->addCrumb( 46 + id(new PhabricatorCrumbView()) 47 + ->setName(pht('Call Logs'))); 45 48 46 - return $this->buildStandardPageResponse( 47 - $panel, 49 + return $this->buildApplicationPage( 50 + array( 51 + $crumbs, 52 + $panel, 53 + ), 48 54 array( 49 55 'title' => 'Conduit Logs', 50 56 ));
+30 -16
src/applications/conduit/controller/PhabricatorConduitTokenController.php
··· 28 28 ->setToken(Filesystem::readRandomCharacters(40)) 29 29 ->save(); 30 30 31 - $panel = new AphrontPanelView(); 32 - $panel->setHeader('Certificate Install Token'); 33 - $panel->setWidth(AphrontPanelView::WIDTH_FORM); 31 + unset($unguarded); 34 32 35 - $panel->appendChild(hsprintf( 36 - '<p class="aphront-form-instructions">Copy and paste this token into '. 37 - 'the prompt given to you by "arc install-certificate":</p>'. 38 - '<p style="padding: 0 0 1em 4em;">'. 39 - '<strong>%s</strong>'. 40 - '</p>'. 41 - '<p class="aphront-form-instructions">arc will then complete the '. 42 - 'install process for you.</p>', 43 - $token->getToken())); 33 + $pre_instructions = pht( 34 + 'Copy and paste this token into the prompt given to you by '. 35 + '`arc install-certificate`'); 44 36 45 - $this->setShowSideNav(false); 37 + $post_instructions = pht( 38 + 'After you copy and paste this token, `arc` will complete '. 39 + 'the certificate install process for you.'); 46 40 47 - return $this->buildStandardPageResponse( 48 - $panel, 41 + $form = id(new AphrontFormView()) 42 + ->setUser($user) 43 + ->appendRemarkupInstructions($pre_instructions) 44 + ->appendChild( 45 + id(new AphrontFormTextAreaControl()) 46 + ->setLabel(pht('Token')) 47 + ->setHeight(AphrontFormTextAreaControl::HEIGHT_VERY_SHORT) 48 + ->setValue($token->getToken())) 49 + ->appendRemarkupInstructions($post_instructions); 50 + 51 + $crumbs = $this->buildApplicationCrumbs(); 52 + $crumbs->addCrumb( 53 + id(new PhabricatorCrumbView()) 54 + ->setName(pht('Install Certificate'))); 55 + 56 + return $this->buildApplicationPage( 49 57 array( 50 - 'title' => 'Certificate Install Token', 58 + $crumbs, 59 + $form, 60 + ), 61 + array( 62 + 'title' => pht('Certificate Install Token'), 63 + 'device' => true, 64 + 'dust' => true, 51 65 )); 52 66 } 53 67 }
+55 -1
src/applications/conduit/method/ConduitAPIMethod.php
··· 5 5 * @task status Method Status 6 6 * @group conduit 7 7 */ 8 - abstract class ConduitAPIMethod { 8 + abstract class ConduitAPIMethod 9 + extends Phobject 10 + implements PhabricatorPolicyInterface { 9 11 10 12 const METHOD_STATUS_STABLE = 'stable'; 11 13 const METHOD_STATUS_UNSTABLE = 'unstable'; ··· 19 21 20 22 public function __construct() { 21 23 24 + } 25 + 26 + /** 27 + * This is mostly for compatibility with 28 + * @{class:AphrontCursorPagedPolicyAwareQuery}. 29 + */ 30 + public function getID() { 31 + return $this->getAPIMethodName(); 22 32 } 23 33 24 34 /** ··· 62 72 return self::getAPIMethodNameFromClassName(get_class($this)); 63 73 } 64 74 75 + /** 76 + * Return a key which sorts methods by application name, then method status, 77 + * then method name. 78 + */ 79 + public function getSortOrder() { 80 + $name = $this->getAPIMethodName(); 81 + 82 + $map = array( 83 + ConduitAPIMethod::METHOD_STATUS_STABLE => 0, 84 + ConduitAPIMethod::METHOD_STATUS_UNSTABLE => 1, 85 + ConduitAPIMethod::METHOD_STATUS_DEPRECATED => 2, 86 + ); 87 + $ord = idx($map, $this->getMethodStatus(), 0); 88 + 89 + list($head, $tail) = explode('.', $name, 2); 90 + 91 + return "{$head}.{$ord}.{$tail}"; 92 + } 93 + 94 + public function getApplicationName() { 95 + return head(explode('.', $this->getAPIMethodName(), 2)); 96 + } 97 + 65 98 public static function getClassNameFromAPIMethodName($method_name) { 66 99 $method_fragment = str_replace('.', '_', $method_name); 67 100 return 'ConduitAPI_'.$method_fragment.'_Method'; ··· 127 160 "same URI to identify the install. Edit your .arcconfig or ". 128 161 "phabricator/conf so they agree on the URI for the install."); 129 162 } 163 + } 164 + 165 + 166 + /* -( PhabricatorPolicyInterface )----------------------------------------- */ 167 + 168 + 169 + public function getCapabilities() { 170 + return array( 171 + PhabricatorPolicyCapability::CAN_VIEW, 172 + ); 173 + } 174 + 175 + public function getPolicy($capability) { 176 + return PhabricatorPolicies::POLICY_USER; 177 + } 178 + 179 + public function hasAutomaticCapability($capability, PhabricatorUser $viewer) { 180 + // The policy interface on Conduit calls is currently just to let us hook 181 + // into ApplicationSearch. Calls are always visible (even to logged out 182 + // users). 183 + return true; 130 184 } 131 185 132 186 }
+124
src/applications/conduit/query/PhabricatorConduitMethodQuery.php
··· 1 + <?php 2 + 3 + final class PhabricatorConduitMethodQuery 4 + extends PhabricatorCursorPagedPolicyAwareQuery { 5 + 6 + private $isDeprecated; 7 + private $isStable; 8 + private $isUnstable; 9 + private $applicationNames; 10 + private $nameContains; 11 + private $methods; 12 + 13 + public function withMethods(array $methods) { 14 + $this->methods = $methods; 15 + return $this; 16 + } 17 + 18 + public function withNameContains($name_contains) { 19 + $this->nameContains = $name_contains; 20 + return $this; 21 + } 22 + 23 + public function withApplicationNames(array $application_names) { 24 + $this->applicationNames = $application_names; 25 + return $this; 26 + } 27 + 28 + public function withIsStable($is_stable) { 29 + $this->isStable = $is_stable; 30 + return $this; 31 + } 32 + 33 + public function withIsUnstable($is_unstable) { 34 + $this->isUnstable = $is_unstable; 35 + return $this; 36 + } 37 + 38 + public function withIsDeprecated($is_deprecated) { 39 + $this->isDeprecated = $is_deprecated; 40 + return $this; 41 + } 42 + 43 + public function loadPage() { 44 + $methods = $this->getAllMethods(); 45 + 46 + $methods = $this->filterMethods($methods); 47 + 48 + return $methods; 49 + } 50 + 51 + private function getAllMethods() { 52 + static $methods; 53 + if ($methods === null) { 54 + $methods = id(new PhutilSymbolLoader()) 55 + ->setAncestorClass('ConduitAPIMethod') 56 + ->loadObjects(); 57 + $methods = msort($methods, 'getSortOrder'); 58 + } 59 + return $methods; 60 + } 61 + 62 + private function filterMethods(array $methods) { 63 + foreach ($methods as $key => $method) { 64 + $application = $method->getApplication(); 65 + if (!$application) { 66 + continue; 67 + } 68 + if (!$application->isInstalled()) { 69 + unset($methods[$key]); 70 + } 71 + } 72 + 73 + $status = array( 74 + ConduitAPIMethod::METHOD_STATUS_STABLE => $this->isStable, 75 + ConduitAPIMethod::METHOD_STATUS_DEPRECATED => $this->isDeprecated, 76 + ConduitAPIMethod::METHOD_STATUS_UNSTABLE => $this->isUnstable, 77 + ); 78 + 79 + // Only apply status filters if any of them are set. 80 + if (array_filter($status)) { 81 + foreach ($methods as $key => $method) { 82 + $keep = idx($status, $method->getMethodStatus()); 83 + if (!$keep) { 84 + unset($methods[$key]); 85 + } 86 + } 87 + } 88 + 89 + if ($this->applicationNames) { 90 + $map = array_fuse($this->applicationNames); 91 + foreach ($methods as $key => $method) { 92 + $needle = $method->getApplicationName(); 93 + $needle = phutil_utf8_strtolower($needle); 94 + if (empty($map[$needle])) { 95 + unset($methods[$key]); 96 + } 97 + } 98 + } 99 + 100 + if ($this->nameContains) { 101 + $needle = phutil_utf8_strtolower($this->nameContains); 102 + foreach ($methods as $key => $method) { 103 + $haystack = $method->getAPIMethodName(); 104 + $haystack = phutil_utf8_strtolower($haystack); 105 + if (strpos($haystack, $needle) === false) { 106 + unset($methods[$key]); 107 + } 108 + } 109 + } 110 + 111 + if ($this->methods) { 112 + $map = array_fuse($this->methods); 113 + foreach ($methods as $key => $method) { 114 + $needle = $method->getAPIMethodName(); 115 + if (empty($map[$needle])) { 116 + unset($methods[$key]); 117 + } 118 + } 119 + } 120 + 121 + return $methods; 122 + } 123 + 124 + }
+137
src/applications/conduit/query/PhabricatorConduitSearchEngine.php
··· 1 + <?php 2 + 3 + final class PhabricatorConduitSearchEngine 4 + extends PhabricatorApplicationSearchEngine { 5 + 6 + public function getPageSize(PhabricatorSavedQuery $saved) { 7 + return INF; 8 + } 9 + 10 + public function buildSavedQueryFromRequest(AphrontRequest $request) { 11 + $saved = new PhabricatorSavedQuery(); 12 + 13 + $saved->setParameter('isStable', $request->getStr('isStable')); 14 + $saved->setParameter('isUnstable', $request->getStr('isUnstable')); 15 + $saved->setParameter('isDeprecated', $request->getStr('isDeprecated')); 16 + 17 + $saved->setParameter( 18 + 'applicationNames', 19 + $request->getStrList('applicationNames')); 20 + 21 + $saved->setParameter('nameContains', $request->getStr('nameContains')); 22 + 23 + return $saved; 24 + } 25 + 26 + public function buildQueryFromSavedQuery(PhabricatorSavedQuery $saved) { 27 + $query = id(new PhabricatorConduitMethodQuery()); 28 + 29 + $query->withIsStable($saved->getParameter('isStable')); 30 + $query->withIsUnstable($saved->getParameter('isUnstable')); 31 + $query->withIsDeprecated($saved->getParameter('isDeprecated')); 32 + 33 + $names = $saved->getParameter('applicationNames', array()); 34 + if ($names) { 35 + $query->withApplicationNames($names); 36 + } 37 + 38 + $contains = $saved->getParameter('nameContains'); 39 + if (strlen($contains)) { 40 + $query->withNameContains($contains); 41 + } 42 + 43 + return $query; 44 + } 45 + 46 + public function buildSearchForm( 47 + AphrontFormView $form, 48 + PhabricatorSavedQuery $saved) { 49 + 50 + $form 51 + ->appendChild( 52 + id(new AphrontFormTextControl()) 53 + ->setLabel('Name Contains') 54 + ->setName('nameContains') 55 + ->setValue($saved->getParameter('nameContains'))); 56 + 57 + $names = $saved->getParameter('applicationNames', array()); 58 + $form 59 + ->appendChild( 60 + id(new AphrontFormTextControl()) 61 + ->setLabel('Applications') 62 + ->setName('applicationNames') 63 + ->setValue(implode(', ', $names)) 64 + ->setCaption( 65 + pht('Example: %s', hsprintf('<tt>differential, paste</tt>')))); 66 + 67 + $is_stable = $saved->getParameter('isStable'); 68 + $is_unstable = $saved->getParameter('isUnstable'); 69 + $is_deprecated = $saved->getParameter('isDeprecated'); 70 + $form 71 + ->appendChild( 72 + id(new AphrontFormCheckboxControl()) 73 + ->setLabel('Stability') 74 + ->addCheckbox( 75 + 'isStable', 76 + 1, 77 + hsprintf( 78 + '<strong>%s</strong>: %s', 79 + pht('Stable Methods'), 80 + pht('Show established API methods with stable interfaces.')), 81 + $is_stable) 82 + ->addCheckbox( 83 + 'isUnstable', 84 + 1, 85 + hsprintf( 86 + '<strong>%s</strong>: %s', 87 + pht('Unstable Methods'), 88 + pht('Show new methods which are subject to change.')), 89 + $is_unstable) 90 + ->addCheckbox( 91 + 'isDeprecated', 92 + 1, 93 + hsprintf( 94 + '<strong>%s</strong>: %s', 95 + pht('Deprecated Methods'), 96 + pht( 97 + 'Show old methods which will be deleted in a future '. 98 + 'version of Phabricator.')), 99 + $is_deprecated)); 100 + 101 + 102 + } 103 + 104 + protected function getURI($path) { 105 + return '/conduit/'.$path; 106 + } 107 + 108 + public function getBuiltinQueryNames() { 109 + $names = array( 110 + 'modern' => pht('Modern Methods'), 111 + 'all' => pht('All Methods'), 112 + ); 113 + 114 + return $names; 115 + } 116 + 117 + public function buildSavedQueryFromBuiltin($query_key) { 118 + 119 + $query = $this->newSavedQuery(); 120 + $query->setQueryKey($query_key); 121 + 122 + switch ($query_key) { 123 + case 'modern': 124 + return $query 125 + ->setParameter('isStable', true) 126 + ->setParameter('isUnstable', true); 127 + case 'all': 128 + return $query 129 + ->setParameter('isStable', true) 130 + ->setParameter('isUnstable', true) 131 + ->setParameter('isDeprecated', true); 132 + } 133 + 134 + return parent::buildSavedQueryFromBuiltin($query_key); 135 + } 136 + 137 + }
+2 -1
src/applications/search/controller/PhabricatorApplicationSearchController.php
··· 173 173 174 174 $pager = new AphrontCursorPagerView(); 175 175 $pager->readFromRequest($request); 176 + $pager->setPageSize($engine->getPageSize($saved_query)); 176 177 $objects = $query->setViewer($request->getUser()) 177 178 ->executeWithCursorPager($pager); 178 179 179 180 $list = $parent->renderResultsList($objects); 180 - $list->setNoDataString(pht("No results found for this query.")); 181 181 182 182 $nav->appendChild($list); 183 183 184 184 // TODO: This is a bit hacky. 185 185 if ($list instanceof PhabricatorObjectItemListView) { 186 + $list->setNoDataString(pht("No results found for this query.")); 186 187 $list->setPager($pager); 187 188 } else { 188 189 $nav->appendChild($pager);
+10
src/applications/search/engine/PhabricatorApplicationSearchEngine.php
··· 305 305 ->setLabel($end_name) 306 306 ->setValue($end_str)); 307 307 } 308 + 309 + 310 + /* -( Pagination )--------------------------------------------------------- */ 311 + 312 + 313 + public function getPageSize(PhabricatorSavedQuery $saved) { 314 + return $saved->getParameter('limit', 100); 315 + } 316 + 317 + 308 318 }