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);
     $view->addSectionHeader(pht('Description'), PHUIPropertyListView::ICON_SUMMARY);
     $view->addTextContent(new PHUIRemarkupView($viewer, $method->getMethodDescription()));
     return $view;
 }
 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;
 }
 private function getAllMethods()
 {
     $classes = $this->getAllMethodImplementationClasses();
     $methods = array();
     foreach ($classes as $class) {
         $name = ConduitAPIMethod::getAPIMethodNameFromClassName($class);
         $methods[$name] = $class;
     }
     return $methods;
 }
 private function buildMethodProperties(ConduitAPIMethod $method)
 {
     $viewer = $this->getViewer();
     $view = id(new PHUIPropertyListView());
     $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;
         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));
     }
     $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);
     $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));
     $view->addSectionHeader(pht('Description'), PHUIPropertyListView::ICON_SUMMARY);
     $view->addTextContent(new PHUIRemarkupView($viewer, $method->getMethodDescription()));
     return $view;
 }
예제 #5
0
 protected function buildMethodHandler($method)
 {
     $method_class = ConduitAPIMethod::getClassNameFromAPIMethodName($method);
     // Test if the method exists.
     $ok = false;
     try {
         $ok = class_exists($method_class);
     } catch (Exception $ex) {
         // Discard, we provide a more specific exception below.
     }
     if (!$ok) {
         throw new Exception("Conduit method '{$method}' does not exist.");
     }
     $class_info = new ReflectionClass($method_class);
     if ($class_info->isAbstract()) {
         throw new Exception("Method '{$method}' is not valid; the implementation is an abstract " . "base class.");
     }
     return newv($method_class, array());
 }
