2011-01-24 18:00:29 +01:00
|
|
|
<?php
|
|
|
|
|
|
|
|
/*
|
2012-01-25 20:50:59 +01:00
|
|
|
* Copyright 2012 Facebook, Inc.
|
2011-01-24 18:00:29 +01:00
|
|
|
*
|
|
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
|
|
* you may not use this file except in compliance with the License.
|
|
|
|
* You may obtain a copy of the License at
|
|
|
|
*
|
|
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
|
|
*
|
|
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
|
|
* See the License for the specific language governing permissions and
|
|
|
|
* limitations under the License.
|
|
|
|
*/
|
|
|
|
|
2011-07-04 21:03:36 +02:00
|
|
|
/**
|
|
|
|
* @group conduit
|
|
|
|
*/
|
2012-03-10 00:46:25 +01:00
|
|
|
final class PhabricatorConduitConsoleController
|
2011-01-24 18:00:29 +01:00
|
|
|
extends PhabricatorConduitController {
|
|
|
|
|
|
|
|
private $method;
|
|
|
|
|
|
|
|
public function willProcessRequest(array $data) {
|
|
|
|
$this->method = idx($data, 'method');
|
|
|
|
}
|
|
|
|
|
|
|
|
public function processRequest() {
|
2011-01-31 03:52:29 +01:00
|
|
|
|
|
|
|
$request = $this->getRequest();
|
|
|
|
|
2011-01-24 18:00:29 +01:00
|
|
|
$methods = $this->getAllMethods();
|
|
|
|
if (empty($methods[$this->method])) {
|
Use head_key() and last_key() to explicitly communicate intent
Summary:
PHP arrays have an internal "current position" marker. (I think because foreach() wasn't introduced until PHP 4 and there was no way to get rid of it by then?)
A few functions affect the position of the marker, like reset(), end(), each(), next(), and prev(). A few functions read the position of the marker, like each(), next(), prev(), current() and key().
For the most part, no one uses any of this because foreach() is vastly easier and more natural. However, we sometimes want to select the first or last key from an array. Since key() returns the key //at the current position//, and you can't guarantee that no one will introduce some next() calls somewhere, the right way to do this is reset() + key(). This is cumbesome, so we introduced head_key() and last_key() (like head() and last()) in D2161.
Switch all the reset()/end() + key() (or omitted reset() since I was feeling like taking risks + key()) calls to head_key() or last_key().
Test Plan: Verified most of these by visiting the affected pages.
Reviewers: btrahan, vrana, jungejason, Koolvin
Reviewed By: jungejason
CC: aran
Differential Revision: https://secure.phabricator.com/D2169
2012-04-09 20:08:59 +02:00
|
|
|
$this->method = head_key($methods);
|
2011-01-24 18:00:29 +01:00
|
|
|
}
|
2012-01-26 21:47:23 +01:00
|
|
|
$this->setFilter('method/'.$this->method);
|
2011-01-24 18:00:29 +01:00
|
|
|
|
|
|
|
$method_class = $methods[$this->method];
|
|
|
|
$method_object = newv($method_class, array());
|
|
|
|
|
2012-04-18 23:25:27 +02:00
|
|
|
$status = $method_object->getMethodStatus();
|
|
|
|
$reason = $method_object->getMethodStatusDescription();
|
|
|
|
|
|
|
|
$status_view = null;
|
|
|
|
if ($status != 'stable') {
|
|
|
|
$status_view = new AphrontErrorView();
|
|
|
|
switch ($status) {
|
|
|
|
case ConduitAPIMethod::METHOD_STATUS_DEPRECATED:
|
|
|
|
$status_view->setTitle('Deprecated Method');
|
|
|
|
$status_view->appendChild(
|
|
|
|
phutil_escape_html(
|
|
|
|
nonempty(
|
|
|
|
$reason,
|
|
|
|
"This method is deprecated.")));
|
|
|
|
break;
|
|
|
|
case ConduitAPIMethod::METHOD_STATUS_UNSTABLE:
|
|
|
|
$status_view->setSeverity(AphrontErrorView::SEVERITY_WARNING);
|
|
|
|
$status_view->setTitle('Unstable Method');
|
|
|
|
$status_view->appendChild(
|
|
|
|
phutil_escape_html(
|
|
|
|
nonempty(
|
|
|
|
$reason,
|
|
|
|
"This method is new and unstable. Its interface is subject ".
|
|
|
|
"to change.")));
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2011-01-24 18:00:29 +01:00
|
|
|
|
|
|
|
$error_description = array();
|
|
|
|
$error_types = $method_object->defineErrorTypes();
|
|
|
|
if ($error_types) {
|
|
|
|
$error_description[] = '<ul>';
|
|
|
|
foreach ($error_types as $error => $meaning) {
|
|
|
|
$error_description[] =
|
|
|
|
'<li>'.
|
|
|
|
'<strong>'.phutil_escape_html($error).':</strong> '.
|
|
|
|
phutil_escape_html($meaning).
|
|
|
|
'</li>';
|
|
|
|
}
|
|
|
|
$error_description[] = '</ul>';
|
|
|
|
$error_description = implode("\n", $error_description);
|
|
|
|
} else {
|
|
|
|
$error_description = "This method does not raise any specific errors.";
|
|
|
|
}
|
|
|
|
|
|
|
|
$form = new AphrontFormView();
|
|
|
|
$form
|
2011-01-31 03:52:29 +01:00
|
|
|
->setUser($request->getUser())
|
2011-01-24 18:00:29 +01:00
|
|
|
->setAction('/api/'.$this->method)
|
|
|
|
->appendChild(
|
|
|
|
id(new AphrontFormStaticControl())
|
|
|
|
->setLabel('Description')
|
2011-01-24 20:36:53 +01:00
|
|
|
->setValue($method_object->getMethodDescription()))
|
2011-01-24 18:00:29 +01:00
|
|
|
->appendChild(
|
|
|
|
id(new AphrontFormStaticControl())
|
|
|
|
->setLabel('Returns')
|
2011-01-24 20:36:53 +01:00
|
|
|
->setValue($method_object->defineReturnType()))
|
2011-01-24 18:00:29 +01:00
|
|
|
->appendChild(
|
2011-01-24 20:36:53 +01:00
|
|
|
id(new AphrontFormMarkupControl())
|
2011-01-24 18:00:29 +01:00
|
|
|
->setLabel('Errors')
|
|
|
|
->setValue($error_description))
|
|
|
|
->appendChild(
|
|
|
|
'<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_object->defineParamTypes();
|
|
|
|
foreach ($params as $param => $desc) {
|
|
|
|
$form->appendChild(
|
|
|
|
id(new AphrontFormTextControl())
|
|
|
|
->setLabel($param)
|
|
|
|
->setName("params[{$param}]")
|
2011-04-22 03:47:04 +02:00
|
|
|
->setCaption(phutil_escape_html($desc)));
|
2011-01-24 18:00:29 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
$form
|
|
|
|
->appendChild(
|
|
|
|
id(new AphrontFormSelectControl())
|
|
|
|
->setLabel('Output Format')
|
|
|
|
->setName('output')
|
|
|
|
->setOptions(
|
|
|
|
array(
|
|
|
|
'human' => 'Human Readable',
|
|
|
|
'json' => 'JSON',
|
|
|
|
)))
|
|
|
|
->appendChild(
|
|
|
|
id(new AphrontFormSubmitControl())
|
|
|
|
->setValue('Call Method'));
|
|
|
|
|
|
|
|
$panel = new AphrontPanelView();
|
|
|
|
$panel->setHeader('Conduit API: '.phutil_escape_html($this->method));
|
|
|
|
$panel->appendChild($form);
|
2011-07-29 06:32:11 +02:00
|
|
|
$panel->setWidth(AphrontPanelView::WIDTH_FULL);
|
2011-01-24 18:00:29 +01:00
|
|
|
|
|
|
|
return $this->buildStandardPageResponse(
|
2012-04-18 23:25:27 +02:00
|
|
|
array(
|
|
|
|
$status_view,
|
|
|
|
$panel,
|
|
|
|
),
|
2011-01-24 18:00:29 +01:00
|
|
|
array(
|
|
|
|
'title' => 'Conduit Console',
|
|
|
|
));
|
|
|
|
}
|
|
|
|
|
|
|
|
private function getAllMethods() {
|
|
|
|
$classes = $this->getAllMethodImplementationClasses();
|
|
|
|
$methods = array();
|
|
|
|
foreach ($classes as $class) {
|
|
|
|
$name = ConduitAPIMethod::getAPIMethodNameFromClassName($class);
|
|
|
|
$methods[$name] = $class;
|
|
|
|
}
|
|
|
|
return $methods;
|
|
|
|
}
|
|
|
|
}
|