miniflux-legacy/vendor/fguillot/json-rpc/src/JsonRPC/ProcedureHandler.php

265 lines
6.8 KiB
PHP
Raw Normal View History

2016-05-08 21:53:45 +02:00
<?php
namespace JsonRPC;
use BadFunctionCallException;
use Closure;
use InvalidArgumentException;
use ReflectionFunction;
use ReflectionMethod;
/**
* Class ProcedureHandler
*
* @package JsonRPC
* @author Frederic Guillot
*/
class ProcedureHandler
{
/**
* List of procedures
*
2016-08-06 02:27:09 +02:00
* @access protected
2016-05-08 21:53:45 +02:00
* @var array
*/
2016-08-06 02:27:09 +02:00
protected $callbacks = array();
2016-05-08 21:53:45 +02:00
/**
* List of classes
*
2016-08-06 02:27:09 +02:00
* @access protected
2016-05-08 21:53:45 +02:00
* @var array
*/
2016-08-06 02:27:09 +02:00
protected $classes = array();
2016-05-08 21:53:45 +02:00
/**
* List of instances
*
2016-08-06 02:27:09 +02:00
* @access protected
2016-05-08 21:53:45 +02:00
* @var array
*/
2016-08-06 02:27:09 +02:00
protected $instances = array();
2016-05-08 21:53:45 +02:00
/**
2016-08-06 02:27:09 +02:00
* Before method name to call
2016-05-08 21:53:45 +02:00
*
2016-08-06 02:27:09 +02:00
* @access protected
2016-05-08 21:53:45 +02:00
* @var string
*/
2016-08-06 02:27:09 +02:00
protected $beforeMethodName = '';
2016-05-08 21:53:45 +02:00
/**
* Register a new procedure
*
* @access public
* @param string $procedure Procedure name
* @param closure $callback Callback
2016-08-06 02:27:09 +02:00
* @return $this
2016-05-08 21:53:45 +02:00
*/
public function withCallback($procedure, Closure $callback)
{
$this->callbacks[$procedure] = $callback;
return $this;
}
/**
* Bind a procedure to a class
*
* @access public
* @param string $procedure Procedure name
* @param mixed $class Class name or instance
* @param string $method Procedure name
2016-08-06 02:27:09 +02:00
* @return $this
2016-05-08 21:53:45 +02:00
*/
public function withClassAndMethod($procedure, $class, $method = '')
{
if ($method === '') {
$method = $procedure;
}
$this->classes[$procedure] = array($class, $method);
return $this;
}
/**
* Bind a class instance
*
* @access public
* @param mixed $instance
2016-08-06 02:27:09 +02:00
* @return $this
2016-05-08 21:53:45 +02:00
*/
public function withObject($instance)
{
$this->instances[] = $instance;
return $this;
}
/**
2016-08-06 02:27:09 +02:00
* Set a before method to call
2016-05-08 21:53:45 +02:00
*
* @access public
2016-08-06 02:27:09 +02:00
* @param string $methodName
* @return $this
2016-05-08 21:53:45 +02:00
*/
2016-08-06 02:27:09 +02:00
public function withBeforeMethod($methodName)
2016-05-08 21:53:45 +02:00
{
2016-08-06 02:27:09 +02:00
$this->beforeMethodName = $methodName;
2016-05-08 21:53:45 +02:00
return $this;
}
/**
* Execute the procedure
*
* @access public
* @param string $procedure Procedure name
* @param array $params Procedure params
* @return mixed
*/
public function executeProcedure($procedure, array $params = array())
{
if (isset($this->callbacks[$procedure])) {
return $this->executeCallback($this->callbacks[$procedure], $params);
2016-08-06 02:27:09 +02:00
} elseif (isset($this->classes[$procedure]) && method_exists($this->classes[$procedure][0], $this->classes[$procedure][1])) {
2016-05-08 21:53:45 +02:00
return $this->executeMethod($this->classes[$procedure][0], $this->classes[$procedure][1], $params);
}
foreach ($this->instances as $instance) {
if (method_exists($instance, $procedure)) {
return $this->executeMethod($instance, $procedure, $params);
}
}
throw new BadFunctionCallException('Unable to find the procedure');
}
/**
* Execute a callback
*
* @access public
* @param Closure $callback Callback
* @param array $params Procedure params
* @return mixed
*/
public function executeCallback(Closure $callback, $params)
{
$reflection = new ReflectionFunction($callback);
$arguments = $this->getArguments(
$params,
$reflection->getParameters(),
$reflection->getNumberOfRequiredParameters(),
$reflection->getNumberOfParameters()
);
return $reflection->invokeArgs($arguments);
}
/**
* Execute a method
*
* @access public
* @param mixed $class Class name or instance
* @param string $method Method name
* @param array $params Procedure params
* @return mixed
*/
public function executeMethod($class, $method, $params)
{
$instance = is_string($class) ? new $class : $class;
$reflection = new ReflectionMethod($class, $method);
2016-08-06 02:27:09 +02:00
$this->executeBeforeMethod($instance, $method);
2016-05-08 21:53:45 +02:00
$arguments = $this->getArguments(
$params,
$reflection->getParameters(),
$reflection->getNumberOfRequiredParameters(),
$reflection->getNumberOfParameters()
);
return $reflection->invokeArgs($instance, $arguments);
}
2016-08-06 02:27:09 +02:00
/**
* Execute before method if defined
*
* @access public
* @param mixed $object
* @param string $method
*/
public function executeBeforeMethod($object, $method)
{
if ($this->beforeMethodName !== '' && method_exists($object, $this->beforeMethodName)) {
call_user_func_array(array($object, $this->beforeMethodName), array($method));
}
}
2016-05-08 21:53:45 +02:00
/**
* Get procedure arguments
*
* @access public
2016-08-06 02:27:09 +02:00
* @param array $requestParams Incoming arguments
* @param array $methodParams Procedure arguments
* @param integer $nbRequiredParams Number of required parameters
* @param integer $nbMaxParams Maximum number of parameters
2016-05-08 21:53:45 +02:00
* @return array
*/
2016-08-06 02:27:09 +02:00
public function getArguments(array $requestParams, array $methodParams, $nbRequiredParams, $nbMaxParams)
2016-05-08 21:53:45 +02:00
{
2016-08-06 02:27:09 +02:00
$nbParams = count($requestParams);
2016-05-08 21:53:45 +02:00
2016-08-06 02:27:09 +02:00
if ($nbParams < $nbRequiredParams) {
2016-05-08 21:53:45 +02:00
throw new InvalidArgumentException('Wrong number of arguments');
}
2016-08-06 02:27:09 +02:00
if ($nbParams > $nbMaxParams) {
2016-05-08 21:53:45 +02:00
throw new InvalidArgumentException('Too many arguments');
}
2016-08-06 02:27:09 +02:00
if ($this->isPositionalArguments($requestParams)) {
return $requestParams;
2016-05-08 21:53:45 +02:00
}
2016-08-06 02:27:09 +02:00
return $this->getNamedArguments($requestParams, $methodParams);
2016-05-08 21:53:45 +02:00
}
/**
* Return true if we have positional parameters
*
* @access public
* @param array $request_params Incoming arguments
* @return bool
*/
public function isPositionalArguments(array $request_params)
{
return array_keys($request_params) === range(0, count($request_params) - 1);
}
/**
* Get named arguments
*
* @access public
2016-08-06 02:27:09 +02:00
* @param array $requestParams Incoming arguments
* @param array $methodParams Procedure arguments
2016-05-08 21:53:45 +02:00
* @return array
*/
2016-08-06 02:27:09 +02:00
public function getNamedArguments(array $requestParams, array $methodParams)
2016-05-08 21:53:45 +02:00
{
$params = array();
2016-08-06 02:27:09 +02:00
foreach ($methodParams as $p) {
2016-05-08 21:53:45 +02:00
$name = $p->getName();
2016-08-06 02:27:09 +02:00
if (isset($requestParams[$name])) {
$params[$name] = $requestParams[$name];
} elseif ($p->isDefaultValueAvailable()) {
2016-05-08 21:53:45 +02:00
$params[$name] = $p->getDefaultValue();
2016-08-06 02:27:09 +02:00
} else {
2016-05-08 21:53:45 +02:00
throw new InvalidArgumentException('Missing argument: '.$name);
}
}
return $params;
}
}