Show how to call Conduit API methods from clients
Summary: Fixes T3628. Ref T5955.
Test Plan:
On the method page, you see a generic example:
{F396471}
After making a call, you see a specific example with your parameters:
{F396472}
{F396474}
{F396475}
Reviewers: chad, btrahan
Reviewed By: btrahan
Subscribers: epriestley
Maniphest Tasks: T3628, T5955
Differential Revision: https://secure.phabricator.com/D12770
This commit is contained in:
@@ -39,6 +39,7 @@ return array(
|
|||||||
'rsrc/css/application/base/phabricator-application-launch-view.css' => '16ca323f',
|
'rsrc/css/application/base/phabricator-application-launch-view.css' => '16ca323f',
|
||||||
'rsrc/css/application/base/standard-page-view.css' => 'd3e1abe9',
|
'rsrc/css/application/base/standard-page-view.css' => 'd3e1abe9',
|
||||||
'rsrc/css/application/chatlog/chatlog.css' => '852140ff',
|
'rsrc/css/application/chatlog/chatlog.css' => '852140ff',
|
||||||
|
'rsrc/css/application/conduit/conduit-api.css' => '7bc725c4',
|
||||||
'rsrc/css/application/config/config-options.css' => '7fedf08b',
|
'rsrc/css/application/config/config-options.css' => '7fedf08b',
|
||||||
'rsrc/css/application/config/config-template.css' => '8e6c6fcd',
|
'rsrc/css/application/config/config-template.css' => '8e6c6fcd',
|
||||||
'rsrc/css/application/config/config-welcome.css' => '6abd79be',
|
'rsrc/css/application/config/config-welcome.css' => '6abd79be',
|
||||||
@@ -345,7 +346,6 @@ return array(
|
|||||||
'rsrc/js/application/aphlict/behavior-aphlict-listen.js' => 'b1a59974',
|
'rsrc/js/application/aphlict/behavior-aphlict-listen.js' => 'b1a59974',
|
||||||
'rsrc/js/application/aphlict/behavior-aphlict-status.js' => 'ea681761',
|
'rsrc/js/application/aphlict/behavior-aphlict-status.js' => 'ea681761',
|
||||||
'rsrc/js/application/auth/behavior-persona-login.js' => '9414ff18',
|
'rsrc/js/application/auth/behavior-persona-login.js' => '9414ff18',
|
||||||
'rsrc/js/application/calendar/event-all-day.js' => '712540b4',
|
|
||||||
'rsrc/js/application/config/behavior-reorder-fields.js' => '14a827de',
|
'rsrc/js/application/config/behavior-reorder-fields.js' => '14a827de',
|
||||||
'rsrc/js/application/conpherence/ConpherenceThreadManager.js' => '9e507b59',
|
'rsrc/js/application/conpherence/ConpherenceThreadManager.js' => '9e507b59',
|
||||||
'rsrc/js/application/conpherence/behavior-drag-and-drop-photo.js' => 'cf86d16a',
|
'rsrc/js/application/conpherence/behavior-drag-and-drop-photo.js' => 'cf86d16a',
|
||||||
@@ -508,6 +508,7 @@ return array(
|
|||||||
'aphront-typeahead-control-css' => '0e403212',
|
'aphront-typeahead-control-css' => '0e403212',
|
||||||
'auth-css' => '1e655982',
|
'auth-css' => '1e655982',
|
||||||
'changeset-view-manager' => '58562350',
|
'changeset-view-manager' => '58562350',
|
||||||
|
'conduit-api-css' => '7bc725c4',
|
||||||
'config-options-css' => '7fedf08b',
|
'config-options-css' => '7fedf08b',
|
||||||
'config-welcome-css' => '6abd79be',
|
'config-welcome-css' => '6abd79be',
|
||||||
'conpherence-durable-column-view' => '2e68a92f',
|
'conpherence-durable-column-view' => '2e68a92f',
|
||||||
@@ -584,7 +585,6 @@ return array(
|
|||||||
'javelin-behavior-doorkeeper-tag' => 'e5822781',
|
'javelin-behavior-doorkeeper-tag' => 'e5822781',
|
||||||
'javelin-behavior-durable-column' => '657c2b50',
|
'javelin-behavior-durable-column' => '657c2b50',
|
||||||
'javelin-behavior-error-log' => '6882e80a',
|
'javelin-behavior-error-log' => '6882e80a',
|
||||||
'javelin-behavior-event-all-day' => '712540b4',
|
|
||||||
'javelin-behavior-fancy-datepicker' => '5c0f680f',
|
'javelin-behavior-fancy-datepicker' => '5c0f680f',
|
||||||
'javelin-behavior-global-drag-and-drop' => 'c8e57404',
|
'javelin-behavior-global-drag-and-drop' => 'c8e57404',
|
||||||
'javelin-behavior-herald-rule-editor' => '7ebaeed3',
|
'javelin-behavior-herald-rule-editor' => '7ebaeed3',
|
||||||
|
|||||||
@@ -150,5 +150,9 @@ final class ConduitCall {
|
|||||||
return $method;
|
return $method;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function getMethodImplementation() {
|
||||||
|
return $this->handler;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -21,6 +21,7 @@ final class PhabricatorConduitAPIController
|
|||||||
$method = $this->method;
|
$method = $this->method;
|
||||||
|
|
||||||
$api_request = null;
|
$api_request = null;
|
||||||
|
$method_implementation = null;
|
||||||
|
|
||||||
$log = new PhabricatorConduitMethodCallLog();
|
$log = new PhabricatorConduitMethodCallLog();
|
||||||
$log->setMethod($method);
|
$log->setMethod($method);
|
||||||
@@ -36,6 +37,7 @@ final class PhabricatorConduitAPIController
|
|||||||
list($metadata, $params) = $this->decodeConduitParams($request, $method);
|
list($metadata, $params) = $this->decodeConduitParams($request, $method);
|
||||||
|
|
||||||
$call = new ConduitCall($method, $params);
|
$call = new ConduitCall($method, $params);
|
||||||
|
$method_implementation = $call->getMethodImplementation();
|
||||||
|
|
||||||
$result = null;
|
$result = null;
|
||||||
|
|
||||||
@@ -151,7 +153,8 @@ final class PhabricatorConduitAPIController
|
|||||||
return $this->buildHumanReadableResponse(
|
return $this->buildHumanReadableResponse(
|
||||||
$method,
|
$method,
|
||||||
$api_request,
|
$api_request,
|
||||||
$response->toDictionary());
|
$response->toDictionary(),
|
||||||
|
$method_implementation);
|
||||||
case 'json':
|
case 'json':
|
||||||
default:
|
default:
|
||||||
return id(new AphrontJSONResponse())
|
return id(new AphrontJSONResponse())
|
||||||
@@ -525,7 +528,8 @@ final class PhabricatorConduitAPIController
|
|||||||
private function buildHumanReadableResponse(
|
private function buildHumanReadableResponse(
|
||||||
$method,
|
$method,
|
||||||
ConduitAPIRequest $request = null,
|
ConduitAPIRequest $request = null,
|
||||||
$result = null) {
|
$result = null,
|
||||||
|
ConduitAPIMethod $method_implementation = null) {
|
||||||
|
|
||||||
$param_rows = array();
|
$param_rows = array();
|
||||||
$param_rows[] = array('Method', $this->renderAPIValue($method));
|
$param_rows[] = array('Method', $this->renderAPIValue($method));
|
||||||
@@ -574,11 +578,20 @@ final class PhabricatorConduitAPIController
|
|||||||
->addTextCrumb($method, $method_uri)
|
->addTextCrumb($method, $method_uri)
|
||||||
->addTextCrumb(pht('Call'));
|
->addTextCrumb(pht('Call'));
|
||||||
|
|
||||||
|
$example_panel = null;
|
||||||
|
if ($request && $method_implementation) {
|
||||||
|
$params = $request->getAllParameters();
|
||||||
|
$example_panel = $this->renderExampleBox(
|
||||||
|
$method_implementation,
|
||||||
|
$params);
|
||||||
|
}
|
||||||
|
|
||||||
return $this->buildApplicationPage(
|
return $this->buildApplicationPage(
|
||||||
array(
|
array(
|
||||||
$crumbs,
|
$crumbs,
|
||||||
$param_panel,
|
$param_panel,
|
||||||
$result_panel,
|
$result_panel,
|
||||||
|
$example_panel,
|
||||||
),
|
),
|
||||||
array(
|
array(
|
||||||
'title' => pht('Method Call Result'),
|
'title' => pht('Method Call Result'),
|
||||||
|
|||||||
@@ -3,31 +3,23 @@
|
|||||||
final class PhabricatorConduitConsoleController
|
final class PhabricatorConduitConsoleController
|
||||||
extends PhabricatorConduitController {
|
extends PhabricatorConduitController {
|
||||||
|
|
||||||
private $method;
|
|
||||||
|
|
||||||
public function shouldAllowPublic() {
|
public function shouldAllowPublic() {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function willProcessRequest(array $data) {
|
public function handleRequest(AphrontRequest $request) {
|
||||||
$this->method = $data['method'];
|
$viewer = $this->getViewer();
|
||||||
}
|
$method_name = $request->getURIData('method');
|
||||||
|
|
||||||
public function processRequest() {
|
|
||||||
|
|
||||||
$request = $this->getRequest();
|
|
||||||
$viewer = $request->getUser();
|
|
||||||
|
|
||||||
$method = id(new PhabricatorConduitMethodQuery())
|
$method = id(new PhabricatorConduitMethodQuery())
|
||||||
->setViewer($viewer)
|
->setViewer($viewer)
|
||||||
->withMethods(array($this->method))
|
->withMethods(array($method_name))
|
||||||
->executeOne();
|
->executeOne();
|
||||||
|
|
||||||
if (!$method) {
|
if (!$method) {
|
||||||
return new Aphront404Response();
|
return new Aphront404Response();
|
||||||
}
|
}
|
||||||
|
|
||||||
$can_call_method = false;
|
$call_uri = '/api/'.$method->getAPIMethodName();
|
||||||
|
|
||||||
$status = $method->getMethodStatus();
|
$status = $method->getMethodStatus();
|
||||||
$reason = $method->getMethodStatusDescription();
|
$reason = $method->getMethodStatusDescription();
|
||||||
@@ -48,37 +40,13 @@ final class PhabricatorConduitConsoleController
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
$error_types = $method->getErrorTypes();
|
$form = id(new AphrontFormView())
|
||||||
$error_types['ERR-CONDUIT-CORE'] = pht('See error message for details.');
|
->setAction($call_uri)
|
||||||
$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);
|
|
||||||
|
|
||||||
$form = new AphrontFormView();
|
|
||||||
$form
|
|
||||||
->setUser($request->getUser())
|
->setUser($request->getUser())
|
||||||
->setAction('/api/'.$this->method)
|
->appendRemarkupInstructions(
|
||||||
->appendChild(
|
pht(
|
||||||
id(new AphrontFormStaticControl())
|
'Enter parameters using **JSON**. For instance, to enter a '.
|
||||||
->setLabel('Description')
|
'list, type: `["apple", "banana", "cherry"]`'));
|
||||||
->setValue($method->getMethodDescription()))
|
|
||||||
->appendChild(
|
|
||||||
id(new AphrontFormStaticControl())
|
|
||||||
->setLabel('Returns')
|
|
||||||
->setValue($method->getReturnType()))
|
|
||||||
->appendChild(
|
|
||||||
id(new AphrontFormMarkupControl())
|
|
||||||
->setLabel('Errors')
|
|
||||||
->setValue($error_description))
|
|
||||||
->appendChild(hsprintf(
|
|
||||||
'<p class="aphront-form-instructions">Enter parameters using '.
|
|
||||||
'<strong>JSON</strong>. For instance, to enter a list, type: '.
|
|
||||||
'<tt>["apple", "banana", "cherry"]</tt>'));
|
|
||||||
|
|
||||||
$params = $method->getParamTypes();
|
$params = $method->getParamTypes();
|
||||||
foreach ($params as $param => $desc) {
|
foreach ($params as $param => $desc) {
|
||||||
@@ -117,12 +85,22 @@ final class PhabricatorConduitConsoleController
|
|||||||
->setHeader($method->getAPIMethodName());
|
->setHeader($method->getAPIMethodName());
|
||||||
|
|
||||||
$form_box = id(new PHUIObjectBoxView())
|
$form_box = id(new PHUIObjectBoxView())
|
||||||
->setHeader($header)
|
->setHeaderText(pht('Call Method'))
|
||||||
->setFormErrors($errors)
|
|
||||||
->appendChild($form);
|
->appendChild($form);
|
||||||
|
|
||||||
$content = array();
|
$content = array();
|
||||||
|
|
||||||
|
$properties = $this->buildMethodProperties($method);
|
||||||
|
|
||||||
|
$info_box = id(new PHUIObjectBoxView())
|
||||||
|
->setHeaderText(pht('API Method: %s', $method->getAPIMethodName()))
|
||||||
|
->setFormErrors($errors)
|
||||||
|
->appendChild($properties);
|
||||||
|
|
||||||
|
$content[] = $info_box;
|
||||||
|
$content[] = $form_box;
|
||||||
|
$content[] = $this->renderExampleBox($method, null);
|
||||||
|
|
||||||
$query = $method->newQueryObject();
|
$query = $method->newQueryObject();
|
||||||
if ($query) {
|
if ($query) {
|
||||||
$orders = $query->getBuiltinOrders();
|
$orders = $query->getBuiltinOrders();
|
||||||
@@ -185,7 +163,6 @@ final class PhabricatorConduitConsoleController
|
|||||||
return $this->buildApplicationPage(
|
return $this->buildApplicationPage(
|
||||||
array(
|
array(
|
||||||
$crumbs,
|
$crumbs,
|
||||||
$form_box,
|
|
||||||
$content,
|
$content,
|
||||||
),
|
),
|
||||||
array(
|
array(
|
||||||
@@ -193,4 +170,41 @@ final class PhabricatorConduitConsoleController
|
|||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private function buildMethodProperties(ConduitAPIMethod $method) {
|
||||||
|
$viewer = $this->getViewer();
|
||||||
|
|
||||||
|
$view = id(new PHUIPropertyListView());
|
||||||
|
|
||||||
|
$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);
|
||||||
|
|
||||||
|
|
||||||
|
$description = $method->getMethodDescription();
|
||||||
|
$description = PhabricatorMarkupEngine::renderOneObject(
|
||||||
|
id(new PhabricatorMarkupOneOff())->setContent($description),
|
||||||
|
'default',
|
||||||
|
$viewer);
|
||||||
|
$view->addSectionHeader(pht('Description'));
|
||||||
|
$view->addTextContent($description);
|
||||||
|
|
||||||
|
return $view;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -24,4 +24,250 @@ abstract class PhabricatorConduitController extends PhabricatorController {
|
|||||||
return $this->buildSideNavView()->getMenu();
|
return $this->buildSideNavView()->getMenu();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected function renderExampleBox(ConduitAPIMethod $method, $params) {
|
||||||
|
$arc_example = id(new PHUIPropertyListView())
|
||||||
|
->addRawContent($this->renderExample($method, 'arc', $params));
|
||||||
|
|
||||||
|
$curl_example = id(new PHUIPropertyListView())
|
||||||
|
->addRawContent($this->renderExample($method, 'curl', $params));
|
||||||
|
|
||||||
|
$php_example = id(new PHUIPropertyListView())
|
||||||
|
->addRawContent($this->renderExample($method, 'php', $params));
|
||||||
|
|
||||||
|
$panel_link = phutil_tag(
|
||||||
|
'a',
|
||||||
|
array(
|
||||||
|
'href' => '/settings/panel/apitokens/',
|
||||||
|
),
|
||||||
|
pht('Conduit API Tokens'));
|
||||||
|
|
||||||
|
$panel_link = phutil_tag('strong', array(), $panel_link);
|
||||||
|
|
||||||
|
$messages = array(
|
||||||
|
pht(
|
||||||
|
'Use the %s panel in Settings to generate or manage API tokens.',
|
||||||
|
$panel_link),
|
||||||
|
);
|
||||||
|
|
||||||
|
$info_view = id(new PHUIInfoView())
|
||||||
|
->setErrors($messages)
|
||||||
|
->setSeverity(PHUIInfoView::SEVERITY_NOTICE);
|
||||||
|
|
||||||
|
return id(new PHUIObjectBoxView())
|
||||||
|
->setHeaderText(pht('Examples'))
|
||||||
|
->setInfoView($info_view)
|
||||||
|
->addPropertyList($arc_example, pht('arc call-conduit'))
|
||||||
|
->addPropertyList($curl_example, pht('cURL'))
|
||||||
|
->addPropertyList($php_example, pht('PHP'));
|
||||||
|
}
|
||||||
|
|
||||||
|
private function renderExample(
|
||||||
|
ConduitAPIMethod $method,
|
||||||
|
$kind,
|
||||||
|
$params) {
|
||||||
|
|
||||||
|
switch ($kind) {
|
||||||
|
case 'arc':
|
||||||
|
$example = $this->buildArcanistExample($method, $params);
|
||||||
|
break;
|
||||||
|
case 'php':
|
||||||
|
$example = $this->buildPHPExample($method, $params);
|
||||||
|
break;
|
||||||
|
case 'curl':
|
||||||
|
$example = $this->buildCURLExample($method, $params);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
throw new Exception(pht('Conduit client "%s" is not known.', $kind));
|
||||||
|
}
|
||||||
|
|
||||||
|
return $example;
|
||||||
|
}
|
||||||
|
|
||||||
|
private function buildArcanistExample(
|
||||||
|
ConduitAPIMethod $method,
|
||||||
|
$params) {
|
||||||
|
|
||||||
|
$parts = array();
|
||||||
|
|
||||||
|
$parts[] = '$ echo ';
|
||||||
|
if ($params === null) {
|
||||||
|
$parts[] = phutil_tag('strong', array(), '<json-parameters>');
|
||||||
|
} else {
|
||||||
|
$params = $this->simplifyParams($params);
|
||||||
|
$params = id(new PhutilJSON())->encodeFormatted($params);
|
||||||
|
$params = trim($params);
|
||||||
|
$params = csprintf('%s', $params);
|
||||||
|
$parts[] = phutil_tag('strong', array('class' => 'real'), $params);
|
||||||
|
}
|
||||||
|
|
||||||
|
$parts[] = ' | ';
|
||||||
|
$parts[] = 'arc call-conduit ';
|
||||||
|
|
||||||
|
$parts[] = '--conduit-uri ';
|
||||||
|
$parts[] = phutil_tag(
|
||||||
|
'strong',
|
||||||
|
array('class' => 'real'),
|
||||||
|
PhabricatorEnv::getURI('/'));
|
||||||
|
$parts[] = ' ';
|
||||||
|
|
||||||
|
$parts[] = '--conduit-token ';
|
||||||
|
$parts[] = phutil_tag('strong', array(), '<conduit-token>');
|
||||||
|
$parts[] = ' ';
|
||||||
|
|
||||||
|
$parts[] = $method->getAPIMethodName();
|
||||||
|
|
||||||
|
return $this->renderExampleCode($parts);
|
||||||
|
}
|
||||||
|
|
||||||
|
private function buildPHPExample(
|
||||||
|
ConduitAPIMethod $method,
|
||||||
|
$params) {
|
||||||
|
|
||||||
|
$parts = array();
|
||||||
|
|
||||||
|
$libphutil_path = 'path/to/libphutil/src/__phutil_library_init__.php';
|
||||||
|
|
||||||
|
$parts[] = '<?php';
|
||||||
|
$parts[] = "\n\n";
|
||||||
|
|
||||||
|
$parts[] = 'require_once ';
|
||||||
|
$parts[] = phutil_var_export($libphutil_path, true);
|
||||||
|
$parts[] = ";\n\n";
|
||||||
|
|
||||||
|
$parts[] = '$api_token = "';
|
||||||
|
$parts[] = phutil_tag('strong', array(), pht('<api-token>'));
|
||||||
|
$parts[] = "\";\n";
|
||||||
|
|
||||||
|
$parts[] = '$api_parameters = ';
|
||||||
|
if ($params === null) {
|
||||||
|
$parts[] = 'array(';
|
||||||
|
$parts[] = phutil_tag('strong', array(), pht('<parameters>'));
|
||||||
|
$parts[] = ');';
|
||||||
|
} else {
|
||||||
|
$params = $this->simplifyParams($params);
|
||||||
|
$params = phutil_var_export($params, true);
|
||||||
|
$parts[] = phutil_tag('strong', array('class' => 'real'), $params);
|
||||||
|
$parts[] = ';';
|
||||||
|
}
|
||||||
|
$parts[] = "\n\n";
|
||||||
|
|
||||||
|
$parts[] = '$client = new ConduitClient(';
|
||||||
|
$parts[] = phutil_tag(
|
||||||
|
'strong',
|
||||||
|
array('class' => 'real'),
|
||||||
|
phutil_var_export(PhabricatorEnv::getURI('/'), true));
|
||||||
|
$parts[] = ");\n";
|
||||||
|
|
||||||
|
$parts[] = '$client->setConduitToken($api_token);';
|
||||||
|
$parts[] = "\n\n";
|
||||||
|
|
||||||
|
$parts[] = '$result = $client->callMethodSynchronous(';
|
||||||
|
$parts[] = phutil_tag(
|
||||||
|
'strong',
|
||||||
|
array('class' => 'real'),
|
||||||
|
phutil_var_export($method->getAPIMethodName(), true));
|
||||||
|
$parts[] = ', ';
|
||||||
|
$parts[] = '$api_parameters';
|
||||||
|
$parts[] = ");\n";
|
||||||
|
|
||||||
|
$parts[] = 'print_r($result);';
|
||||||
|
|
||||||
|
return $this->renderExampleCode($parts);
|
||||||
|
}
|
||||||
|
|
||||||
|
private function buildCURLExample(
|
||||||
|
ConduitAPIMethod $method,
|
||||||
|
$params) {
|
||||||
|
|
||||||
|
$call_uri = '/api/'.$method->getAPIMethodName();
|
||||||
|
|
||||||
|
$parts = array();
|
||||||
|
|
||||||
|
$linebreak = array('\\', phutil_tag('br'), ' ');
|
||||||
|
|
||||||
|
$parts[] = '$ curl ';
|
||||||
|
$parts[] = phutil_tag(
|
||||||
|
'strong',
|
||||||
|
array('class' => 'real'),
|
||||||
|
csprintf('%R', PhabricatorEnv::getURI($call_uri)));
|
||||||
|
$parts[] = ' ';
|
||||||
|
$parts[] = $linebreak;
|
||||||
|
|
||||||
|
$parts[] = '-d api.token=';
|
||||||
|
$parts[] = phutil_tag('strong', array(), 'api-token');
|
||||||
|
$parts[] = ' ';
|
||||||
|
$parts[] = $linebreak;
|
||||||
|
|
||||||
|
if ($params === null) {
|
||||||
|
$parts[] = '-d ';
|
||||||
|
$parts[] = phutil_tag('strong', array(), 'param');
|
||||||
|
$parts[] = '=';
|
||||||
|
$parts[] = phutil_tag('strong', array(), 'value');
|
||||||
|
$parts[] = ' ';
|
||||||
|
$parts[] = $linebreak;
|
||||||
|
$parts[] = phutil_tag('strong', array(), '...');
|
||||||
|
} else {
|
||||||
|
$lines = array();
|
||||||
|
$params = $this->simplifyParams($params);
|
||||||
|
|
||||||
|
foreach ($params as $key => $value) {
|
||||||
|
$pieces = $this->getQueryStringParts(null, $key, $value);
|
||||||
|
foreach ($pieces as $piece) {
|
||||||
|
$lines[] = array(
|
||||||
|
'-d ',
|
||||||
|
phutil_tag('strong', array('class' => 'real'), $piece),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$parts[] = phutil_implode_html(array(' ', $linebreak), $lines);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this->renderExampleCode($parts);
|
||||||
|
}
|
||||||
|
|
||||||
|
private function renderExampleCode($example) {
|
||||||
|
require_celerity_resource('conduit-api-css');
|
||||||
|
|
||||||
|
return phutil_tag(
|
||||||
|
'div',
|
||||||
|
array(
|
||||||
|
'class' => 'PhabricatorMonospaced conduit-api-example-code',
|
||||||
|
),
|
||||||
|
$example);
|
||||||
|
}
|
||||||
|
|
||||||
|
private function simplifyParams(array $params) {
|
||||||
|
foreach ($params as $key => $value) {
|
||||||
|
if ($value === null) {
|
||||||
|
unset($params[$key]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return $params;
|
||||||
|
}
|
||||||
|
|
||||||
|
private function getQueryStringParts($prefix, $key, $value) {
|
||||||
|
if ($prefix === null) {
|
||||||
|
$head = phutil_escape_uri($key);
|
||||||
|
} else {
|
||||||
|
$head = $prefix.'['.phutil_escape_uri($key).']';
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!is_array($value)) {
|
||||||
|
return array(
|
||||||
|
$head.'='.phutil_escape_uri($value),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
$results = array();
|
||||||
|
foreach ($value as $subkey => $subvalue) {
|
||||||
|
$subparts = $this->getQueryStringParts($head, $subkey, $subvalue);
|
||||||
|
foreach ($subparts as $subpart) {
|
||||||
|
$results[] = $subpart;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $results;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
16
webroot/rsrc/css/application/conduit/conduit-api.css
Normal file
16
webroot/rsrc/css/application/conduit/conduit-api.css
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
/**
|
||||||
|
* @provides conduit-api-css
|
||||||
|
*/
|
||||||
|
.conduit-api-example-code {
|
||||||
|
margin: 16px;
|
||||||
|
white-space: pre;
|
||||||
|
color: {$darkgreytext};
|
||||||
|
}
|
||||||
|
|
||||||
|
.conduit-api-example-code strong {
|
||||||
|
color: {$red};
|
||||||
|
}
|
||||||
|
|
||||||
|
.conduit-api-example-code strong.real {
|
||||||
|
color: {$blue};
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user