class Handler in JSON-RPC 2.x
Same name and namespace in other branches
- 8 src/Handler.php \Drupal\jsonrpc\Handler
Manages all the JSON-RPC business logic.
Hierarchy
- class \Drupal\jsonrpc\Handler implements HandlerInterface
Expanded class hierarchy of Handler
2 files declare their use of Handler
- SecondMethod.php in tests/
modules/ jsonrpc_test/ src/ Plugin/ jsonrpc/ Method/ SecondMethod.php - ThirdMethod.php in tests/
modules/ jsonrpc_test/ src/ Plugin/ jsonrpc/ Method/ ThirdMethod.php
1 string reference to 'Handler'
1 service uses Handler
File
- src/
Handler.php, line 21
Namespace
Drupal\jsonrpcView source
class Handler implements HandlerInterface {
/**
* The support JSON-RPC version.
*
* @var string
*/
const SUPPORTED_VERSION = '2.0';
/**
* The JSON-RPC method plugin manager.
*
* @var \Drupal\Component\Plugin\PluginManagerInterface
*/
protected $methodManager;
/**
* The renderer.
*
* @var \Drupal\Core\Render\RendererInterface
*/
protected $renderer;
/**
* Handler constructor.
*
* @param \Drupal\Component\Plugin\PluginManagerInterface $method_manager
* The plugin manager for the JSON RPC methods.
* @param \Drupal\Core\Render\RendererInterface $renderer
* The Drupal renderer.
*/
public function __construct(PluginManagerInterface $method_manager, RendererInterface $renderer) {
$this->methodManager = $method_manager;
$this->renderer = $renderer;
}
/**
* {@inheritdoc}
*/
public static function supportedVersion() {
return static::SUPPORTED_VERSION;
}
/**
* {@inheritdoc}
*/
public function batch(array $requests) {
return array_filter(array_map(function (Request $request) {
return $this
->doRequest($request);
}, $requests));
}
/**
* {@inheritdoc}
*/
public function supportedMethods() {
return $this->methodManager
->getDefinitions();
}
/**
* {@inheritdoc}
*/
public function supportsMethod($name) {
return !is_null($this
->getMethod($name));
}
/**
* {@inheritdoc}
*/
public function availableMethods(AccountInterface $account = NULL) {
return array_filter($this
->supportedMethods(), function (MethodInterface $method) {
return $method
->access('execute');
});
}
/**
* {@inheritdoc}
*/
public function getMethod($name) {
return $this->methodManager
->getDefinition($name, FALSE);
}
/**
* Executes an RPC call and returns a JSON-RPC response.
*
* @param \Drupal\jsonrpc\Object\Request $request
* The JSON-RPC request.
*
* @return \Drupal\jsonrpc\Object\Response|null
* The JSON-RPC response.
*/
protected function doRequest(Request $request) {
// Helper closure to handle eventual exceptions.
$handle_exception = function ($e, Request $request) {
if (!$e instanceof JsonRpcException) {
$id = $request
->isNotification() ? FALSE : $request
->id();
$e = JsonRpcException::fromPrevious($e, $id);
}
return $e
->getResponse();
};
try {
$context = new RenderContext();
$result = $this->renderer
->executeInRenderContext($context, function () use ($request) {
return $this
->doExecution($request);
});
if ($request
->isNotification()) {
return NULL;
}
$rpc_response = $result instanceof Response ? $result : new Response(static::SUPPORTED_VERSION, $request
->id(), $result);
$methodPluginClass = $this
->getMethod($request
->getMethod())
->getClass();
$result_schema = call_user_func([
$methodPluginClass,
'outputSchema',
]);
$rpc_response
->setResultSchema($result_schema);
$response_headers = $this
->getMethod($request
->getMethod())->responseHeaders;
$rpc_response
->getHeaders()
->add($response_headers);
if (!$context
->isEmpty()) {
/** @var \Drupal\Core\Render\BubbleableMetadata $bubbleable_metadata */
$bubbleable_metadata = $context
->pop();
$rpc_response
->addCacheableDependency($bubbleable_metadata);
if ($rpc_response instanceof AttachmentsInterface) {
$rpc_response
->addAttachments($bubbleable_metadata
->getAttachments());
}
}
return $rpc_response;
} catch (\Throwable $e) {
return $handle_exception($e, $request);
} catch (\Exception $e) {
return $handle_exception($e, $request);
}
}
/**
* Gets an anonymous function which executes the RPC method.
*
* @param \Drupal\jsonrpc\Object\Request $request
* The JSON-RPC request.
*
* @return \Drupal\jsonrpc\Object\Response|null
* The JSON-RPC response.
*
* @throws \Drupal\jsonrpc\Exception\JsonRpcException
*/
protected function doExecution(Request $request) {
if ($method = $this
->getMethod($request
->getMethod())) {
$this
->checkAccess($method);
$configuration = [
HandlerInterface::JSONRPC_REQUEST_KEY => $request,
];
$executable = $this
->getExecutable($method, $configuration);
return $request
->hasParams() ? $executable
->execute($request
->getParams()) : $executable
->execute(new ParameterBag([]));
}
else {
throw JsonRpcException::fromError(Error::methodNotFound($method
->id()));
}
}
/**
* Gets an executable instance of an RPC method.
*
* @param \Drupal\jsonrpc\MethodInterface $method
* The method definition.
* @param array $configuration
* Method configuration.
*
* @return object
* The executable method.
*
* @throws \Drupal\jsonrpc\Exception\JsonRpcException
* In case of error.
*/
protected function getExecutable(MethodInterface $method, array $configuration) {
try {
return $this->methodManager
->createInstance($method
->id(), $configuration);
} catch (PluginException $e) {
throw JsonRpcException::fromError(Error::methodNotFound($method
->id()));
}
}
/**
* Check execution access.
*
* @param \Drupal\jsonrpc\MethodInterface $method
* The method for which to check access.
*
* @throws \Drupal\jsonrpc\Exception\JsonRpcException
*/
protected function checkAccess(MethodInterface $method) {
// TODO: Add cacheability metadata here.
/* @var \Drupal\jsonrpc\MethodInterface $method_definition */
$access_result = $method
->access('execute', NULL, TRUE);
if (!$access_result
->isAllowed()) {
$reason = 'Access Denied';
if ($access_result instanceof AccessResultReasonInterface && ($detail = $access_result
->getReason())) {
$reason .= ': ' . $detail;
}
throw JsonRpcException::fromError(Error::invalidRequest($reason, $access_result));
}
}
}
Members
Name | Modifiers | Type | Description | Overrides |
---|---|---|---|---|
Handler:: |
protected | property | The JSON-RPC method plugin manager. | |
Handler:: |
protected | property | The renderer. | |
Handler:: |
public | function |
The methods which are available to the given account. Overrides HandlerInterface:: |
|
Handler:: |
public | function |
Executes a batch of remote procedure calls. Overrides HandlerInterface:: |
|
Handler:: |
protected | function | Check execution access. | |
Handler:: |
protected | function | Gets an anonymous function which executes the RPC method. | |
Handler:: |
protected | function | Executes an RPC call and returns a JSON-RPC response. | |
Handler:: |
protected | function | Gets an executable instance of an RPC method. | |
Handler:: |
public | function |
Gets a method definition by method name. Overrides HandlerInterface:: |
|
Handler:: |
public | function |
The methods supported by the handler. Overrides HandlerInterface:: |
|
Handler:: |
public static | function |
The supported JSON-RPC version. Overrides HandlerInterface:: |
|
Handler:: |
constant | The support JSON-RPC version. | ||
Handler:: |
public | function |
Whether the given method is supported. Overrides HandlerInterface:: |
|
Handler:: |
public | function | Handler constructor. | |
HandlerInterface:: |
constant | The configuration array key for the JSON-RPC request object. |