From d9eccd996fdfc6a00175cfd1a227f80f517f4d0d Mon Sep 17 00:00:00 2001 From: Spencer Rinehart Date: Thu, 26 May 2016 20:54:36 +0930 Subject: [PATCH] Enhance invalid parameter exceptions. closes #96 --- .../InvalidParameterExceptionHandler.php | 10 +++++ src/Exception/InvalidParameterException.php | 25 ++++++++++- src/Parameters.php | 16 +++++-- .../InvalidParameterExceptionHandlerTest.php | 44 +++++++++++++++++++ tests/ParametersTest.php | 25 ++++++++++- 5 files changed, 115 insertions(+), 5 deletions(-) create mode 100644 tests/Exception/Handler/InvalidParameterExceptionHandlerTest.php diff --git a/src/Exception/Handler/InvalidParameterExceptionHandler.php b/src/Exception/Handler/InvalidParameterExceptionHandler.php index d4ff608..374020a 100644 --- a/src/Exception/Handler/InvalidParameterExceptionHandler.php +++ b/src/Exception/Handler/InvalidParameterExceptionHandler.php @@ -32,6 +32,16 @@ public function handle(Exception $e) $status = 400; $error = []; + $code = $e->getCode(); + if ($code) { + $error['code'] = $code; + } + + $invalidParameter = $e->getInvalidParameter(); + if ($invalidParameter) { + $error['source'] = ['parameter' => $invalidParameter]; + } + return new ResponseBag($status, [$error]); } } diff --git a/src/Exception/InvalidParameterException.php b/src/Exception/InvalidParameterException.php index 02aad05..72027c0 100644 --- a/src/Exception/InvalidParameterException.php +++ b/src/Exception/InvalidParameterException.php @@ -15,5 +15,28 @@ class InvalidParameterException extends Exception { - // + /** + * @var string The parameter that caused this exception. + */ + private $invalidParameter; + + /** + * {@inheritdoc} + * + * @param string $invalidParameter The parameter that caused this exception. + */ + public function __construct($message = '', $code = 0, $previous = null, $invalidParameter = '') + { + parent::__construct($message, $code, $previous); + + $this->invalidParameter = $invalidParameter; + } + + /** + * @return string The parameter that caused this exception. + */ + public function getInvalidParameter() + { + return $this->invalidParameter; + } } diff --git a/src/Parameters.php b/src/Parameters.php index acf9f2b..0280e47 100644 --- a/src/Parameters.php +++ b/src/Parameters.php @@ -45,7 +45,12 @@ public function getInclude(array $available = []) $invalid = array_diff($relationships, $available); if (count($invalid)) { - throw new InvalidParameterException('Invalid includes ['.implode(',', $invalid).']'); + throw new InvalidParameterException( + 'Invalid includes ['.implode(',', $invalid).']', + 1, + null, + 'include' + ); } return $relationships; @@ -72,7 +77,7 @@ public function getOffset($perPage = null) $offset = (int) $this->getPage('offset'); if ($offset < 0) { - throw new InvalidParameterException('page[offset] must be >=0'); + throw new InvalidParameterException('page[offset] must be >=0', 2, null, 'page[offset]'); } return $offset; @@ -146,7 +151,12 @@ public function getSort(array $available = []) $invalid = array_diff(array_keys($sort), $available); if (count($invalid)) { - throw new InvalidParameterException('Invalid sort fields ['.implode(',', $invalid).']'); + throw new InvalidParameterException( + 'Invalid sort fields ['.implode(',', $invalid).']', + 3, + null, + 'sort' + ); } } diff --git a/tests/Exception/Handler/InvalidParameterExceptionHandlerTest.php b/tests/Exception/Handler/InvalidParameterExceptionHandlerTest.php new file mode 100644 index 0000000..eb01ec2 --- /dev/null +++ b/tests/Exception/Handler/InvalidParameterExceptionHandlerTest.php @@ -0,0 +1,44 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Tobscure\Tests\Exception\Handler; + +use Exception; +use Tobscure\JsonApi\Exception\Handler\InvalidParameterExceptionHandler; +use Tobscure\JsonApi\Exception\Handler\ResponseBag; +use Tobscure\JsonApi\Exception\InvalidParameterException; + +class InvalidParameterExceptionHandlerTest extends \PHPUnit_Framework_TestCase +{ + public function testHandlerCanManageInvalidParameterExceptions() + { + $handler = new InvalidParameterExceptionHandler(); + + $this->assertTrue($handler->manages(new InvalidParameterException)); + } + + public function testHandlerCanNotManageOtherExceptions() + { + $handler = new InvalidParameterExceptionHandler(); + + $this->assertFalse($handler->manages(new Exception)); + } + + public function testErrorHandling() + { + $handler = new InvalidParameterExceptionHandler(); + $response = $handler->handle(new InvalidParameterException('error', 1, null, 'include')); + + $this->assertInstanceOf(ResponseBag::class, $response); + $this->assertEquals(400, $response->getStatus()); + $this->assertEquals([['code' => 1, 'source' => ['parameter' => 'include']]], $response->getErrors()); + } +} diff --git a/tests/ParametersTest.php b/tests/ParametersTest.php index a2f0bbe..e38362b 100644 --- a/tests/ParametersTest.php +++ b/tests/ParametersTest.php @@ -34,6 +34,17 @@ public function testGetIncludeReturnsEmptyArray() $this->assertEquals([], $parameters->getInclude(['posts', 'images'])); } + /** + * @expectedException \Tobscure\JsonApi\Exception\InvalidParameterException + * @expectedExceptionCode 1 + */ + public function testGetIncludeWithUnallowedField() + { + $parameters = new Parameters(['include' => 'posts,images']); + + $parameters->getInclude(['posts']); + } + public function testGetSortReturnsArrayOfFieldToSortDirection() { $parameters = new Parameters(['sort' => 'firstname']); @@ -55,6 +66,17 @@ public function testGetSortDefaultsToEmptyArray() $this->assertEmpty($parameters->getSort()); } + /** + * @expectedException \Tobscure\JsonApi\Exception\InvalidParameterException + * @expectedExceptionCode 3 + */ + public function testGetSortWithUnallowedField() + { + $parameters = new Parameters(['sort' => 'firstname,lastname']); + + $parameters->getSort(['firstname']); + } + public function testGetOffsetParsesThePageOffset() { $parameters = new Parameters(['page' => ['offset' => 10]]); @@ -64,12 +86,13 @@ public function testGetOffsetParsesThePageOffset() /** * @expectedException \Tobscure\JsonApi\Exception\InvalidParameterException + * @expectedExceptionCode 2 */ public function testGetOffsetIsAtLeastZero() { $parameters = new Parameters(['page' => ['offset' => -5]]); - $this->assertEquals(0, $parameters->getOffset()); + $parameters->getOffset(); } public function testGetOffsetParsesThePageNumber()