예제 #6
0
 public static final function callConduitWithDiffusionRequest(PhabricatorUser $user, DiffusionRequest $drequest, $method, array $params = array())
 {
     $repository = $drequest->getRepository();
     $core_params = array('repository' => $repository->getPHID());
     if ($drequest->getBranch() !== null) {
         $core_params['branch'] = $drequest->getBranch();
     }
     // If the method we're calling doesn't actually take some of the implicit
     // parameters we derive from the DiffusionRequest, omit them.
     $method_object = ConduitAPIMethod::getConduitMethod($method);
     $method_params = $method_object->getParamTypes();
     foreach ($core_params as $key => $value) {
         if (empty($method_params[$key])) {
             unset($core_params[$key]);
         }
     }
     $params = $params + $core_params;
     $client = $repository->newConduitClient($user, $drequest->getIsClusterRequest());
     if (!$client) {
         return id(new ConduitCall($method, $params))->setUser($user)->execute();
     } else {
         return $client->callMethodSynchronous($method, $params);
     }
 }
 public function buildConduitResponse(ConduitAPIRequest $request, ConduitAPIMethod $method)
 {
     $viewer = $this->requireViewer();
     $query_key = $request->getValue('queryKey');
     if (!strlen($query_key)) {
         $saved_query = new PhabricatorSavedQuery();
     } else {
         if ($this->isBuiltinQuery($query_key)) {
             $saved_query = $this->buildSavedQueryFromBuiltin($query_key);
         } else {
             $saved_query = id(new PhabricatorSavedQueryQuery())->setViewer($viewer)->withQueryKeys(array($query_key))->executeOne();
             if (!$saved_query) {
                 throw new Exception(pht('Query key "%s" does not correspond to a valid query.', $query_key));
             }
         }
     }
     $constraints = $request->getValue('constraints', array());
     $fields = $this->getSearchFieldsForConduit();
     foreach ($fields as $key => $field) {
         if (!$field->getConduitParameterType()) {
             unset($fields[$key]);
         }
     }
     $valid_constraints = array();
     foreach ($fields as $field) {
         foreach ($field->getValidConstraintKeys() as $key) {
             $valid_constraints[$key] = true;
         }
     }
     foreach ($constraints as $key => $constraint) {
         if (empty($valid_constraints[$key])) {
             throw new Exception(pht('Constraint "%s" is not a valid constraint for this query.', $key));
         }
     }
     foreach ($fields as $field) {
         if (!$field->getValueExistsInConduitRequest($constraints)) {
             continue;
         }
         $value = $field->readValueFromConduitRequest($constraints, $request->getIsStrictlyTyped());
         $saved_query->setParameter($field->getKey(), $value);
     }
     // NOTE: Currently, when running an ad-hoc query we never persist it into
     // a saved query. We might want to add an option to do this in the future
     // (for example, to enable a CLI-to-Web workflow where user can view more
     // details about results by following a link), but have no use cases for
     // it today. If we do identify a use case, we could save the query here.
     $query = $this->buildQueryFromSavedQuery($saved_query);
     $pager = $this->newPagerForSavedQuery($saved_query);
     $attachments = $this->getConduitSearchAttachments();
     // TODO: Validate this better.
     $attachment_specs = $request->getValue('attachments', array());
     $attachments = array_select_keys($attachments, array_keys($attachment_specs));
     foreach ($attachments as $key => $attachment) {
         $attachment->setViewer($viewer);
     }
     foreach ($attachments as $key => $attachment) {
         $attachment->willLoadAttachmentData($query, $attachment_specs[$key]);
     }
     $this->setQueryOrderForConduit($query, $request);
     $this->setPagerLimitForConduit($pager, $request);
     $this->setPagerOffsetsForConduit($pager, $request);
     $objects = $this->executeQuery($query, $pager);
     $data = array();
     if ($objects) {
         $field_extensions = $this->getConduitFieldExtensions();
         $extension_data = array();
         foreach ($field_extensions as $key => $extension) {
             $extension_data[$key] = $extension->loadExtensionConduitData($objects);
         }
         $attachment_data = array();
         foreach ($attachments as $key => $attachment) {
             $attachment_data[$key] = $attachment->loadAttachmentData($objects, $attachment_specs[$key]);
         }
         foreach ($objects as $object) {
             $field_map = $this->getObjectWireFieldsForConduit($object, $field_extensions, $extension_data);
             $attachment_map = array();
             foreach ($attachments as $key => $attachment) {
                 $attachment_map[$key] = $attachment->getAttachmentForObject($object, $attachment_data[$key], $attachment_specs[$key]);
             }
             // If this is empty, we still want to emit a JSON object, not a
             // JSON list.
             if (!$attachment_map) {
                 $attachment_map = (object) $attachment_map;
             }
             $id = (int) $object->getID();
             $phid = $object->getPHID();
             $data[] = array('id' => $id, 'type' => phid_get_type($phid), 'phid' => $phid, 'fields' => $field_map, 'attachments' => $attachment_map);
         }
     }
     return array('data' => $data, 'maps' => $method->getQueryMaps($query), 'query' => array('queryKey' => $saved_query->getQueryKey()), 'cursor' => array('limit' => $pager->getPageSize(), 'after' => $pager->getNextPageID(), 'before' => $pager->getPrevPageID(), 'order' => $request->getValue('order')));
 }
 protected function getMethodFilters()
 {
     $classes = $this->getAllMethodImplementationClasses();
     $method_names = array();
     foreach ($classes as $method_class) {
         $method_name = ConduitAPIMethod::getAPIMethodNameFromClassName($method_class);
         $group_name = head(explode('.', $method_name));
         $method_object = newv($method_class, array());
         $status = $method_object->getMethodStatus();
         $key = sprintf('%02d %s %s', $this->getOrderForMethodStatus($status), $group_name, $method_name);
         $method_names[$key] = array('full_name' => $method_name, 'group_name' => $group_name, 'status' => $status, 'description' => $method_object->getMethodDescription());
     }
     ksort($method_names);
     $method_names = igroup($method_names, 'group_name');
     ksort($method_names);
     return $method_names;
 }
 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, true);
             }
             $params = $params_post;
         } else {
             $params_json = $request->getStr('params');
             if (!strlen($params_json)) {
                 $params = array();
             } else {
                 $params = json_decode($params_json, true);
                 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__']);
         $result = null;
         $api_request = new ConduitAPIRequest($params);
         $auth_error = null;
         if ($method_handler->shouldRequireAuthentication()) {
             $auth_error = $this->authenticateUser($api_request, $metadata);
         }
         if ($auth_error === null) {
             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);
             }
         } else {
             list($error_code, $error_info) = $auth_error;
         }
     } 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));
     // TODO: This is a hack, but the insert is comparatively expensive and
     // we only really care about having these logs for real CLI clients, if
     // even that.
     if (empty($metadata['authToken'])) {
         $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('for(;;);' . json_encode($result));
     }
 }
 private function decodeConduitParams(AphrontRequest $request, $method)
 {
     // Look for parameters from the Conduit API Console, which are encoded
     // as HTTP POST parameters in an array, e.g.:
     //
     //   params[name]=value&params[name2]=value2
     //
     // The fields are individually JSON encoded, since we require users to
     // enter JSON so that we avoid type ambiguity.
     $params = $request->getArr('params', null);
     if ($params !== null) {
         foreach ($params as $key => $value) {
             if ($value == '') {
                 // Interpret empty string null (e.g., the user didn't type anything
                 // into the box).
                 $value = 'null';
             }
             $decoded_value = json_decode($value, true);
             if ($decoded_value === null && strtolower($value) != 'null') {
                 // When json_decode() fails, it returns null. This almost certainly
                 // indicates that a user was using the web UI and didn't put quotes
                 // around a string value. We can either do what we think they meant
                 // (treat it as a string) or fail. For now, err on the side of
                 // caution and fail. In the future, if we make the Conduit API
                 // actually do type checking, it might be reasonable to treat it as
                 // a string if the parameter type is string.
                 throw new Exception(pht("The value for parameter '%s' is not valid JSON. All " . "parameters must be encoded as JSON values, including strings " . "(which means you need to surround them in double quotes). " . "Check your syntax. Value was: %s.", $key, $value));
             }
             $params[$key] = $decoded_value;
         }
         $metadata = idx($params, '__conduit__', array());
         unset($params['__conduit__']);
         return array($metadata, $params);
     }
     // Otherwise, look for a single parameter called 'params' which has the
     // entire param dictionary JSON encoded.
     $params_json = $request->getStr('params');
     if (strlen($params_json)) {
         $params = null;
         try {
             $params = phutil_json_decode($params_json);
         } catch (PhutilJSONParserException $ex) {
             throw new PhutilProxyException(pht("Invalid parameter information was passed to method '%s'.", $method), $ex);
         }
         $metadata = idx($params, '__conduit__', array());
         unset($params['__conduit__']);
         return array($metadata, $params);
     }
     // If we do not have `params`, assume this is a simple HTTP request with
     // HTTP key-value pairs.
     $params = array();
     $metadata = array();
     foreach ($request->getPassthroughRequestData() as $key => $value) {
         $meta_key = ConduitAPIMethod::getParameterMetadataKey($key);
         if ($meta_key !== null) {
             $metadata[$meta_key] = $value;
         } else {
             $params[$key] = $value;
         }
     }
     return array($metadata, $params);
 }
 public function testLoadAllConduitMethods()
 {
     ConduitAPIMethod::loadAllConduitMethods();
     $this->assertTrue(true);
 }
 private function authorizeOAuthMethodAccess(PhabricatorOAuthClientAuthorization $authorization, $method_name)
 {
     $method = ConduitAPIMethod::getConduitMethod($method_name);
     if (!$method) {
         return false;
     }
     $required_scope = $method->getRequiredScope();
     switch ($required_scope) {
         case ConduitAPIMethod::SCOPE_ALWAYS:
             return true;
         case ConduitAPIMethod::SCOPE_NEVER:
             return false;
     }
     $authorization_scope = $authorization->getScope();
     if (!empty($authorization_scope[$required_scope])) {
         return true;
     }
     return false;
 }
 protected function buildCustomSearchFields()
 {
     return array(id(new PhabricatorUsersSearchField())->setKey('callerPHIDs')->setLabel(pht('Methods'))->setAliases(array('caller', 'callers'))->setDescription(pht('Find calls by specific users.')), id(new PhabricatorSearchStringListField())->setKey('methods')->setLabel(pht('Methods'))->setDescription(pht('Find calls to specific methods.')), id(new PhabricatorSearchCheckboxesField())->setKey('statuses')->setLabel(pht('Method Status'))->setAliases(array('status'))->setDescription(pht('Find calls to stable, unstable, or deprecated methods.'))->setOptions(ConduitAPIMethod::getMethodStatusMap()));
 }
 private function getMethodFilters()
 {
     $classes = $this->getAllMethodImplementationClasses();
     $method_names = array();
     foreach ($classes as $method_class) {
         $method_name = ConduitAPIMethod::getAPIMethodNameFromClassName($method_class);
         $parts = explode('.', $method_name);
         $method_names[] = array('full_name' => $method_name, 'group_name' => reset($parts));
     }
     $method_names = igroup($method_names, 'group_name');
     ksort($method_names);
     return $method_names;
 }
