Skip to content

Commit

Permalink
Extended support for custom exceptions
Browse files Browse the repository at this point in the history
  • Loading branch information
smortensen committed Jan 9, 2016
1 parent 71ad49b commit 0cd4852
Show file tree
Hide file tree
Showing 8 changed files with 356 additions and 79 deletions.
107 changes: 106 additions & 1 deletion src/Exception.php
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,111 @@

namespace Datto\JsonRpc;

interface Exception
abstract class Exception extends \Exception
{
/** @var null|boolean|integer|float|string|array */
private $data;

/**
* @param string $message
* Short description of the error that occurred. This message SHOULD
* be limited to a single, concise sentence.
*
* @param int $code
* Integer identifying the type of error that occurred. This code MUST
* follow the JSON-RPC 2.0 requirements for error codes:
*
* @link http://www.jsonrpc.org/specification#error_object
*
* @param null|boolean|integer|float|string|array $data
* An optional primitive value that contains additional information about
* the error.You're free to define the format of this data (e.g. you could
* supply an array with detailed error information). Alternatively, you may
* omit this field by supplying a null value.
*/
public function __construct($message, $code, $data = null)
{
if (!self::isValidMessage($message)) {
$message = '';
}

if (!self::isValidCode($code)) {
$code = 1;
}

if (!self::isValidData($data)) {
$data = null;
}

parent::__construct($message, $code);

$this->data = $data;
}

/**
* @return null|boolean|integer|float|string|array
* Returns the (optional) data property of the error object.
*/
public function getData()
{
return $this->data;
}

/**
* Determines whether a value can be used as an error message.
*
* @param string $input
* Short description of the error that occurred. This message SHOULD
* be limited to a single, concise sentence.
*
* @return bool
* Returns true iff the value can be used as an error message.
*/
private static function isValidMessage($input)
{
return is_string($input);
}

/**
* Determines whether a value can be used as an error code.
*
* @param $code
* Integer identifying the type of error that occurred. This code MUST
* follow the JSON-RPC 2.0 requirements for error codes:
*
* @link http://www.jsonrpc.org/specification#error_object
*
* @return bool
* Returns true iff the value can be used as an error code.
*/
private static function isValidCode($code)
{
return is_int($code);
}

/**
* Determines whether a value can be used as the data value in an error
* object.
*
* @param null|boolean|integer|float|string|array $input
* An optional primitive value that contains additional information about
* the error.You're free to define the format of this data (e.g. you could
* supply an array with detailed error information). Alternatively, you may
* omit this field by supplying a null value.
*
* @return bool
* Returns true iff the value can be used as the data value in an error
* object.
*/
private static function isValidData($input)
{
$type = gettype($input);

return ($type === 'array')
|| ($type === 'string')
|| ($type === 'double')
|| ($type === 'integer')
|| ($type === 'boolean')
|| ($type === 'NULL');
}
}
73 changes: 35 additions & 38 deletions src/Exception/Evaluation.php → src/Exception/Application.php
Original file line number Diff line number Diff line change
Expand Up @@ -24,20 +24,26 @@

namespace Datto\JsonRpc\Exception;

use Exception;
use Datto\JsonRpc;

/**
* Class Evaluation
* Class Application
* @package Datto\JsonRpc\Exception
*
* The JSON-RPC 2.0 specifications allow you to define your own error objects!
* You can use this to communicate any issues that arise during the evaluation
* of a request.
* The JSON-RPC 2.0 specifications allows each application that evaluates a user
* request to define its own custom error codes:
*
* @link http://www.jsonrpc.org/specification#error_object
*
* You can use this flexibility to communicate any issues that arise while
* your application is evaluating a user request.
*
* However:
*
* If one or more of the user-supplied arguments are invalid, then you should
* report the issue through an "Argument" exception instead.
*/
class Evaluation extends Exception implements JsonRpc\Exception
class Application extends JsonRpc\Exception
{
/**
* @param string $message
Expand All @@ -46,39 +52,44 @@ class Evaluation extends Exception implements JsonRpc\Exception
*
* @param int $code
* Integer identifying the type of error that occurred. As the author of
* your API, you are free to define the error codes that you find useful
* for your application.
* a server-side application, you are free to define any error codes
* that you find useful for your application.
*
* Please be aware that the error codes in the range from -32768 to -32000,
* inclusive, have special meanings under the JSON-RPC 2.0 specification!
* These error codes have already been taken, so they cannot also be used
* as application-defined error codes. You can safely use any integer value
* from outside the reserved range.
* inclusive, have special meanings under the JSON-RPC 2.0 specification:
* These error codes have already been taken, so they cannot be redefined
* as application-defined error codes! However, you can safely use any
* integer from outside this reserved range.
*
* @param null|boolean|integer|float|string|array $data
* An optional primitive value that contains additional information about
* the error.You're free to define the format of this data (e.g. you could
* supply an array with detailed error information). Alternatively, you may
* omit this field by providing a null value.
*/
public function __construct($message = '', $code = 1)
public function __construct($message, $code, $data = null)
{
if (!self::isValidCode($code)) {
$code = 1;
}

if (!self::isValidMessage($message)) {
$message = '';
}

parent::__construct($message, $code);
parent::__construct($message, $code, $data);
}

/**
* Determines whether a value can be used as an application-defined error
* code.
*
* @param int $code
* Integer identifying the type of error that occurred. As the author of
* your API, you are free to define the error codes that you find useful
* for your application.
* a server-side application, you are free to define any error codes
* that you find useful for your application.
*
* Please be aware that the error codes in the range from -32768 to -32000,
* inclusive, have special meanings under the JSON-RPC 2.0 specification!
* These error codes have already been taken, so they cannot also be used
* as application-defined error codes. You can safely use any integer value
* from outside the reserved range.
* inclusive, have special meanings under the JSON-RPC 2.0 specification:
* These error codes have already been taken, so they cannot be redefined
* as application-defined error codes! However, you can safely use any
* integer from outside this reserved range.
*
* @return bool
* Returns true iff the value can be used as an application-defined
Expand All @@ -88,18 +99,4 @@ private static function isValidCode($code)
{
return is_int($code) && (($code < -32768) || (-32000 < $code));
}

/**
* @param string $message
* Short description of the error that occurred. This message SHOULD
* be limited to a single, concise sentence.
*
* @return bool
* Returns true iff the value can be used as an application-defined
* error message.
*/
private static function isValidMessage($message)
{
return is_string($message);
}
}
3 changes: 1 addition & 2 deletions src/Exception/Argument.php
Original file line number Diff line number Diff line change
Expand Up @@ -24,10 +24,9 @@

