Changeset View
Changeset View
Standalone View
Standalone View
src/workflow/ArcanistCallConduitWorkflow.php
| <?php | <?php | ||||
| /** | /** | ||||
| * Provides command-line access to the Conduit API. | * Provides command-line access to the Conduit API. | ||||
| */ | */ | ||||
| final class ArcanistCallConduitWorkflow extends ArcanistWorkflow { | final class ArcanistCallConduitWorkflow extends ArcanistWorkflow { | ||||
| public function getWorkflowName() { | public function getWorkflowName() { | ||||
| return 'call-conduit'; | return 'call-conduit'; | ||||
| } | } | ||||
| public function getCommandSynopses() { | public function getWorkflowInformation() { | ||||
| return phutil_console_format(<<<EOTEXT | $help = pht(<<<EOTEXT | ||||
| **call-conduit** __method__ | Make a call to Conduit, the Phabricator API. | ||||
| EOTEXT | |||||
| ); | |||||
| } | |||||
| public function getCommandHelp() { | |||||
| return phutil_console_format(<<<EOTEXT | |||||
| Supports: http, https | |||||
| Allows you to make a raw Conduit method call: | |||||
| - Run this command from a working directory. | |||||
| - Call parameters are REQUIRED and read as a JSON blob from stdin. | |||||
| - Results are written to stdout as a JSON blob. | |||||
| This workflow is primarily useful for writing scripts which integrate | For example: | ||||
| with Phabricator. Examples: | |||||
| $ echo '{}' | arc call-conduit conduit.ping | $ echo '{}' | arc call-conduit conduit.ping | ||||
| $ echo '{"phid":"PHID-FILE-xxxx"}' | arc call-conduit file.download | |||||
| EOTEXT | EOTEXT | ||||
| ); | ); | ||||
| return $this->newWorkflowInformation() | |||||
| ->addExample(pht('**call-conduit** __method__')) | |||||
| ->setHelp($help); | |||||
| } | } | ||||
| public function getArguments() { | public function getWorkflowArguments() { | ||||
| return array( | return array( | ||||
| '*' => 'method', | $this->newWorkflowArgument('argv') | ||||
| ->setWildcard(true), | |||||
| ); | ); | ||||
| } | } | ||||
| protected function shouldShellComplete() { | public function runWorkflow() { | ||||
| return false; | $argv = $this->getArgument('argv'); | ||||
| } | |||||
| public function requiresConduit() { | if (!$argv) { | ||||
| return true; | // TOOLSETS: We should call "conduit.query" and list available methods | ||||
| // here. | |||||
| throw new PhutilArgumentUsageException( | |||||
| pht( | |||||
| 'Provide the name of the Conduit method you want to call on the '. | |||||
| 'command line.')); | |||||
| } else if (count($argv) > 1) { | |||||
| throw new PhutilArgumentUsageException( | |||||
| pht( | |||||
| 'Provide the name of only one method to call.')); | |||||
| } | } | ||||
| public function requiresAuthentication() { | $method = head($argv); | ||||
| return true; | |||||
| } | |||||
| public function run() { | |||||
| $method = $this->getArgument('method', array()); | |||||
| if (count($method) !== 1) { | |||||
| throw new ArcanistUsageException( | |||||
| pht('Provide exactly one Conduit method name.')); | |||||
| } | |||||
| $method = reset($method); | |||||
| $console = PhutilConsole::getConsole(); | |||||
| if (!function_exists('posix_isatty') || posix_isatty(STDIN)) { | if (!function_exists('posix_isatty') || posix_isatty(STDIN)) { | ||||
| $console->writeErr( | fprintf( | ||||
| STDERR, | |||||
| tsprintf( | |||||
| "%s\n", | "%s\n", | ||||
| pht('Waiting for JSON parameters on stdin...')); | pht('Waiting for JSON parameters on stdin...'))); | ||||
| } | } | ||||
| $params = @file_get_contents('php://stdin'); | $params = @file_get_contents('php://stdin'); | ||||
| try { | try { | ||||
| $params = phutil_json_decode($params); | $params = phutil_json_decode($params); | ||||
| } catch (PhutilJSONParserException $ex) { | } catch (PhutilJSONParserException $ex) { | ||||
| throw new ArcanistUsageException( | throw new ArcanistUsageException( | ||||
| pht('Provide method parameters on stdin as a JSON blob.')); | pht('Provide method parameters on stdin as a JSON blob.')); | ||||
| } | } | ||||
| $error = null; | $error = null; | ||||
| $error_message = null; | $error_message = null; | ||||
| try { | try { | ||||
| $result = $this->getConduit()->callMethodSynchronous( | $result = $this->getConduitEngine()->resolveCall($method, $params); | ||||
| $method, | |||||
| $params); | |||||
| } catch (ConduitClientException $ex) { | } catch (ConduitClientException $ex) { | ||||
| // TOOLSETS: We should use "conduit.query" to suggest similar calls if | |||||
| // it looks like the user called a method which does not exist. | |||||
| $error = $ex->getErrorCode(); | $error = $ex->getErrorCode(); | ||||
| $error_message = $ex->getMessage(); | $error_message = $ex->getMessage(); | ||||
| $result = null; | $result = null; | ||||
| } | } | ||||
| echo json_encode(array( | echo id(new PhutilJSON()) | ||||
| ->encodeFormatted( | |||||
| array( | |||||
| 'error' => $error, | 'error' => $error, | ||||
| 'errorMessage' => $error_message, | 'errorMessage' => $error_message, | ||||
| 'response' => $result, | 'response' => $result, | ||||
| ))."\n"; | )); | ||||
| return 0; | return 0; | ||||
| } | } | ||||
| } | } | ||||