diff --git a/composer.json b/composer.json index 2749692..df986cb 100644 --- a/composer.json +++ b/composer.json @@ -13,7 +13,7 @@ }, "require": { "fguillot/simple-validator": "v1.0.0", - "fguillot/json-rpc": "v1.1.0", + "fguillot/json-rpc": "v1.2.1", "fguillot/picodb": "v1.0.14 ", "fguillot/picofeed": "v0.1.24", "pda/pheanstalk": "v3.1.0" diff --git a/jsonrpc.php b/jsonrpc.php index c448634..e2b1fee 100644 --- a/jsonrpc.php +++ b/jsonrpc.php @@ -11,13 +11,15 @@ $server->authentication(array( Config\get('username') => Config\get('api_token') )); +$procedureHandler = $server->getProcedureHandler(); + // Get version -$server->register('app.version', function () { +$procedureHandler->withCallback('app.version', function () { return array('version' => APP_VERSION); }); // Get all feeds -$server->register('feed.list', function () { +$procedureHandler->withCallback('feed.list', function () { $feeds = Model\Feed\get_all(); if (empty($feeds)) { return array(); @@ -36,14 +38,14 @@ $server->register('feed.list', function () { }); // Get one feed -$server->register('feed.info', function ($feed_id) { +$procedureHandler->withCallback('feed.info', function ($feed_id) { $result = Model\Feed\get($feed_id); $result['feed_group_ids'] = Model\Group\get_feed_group_ids($feed_id); return $result; }); // Add a new feed -$server->register('feed.create', function($url) { +$procedureHandler->withCallback('feed.create', function($url) { try { $result = Model\Feed\create($url); } catch (Exception $e) { @@ -56,172 +58,172 @@ $server->register('feed.create', function($url) { }); // Delete a feed -$server->register('feed.delete', function($feed_id) { +$procedureHandler->withCallback('feed.delete', function($feed_id) { return Model\Feed\remove($feed_id); }); // Delete all feeds -$server->register('feed.delete_all', function() { +$procedureHandler->withCallback('feed.delete_all', function() { return Model\Feed\remove_all(); }); // Enable a feed -$server->register('feed.enable', function($feed_id) { +$procedureHandler->withCallback('feed.enable', function($feed_id) { return Model\Feed\enable($feed_id); }); // Disable a feed -$server->register('feed.disable', function($feed_id) { +$procedureHandler->withCallback('feed.disable', function($feed_id) { return Model\Feed\disable($feed_id); }); // Update a feed -$server->register('feed.update', function($feed_id) { +$procedureHandler->withCallback('feed.update', function($feed_id) { return Model\Feed\refresh($feed_id); }); // Get all groups -$server->register('group.list', function () { +$procedureHandler->withCallback('group.list', function () { return Model\Group\get_all(); }); // Add a new group -$server->register('group.create', function($title) { +$procedureHandler->withCallback('group.create', function($title) { return Model\Group\create($title); }); // Get assoc array of group ids with assigned feeds ids -$server->register('group.map', function() { +$procedureHandler->withCallback('group.map', function() { return Model\Group\get_map(); }); // Get the id of a group -$server->register('group.id', function($title) { +$procedureHandler->withCallback('group.id', function($title) { return Model\Group\get_group_id($title); }); // Get all feed ids assigned to a group -$server->register('group.feeds', function($group_id) { +$procedureHandler->withCallback('group.feeds', function($group_id) { return Model\Group\get_feeds_by_group($group_id); }); // Add groups to feed -$server->register('group.add', function($feed_id, $group_ids) { +$procedureHandler->withCallback('group.add', function($feed_id, $group_ids) { return Model\Group\add($feed_id, $group_ids); }); // Remove groups from feed -$server->register('group.remove', function($feed_id, $group_ids) { +$procedureHandler->withCallback('group.remove', function($feed_id, $group_ids) { return Model\Group\remove($feed_id, $group_ids); }); // Remove all groups from feed -$server->register('group.remove_all', function($feed_id) { +$procedureHandler->withCallback('group.remove_all', function($feed_id) { return Model\Group\remove_all($feed_id); }); // Update feed group associations -$server->register('group.update_feed_groups', function($feed_id, $group_ids, $create_group = '') { +$procedureHandler->withCallback('group.update_feed_groups', function($feed_id, $group_ids, $create_group = '') { return Model\Group\update_feed_groups($feed_id, $group_ids, $create_group); }); // Get all items for a specific feed -$server->register('item.feed.list', function ($feed_id, $offset = null, $limit = null) { +$procedureHandler->withCallback('item.feed.list', function ($feed_id, $offset = null, $limit = null) { return Model\Item\get_all_by_feed($feed_id, $offset, $limit); }); // Count all feed items -$server->register('item.feed.count', function ($feed_id) { +$procedureHandler->withCallback('item.feed.count', function ($feed_id) { return Model\Item\count_by_feed($feed_id); }); // Get all bookmark items -$server->register('item.bookmark.list', function ($offset = null, $limit = null) { +$procedureHandler->withCallback('item.bookmark.list', function ($offset = null, $limit = null) { return Model\Item\get_bookmarks($offset, $limit); }); // Count bookmarks -$server->register('item.bookmark.count', function () { +$procedureHandler->withCallback('item.bookmark.count', function () { return Model\Item\count_bookmarks(); }); // Add a bookmark -$server->register('item.bookmark.create', function ($item_id) { +$procedureHandler->withCallback('item.bookmark.create', function ($item_id) { return Model\Item\set_bookmark_value($item_id, 1); }); // Remove a bookmark -$server->register('item.bookmark.delete', function ($item_id) { +$procedureHandler->withCallback('item.bookmark.delete', function ($item_id) { return Model\Item\set_bookmark_value($item_id, 0); }); // Get all unread items -$server->register('item.list_unread', function ($offset = null, $limit = null) { +$procedureHandler->withCallback('item.list_unread', function ($offset = null, $limit = null) { return Model\Item\get_all_by_status('unread', array(), $offset, $limit); }); // Count all unread items -$server->register('item.count_unread', function () { +$procedureHandler->withCallback('item.count_unread', function () { return Model\Item\count_by_status('unread'); }); // Get all read items -$server->register('item.list_read', function ($offset = null, $limit = null) { +$procedureHandler->withCallback('item.list_read', function ($offset = null, $limit = null) { return Model\Item\get_all_by_status('read', array(), $offset, $limit); }); // Count all read items -$server->register('item.count_read', function () { +$procedureHandler->withCallback('item.count_read', function () { return Model\Item\count_by_status('read'); }); // Get one item -$server->register('item.info', function ($item_id) { +$procedureHandler->withCallback('item.info', function ($item_id) { return Model\Item\get($item_id); }); // Delete an item -$server->register('item.delete', function($item_id) { +$procedureHandler->withCallback('item.delete', function($item_id) { return Model\Item\set_removed($item_id); }); // Mark item as read -$server->register('item.mark_as_read', function($item_id) { +$procedureHandler->withCallback('item.mark_as_read', function($item_id) { return Model\Item\set_read($item_id); }); // Mark item as unread -$server->register('item.mark_as_unread', function($item_id) { +$procedureHandler->withCallback('item.mark_as_unread', function($item_id) { return Model\Item\set_unread($item_id); }); // Change the status of list of items -$server->register('item.set_list_status', function($status, array $items) { +$procedureHandler->withCallback('item.set_list_status', function($status, array $items) { return Model\Item\set_status($status, $items); }); // Flush all read items -$server->register('item.flush', function() { +$procedureHandler->withCallback('item.flush', function() { return Model\Item\mark_all_as_removed(); }); // Mark all unread items as read -$server->register('item.mark_all_as_read', function() { +$procedureHandler->withCallback('item.mark_all_as_read', function() { return Model\Item\mark_all_as_read(); }); // Get all items with the content -$server->register('item.get_all', function() { +$procedureHandler->withCallback('item.get_all', function() { return Model\Item\get_all(); }); // Get all items since a date -$server->register('item.get_all_since', function($timestamp) { +$procedureHandler->withCallback('item.get_all_since', function($timestamp) { return Model\Item\get_all_since($timestamp); }); // Get all items id and status -$server->register('item.get_all_status', function() { +$procedureHandler->withCallback('item.get_all_status', function() { return Model\Item\get_all_status(); }); diff --git a/vendor/composer/autoload_classmap.php b/vendor/composer/autoload_classmap.php index 98da40a..69c5fec 100644 --- a/vendor/composer/autoload_classmap.php +++ b/vendor/composer/autoload_classmap.php @@ -16,6 +16,8 @@ return array( 'JsonRPC\\Exception\\ResponseException' => $vendorDir . '/fguillot/json-rpc/src/JsonRPC/Exception/ResponseException.php', 'JsonRPC\\Exception\\ServerErrorException' => $vendorDir . '/fguillot/json-rpc/src/JsonRPC/Exception/ServerErrorException.php', 'JsonRPC\\HttpClient' => $vendorDir . '/fguillot/json-rpc/src/JsonRPC/HttpClient.php', + 'JsonRPC\\MiddlewareHandler' => $vendorDir . '/fguillot/json-rpc/src/JsonRPC/MiddlewareHandler.php', + 'JsonRPC\\MiddlewareInterface' => $vendorDir . '/fguillot/json-rpc/src/JsonRPC/MiddlewareInterface.php', 'JsonRPC\\ProcedureHandler' => $vendorDir . '/fguillot/json-rpc/src/JsonRPC/ProcedureHandler.php', 'JsonRPC\\Request\\BatchRequestParser' => $vendorDir . '/fguillot/json-rpc/src/JsonRPC/Request/BatchRequestParser.php', 'JsonRPC\\Request\\RequestBuilder' => $vendorDir . '/fguillot/json-rpc/src/JsonRPC/Request/RequestBuilder.php', diff --git a/vendor/composer/autoload_static.php b/vendor/composer/autoload_static.php index 055e64b..6b118af 100644 --- a/vendor/composer/autoload_static.php +++ b/vendor/composer/autoload_static.php @@ -88,6 +88,8 @@ class ComposerStaticInitfd7e8d436e1dc450edc3153ac8bc31b4 'JsonRPC\\Exception\\ResponseException' => __DIR__ . '/..' . '/fguillot/json-rpc/src/JsonRPC/Exception/ResponseException.php', 'JsonRPC\\Exception\\ServerErrorException' => __DIR__ . '/..' . '/fguillot/json-rpc/src/JsonRPC/Exception/ServerErrorException.php', 'JsonRPC\\HttpClient' => __DIR__ . '/..' . '/fguillot/json-rpc/src/JsonRPC/HttpClient.php', + 'JsonRPC\\MiddlewareHandler' => __DIR__ . '/..' . '/fguillot/json-rpc/src/JsonRPC/MiddlewareHandler.php', + 'JsonRPC\\MiddlewareInterface' => __DIR__ . '/..' . '/fguillot/json-rpc/src/JsonRPC/MiddlewareInterface.php', 'JsonRPC\\ProcedureHandler' => __DIR__ . '/..' . '/fguillot/json-rpc/src/JsonRPC/ProcedureHandler.php', 'JsonRPC\\Request\\BatchRequestParser' => __DIR__ . '/..' . '/fguillot/json-rpc/src/JsonRPC/Request/BatchRequestParser.php', 'JsonRPC\\Request\\RequestBuilder' => __DIR__ . '/..' . '/fguillot/json-rpc/src/JsonRPC/Request/RequestBuilder.php', diff --git a/vendor/composer/installed.json b/vendor/composer/installed.json index e4579fd..d93abc2 100644 --- a/vendor/composer/installed.json +++ b/vendor/composer/installed.json @@ -136,44 +136,6 @@ "beanstalkd" ] }, - { - "name": "fguillot/json-rpc", - "version": "v1.1.0", - "version_normalized": "1.1.0.0", - "source": { - "type": "git", - "url": "https://github.com/fguillot/JsonRPC.git", - "reference": "e915dab71940e7ac251955c785570048f460d332" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/fguillot/JsonRPC/zipball/e915dab71940e7ac251955c785570048f460d332", - "reference": "e915dab71940e7ac251955c785570048f460d332", - "shasum": "" - }, - "require": { - "php": ">=5.3.4" - }, - "time": "2016-04-27 02:48:10", - "type": "library", - "installation-source": "dist", - "autoload": { - "psr-0": { - "JsonRPC": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Frédéric Guillot" - } - ], - "description": "Simple Json-RPC client/server library that just works", - "homepage": "https://github.com/fguillot/JsonRPC" - }, { "name": "fguillot/picofeed", "version": "v0.1.24", @@ -265,5 +227,46 @@ ], "description": "Minimalist database query builder", "homepage": "https://github.com/fguillot/picoDb" + }, + { + "name": "fguillot/json-rpc", + "version": "v1.2.1", + "version_normalized": "1.2.1.0", + "source": { + "type": "git", + "url": "https://github.com/fguillot/JsonRPC.git", + "reference": "d491bb549bfa11aff4c37abcea2ffb28c9523f69" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/fguillot/JsonRPC/zipball/d491bb549bfa11aff4c37abcea2ffb28c9523f69", + "reference": "d491bb549bfa11aff4c37abcea2ffb28c9523f69", + "shasum": "" + }, + "require": { + "php": ">=5.3.4" + }, + "require-dev": { + "phpunit/phpunit": "4.8.*" + }, + "time": "2016-06-25 23:11:10", + "type": "library", + "installation-source": "dist", + "autoload": { + "psr-0": { + "JsonRPC": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Frédéric Guillot" + } + ], + "description": "Simple Json-RPC client/server library that just works", + "homepage": "https://github.com/fguillot/JsonRPC" } ] diff --git a/vendor/fguillot/json-rpc/src/JsonRPC/Client.php b/vendor/fguillot/json-rpc/src/JsonRPC/Client.php index dba0739..fed1ce3 100644 --- a/vendor/fguillot/json-rpc/src/JsonRPC/Client.php +++ b/vendor/fguillot/json-rpc/src/JsonRPC/Client.php @@ -155,15 +155,17 @@ class Client * Execute a procedure * * @access public - * @param string $procedure Procedure name - * @param array $params Procedure arguments + * @param string $procedure Procedure name + * @param array $params Procedure arguments + * @param array $reqattrs * @return mixed */ - public function execute($procedure, array $params = array()) + public function execute($procedure, array $params = array(), array $reqattrs = array()) { $payload = RequestBuilder::create() ->withProcedure($procedure) ->withParams($params) + ->withRequestAttributes($reqattrs) ->build(); if ($this->isBatch) { @@ -184,18 +186,9 @@ class Client */ private function sendPayload($payload) { - try { - - return ResponseParser::create() - ->withPayload($this->httpClient->execute($payload)) - ->parse(); - - } catch (Exception $e) { - if ($this->returnException) { - return $e; - } - - throw $e; - } + return ResponseParser::create() + ->withReturnException($this->returnException) + ->withPayload($this->httpClient->execute($payload)) + ->parse(); } } diff --git a/vendor/fguillot/json-rpc/src/JsonRPC/HttpClient.php b/vendor/fguillot/json-rpc/src/JsonRPC/HttpClient.php index f41d1a6..90ce705 100644 --- a/vendor/fguillot/json-rpc/src/JsonRPC/HttpClient.php +++ b/vendor/fguillot/json-rpc/src/JsonRPC/HttpClient.php @@ -257,7 +257,7 @@ class HttpClient $response = json_decode(stream_get_contents($stream), true); if ($this->debug) { - error_log('==> Request: '.PHP_EOL.json_encode($payload, JSON_PRETTY_PRINT)); + error_log('==> Request: '.PHP_EOL.(is_string($payload) ? $payload : json_encode($payload, JSON_PRETTY_PRINT))); error_log('==> Headers: '.PHP_EOL.var_export($headers, true)); error_log('==> Response: '.PHP_EOL.json_encode($response, JSON_PRETTY_PRINT)); } diff --git a/vendor/fguillot/json-rpc/src/JsonRPC/MiddlewareHandler.php b/vendor/fguillot/json-rpc/src/JsonRPC/MiddlewareHandler.php new file mode 100644 index 0000000..61d5a2d --- /dev/null +++ b/vendor/fguillot/json-rpc/src/JsonRPC/MiddlewareHandler.php @@ -0,0 +1,114 @@ +username = $username; + } + + return $this; + } + + /** + * Set password + * + * @access public + * @param string $password + * @return $this + */ + public function withPassword($password) + { + if (! empty($password)) { + $this->password = $password; + } + + return $this; + } + + /** + * Set procedure name + * + * @access public + * @param string $procedureName + * @return $this + */ + public function withProcedure($procedureName) + { + $this->procedureName = $procedureName; + return $this; + } + + /** + * Add a new middleware + * + * @access public + * @param MiddlewareInterface $middleware + * @return MiddlewareHandler + */ + public function withMiddleware(MiddlewareInterface $middleware) + { + $this->middleware[] = $middleware; + return $this; + } + + /** + * Execute all middleware + * + * @access public + */ + public function execute() + { + foreach ($this->middleware as $middleware) { + $middleware->execute($this->username, $this->password, $this->procedureName); + } + } +} diff --git a/vendor/fguillot/json-rpc/src/JsonRPC/MiddlewareInterface.php b/vendor/fguillot/json-rpc/src/JsonRPC/MiddlewareInterface.php new file mode 100644 index 0000000..ab55261 --- /dev/null +++ b/vendor/fguillot/json-rpc/src/JsonRPC/MiddlewareInterface.php @@ -0,0 +1,27 @@ +username = $username; - return $this; - } - - /** - * Set password - * - * @access public - * @param string $password - * @return $this - */ - public function withPassword($password) - { - $this->password = $password; - return $this; - } + protected $beforeMethodName = ''; /** * Register a new procedure @@ -96,7 +54,7 @@ class ProcedureHandler * @access public * @param string $procedure Procedure name * @param closure $callback Callback - * @return Server + * @return $this */ public function withCallback($procedure, Closure $callback) { @@ -111,7 +69,7 @@ class ProcedureHandler * @param string $procedure Procedure name * @param mixed $class Class name or instance * @param string $method Procedure name - * @return Server + * @return $this */ public function withClassAndMethod($procedure, $class, $method = '') { @@ -128,7 +86,7 @@ class ProcedureHandler * * @access public * @param mixed $instance - * @return Server + * @return $this */ public function withObject($instance) { @@ -137,15 +95,15 @@ class ProcedureHandler } /** - * Attach a method that will be called before the procedure + * Set a before method to call * * @access public - * @param string $before - * @return Server + * @param string $methodName + * @return $this */ - public function withBeforeMethod($before) + public function withBeforeMethod($methodName) { - $this->before = $before; + $this->beforeMethodName = $methodName; return $this; } @@ -161,8 +119,7 @@ class ProcedureHandler { if (isset($this->callbacks[$procedure])) { return $this->executeCallback($this->callbacks[$procedure], $params); - } - else if (isset($this->classes[$procedure]) && method_exists($this->classes[$procedure][0], $this->classes[$procedure][1])) { + } elseif (isset($this->classes[$procedure]) && method_exists($this->classes[$procedure][0], $this->classes[$procedure][1])) { return $this->executeMethod($this->classes[$procedure][0], $this->classes[$procedure][1], $params); } @@ -209,19 +166,10 @@ class ProcedureHandler public function executeMethod($class, $method, $params) { $instance = is_string($class) ? new $class : $class; - - // Execute before action - if (! empty($this->before)) { - if (is_callable($this->before)) { - call_user_func_array($this->before, array($this->username, $this->password, get_class($class), $method)); - } - else if (method_exists($instance, $this->before)) { - $instance->{$this->before}($this->username, $this->password, get_class($class), $method); - } - } - $reflection = new ReflectionMethod($class, $method); + $this->executeBeforeMethod($instance, $method); + $arguments = $this->getArguments( $params, $reflection->getParameters(), @@ -232,33 +180,47 @@ class ProcedureHandler return $reflection->invokeArgs($instance, $arguments); } + /** + * 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)); + } + } + /** * Get procedure arguments * * @access public - * @param array $request_params Incoming arguments - * @param array $method_params Procedure arguments - * @param integer $nb_required_params Number of required parameters - * @param integer $nb_max_params Maximum number of parameters + * @param array $requestParams Incoming arguments + * @param array $methodParams Procedure arguments + * @param integer $nbRequiredParams Number of required parameters + * @param integer $nbMaxParams Maximum number of parameters * @return array */ - public function getArguments(array $request_params, array $method_params, $nb_required_params, $nb_max_params) + public function getArguments(array $requestParams, array $methodParams, $nbRequiredParams, $nbMaxParams) { - $nb_params = count($request_params); + $nbParams = count($requestParams); - if ($nb_params < $nb_required_params) { + if ($nbParams < $nbRequiredParams) { throw new InvalidArgumentException('Wrong number of arguments'); } - if ($nb_params > $nb_max_params) { + if ($nbParams > $nbMaxParams) { throw new InvalidArgumentException('Too many arguments'); } - if ($this->isPositionalArguments($request_params)) { - return $request_params; + if ($this->isPositionalArguments($requestParams)) { + return $requestParams; } - return $this->getNamedArguments($request_params, $method_params); + return $this->getNamedArguments($requestParams, $methodParams); } /** @@ -277,24 +239,22 @@ class ProcedureHandler * Get named arguments * * @access public - * @param array $request_params Incoming arguments - * @param array $method_params Procedure arguments + * @param array $requestParams Incoming arguments + * @param array $methodParams Procedure arguments * @return array */ - public function getNamedArguments(array $request_params, array $method_params) + public function getNamedArguments(array $requestParams, array $methodParams) { $params = array(); - foreach ($method_params as $p) { + foreach ($methodParams as $p) { $name = $p->getName(); - if (isset($request_params[$name])) { - $params[$name] = $request_params[$name]; - } - else if ($p->isDefaultValueAvailable()) { + if (isset($requestParams[$name])) { + $params[$name] = $requestParams[$name]; + } elseif ($p->isDefaultValueAvailable()) { $params[$name] = $p->getDefaultValue(); - } - else { + } else { throw new InvalidArgumentException('Missing argument: '.$name); } } diff --git a/vendor/fguillot/json-rpc/src/JsonRPC/Request/BatchRequestParser.php b/vendor/fguillot/json-rpc/src/JsonRPC/Request/BatchRequestParser.php index 208d167..c0fc776 100644 --- a/vendor/fguillot/json-rpc/src/JsonRPC/Request/BatchRequestParser.php +++ b/vendor/fguillot/json-rpc/src/JsonRPC/Request/BatchRequestParser.php @@ -24,6 +24,8 @@ class BatchRequestParser extends RequestParser $responses[] = RequestParser::create() ->withPayload($payload) ->withProcedureHandler($this->procedureHandler) + ->withMiddlewareHandler($this->middlewareHandler) + ->withLocalException($this->localExceptions) ->parse(); } @@ -34,6 +36,13 @@ class BatchRequestParser extends RequestParser /** * Return true if we have a batch request * + * ex : [ + * 0 => '...', + * 1 => '...', + * 2 => '...', + * 3 => '...', + * ] + * * @static * @access public * @param array $payload @@ -41,6 +50,6 @@ class BatchRequestParser extends RequestParser */ public static function isBatchRequest(array $payload) { - return is_array($payload) && array_keys($payload) === range(0, count($payload) - 1); + return array_keys($payload) === range(0, count($payload) - 1); } } diff --git a/vendor/fguillot/json-rpc/src/JsonRPC/Request/RequestBuilder.php b/vendor/fguillot/json-rpc/src/JsonRPC/Request/RequestBuilder.php index 95ff661..145d21c 100644 --- a/vendor/fguillot/json-rpc/src/JsonRPC/Request/RequestBuilder.php +++ b/vendor/fguillot/json-rpc/src/JsonRPC/Request/RequestBuilder.php @@ -34,6 +34,14 @@ class RequestBuilder */ private $params = array(); + /** + * Additional request attributes + * + * @access private + * @var array + */ + private $reqattrs = array(); + /** * Get new object instance * @@ -85,6 +93,19 @@ class RequestBuilder return $this; } + /** + * Set additional request attributes + * + * @access public + * @param array $reqattrs + * @return RequestBuilder + */ + public function withRequestAttributes(array $reqattrs) + { + $this->reqattrs = $reqattrs; + return $this; + } + /** * Build the payload * @@ -93,11 +114,11 @@ class RequestBuilder */ public function build() { - $payload = array( + $payload = array_merge_recursive($this->reqattrs, array( 'jsonrpc' => '2.0', 'method' => $this->procedure, 'id' => $this->id ?: mt_rand(), - ); + )); if (! empty($this->params)) { $payload['params'] = $this->params; diff --git a/vendor/fguillot/json-rpc/src/JsonRPC/Request/RequestParser.php b/vendor/fguillot/json-rpc/src/JsonRPC/Request/RequestParser.php index 36db1de..ea1b7d4 100644 --- a/vendor/fguillot/json-rpc/src/JsonRPC/Request/RequestParser.php +++ b/vendor/fguillot/json-rpc/src/JsonRPC/Request/RequestParser.php @@ -6,6 +6,7 @@ use Exception; use JsonRPC\Exception\AccessDeniedException; use JsonRPC\Exception\AuthenticationFailureException; use JsonRPC\Exception\InvalidJsonRpcFormatException; +use JsonRPC\MiddlewareHandler; use JsonRPC\ProcedureHandler; use JsonRPC\Response\ResponseBuilder; use JsonRPC\Validator\JsonFormatValidator; @@ -27,6 +28,17 @@ class RequestParser */ protected $payload; + /** + * List of exceptions that should not be relayed to the client + * + * @access protected + * @var array() + */ + protected $localExceptions = array( + 'JsonRPC\Exception\AuthenticationFailureException', + 'JsonRPC\Exception\AccessDeniedException', + ); + /** * ProcedureHandler * @@ -35,6 +47,14 @@ class RequestParser */ protected $procedureHandler; + /** + * MiddlewareHandler + * + * @access protected + * @var MiddlewareHandler + */ + protected $middlewareHandler; + /** * Get new object instance * @@ -60,6 +80,24 @@ class RequestParser return $this; } + /** + * Exception classes that should not be relayed to the client + * + * @access public + * @param mixed $exception + * @return $this + */ + public function withLocalException($exception) + { + if (is_array($exception)) { + $this->localExceptions = array_merge($this->localExceptions, $exception); + } else { + $this->localExceptions[] = $exception; + } + + return $this; + } + /** * Set procedure handler * @@ -73,6 +111,19 @@ class RequestParser return $this; } + /** + * Set middleware handler + * + * @access public + * @param MiddlewareHandler $middlewareHandler + * @return $this + */ + public function withMiddlewareHandler(MiddlewareHandler $middlewareHandler) + { + $this->middlewareHandler = $middlewareHandler; + return $this; + } + /** * Parse incoming request * @@ -88,6 +139,10 @@ class RequestParser JsonFormatValidator::validate($this->payload); RpcFormatValidator::validate($this->payload); + $this->middlewareHandler + ->withProcedure($this->payload['method']) + ->execute(); + $result = $this->procedureHandler->executeProcedure( $this->payload['method'], empty($this->payload['params']) ? array() : $this->payload['params'] @@ -100,17 +155,33 @@ class RequestParser ->build(); } } catch (Exception $e) { + return $this->handleExceptions($e); + } - if ($e instanceof AccessDeniedException || $e instanceof AuthenticationFailureException) { + return ''; + } + + /** + * Handle exceptions + * + * @access protected + * @param Exception $e + * @return string + * @throws Exception + */ + protected function handleExceptions(Exception $e) + { + foreach ($this->localExceptions as $exception) { + if ($e instanceof $exception) { throw $e; } + } - if ($e instanceof InvalidJsonRpcFormatException || ! $this->isNotification()) { - return ResponseBuilder::create() - ->withId(isset($this->payload['id']) ? $this->payload['id'] : null) - ->withException($e) - ->build(); - } + if ($e instanceof InvalidJsonRpcFormatException || ! $this->isNotification()) { + return ResponseBuilder::create() + ->withId(isset($this->payload['id']) ? $this->payload['id'] : null) + ->withException($e) + ->build(); } return ''; @@ -119,10 +190,10 @@ class RequestParser /** * Return true if the message is a notification * - * @access private + * @access protected * @return bool */ - private function isNotification() + protected function isNotification() { return is_array($this->payload) && !isset($this->payload['id']); } diff --git a/vendor/fguillot/json-rpc/src/JsonRPC/Response/ResponseParser.php b/vendor/fguillot/json-rpc/src/JsonRPC/Response/ResponseParser.php index 6763753..02d449b 100644 --- a/vendor/fguillot/json-rpc/src/JsonRPC/Response/ResponseParser.php +++ b/vendor/fguillot/json-rpc/src/JsonRPC/Response/ResponseParser.php @@ -4,6 +4,7 @@ namespace JsonRPC\Response; use BadFunctionCallException; use InvalidArgumentException; +use Exception; use JsonRPC\Exception\InvalidJsonFormatException; use JsonRPC\Exception\InvalidJsonRpcFormatException; use JsonRPC\Exception\ResponseException; @@ -25,6 +26,13 @@ class ResponseParser */ private $payload; + /** + * Do not immediately throw an exception on error. Return it instead. + * + * @var bool + */ + private $returnException = false; + /** * Get new object instance * @@ -37,6 +45,18 @@ class ResponseParser return new static(); } + /** + * Set Return Exception Or Throw It + * + * @param $returnException + * @return ResponseParser + */ + public function withReturnException($returnException) + { + $this->returnException = $returnException; + return $this; + } + /** * Set payload * @@ -53,11 +73,13 @@ class ResponseParser /** * Parse response * - * @access public + * @return array|Exception|null * @throws InvalidJsonFormatException + * @throws BadFunctionCallException * @throws InvalidJsonRpcFormatException + * @throws InvalidArgumentException + * @throws Exception * @throws ResponseException - * @return mixed */ public function parse() { @@ -68,6 +90,7 @@ class ResponseParser foreach ($this->payload as $response) { $results[] = self::create() + ->withReturnException($this->returnException) ->withPayload($response) ->parse(); } @@ -76,7 +99,14 @@ class ResponseParser } if (isset($this->payload['error']['code'])) { - $this->handleExceptions(); + try { + $this->handleExceptions(); + } catch (Exception $e) { + if ($this->returnException) { + return $e; + } + throw $e; + } } return isset($this->payload['result']) ? $this->payload['result'] : null; diff --git a/vendor/fguillot/json-rpc/src/JsonRPC/Server.php b/vendor/fguillot/json-rpc/src/JsonRPC/Server.php index 13de294..1ed075a 100644 --- a/vendor/fguillot/json-rpc/src/JsonRPC/Server.php +++ b/vendor/fguillot/json-rpc/src/JsonRPC/Server.php @@ -22,76 +22,121 @@ class Server /** * Allowed hosts * - * @access private + * @access protected * @var array */ - private $hosts = array(); + protected $hosts = array(); /** * Data received from the client * - * @access private + * @access protected * @var array */ - private $payload = array(); + protected $payload = array(); /** - * List of exception classes that should be relayed to client + * List of exceptions that should not be relayed to the client * - * @access private - * @var array + * @access protected + * @var array() */ - private $exceptions = array(); + protected $localExceptions = array(); /** * Username * - * @access private + * @access protected * @var string */ - private $username = ''; + protected $username = ''; /** * Password * - * @access private + * @access protected * @var string */ - private $password = ''; + protected $password = ''; /** * Allowed users * - * @access private + * @access protected * @var array */ - private $users = array(); + protected $users = array(); /** * $_SERVER * - * @access private + * @access protected * @var array */ - private $serverVariable; + protected $serverVariable; /** * ProcedureHandler object * - * @access private + * @access protected * @var ProcedureHandler */ - private $procedureHandler; + protected $procedureHandler; + + /** + * MiddlewareHandler object + * + * @access protected + * @var MiddlewareHandler + */ + protected $middlewareHandler; + + /** + * Response builder + * + * @access protected + * @var ResponseBuilder + */ + protected $responseBuilder; + + /** + * Response builder + * + * @access protected + * @var RequestParser + */ + protected $requestParser; + + /** + * + * Batch request parser + * + * @access protected + * @var BatchRequestParser + */ + protected $batchRequestParser; /** * Constructor * * @access public - * @param string $request - * @param array $server + * @param string $request + * @param array $server + * @param ResponseBuilder $responseBuilder + * @param RequestParser $requestParser + * @param BatchRequestParser $batchRequestParser + * @param ProcedureHandler $procedureHandler + * @param MiddlewareHandler $middlewareHandler */ - public function __construct($request = '', array $server = array()) - { + public function __construct( + $request = '', + array $server = array(), + ResponseBuilder $responseBuilder = null, + RequestParser $requestParser = null, + BatchRequestParser $batchRequestParser = null, + ProcedureHandler $procedureHandler = null, + MiddlewareHandler $middlewareHandler = null + ) { if ($request !== '') { $this->payload = json_decode($request, true); } else { @@ -99,7 +144,11 @@ class Server } $this->serverVariable = $server ?: $_SERVER; - $this->procedureHandler = new ProcedureHandler(); + $this->responseBuilder = $responseBuilder ?: ResponseBuilder::create(); + $this->requestParser = $requestParser ?: RequestParser::create(); + $this->batchRequestParser = $batchRequestParser ?: BatchRequestParser::create(); + $this->procedureHandler = $procedureHandler ?: new ProcedureHandler(); + $this->middlewareHandler = $middlewareHandler ?: new MiddlewareHandler(); } /** @@ -107,7 +156,7 @@ class Server * * @access public * @param string $header Header name - * @return Server + * @return $this */ public function setAuthenticationHeader($header) { @@ -134,6 +183,17 @@ class Server return $this->procedureHandler; } + /** + * Get MiddlewareHandler + * + * @access public + * @return MiddlewareHandler + */ + public function getMiddlewareHandler() + { + return $this->middlewareHandler; + } + /** * Get username * @@ -161,7 +221,7 @@ class Server * * @access public * @param array $hosts List of hosts - * @return Server + * @return $this */ public function allowHosts(array $hosts) { @@ -174,7 +234,7 @@ class Server * * @access public * @param array $users Dictionary of username/password - * @return Server + * @return $this */ public function authentication(array $users) { @@ -186,9 +246,10 @@ class Server * Register a new procedure * * @access public + * @deprecated Use $server->getProcedureHandler()->withCallback($procedure, $callback) * @param string $procedure Procedure name * @param closure $callback Callback - * @return Server + * @return $this */ public function register($procedure, Closure $callback) { @@ -200,10 +261,11 @@ class Server * Bind a procedure to a class * * @access public + * @deprecated Use $server->getProcedureHandler()->withClassAndMethod($procedure, $class, $method); * @param string $procedure Procedure name * @param mixed $class Class name or instance * @param string $method Procedure name - * @return Server + * @return $this */ public function bind($procedure, $class, $method = '') { @@ -215,8 +277,9 @@ class Server * Bind a class instance * * @access public + * @deprecated Use $server->getProcedureHandler()->withObject($instance); * @param mixed $instance Instance name - * @return Server + * @return $this */ public function attach($instance) { @@ -225,29 +288,15 @@ class Server } /** - * Bind an exception - * If this exception occurs it is relayed to the client as JSON-RPC error + * Exception classes that should not be relayed to the client * * @access public - * @param mixed $exception Exception class. Defaults to all. - * @return Server + * @param Exception|string $exception + * @return $this */ - public function attachException($exception = 'Exception') + public function withLocalException($exception) { - $this->exceptions[] = $exception; - return $this; - } - - /** - * Attach a method that will be called before the procedure - * - * @access public - * @param string $before - * @return Server - */ - public function before($before) - { - $this->procedureHandler->withBeforeMethod($before); + $this->localExceptions[] = $exception; return $this; } @@ -259,56 +308,78 @@ class Server */ public function execute() { - $responseBuilder = ResponseBuilder::create(); - try { - $this->procedureHandler - ->withUsername($this->getUsername()) - ->withPassword($this->getPassword()); - JsonFormatValidator::validate($this->payload); HostValidator::validate($this->hosts, $this->getServerVariable('REMOTE_ADDR')); UserValidator::validate($this->users, $this->getUsername(), $this->getPassword()); + $this->middlewareHandler + ->withUsername($this->getUsername()) + ->withPassword($this->getPassword()) + ; + $response = $this->parseRequest(); } catch (Exception $e) { - $response = $responseBuilder->withException($e)->build(); + $response = $this->handleExceptions($e); } - $responseBuilder->sendHeaders(); + $this->responseBuilder->sendHeaders(); return $response; } + /** + * Handle exceptions + * + * @access protected + * @param Exception $e + * @return string + * @throws Exception + */ + protected function handleExceptions(Exception $e) + { + foreach ($this->localExceptions as $exception) { + if ($e instanceof $exception) { + throw $e; + } + } + + return $this->responseBuilder->withException($e)->build(); + } + /** * Parse incoming request * - * @access private + * @access protected * @return string */ - private function parseRequest() + protected function parseRequest() { if (BatchRequestParser::isBatchRequest($this->payload)) { - return BatchRequestParser::create() + return $this->batchRequestParser ->withPayload($this->payload) ->withProcedureHandler($this->procedureHandler) + ->withMiddlewareHandler($this->middlewareHandler) + ->withLocalException($this->localExceptions) ->parse(); } - return RequestParser::create() + return $this->requestParser ->withPayload($this->payload) ->withProcedureHandler($this->procedureHandler) + ->withMiddlewareHandler($this->middlewareHandler) + ->withLocalException($this->localExceptions) ->parse(); } /** * Check existence and get value of server variable * - * @access private + * @access protected * @param string $variable * @return string|null */ - private function getServerVariable($variable) + protected function getServerVariable($variable) { return isset($this->serverVariable[$variable]) ? $this->serverVariable[$variable] : null; }