mirror of
https://we.phorge.it/source/phorge.git
synced 2024-11-25 16:22:43 +01:00
Conduit server-side basics.
This commit is contained in:
parent
fb9b0db726
commit
2aaa95e640
28 changed files with 987 additions and 0 deletions
|
@ -40,16 +40,28 @@ phutil_register_library_map(array(
|
||||||
'AphrontRedirectResponse' => 'aphront/response/redirect',
|
'AphrontRedirectResponse' => 'aphront/response/redirect',
|
||||||
'AphrontRequest' => 'aphront/request',
|
'AphrontRequest' => 'aphront/request',
|
||||||
'AphrontResponse' => 'aphront/response/base',
|
'AphrontResponse' => 'aphront/response/base',
|
||||||
|
'AphrontSideNavView' => 'view/layout/sidenav',
|
||||||
'AphrontTableView' => 'view/control/table',
|
'AphrontTableView' => 'view/control/table',
|
||||||
'AphrontURIMapper' => 'aphront/mapper',
|
'AphrontURIMapper' => 'aphront/mapper',
|
||||||
'AphrontView' => 'view/base',
|
'AphrontView' => 'view/base',
|
||||||
'AphrontWebpageResponse' => 'aphront/response/webpage',
|
'AphrontWebpageResponse' => 'aphront/response/webpage',
|
||||||
|
'ConduitAPIMethod' => 'applications/conduit/method/base',
|
||||||
|
'ConduitAPIRequest' => 'applications/conduit/protocol/request',
|
||||||
|
'ConduitAPI_file_upload_Method' => 'applications/conduit/method/file/upload',
|
||||||
|
'ConduitException' => 'applications/conduit/protocol/exception',
|
||||||
'DifferentialAction' => 'applications/differential/constants/action',
|
'DifferentialAction' => 'applications/differential/constants/action',
|
||||||
'DifferentialChangeType' => 'applications/differential/constants/changetype',
|
'DifferentialChangeType' => 'applications/differential/constants/changetype',
|
||||||
'DifferentialLintStatus' => 'applications/differential/constants/lintstatus',
|
'DifferentialLintStatus' => 'applications/differential/constants/lintstatus',
|
||||||
'DifferentialRevisionStatus' => 'applications/differential/constants/revisionstatus',
|
'DifferentialRevisionStatus' => 'applications/differential/constants/revisionstatus',
|
||||||
'DifferentialUnitStatus' => 'applications/differential/constants/unitstatus',
|
'DifferentialUnitStatus' => 'applications/differential/constants/unitstatus',
|
||||||
'LiskDAO' => 'storage/lisk/dao',
|
'LiskDAO' => 'storage/lisk/dao',
|
||||||
|
'PhabricatorConduitAPIController' => 'applications/conduit/controller/api',
|
||||||
|
'PhabricatorConduitConnectionLog' => 'applications/conduit/storage/connectionlog',
|
||||||
|
'PhabricatorConduitConsoleController' => 'applications/conduit/controller/console',
|
||||||
|
'PhabricatorConduitController' => 'applications/conduit/controller/base',
|
||||||
|
'PhabricatorConduitDAO' => 'applications/conduit/storage/base',
|
||||||
|
'PhabricatorConduitLogController' => 'applications/conduit/controller/log',
|
||||||
|
'PhabricatorConduitMethodCallLog' => 'applications/conduit/storage/methodcalllog',
|
||||||
'PhabricatorController' => 'applications/base/controller/base',
|
'PhabricatorController' => 'applications/base/controller/base',
|
||||||
'PhabricatorDirectoryCategory' => 'applications/directory/storage/category',
|
'PhabricatorDirectoryCategory' => 'applications/directory/storage/category',
|
||||||
'PhabricatorDirectoryCategoryDeleteController' => 'applications/directory/controller/categorydelete',
|
'PhabricatorDirectoryCategoryDeleteController' => 'applications/directory/controller/categorydelete',
|
||||||
|
@ -126,8 +138,17 @@ phutil_register_library_map(array(
|
||||||
'AphrontQueryParameterException' => 'AphrontQueryException',
|
'AphrontQueryParameterException' => 'AphrontQueryException',
|
||||||
'AphrontQueryRecoverableException' => 'AphrontQueryException',
|
'AphrontQueryRecoverableException' => 'AphrontQueryException',
|
||||||
'AphrontRedirectResponse' => 'AphrontResponse',
|
'AphrontRedirectResponse' => 'AphrontResponse',
|
||||||
|
'AphrontSideNavView' => 'AphrontView',
|
||||||
'AphrontTableView' => 'AphrontView',
|
'AphrontTableView' => 'AphrontView',
|
||||||
'AphrontWebpageResponse' => 'AphrontResponse',
|
'AphrontWebpageResponse' => 'AphrontResponse',
|
||||||
|
'ConduitAPI_file_upload_Method' => 'ConduitAPIMethod',
|
||||||
|
'PhabricatorConduitAPIController' => 'PhabricatorConduitController',
|
||||||
|
'PhabricatorConduitConnectionLog' => 'PhabricatorConduitDAO',
|
||||||
|
'PhabricatorConduitConsoleController' => 'PhabricatorConduitController',
|
||||||
|
'PhabricatorConduitController' => 'PhabricatorController',
|
||||||
|
'PhabricatorConduitDAO' => 'PhabricatorLiskDAO',
|
||||||
|
'PhabricatorConduitLogController' => 'PhabricatorConduitController',
|
||||||
|
'PhabricatorConduitMethodCallLog' => 'PhabricatorConduitDAO',
|
||||||
'PhabricatorController' => 'AphrontController',
|
'PhabricatorController' => 'AphrontController',
|
||||||
'PhabricatorDirectoryCategory' => 'PhabricatorDirectoryDAO',
|
'PhabricatorDirectoryCategory' => 'PhabricatorDirectoryDAO',
|
||||||
'PhabricatorDirectoryCategoryDeleteController' => 'PhabricatorDirectoryController',
|
'PhabricatorDirectoryCategoryDeleteController' => 'PhabricatorDirectoryController',
|
||||||
|
|
|
@ -69,6 +69,12 @@ class AphrontDefaultApplicationConfiguration
|
||||||
'edit/(?:(?<username>\w+)/)?$' => 'PhabricatorPeopleEditController',
|
'edit/(?:(?<username>\w+)/)?$' => 'PhabricatorPeopleEditController',
|
||||||
),
|
),
|
||||||
'/p/(?<username>\w+)/$' => 'PhabricatorPeopleProfileController',
|
'/p/(?<username>\w+)/$' => 'PhabricatorPeopleProfileController',
|
||||||
|
'/conduit/' => array(
|
||||||
|
'$' => 'PhabricatorConduitConsoleController',
|
||||||
|
'method/(?<method>[^/]+)$' => 'PhabricatorConduitConsoleController',
|
||||||
|
'log/$' => 'PhabricatorConduitLogController',
|
||||||
|
),
|
||||||
|
'/api/(?<method>[^/]+)$' => 'PhabricatorConduitAPIController',
|
||||||
'.*' => 'AphrontDefaultApplicationController',
|
'.*' => 'AphrontDefaultApplicationController',
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,185 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright 2011 Facebook, Inc.
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
class PhabricatorConduitAPIController
|
||||||
|
extends PhabricatorConduitController {
|
||||||
|
|
||||||
|
private $method;
|
||||||
|
|
||||||
|
public function willProcessRequest(array $data) {
|
||||||
|
$this->method = $data['method'];
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function processRequest() {
|
||||||
|
$time_start = microtime(true);
|
||||||
|
$request = $this->getRequest();
|
||||||
|
|
||||||
|
$method = $this->method;
|
||||||
|
|
||||||
|
$method_class = ConduitAPIMethod::getClassNameFromAPIMethodName($method);
|
||||||
|
$api_request = null;
|
||||||
|
|
||||||
|
$log = new PhabricatorConduitMethodCallLog();
|
||||||
|
$log->setMethod($method);
|
||||||
|
$metadata = array();
|
||||||
|
|
||||||
|
try {
|
||||||
|
|
||||||
|
if (!class_exists($method_class)) {
|
||||||
|
throw new Exception(
|
||||||
|
"Unable to load the implementation class for method '{$method}'. ".
|
||||||
|
"You may have misspelled the method, need to define ".
|
||||||
|
"'{$method_class}', or need to run 'arc build'.");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fake out checkModule, the class has already been autoloaded by the
|
||||||
|
// class_exists() call above.
|
||||||
|
$method_handler = newv($method_class, array());
|
||||||
|
|
||||||
|
if (isset($_REQUEST['params']) && is_array($_REQUEST['params'])) {
|
||||||
|
$params_post = $request->getArr('params');
|
||||||
|
foreach ($params_post as $key => $value) {
|
||||||
|
$params_post[$key] = json_decode($value);
|
||||||
|
}
|
||||||
|
$params = $params_post;
|
||||||
|
} else {
|
||||||
|
$params_json = $request->getStr('params');
|
||||||
|
if (!strlen($params_json)) {
|
||||||
|
$params = array();
|
||||||
|
} else {
|
||||||
|
$params = json_decode($params_json);
|
||||||
|
if (!is_array($params)) {
|
||||||
|
throw new Exception(
|
||||||
|
"Invalid parameter information was passed to method ".
|
||||||
|
"'{$method}', could not decode JSON serialization.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$metadata = idx($params, '__conduit__', array());
|
||||||
|
unset($params['__conduit__']);
|
||||||
|
|
||||||
|
$api_request = new ConduitAPIRequest($params);
|
||||||
|
|
||||||
|
try {
|
||||||
|
$result = $method_handler->executeMethod($api_request);
|
||||||
|
$error_code = null;
|
||||||
|
$error_info = null;
|
||||||
|
} catch (ConduitException $ex) {
|
||||||
|
$result = null;
|
||||||
|
$error_code = $ex->getMessage();
|
||||||
|
$error_info = $method_handler->getErrorDescription($error_code);
|
||||||
|
}
|
||||||
|
} catch (Exception $ex) {
|
||||||
|
$result = null;
|
||||||
|
$error_code = 'ERR-CONDUIT-CORE';
|
||||||
|
$error_info = $ex->getMessage();
|
||||||
|
}
|
||||||
|
|
||||||
|
$time_end = microtime(true);
|
||||||
|
|
||||||
|
$connection_id = null;
|
||||||
|
if (idx($metadata, 'connectionID')) {
|
||||||
|
$connection_id = $metadata['connectionID'];
|
||||||
|
} else if (($method == 'conduit.connect') && $result) {
|
||||||
|
$connection_id = idx($result, 'connectionID');
|
||||||
|
}
|
||||||
|
|
||||||
|
$log->setConnectionID($connection_id);
|
||||||
|
$log->setError((string)$error_code);
|
||||||
|
$log->setDuration(1000000 * ($time_end - $time_start));
|
||||||
|
$log->save();
|
||||||
|
|
||||||
|
$result = array(
|
||||||
|
'result' => $result,
|
||||||
|
'error_code' => $error_code,
|
||||||
|
'error_info' => $error_info,
|
||||||
|
);
|
||||||
|
|
||||||
|
switch ($request->getStr('output')) {
|
||||||
|
case 'human':
|
||||||
|
return $this->buildHumanReadableResponse(
|
||||||
|
$method,
|
||||||
|
$api_request,
|
||||||
|
$result);
|
||||||
|
case 'json':
|
||||||
|
default:
|
||||||
|
return id(new AphrontFileResponse())
|
||||||
|
->setMimeType('application/json')
|
||||||
|
->setContent(json_encode($result));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private function buildHumanReadableResponse(
|
||||||
|
$method,
|
||||||
|
ConduitAPIRequest $request = null,
|
||||||
|
$result = null) {
|
||||||
|
|
||||||
|
$param_rows = array();
|
||||||
|
$param_rows[] = array('Method', phutil_escape_html($method));
|
||||||
|
if ($request) {
|
||||||
|
foreach ($request->getAllParameters() as $key => $value) {
|
||||||
|
$param_rows[] = array(
|
||||||
|
phutil_escape_html($key),
|
||||||
|
phutil_escape_html(json_encode($value)),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$param_table = new AphrontTableView($param_rows);
|
||||||
|
$param_table->setColumnClasses(
|
||||||
|
array(
|
||||||
|
'header',
|
||||||
|
'wide',
|
||||||
|
));
|
||||||
|
|
||||||
|
$result_rows = array();
|
||||||
|
foreach ($result as $key => $value) {
|
||||||
|
$result_rows[] = array(
|
||||||
|
phutil_escape_html($key),
|
||||||
|
phutil_escape_html(json_encode($value)),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
$result_table = new AphrontTableView($result_rows);
|
||||||
|
$result_table->setColumnClasses(
|
||||||
|
array(
|
||||||
|
'header',
|
||||||
|
'wide',
|
||||||
|
));
|
||||||
|
|
||||||
|
$param_panel = new AphrontPanelView();
|
||||||
|
$param_panel->setHeader('Method Parameters');
|
||||||
|
$param_panel->appendChild($param_table);
|
||||||
|
|
||||||
|
$result_panel = new AphrontPanelView();
|
||||||
|
$result_panel->setHeader('Method Result');
|
||||||
|
$result_panel->appendChild($result_table);
|
||||||
|
|
||||||
|
return $this->buildStandardPageResponse(
|
||||||
|
array(
|
||||||
|
$param_panel,
|
||||||
|
$result_panel,
|
||||||
|
),
|
||||||
|
array(
|
||||||
|
'title' => 'Method Call Result',
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
21
src/applications/conduit/controller/api/__init__.php
Normal file
21
src/applications/conduit/controller/api/__init__.php
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* This file is automatically generated. Lint this module to rebuild it.
|
||||||
|
* @generated
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
phutil_require_module('phabricator', 'aphront/response/file');
|
||||||
|
phutil_require_module('phabricator', 'applications/conduit/controller/base');
|
||||||
|
phutil_require_module('phabricator', 'applications/conduit/method/base');
|
||||||
|
phutil_require_module('phabricator', 'applications/conduit/protocol/request');
|
||||||
|
phutil_require_module('phabricator', 'applications/conduit/storage/methodcalllog');
|
||||||
|
phutil_require_module('phabricator', 'view/control/table');
|
||||||
|
phutil_require_module('phabricator', 'view/layout/panel');
|
||||||
|
|
||||||
|
phutil_require_module('phutil', 'markup');
|
||||||
|
phutil_require_module('phutil', 'utils');
|
||||||
|
|
||||||
|
|
||||||
|
phutil_require_source('PhabricatorConduitAPIController.php');
|
|
@ -0,0 +1,46 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright 2011 Facebook, Inc.
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
abstract class PhabricatorConduitController extends PhabricatorController {
|
||||||
|
|
||||||
|
public function buildStandardPageResponse($view, array $data) {
|
||||||
|
$page = new PhabricatorStandardPageView();
|
||||||
|
|
||||||
|
$page->setApplicationName('Conduit');
|
||||||
|
$page->setBaseURI('/conduit/');
|
||||||
|
$page->setTitle(idx($data, 'title'));
|
||||||
|
$page->setTabs(
|
||||||
|
array(
|
||||||
|
'console' => array(
|
||||||
|
'href' => '/conduit/',
|
||||||
|
'name' => 'Console',
|
||||||
|
),
|
||||||
|
'logs' => array(
|
||||||
|
'href' => '/conduit/log/',
|
||||||
|
'name' => 'Logs',
|
||||||
|
),
|
||||||
|
),
|
||||||
|
idx($data, 'tab'));
|
||||||
|
$page->setGlyph("\xE2\x87\xB5");
|
||||||
|
$page->appendChild($view);
|
||||||
|
|
||||||
|
$response = new AphrontWebpageResponse();
|
||||||
|
return $response->setContent($page->render());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
16
src/applications/conduit/controller/base/__init__.php
Normal file
16
src/applications/conduit/controller/base/__init__.php
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* This file is automatically generated. Lint this module to rebuild it.
|
||||||
|
* @generated
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
phutil_require_module('phabricator', 'aphront/response/webpage');
|
||||||
|
phutil_require_module('phabricator', 'applications/base/controller/base');
|
||||||
|
phutil_require_module('phabricator', 'view/page/standard');
|
||||||
|
|
||||||
|
phutil_require_module('phutil', 'utils');
|
||||||
|
|
||||||
|
|
||||||
|
phutil_require_source('PhabricatorConduitController.php');
|
|
@ -0,0 +1,181 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright 2011 Facebook, Inc.
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
class PhabricatorConduitConsoleController
|
||||||
|
extends PhabricatorConduitController {
|
||||||
|
|
||||||
|
private $method;
|
||||||
|
|
||||||
|
public function willProcessRequest(array $data) {
|
||||||
|
$this->method = idx($data, 'method');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function processRequest() {
|
||||||
|
$methods = $this->getAllMethods();
|
||||||
|
if (empty($methods[$this->method])) {
|
||||||
|
$this->method = key($methods);
|
||||||
|
}
|
||||||
|
|
||||||
|
$method_class = $methods[$this->method];
|
||||||
|
PhutilSymbolLoader::loadClass($method_class);
|
||||||
|
$method_object = newv($method_class, array());
|
||||||
|
|
||||||
|
|
||||||
|
$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
|
||||||
|
->setAction('/api/'.$this->method)
|
||||||
|
->appendChild(
|
||||||
|
id(new AphrontFormStaticControl())
|
||||||
|
->setLabel('Description')
|
||||||
|
->setValue(
|
||||||
|
phutil_escape_html($method_object->getMethodDescription())))
|
||||||
|
->appendChild(
|
||||||
|
id(new AphrontFormStaticControl())
|
||||||
|
->setLabel('Returns')
|
||||||
|
->setValue(
|
||||||
|
phutil_escape_html($method_object->defineReturnType())))
|
||||||
|
->appendChild(
|
||||||
|
id(new AphrontFormStaticControl())
|
||||||
|
->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}]")
|
||||||
|
->setCaption($desc));
|
||||||
|
}
|
||||||
|
|
||||||
|
$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);
|
||||||
|
$panel->setWidth(AphrontPanelView::WIDTH_WIDE);
|
||||||
|
|
||||||
|
$view = new AphrontSideNavView();
|
||||||
|
foreach ($this->buildNavItems() as $item) {
|
||||||
|
$view->addNavItem($item);
|
||||||
|
}
|
||||||
|
|
||||||
|
$view->appendChild($panel);
|
||||||
|
|
||||||
|
return $this->buildStandardPageResponse(
|
||||||
|
array($view),
|
||||||
|
array(
|
||||||
|
'title' => 'Conduit Console',
|
||||||
|
'tab' => 'console',
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
private function buildNavItems() {
|
||||||
|
$classes = $this->getAllMethodImplementationClasses();
|
||||||
|
$method_names = array();
|
||||||
|
foreach ($classes as $method_class) {
|
||||||
|
$method_name = ConduitAPIMethod::getAPIMethodNameFromClassName(
|
||||||
|
$method_class);
|
||||||
|
$method_names[] = array(
|
||||||
|
'full_name' => $method_name,
|
||||||
|
'group_name' => reset(explode('.', $method_name)),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
$method_names = igroup($method_names, 'group_name');
|
||||||
|
ksort($method_names);
|
||||||
|
|
||||||
|
$items = array();
|
||||||
|
foreach ($method_names as $group => $methods) {
|
||||||
|
$items[] = phutil_render_tag(
|
||||||
|
'a',
|
||||||
|
array(
|
||||||
|
),
|
||||||
|
phutil_escape_html($group));
|
||||||
|
foreach ($methods as $method) {
|
||||||
|
$method_name = $method['full_name'];
|
||||||
|
$selected = ($method_name == $this->method);
|
||||||
|
$items[] = phutil_render_tag(
|
||||||
|
'a',
|
||||||
|
array(
|
||||||
|
'class' => $selected ? 'aphront-side-nav-selected' : null,
|
||||||
|
'href' => '/conduit/method/'.$method_name,
|
||||||
|
),
|
||||||
|
'<span style="padding-left: 1em;">'.
|
||||||
|
phutil_escape_html($method_name).
|
||||||
|
'</span>');
|
||||||
|
}
|
||||||
|
$items[] = '<hr />';
|
||||||
|
}
|
||||||
|
// Pop off the last '<hr />'.
|
||||||
|
array_pop($items);
|
||||||
|
|
||||||
|
return $items;
|
||||||
|
}
|
||||||
|
|
||||||
|
private function getAllMethods() {
|
||||||
|
$classes = $this->getAllMethodImplementationClasses();
|
||||||
|
$methods = array();
|
||||||
|
foreach ($classes as $class) {
|
||||||
|
$name = ConduitAPIMethod::getAPIMethodNameFromClassName($class);
|
||||||
|
$methods[$name] = $class;
|
||||||
|
}
|
||||||
|
return $methods;
|
||||||
|
}
|
||||||
|
|
||||||
|
private function getAllMethodImplementationClasses() {
|
||||||
|
$classes = id(new PhutilSymbolLoader())
|
||||||
|
->setAncestorClass('ConduitAPIMethod')
|
||||||
|
->setType('class')
|
||||||
|
->selectSymbolsWithoutLoading();
|
||||||
|
return array_values(ipull($classes, 'name'));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
22
src/applications/conduit/controller/console/__init__.php
Normal file
22
src/applications/conduit/controller/console/__init__.php
Normal file
|
@ -0,0 +1,22 @@
|
||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* This file is automatically generated. Lint this module to rebuild it.
|
||||||
|
* @generated
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
phutil_require_module('phabricator', 'applications/conduit/controller/base');
|
||||||
|
phutil_require_module('phabricator', 'applications/conduit/method/base');
|
||||||
|
phutil_require_module('phabricator', 'view/form/base');
|
||||||
|
phutil_require_module('phabricator', 'view/form/control/submit');
|
||||||
|
phutil_require_module('phabricator', 'view/form/control/text');
|
||||||
|
phutil_require_module('phabricator', 'view/layout/panel');
|
||||||
|
phutil_require_module('phabricator', 'view/layout/sidenav');
|
||||||
|
|
||||||
|
phutil_require_module('phutil', 'markup');
|
||||||
|
phutil_require_module('phutil', 'symbols');
|
||||||
|
phutil_require_module('phutil', 'utils');
|
||||||
|
|
||||||
|
|
||||||
|
phutil_require_source('PhabricatorConduitConsoleController.php');
|
|
@ -0,0 +1,28 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright 2011 Facebook, Inc.
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
class PhabricatorConduitLogController extends PhabricatorConduitController {
|
||||||
|
|
||||||
|
public function processRequest() {
|
||||||
|
|
||||||
|
return $this->buildStandardPageResponse('stuff', array(
|
||||||
|
'title' => 'Conduit Logs',
|
||||||
|
'tab' => 'logs',
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
12
src/applications/conduit/controller/log/__init__.php
Normal file
12
src/applications/conduit/controller/log/__init__.php
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* This file is automatically generated. Lint this module to rebuild it.
|
||||||
|
* @generated
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
phutil_require_module('phabricator', 'applications/conduit/controller/base');
|
||||||
|
|
||||||
|
|
||||||
|
phutil_require_source('PhabricatorConduitLogController.php');
|
62
src/applications/conduit/method/base/ConduitAPIMethod.php
Normal file
62
src/applications/conduit/method/base/ConduitAPIMethod.php
Normal file
|
@ -0,0 +1,62 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright 2011 Facebook, Inc.
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
abstract class ConduitAPIMethod {
|
||||||
|
|
||||||
|
abstract public function getMethodDescription();
|
||||||
|
abstract public function defineParamTypes();
|
||||||
|
abstract public function defineReturnType();
|
||||||
|
abstract public function defineErrorTypes();
|
||||||
|
abstract protected function execute(ConduitAPIRequest $request);
|
||||||
|
|
||||||
|
public function __construct() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getErrorDescription($error_code) {
|
||||||
|
return idx($this->defineErrorTypes(), $error_code, 'Unknown Error');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function executeMethod(ConduitAPIRequest $request) {
|
||||||
|
return $this->execute($request);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getAPIMethodName() {
|
||||||
|
return self::getAPIMethodNameFromClassName(get_class($this));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function getClassNameFromAPIMethodName($method_name) {
|
||||||
|
$method_fragment = str_replace('.', '_', $method_name);
|
||||||
|
return 'ConduitAPI_'.$method_fragment.'_Method';
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function getAPIMethodNameFromClassName($class_name) {
|
||||||
|
$match = null;
|
||||||
|
$is_valid = preg_match(
|
||||||
|
'/^ConduitAPI_(.*)_Method$/',
|
||||||
|
$class_name,
|
||||||
|
$match);
|
||||||
|
if (!$is_valid) {
|
||||||
|
throw new Exception(
|
||||||
|
"Parameter '{$class_name}' is not a valid Conduit API method class.");
|
||||||
|
}
|
||||||
|
$method_fragment = $match[1];
|
||||||
|
return str_replace('_', '.', $method_fragment);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
12
src/applications/conduit/method/base/__init__.php
Normal file
12
src/applications/conduit/method/base/__init__.php
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* This file is automatically generated. Lint this module to rebuild it.
|
||||||
|
* @generated
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
phutil_require_module('phutil', 'utils');
|
||||||
|
|
||||||
|
|
||||||
|
phutil_require_source('ConduitAPIMethod.php');
|
|
@ -0,0 +1,54 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright 2011 Facebook, Inc.
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
class ConduitAPI_file_upload_Method extends ConduitAPIMethod {
|
||||||
|
|
||||||
|
public function getMethodDescription() {
|
||||||
|
return "Upload a file to the server.";
|
||||||
|
}
|
||||||
|
|
||||||
|
public function defineParamTypes() {
|
||||||
|
return array(
|
||||||
|
'data_base64' => 'required nonempty base64-bytes',
|
||||||
|
'name' => 'optional string',
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function defineReturnType() {
|
||||||
|
return 'nonempty guid';
|
||||||
|
}
|
||||||
|
|
||||||
|
public function defineErrorTypes() {
|
||||||
|
return array(
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function execute(ConduitAPIRequest $request) {
|
||||||
|
$data = $request->getValue('data_base64');
|
||||||
|
$name = $request->getValue('name');
|
||||||
|
$data = base64_decode($data, $strict = true);
|
||||||
|
|
||||||
|
$file = PhabricatorFile::newFromFileData(
|
||||||
|
$data,
|
||||||
|
array(
|
||||||
|
'name' => $name
|
||||||
|
));
|
||||||
|
return $file->getPHID();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
13
src/applications/conduit/method/file/upload/__init__.php
Normal file
13
src/applications/conduit/method/file/upload/__init__.php
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* This file is automatically generated. Lint this module to rebuild it.
|
||||||
|
* @generated
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
phutil_require_module('phabricator', 'applications/conduit/method/base');
|
||||||
|
phutil_require_module('phabricator', 'applications/files/storage/file');
|
||||||
|
|
||||||
|
|
||||||
|
phutil_require_source('ConduitAPI_file_upload_Method.php');
|
|
@ -0,0 +1,20 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright 2011 Facebook, Inc.
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
class ConduitException extends Exception {
|
||||||
|
}
|
10
src/applications/conduit/protocol/exception/__init__.php
Normal file
10
src/applications/conduit/protocol/exception/__init__.php
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* This file is automatically generated. Lint this module to rebuild it.
|
||||||
|
* @generated
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
phutil_require_source('ConduitException.php');
|
|
@ -0,0 +1,35 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright 2011 Facebook, Inc.
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
class ConduitAPIRequest {
|
||||||
|
|
||||||
|
protected $params;
|
||||||
|
|
||||||
|
public function __construct(array $params) {
|
||||||
|
$this->params = $params;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getValue($key) {
|
||||||
|
return $this->params[$key];
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getAllParameters() {
|
||||||
|
return $this->params;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
10
src/applications/conduit/protocol/request/__init__.php
Normal file
10
src/applications/conduit/protocol/request/__init__.php
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* This file is automatically generated. Lint this module to rebuild it.
|
||||||
|
* @generated
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
phutil_require_source('ConduitAPIRequest.php');
|
|
@ -0,0 +1,25 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright 2011 Facebook, Inc.
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
abstract class PhabricatorConduitDAO extends PhabricatorLiskDAO {
|
||||||
|
|
||||||
|
public function getApplicationName() {
|
||||||
|
return 'conduit';
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
12
src/applications/conduit/storage/base/__init__.php
Normal file
12
src/applications/conduit/storage/base/__init__.php
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* This file is automatically generated. Lint this module to rebuild it.
|
||||||
|
* @generated
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
phutil_require_module('phabricator', 'applications/base/storage/lisk');
|
||||||
|
|
||||||
|
|
||||||
|
phutil_require_source('PhabricatorConduitDAO.php');
|
|
@ -0,0 +1,26 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright 2011 Facebook, Inc.
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
class PhabricatorConduitConnectionLog extends PhabricatorConduitDAO {
|
||||||
|
|
||||||
|
protected $client;
|
||||||
|
protected $clientVersion;
|
||||||
|
protected $clientDescription;
|
||||||
|
protected $username;
|
||||||
|
|
||||||
|
}
|
12
src/applications/conduit/storage/connectionlog/__init__.php
Normal file
12
src/applications/conduit/storage/connectionlog/__init__.php
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* This file is automatically generated. Lint this module to rebuild it.
|
||||||
|
* @generated
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
phutil_require_module('phabricator', 'applications/conduit/storage/base');
|
||||||
|
|
||||||
|
|
||||||
|
phutil_require_source('PhabricatorConduitConnectionLog.php');
|
|
@ -0,0 +1,26 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright 2011 Facebook, Inc.
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
class PhabricatorConduitMethodCallLog extends PhabricatorConduitDAO {
|
||||||
|
|
||||||
|
protected $connectionID;
|
||||||
|
protected $method;
|
||||||
|
protected $error;
|
||||||
|
protected $duration;
|
||||||
|
|
||||||
|
}
|
12
src/applications/conduit/storage/methodcalllog/__init__.php
Normal file
12
src/applications/conduit/storage/methodcalllog/__init__.php
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* This file is automatically generated. Lint this module to rebuild it.
|
||||||
|
* @generated
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
phutil_require_module('phabricator', 'applications/conduit/storage/base');
|
||||||
|
|
||||||
|
|
||||||
|
phutil_require_source('PhabricatorConduitMethodCallLog.php');
|
|
@ -20,6 +20,7 @@ final class AphrontPanelView extends AphrontView {
|
||||||
|
|
||||||
const WIDTH_FULL = 'full';
|
const WIDTH_FULL = 'full';
|
||||||
const WIDTH_FORM = 'form';
|
const WIDTH_FORM = 'form';
|
||||||
|
const WIDTH_WIDE = 'wide';
|
||||||
|
|
||||||
private $createButton;
|
private $createButton;
|
||||||
private $header;
|
private $header;
|
||||||
|
|
45
src/view/layout/sidenav/AphrontSideNavView.php
Executable file
45
src/view/layout/sidenav/AphrontSideNavView.php
Executable file
|
@ -0,0 +1,45 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright 2011 Facebook, Inc.
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
final class AphrontSideNavView extends AphrontView {
|
||||||
|
|
||||||
|
protected $items = array();
|
||||||
|
|
||||||
|
public function addNavItem($item) {
|
||||||
|
$this->items[] = $item;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function render() {
|
||||||
|
$view = new AphrontNullView();
|
||||||
|
$view->appendChild($this->items);
|
||||||
|
|
||||||
|
return
|
||||||
|
'<table class="aphront-side-nav-view">'.
|
||||||
|
'<tr>'.
|
||||||
|
'<th class="aphront-side-nav-navigation">'.
|
||||||
|
$view->render().
|
||||||
|
'</th>'.
|
||||||
|
'<td class="aphront-side-nav-content">'.
|
||||||
|
$this->renderChildren().
|
||||||
|
'</td>'.
|
||||||
|
'</tr>'.
|
||||||
|
'</table>';
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
13
src/view/layout/sidenav/__init__.php
Normal file
13
src/view/layout/sidenav/__init__.php
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* This file is automatically generated. Lint this module to rebuild it.
|
||||||
|
* @generated
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
phutil_require_module('phabricator', 'view/base');
|
||||||
|
phutil_require_module('phabricator', 'view/null');
|
||||||
|
|
||||||
|
|
||||||
|
phutil_require_source('AphrontSideNavView.php');
|
|
@ -343,6 +343,12 @@ a.small:visited {
|
||||||
margin-left: auto;
|
margin-left: auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.aphront-panel-width-wide {
|
||||||
|
width: 1080px;
|
||||||
|
margin-right: auto;
|
||||||
|
margin-left: auto;
|
||||||
|
}
|
||||||
|
|
||||||
.aphront-table-view {
|
.aphront-table-view {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
border-collapse: collapse;
|
border-collapse: collapse;
|
||||||
|
@ -486,7 +492,14 @@ a.small:visited {
|
||||||
background: #f9b9bc;
|
background: #f9b9bc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.aphront-form-instructions {
|
||||||
|
margin: 2em 3%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.aphront-form-control-static .aphront-form-input {
|
||||||
|
padding-top: 4px;
|
||||||
|
font-size: 13px;
|
||||||
|
}
|
||||||
|
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
|
|
||||||
|
@ -532,3 +545,51 @@ a.small:visited {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/******************************************************************************/
|
||||||
|
|
||||||
|
/* side nav */
|
||||||
|
|
||||||
|
/******************************************************************************/
|
||||||
|
|
||||||
|
|
||||||
|
table.aphront-side-nav-view {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
td.aphront-side-nav-content {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
th.aphront-side-nav-navigation {
|
||||||
|
border-right: 1px solid #bbbbbb;
|
||||||
|
}
|
||||||
|
|
||||||
|
th.aphront-side-nav-navigation a {
|
||||||
|
display: block;
|
||||||
|
margin: 0 0 2px;
|
||||||
|
min-width: 150px;
|
||||||
|
padding: 3px 8px 3px 24px;
|
||||||
|
font-weight: bold;
|
||||||
|
white-space: nowrap;
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
th.aphront-side-nav-navigation a:hover {
|
||||||
|
text-decoration: none;
|
||||||
|
background: #f3f3f9;
|
||||||
|
}
|
||||||
|
|
||||||
|
th.aphront-side-nav-navigation hr {
|
||||||
|
height: 1px;
|
||||||
|
background: #eeeeee;
|
||||||
|
border: 0px;
|
||||||
|
margin: 12px 0px;
|
||||||
|
}
|
||||||
|
|
||||||
|
th.aphront-side-nav-navigation a.aphront-side-nav-selected,
|
||||||
|
th.aphront-side-nav-navigation a.aphront-side-nav-selected:hover {
|
||||||
|
background: #d8dfea;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue