2011-01-24 18:00:29 +01:00
|
|
|
<?php
|
|
|
|
|
2012-03-10 00:46:25 +01:00
|
|
|
final class PhabricatorConduitConsoleController
|
2011-01-24 18:00:29 +01:00
|
|
|
extends PhabricatorConduitController {
|
|
|
|
|
2014-04-22 00:32:48 +02:00
|
|
|
public function shouldAllowPublic() {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2015-05-08 21:19:52 +02:00
|
|
|
public function handleRequest(AphrontRequest $request) {
|
|
|
|
$viewer = $this->getViewer();
|
|
|
|
$method_name = $request->getURIData('method');
|
2011-01-31 03:52:29 +01:00
|
|
|
|
2013-07-01 21:36:34 +02:00
|
|
|
$method = id(new PhabricatorConduitMethodQuery())
|
|
|
|
->setViewer($viewer)
|
2015-05-08 21:19:52 +02:00
|
|
|
->withMethods(array($method_name))
|
2013-07-01 21:36:34 +02:00
|
|
|
->executeOne();
|
|
|
|
if (!$method) {
|
2012-04-27 07:25:05 +02:00
|
|
|
return new Aphront404Response();
|
2011-01-24 18:00:29 +01:00
|
|
|
}
|
|
|
|
|
2015-12-13 11:45:08 +01:00
|
|
|
$method->setViewer($viewer);
|
|
|
|
|
2015-05-08 21:19:52 +02:00
|
|
|
$call_uri = '/api/'.$method->getAPIMethodName();
|
2014-04-22 00:32:48 +02:00
|
|
|
|
|
|
|
$errors = array();
|
|
|
|
|
2015-05-08 21:19:52 +02:00
|
|
|
$form = id(new AphrontFormView())
|
|
|
|
->setAction($call_uri)
|
2011-01-31 03:52:29 +01:00
|
|
|
->setUser($request->getUser())
|
2015-05-08 21:19:52 +02:00
|
|
|
->appendRemarkupInstructions(
|
|
|
|
pht(
|
|
|
|
'Enter parameters using **JSON**. For instance, to enter a '.
|
2015-05-22 09:27:56 +02:00
|
|
|
'list, type: `%s`',
|
|
|
|
'["apple", "banana", "cherry"]'));
|
2011-01-24 18:00:29 +01:00
|
|
|
|
2015-04-13 00:59:07 +02:00
|
|
|
$params = $method->getParamTypes();
|
2011-01-24 18:00:29 +01:00
|
|
|
foreach ($params as $param => $desc) {
|
|
|
|
$form->appendChild(
|
|
|
|
id(new AphrontFormTextControl())
|
|
|
|
->setLabel($param)
|
|
|
|
->setName("params[{$param}]")
|
2013-02-05 22:23:05 +01:00
|
|
|
->setCaption($desc));
|
2011-01-24 18:00:29 +01:00
|
|
|
}
|
|
|
|
|
2014-04-22 00:32:48 +02:00
|
|
|
$must_login = !$viewer->isLoggedIn() &&
|
|
|
|
$method->shouldRequireAuthentication();
|
|
|
|
if ($must_login) {
|
|
|
|
$errors[] = pht(
|
|
|
|
'Login Required: This method requires authentication. You must '.
|
|
|
|
'log in before you can make calls to it.');
|
|
|
|
} else {
|
|
|
|
$form
|
|
|
|
->appendChild(
|
|
|
|
id(new AphrontFormSelectControl())
|
2015-05-22 09:27:56 +02:00
|
|
|
->setLabel(pht('Output Format'))
|
2014-04-22 00:32:48 +02:00
|
|
|
->setName('output')
|
|
|
|
->setOptions(
|
|
|
|
array(
|
2015-05-22 09:27:56 +02:00
|
|
|
'human' => pht('Human Readable'),
|
|
|
|
'json' => pht('JSON'),
|
2014-04-22 00:32:48 +02:00
|
|
|
)))
|
|
|
|
->appendChild(
|
|
|
|
id(new AphrontFormSubmitControl())
|
|
|
|
->addCancelButton($this->getApplicationURI())
|
|
|
|
->setValue(pht('Call Method')));
|
|
|
|
}
|
|
|
|
|
|
|
|
$header = id(new PHUIHeaderView())
|
|
|
|
->setUser($viewer)
|
2016-04-05 01:30:55 +02:00
|
|
|
->setHeader($method->getAPIMethodName())
|
|
|
|
->setHeaderIcon('fa-tty');
|
2011-01-24 18:00:29 +01:00
|
|
|
|
2013-09-25 20:23:29 +02:00
|
|
|
$form_box = id(new PHUIObjectBoxView())
|
2015-05-08 21:19:52 +02:00
|
|
|
->setHeaderText(pht('Call Method'))
|
2016-04-05 01:30:55 +02:00
|
|
|
->setBackground(PHUIObjectBoxView::BLUE_PROPERTY)
|
[Redesign] Add Table, Collapse support to ObjectBox
Summary: Converts most all tables to be directly set via `setTable` to an ObjectBox. I think this path is more flexible design wise, as we can change the box based on children, and not just CSS. We also already do this with PropertyList, Forms, ObjectList, and Header. `setCollapsed` is added to ObjectBox to all children objects to bleed to the edges (like diffs).
Test Plan: I did a grep of `appendChild($table)` as well as searches for `PHUIObjectBoxView`, also with manual opening of hundreds of files. I'm sure I missed 5-8 places. If you just appendChild($table) nothing breaks, it just looks a little funny.
Reviewers: epriestley, btrahan
Subscribers: Korvin, epriestley
Differential Revision: https://secure.phabricator.com/D12955
2015-05-20 21:43:34 +02:00
|
|
|
->setForm($form);
|
2015-04-13 01:26:57 +02:00
|
|
|
|
2015-05-08 21:19:52 +02:00
|
|
|
$properties = $this->buildMethodProperties($method);
|
|
|
|
|
|
|
|
$info_box = id(new PHUIObjectBoxView())
|
|
|
|
->setHeaderText(pht('API Method: %s', $method->getAPIMethodName()))
|
|
|
|
->setFormErrors($errors)
|
2016-04-05 01:30:55 +02:00
|
|
|
->setBackground(PHUIObjectBoxView::BLUE_PROPERTY)
|
2015-05-08 21:19:52 +02:00
|
|
|
->appendChild($properties);
|
|
|
|
|
2013-07-01 21:36:34 +02:00
|
|
|
$crumbs = $this->buildApplicationCrumbs();
|
2013-12-19 02:47:34 +01:00
|
|
|
$crumbs->addTextCrumb($method->getAPIMethodName());
|
2016-04-05 01:30:55 +02:00
|
|
|
$crumbs->setBorder(true);
|
|
|
|
|
2021-07-16 18:53:10 +02:00
|
|
|
$documentation_pages = $method->getDocumentationPages($viewer);
|
|
|
|
|
|
|
|
$documentation_view = $this->newDocumentationView(
|
|
|
|
$method,
|
|
|
|
$documentation_pages);
|
|
|
|
|
2016-04-05 01:30:55 +02:00
|
|
|
$view = id(new PHUITwoColumnView())
|
|
|
|
->setHeader($header)
|
|
|
|
->setFooter(array(
|
2021-07-16 18:53:10 +02:00
|
|
|
|
|
|
|
id(new PhabricatorAnchorView())
|
|
|
|
->setAnchorName('overview'),
|
2016-04-05 01:30:55 +02:00
|
|
|
$info_box,
|
2021-07-16 18:53:10 +02:00
|
|
|
|
|
|
|
id(new PhabricatorAnchorView())
|
|
|
|
->setAnchorName('documentation'),
|
|
|
|
$documentation_view,
|
|
|
|
|
|
|
|
id(new PhabricatorAnchorView())
|
|
|
|
->setAnchorName('call'),
|
2016-04-05 01:30:55 +02:00
|
|
|
$form_box,
|
2021-07-16 18:53:10 +02:00
|
|
|
|
|
|
|
id(new PhabricatorAnchorView())
|
|
|
|
->setAnchorName('examples'),
|
2016-04-05 01:30:55 +02:00
|
|
|
$this->renderExampleBox($method, null),
|
2011-01-24 18:00:29 +01:00
|
|
|
));
|
2016-04-05 01:30:55 +02:00
|
|
|
|
|
|
|
$title = $method->getAPIMethodName();
|
|
|
|
|
2021-07-16 18:53:10 +02:00
|
|
|
$nav = $this->newNavigationView($method, $documentation_pages);
|
|
|
|
|
2016-04-05 01:30:55 +02:00
|
|
|
return $this->newPage()
|
|
|
|
->setTitle($title)
|
|
|
|
->setCrumbs($crumbs)
|
2021-07-16 18:53:10 +02:00
|
|
|
->setNavigation($nav)
|
2016-04-05 01:30:55 +02:00
|
|
|
->appendChild($view);
|
2011-01-24 18:00:29 +01:00
|
|
|
}
|
|
|
|
|
2021-07-16 18:53:10 +02:00
|
|
|
private function newDocumentationView(
|
|
|
|
ConduitAPIMethod $method,
|
|
|
|
array $documentation_pages) {
|
|
|
|
assert_instances_of($documentation_pages, 'ConduitAPIDocumentationPage');
|
|
|
|
|
|
|
|
$viewer = $this->getViewer();
|
|
|
|
|
|
|
|
$description_properties = id(new PHUIPropertyListView());
|
|
|
|
|
|
|
|
$description_properties->addTextContent(
|
|
|
|
new PHUIRemarkupView($viewer, $method->getMethodDescription()));
|
|
|
|
|
|
|
|
$description_box = id(new PHUIObjectBoxView())
|
|
|
|
->setHeaderText(pht('Method Description'))
|
|
|
|
->setBackground(PHUIObjectBoxView::BLUE_PROPERTY)
|
|
|
|
->appendChild($description_properties);
|
|
|
|
|
|
|
|
$view = array();
|
|
|
|
$view[] = $description_box;
|
|
|
|
|
|
|
|
foreach ($documentation_pages as $page) {
|
|
|
|
$view[] = $page->newView();
|
|
|
|
}
|
|
|
|
|
|
|
|
return $view;
|
|
|
|
}
|
|
|
|
|
|
|
|
private function newNavigationView(
|
|
|
|
ConduitAPIMethod $method,
|
|
|
|
array $documentation_pages) {
|
|
|
|
assert_instances_of($documentation_pages, 'ConduitAPIDocumentationPage');
|
|
|
|
|
|
|
|
$console_uri = urisprintf(
|
|
|
|
'/method/%s/',
|
|
|
|
$method->getAPIMethodName());
|
|
|
|
$console_uri = $this->getApplicationURI($console_uri);
|
|
|
|
$console_uri = new PhutilURI($console_uri);
|
|
|
|
|
|
|
|
$nav = id(new AphrontSideNavFilterView())
|
|
|
|
->setBaseURI($console_uri);
|
|
|
|
|
|
|
|
$nav->selectFilter(null);
|
|
|
|
|
|
|
|
$nav->newLink('overview')
|
|
|
|
->setHref('#overview')
|
|
|
|
->setName(pht('Overview'))
|
|
|
|
->setIcon('fa-list');
|
|
|
|
|
|
|
|
$nav->newLink('documentation')
|
|
|
|
->setHref('#documentation')
|
|
|
|
->setName(pht('Documentation'))
|
|
|
|
->setIcon('fa-book');
|
|
|
|
|
|
|
|
foreach ($documentation_pages as $page) {
|
|
|
|
$nav->newLink($page->getAnchor())
|
|
|
|
->setHref('#'.$page->getAnchor())
|
|
|
|
->setName($page->getName())
|
|
|
|
->setIcon($page->getIconIcon())
|
|
|
|
->setIndented(true);
|
|
|
|
}
|
|
|
|
|
|
|
|
$nav->newLink('call')
|
|
|
|
->setHref('#call')
|
|
|
|
->setName(pht('Call Method'))
|
|
|
|
->setIcon('fa-play');
|
|
|
|
|
|
|
|
$nav->newLink('examples')
|
|
|
|
->setHref('#examples')
|
|
|
|
->setName(pht('Examples'))
|
|
|
|
->setIcon('fa-folder-open-o');
|
|
|
|
|
|
|
|
return $nav;
|
|
|
|
}
|
|
|
|
|
2015-05-08 21:19:52 +02:00
|
|
|
private function buildMethodProperties(ConduitAPIMethod $method) {
|
|
|
|
$viewer = $this->getViewer();
|
|
|
|
|
|
|
|
$view = id(new PHUIPropertyListView());
|
|
|
|
|
2016-04-20 17:48:11 +02:00
|
|
|
$status = $method->getMethodStatus();
|
|
|
|
$reason = $method->getMethodStatusDescription();
|
|
|
|
|
|
|
|
switch ($status) {
|
|
|
|
case ConduitAPIMethod::METHOD_STATUS_UNSTABLE:
|
|
|
|
$stability_icon = 'fa-exclamation-triangle yellow';
|
|
|
|
$stability_label = pht('Unstable Method');
|
|
|
|
$stability_info = nonempty(
|
|
|
|
$reason,
|
|
|
|
pht(
|
|
|
|
'This method is new and unstable. Its interface is subject '.
|
|
|
|
'to change.'));
|
|
|
|
break;
|
|
|
|
case ConduitAPIMethod::METHOD_STATUS_DEPRECATED:
|
|
|
|
$stability_icon = 'fa-exclamation-triangle red';
|
|
|
|
$stability_label = pht('Deprecated Method');
|
|
|
|
$stability_info = nonempty($reason, pht('This method is deprecated.'));
|
|
|
|
break;
|
2017-01-08 21:54:39 +01:00
|
|
|
case ConduitAPIMethod::METHOD_STATUS_FROZEN:
|
|
|
|
$stability_icon = 'fa-archive grey';
|
|
|
|
$stability_label = pht('Frozen Method');
|
|
|
|
$stability_info = nonempty(
|
|
|
|
$reason,
|
|
|
|
pht('This method is frozen and will eventually be deprecated.'));
|
|
|
|
break;
|
2016-04-20 17:48:11 +02:00
|
|
|
default:
|
|
|
|
$stability_label = null;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ($stability_label) {
|
|
|
|
$view->addProperty(
|
|
|
|
pht('Stability'),
|
|
|
|
array(
|
|
|
|
id(new PHUIIconView())->setIcon($stability_icon),
|
|
|
|
' ',
|
|
|
|
phutil_tag('strong', array(), $stability_label.':'),
|
|
|
|
' ',
|
|
|
|
$stability_info,
|
|
|
|
));
|
|
|
|
}
|
|
|
|
|
2023-02-11 11:10:58 +01:00
|
|
|
$view->addProperty(
|
|
|
|
pht('Summary'),
|
|
|
|
$method->getMethodSummary());
|
|
|
|
|
2015-05-08 21:19:52 +02:00
|
|
|
$view->addProperty(
|
|
|
|
pht('Returns'),
|
|
|
|
$method->getReturnType());
|
|
|
|
|
|
|
|
$error_types = $method->getErrorTypes();
|
|
|
|
$error_types['ERR-CONDUIT-CORE'] = pht('See error message for details.');
|
|
|
|
$error_description = array();
|
|
|
|
foreach ($error_types as $error => $meaning) {
|
|
|
|
$error_description[] = hsprintf(
|
|
|
|
'<li><strong>%s:</strong> %s</li>',
|
|
|
|
$error,
|
|
|
|
$meaning);
|
|
|
|
}
|
|
|
|
$error_description = phutil_tag('ul', array(), $error_description);
|
|
|
|
|
|
|
|
$view->addProperty(
|
|
|
|
pht('Errors'),
|
|
|
|
$error_description);
|
|
|
|
|
2016-04-03 17:25:02 +02:00
|
|
|
$scope = $method->getRequiredScope();
|
|
|
|
switch ($scope) {
|
|
|
|
case ConduitAPIMethod::SCOPE_ALWAYS:
|
|
|
|
$oauth_icon = 'fa-globe green';
|
|
|
|
$oauth_description = pht(
|
|
|
|
'OAuth clients may always call this method.');
|
|
|
|
break;
|
|
|
|
case ConduitAPIMethod::SCOPE_NEVER:
|
|
|
|
$oauth_icon = 'fa-ban red';
|
|
|
|
$oauth_description = pht(
|
|
|
|
'OAuth clients may never call this method.');
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
$oauth_icon = 'fa-unlock-alt blue';
|
|
|
|
$oauth_description = pht(
|
|
|
|
'OAuth clients may call this method after requesting access to '.
|
|
|
|
'the "%s" scope.',
|
|
|
|
$scope);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
$view->addProperty(
|
|
|
|
pht('OAuth Scope'),
|
|
|
|
array(
|
|
|
|
id(new PHUIIconView())->setIcon($oauth_icon),
|
|
|
|
' ',
|
|
|
|
$oauth_description,
|
|
|
|
));
|
|
|
|
|
2015-05-08 21:19:52 +02:00
|
|
|
return $view;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2011-01-24 18:00:29 +01:00
|
|
|
}
|