예제 #15
0
파일: api.php 프로젝트: nexeck/phabricator
    echo "usage: api.php <user_phid> <method>\n";
    exit(1);
}
$user = null;
$user_str = $argv[1];
try {
    $user = id(new PhabricatorUser())->loadOneWhere('phid = %s', $user_str);
} catch (Exception $e) {
    // no op; we'll error in a line or two
}
if (empty($user)) {
    echo "usage: api.php <user_phid> <method>\n" . "user {$user_str} does not exist or failed to load\n";
    exit(1);
}
$method = $argv[2];
$method_class_str = ConduitAPIMethod::getClassNameFromAPIMethodName($method);
try {
    $method_class = newv($method_class_str, array());
} catch (Exception $e) {
    echo "usage: api.php <user_phid> <method>\n" . "method {$method_class_str} does not exist\n";
    exit(1);
}
$log = new PhabricatorConduitMethodCallLog();
$log->setMethod($method);
$params = @file_get_contents('php://stdin');
$params = json_decode($params, true);
if (!is_array($params)) {
    echo "provide method parameters on stdin as a JSON blob";
    exit(1);
}
// build a quick ConduitAPIRequest from stdin PLUS the authenticated user
 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'.");
         }
         $class_info = new ReflectionClass($method_class);
         if ($class_info->isAbstract()) {
             throw new Exception("Method '{$method}' is not valid; the implementation is an abstract " . "base class.");
         }
         $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) {
                 if ($value == '') {
                     // Interpret empty string null (e.g., the user didn't type anything
                     // into the box).
                     $value = 'null';
                 }
                 $decoded_value = json_decode($value, true);
                 if ($decoded_value === null && strtolower($value) != 'null') {
                     // When json_decode() fails, it returns null. This almost certainly
                     // indicates that a user was using the web UI and didn't put quotes
                     // around a string value. We can either do what we think they meant
                     // (treat it as a string) or fail. For now, err on the side of
                     // caution and fail. In the future, if we make the Conduit API
                     // actually do type checking, it might be reasonable to treat it as
                     // a string if the parameter type is string.
                     throw new Exception("The value for parameter '{$key}' is not valid JSON. All " . "parameters must be encoded as JSON values, including strings " . "(which means you need to surround them in double quotes). " . "Check your syntax. Value was: {$value}");
                 }
                 $params_post[$key] = $decoded_value;
             }
             $params = $params_post;
         } else {
             $params_json = $request->getStr('params');
             if (!strlen($params_json)) {
                 $params = array();
             } else {
                 $params = json_decode($params_json, true);
                 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__']);
         $result = null;
         $api_request = new ConduitAPIRequest($params);
         $allow_unguarded_writes = false;
         $auth_error = null;
         if ($method_handler->shouldRequireAuthentication()) {
             $auth_error = $this->authenticateUser($api_request, $metadata);
             // If we've explicitly authenticated the user here and either done
             // CSRF validation or are using a non-web authentication mechanism.
             $allow_unguarded_writes = true;
             if (isset($metadata['actAsUser'])) {
                 $this->actAsUser($api_request, $metadata['actAsUser']);
             }
         }
         if ($method_handler->shouldAllowUnguardedWrites()) {
             $allow_unguarded_writes = true;
         }
         if ($auth_error === null) {
             if ($allow_unguarded_writes) {
                 $unguarded = AphrontWriteGuard::beginScopedUnguardedWrites();
             }
             try {
                 $result = $method_handler->executeMethod($api_request);
                 $error_code = null;
                 $error_info = null;
             } catch (ConduitException $ex) {
                 $result = null;
                 $error_code = $ex->getMessage();
                 if ($ex->getErrorDescription()) {
                     $error_info = $ex->getErrorDescription();
                 } else {
                     $error_info = $method_handler->getErrorDescription($error_code);
                 }
             }
             if ($allow_unguarded_writes) {
                 unset($unguarded);
             }
         } else {
             list($error_code, $error_info) = $auth_error;
         }
     } catch (Exception $ex) {
         phlog($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));
     // TODO: This is a hack, but the insert is comparatively expensive and
     // we only really care about having these logs for real CLI clients, if
     // even that.
     if (empty($metadata['authToken'])) {
         $unguarded = AphrontWriteGuard::beginScopedUnguardedWrites();
         $log->save();
         unset($unguarded);
     }
     $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('for(;;);' . json_encode($result));
     }
 }
 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);
 }
 public function buildConduitResponse(ConduitAPIRequest $request, ConduitAPIMethod $method)
 {
     $viewer = $this->requireViewer();
     $query_key = $request->getValue('queryKey');
     if (!strlen($query_key)) {
         $saved_query = new PhabricatorSavedQuery();
     } else {
         if ($this->isBuiltinQuery($query_key)) {
             $saved_query = $this->buildSavedQueryFromBuiltin($query_key);
         } else {
             $saved_query = id(new PhabricatorSavedQueryQuery())->setViewer($viewer)->withQueryKeys(array($query_key))->executeOne();
             if (!$saved_query) {
                 throw new Exception(pht('Query key "%s" does not correspond to a valid query.', $query_key));
             }
         }
     }
     $constraints = $request->getValue('constraints', array());
     $fields = $this->getSearchFieldsForConduit();
     foreach ($fields as $key => $field) {
         if (!$field->getConduitParameterType()) {
             unset($fields[$key]);
         }
     }
     foreach ($fields as $field) {
         if (!$field->getValueExistsInConduitRequest($constraints)) {
             continue;
         }
         $value = $field->readValueFromConduitRequest($constraints);
         $saved_query->setParameter($field->getKey(), $value);
     }
     $this->saveQuery($saved_query);
     $query = $this->buildQueryFromSavedQuery($saved_query);
     $pager = $this->newPagerForSavedQuery($saved_query);
     $attachments = $this->getConduitSearchAttachments();
     // TODO: Validate this better.
     $attachment_specs = $request->getValue('attachments', array());
     $attachments = array_select_keys($attachments, array_keys($attachment_specs));
     foreach ($attachments as $key => $attachment) {
         $attachment->setViewer($viewer);
     }
     foreach ($attachments as $key => $attachment) {
         $attachment->willLoadAttachmentData($query, $attachment_specs[$key]);
     }
     $this->setQueryOrderForConduit($query, $request);
     $this->setPagerLimitForConduit($pager, $request);
     $this->setPagerOffsetsForConduit($pager, $request);
     $objects = $this->executeQuery($query, $pager);
     $data = array();
     if ($objects) {
         $field_extensions = $this->getConduitFieldExtensions();
         $attachment_data = array();
         foreach ($attachments as $key => $attachment) {
             $attachment_data[$key] = $attachment->loadAttachmentData($objects, $attachment_specs[$key]);
         }
         foreach ($objects as $object) {
             $field_map = $this->getObjectWireFieldsForConduit($object, $field_extensions);
             $attachment_map = array();
             foreach ($attachments as $key => $attachment) {
                 $attachment_map[$key] = $attachment->getAttachmentForObject($object, $attachment_data[$key], $attachment_specs[$key]);
             }
             // If this is empty, we still want to emit a JSON object, not a
             // JSON list.
             if (!$attachment_map) {
                 $attachment_map = (object) $attachment_map;
             }
             $id = (int) $object->getID();
             $phid = $object->getPHID();
             $data[] = array('id' => $id, 'type' => phid_get_type($phid), 'phid' => $phid, 'fields' => $field_map, 'attachments' => $attachment_map);
         }
     }
     return array('data' => $data, 'maps' => $method->getQueryMaps($query), 'query' => array('queryKey' => $saved_query->getQueryKey()), 'cursor' => array('limit' => $pager->getPageSize(), 'after' => $pager->getNextPageID(), 'before' => $pager->getPrevPageID(), 'order' => $request->getValue('order')));
 }
 public function __construct(ConduitAPIMethod $method, $application)
 {
     parent::__construct(pht("Method '%s' belongs to application '%s', which is not installed.", $method->getAPIMethodName(), $application));
 }
예제 #20
0
 protected function buildMethodHandler($method_name)
 {
     $method = ConduitAPIMethod::getConduitMethod($method_name);
     if (!$method) {
         throw new ConduitMethodDoesNotExistException($method_name);
     }
     $application = $method->getApplication();
     if ($application && !$application->isInstalled()) {
         $app_name = $application->getName();
         throw new ConduitApplicationNotInstalledException($method, $app_name);
     }
     return $method;
 }