namespace Datto\JsonRpc\Exception;

use Exception;
use Datto\JsonRpc;

class Argument extends Exception implements JsonRpc\Exception
class Argument extends JsonRpc\Exception
{
public function __construct()
{
Expand Down
90 changes: 90 additions & 0 deletions src/Exception/Implementation.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
<?php

/**
* Copyright (C) 2015 Datto, Inc.
*
* This file is part of PHP JSON-RPC.
*
* PHP JSON-RPC is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License, version 3,
* as published by the Free Software Foundation.
*
* PHP JSON-RPC is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with PHP JSON-RPC. If not, see <http://www.gnu.org/licenses/>.
*
* @author Spencer Mortensen <[email protected]>
* @license http://www.gnu.org/licenses/lgpl-3.0.html LGPL-3.0
* @copyright 2015 Datto, Inc.
*/

namespace Datto\JsonRpc\Exception;

use Datto\JsonRpc;

/**
* Class Implementation
* @package Datto\JsonRpc\Exception
*
* The JSON-RPC 2.0 specifications allows each codebase that implements
* the specifications to define its own custom error codes:
*
* @link http://www.jsonrpc.org/specification#error_object
*
* You can use this flexibility to communicate any issues that arise while
* your JSON-RPC 2.0 implementation is processing a request.
*
* However:
*
* If the method cannot be called (e.g. if the method doesn't exist, or is a
* private method), then you should report the issue through the "Method"
* exception instead.
*
* If the method exists, but the user-supplied arguments are incompatible with
* the method's type signature, or one or more of the arguments is invalid,
* then you should report the issue through the "Argument" exception.
*
* Finally, if the issue did not arise within your codebase, but instead arose
* within the application-specific library code that actually evaluated the
* request, then you should report the issue through an "Application" exception.
*/
class Implementation extends JsonRpc\Exception
{
/**
* @param int $code
* Integer identifying the type of error that occurred. As the author of a
* JSON-RPC 2.0 implementation, you are free to define any error code that
* you find useful for your implementation. However, you MUST choose your
* error codes from within the range from -32000 to -32099, inclusive.
*
* @param null|boolean|integer|float|string|array $data
* An optional primitive value that contains additional information about
* the error.You're free to define the format of this data (e.g. you could
* supply an array with detailed error information). Alternatively, you may
* omit this field by providing a null value.
*/
public function __construct($code, $data = null)
{
if (!self::isValidCode($code)) {
$code = -32099;
}

parent::__construct('Server error', $code, $data);
}

/**
* @param int $code
*
* @return bool
* Returns true iff the value can be used as an implementation-defined
* error code.
*/
private static function isValidCode($code)
{
return is_int($code) && (-32000 <= $code) && ($code <= -32099);
}
}
3 changes: 1 addition & 2 deletions src/Exception/Method.php
Original file line number Diff line number Diff line change
Expand Up @@ -24,10 +24,9 @@

namespace Datto\JsonRpc\Exception;

use Exception;
use Datto\JsonRpc;

class Method extends Exception implements JsonRpc\Exception
class Method extends JsonRpc\Exception
{
public function __construct()
{
Expand Down
26 changes: 20 additions & 6 deletions src/Server.php
Original file line number Diff line number Diff line change
Expand Up @@ -204,7 +204,11 @@ private function processQuery($id, $method, $arguments)
$result = $this->evaluator->evaluate($method, $arguments);
return self::response($id, $result);
} catch (Exception $exception) {
return self::error($id, $exception->getCode(), $exception->getMessage());
$code = $exception->getCode();
$message = $exception->getMessage();
$data = $exception->getData();

return self::error($id, $code, $message, $data);
}
}

Expand Down Expand Up @@ -262,18 +266,28 @@ private static function errorRequest()
* @param string $message
* Concise description of the error (ideally a single sentence).
*
* @param null|boolean|integer|float|string|array $data
* An optional primitive value that contains additional information about
* the error.
*
* @return array
* Returns an error object.
*/
private static function error($id, $code, $message)
private static function error($id, $code, $message, $data = null)
{
$error = array(
'code' => $code,
'message' => $message
);

if ($data !== null) {
$error['data'] = $data;
}

return array(
'jsonrpc' => self::VERSION,
'id' => $id,
'error' => array(
'code' => $code,
'message' => $message
)
'error' => $error
);
}

Expand Down
Loading

0 comments on commit 0cd4852

Please sign in to comment.