From d4ed543cd6a07cb24418bea4f54d39d2c9c6631c Mon Sep 17 00:00:00 2001 From: TobiasHauck Date: Thu, 4 Aug 2016 11:56:44 +0200 Subject: [PATCH 01/15] added new annotation attributes --- Annotations/DataSource.php | 56 +++++++++++++ Annotations/Delete.php | 2 +- Annotations/Fetch.php | 2 +- Annotations/Insert.php | 2 +- Annotations/Reader.php | 2 +- Annotations/Route.php | 59 +++++++++++++- Annotations/Routing.php | 10 +-- Annotations/Select.php | 2 +- Annotations/Update.php | 2 +- Exceptions/Exceptions.php | 2 +- Factory/RequestFactory.php | 35 +++++--- Security/HttpAuthentication.php | 2 +- Statement.php | 12 ++- Tests/Annotations/DeleteTest.php | 11 ++- Tests/Annotations/ReaderTest.php | 10 ++- Tests/Controller/MockController.php | 4 +- Tests/Exceptions/ExceptionsTest.php | 2 +- Tests/Factory/RequestFactoryTest.php | 8 +- Tests/StatementTest.php | 8 +- Tests/Transformers/MysqlToRequestTest.php | 20 +++-- Tests/Types/AnnotationTest.php | 17 ++++ Tests/Types/HttpMethodTest.php | 68 ++++++++++++++++ Tests/Types/InsertPayloadTest.php | 32 +++++++- Tests/Types/RequestTest.php | 6 +- Tests/Types/StatusCodeTest.php | 67 +++++++++++++++ Tests/Types/TableTest.php | 34 -------- Tests/Types/UrlTest.php | 36 +++++---- Tests/Validation/AssertionsTest.php | 99 +++++++++++++++++++++++ Transformers/MysqlToRequest.php | 6 +- Types/Annotation.php | 15 ++++ Types/HttpMethod.php | 46 +++++++++++ Types/HttpQuery.php | 4 +- Types/InsertPayload.php | 31 ++++++- Types/Request.php | 30 +++++-- Types/StatusCode.php | 57 +++++++++++++ Types/Table.php | 18 ----- Types/UpdatePayload.php | 2 +- Types/Url.php | 40 ++++++--- Types/Value.php | 3 +- Validation/Assertions.php | 51 ++++++++++++ 40 files changed, 770 insertions(+), 143 deletions(-) create mode 100644 Annotations/DataSource.php create mode 100644 Tests/Types/HttpMethodTest.php create mode 100644 Tests/Types/StatusCodeTest.php create mode 100644 Types/HttpMethod.php create mode 100644 Types/StatusCode.php diff --git a/Annotations/DataSource.php b/Annotations/DataSource.php new file mode 100644 index 0000000..6155b2f --- /dev/null +++ b/Annotations/DataSource.php @@ -0,0 +1,56 @@ +. + */ + +namespace Circle\DoctrineRestDriver\Annotations; + +/** + * Contract for all data source annotations + * + * @author Tobias Hauck + * @copyright 2015 TeeAge-Beatz UG + */ +interface DataSource { + + /** + * returns the route + * + * @return string + */ + public function getRoute(); + + /** + * returns the status code + * + * @return int|null + */ + public function getStatusCode(); + + /** + * returns the method + * + * @return null|string + */ + public function getMethod(); + + /** + * returns the options + * + * @return array|null + */ + public function getOptions(); +} \ No newline at end of file diff --git a/Annotations/Delete.php b/Annotations/Delete.php index 873381b..c06f561 100644 --- a/Annotations/Delete.php +++ b/Annotations/Delete.php @@ -26,6 +26,6 @@ * * @Annotation */ -class Delete { +class Delete implements DataSource{ use Route; } \ No newline at end of file diff --git a/Annotations/Fetch.php b/Annotations/Fetch.php index 77e927d..1ca9cf7 100644 --- a/Annotations/Fetch.php +++ b/Annotations/Fetch.php @@ -26,6 +26,6 @@ * * @Annotation */ -class Fetch { +class Fetch implements DataSource { use Route; } \ No newline at end of file diff --git a/Annotations/Insert.php b/Annotations/Insert.php index 632798d..8ba7aa2 100644 --- a/Annotations/Insert.php +++ b/Annotations/Insert.php @@ -29,6 +29,6 @@ * * @Annotation */ -class Insert { +class Insert implements DataSource { use Route; } \ No newline at end of file diff --git a/Annotations/Reader.php b/Annotations/Reader.php index c3000f6..8a6b958 100644 --- a/Annotations/Reader.php +++ b/Annotations/Reader.php @@ -50,6 +50,6 @@ public function __construct() { public function read(\ReflectionClass $class, $namespace) { $annotation = $this->annotationReader->getClassAnnotation($class, $namespace); - return $annotation instanceof $namespace ? $annotation->getRoute() : null; + return $annotation instanceof $namespace ? $annotation : null; } } \ No newline at end of file diff --git a/Annotations/Route.php b/Annotations/Route.php index baed74e..96c4b37 100644 --- a/Annotations/Route.php +++ b/Annotations/Route.php @@ -20,6 +20,7 @@ use Circle\DoctrineRestDriver\Exceptions\Exceptions; use Circle\DoctrineRestDriver\Validation\Assertions; +use Doctrine\Common\Collections\ArrayCollection; /** * Trait for all annotations regarding routes @@ -36,6 +37,21 @@ trait Route { */ private $route; + /** + * @var string + */ + private $method; + + /** + * @var int + */ + private $statusCode; + + /** + * @var array + */ + private $options = []; + /** * Constructor * @@ -44,9 +60,19 @@ trait Route { * @SuppressWarnings("PHPMD.StaticAccess") */ public function __construct(array $values) { - $route = $values['value']; - if (!Assertions::isUrl($route)) return Exceptions::InvalidTypeException('Url', 'route', $route); - $this->route = $route; + $settings = new ArrayCollection($values); + + $this->route = $settings->get('value'); + Assertions::assertUrl('value', $this->route); + + $this->statusCode = $settings->get('statusCode'); + Assertions::assertMaybeInt('statusCode', $this->statusCode); + + $this->method = $settings->get('method'); + Assertions::assertMaybeString('method', $this->method); + + $this->options = $settings->get('options'); + Assertions::assertMaybeList('options', $this->options); } /** @@ -57,4 +83,31 @@ public function __construct(array $values) { public function getRoute() { return $this->route; } + + /** + * returns the status code + * + * @return int|null + */ + public function getStatusCode() { + return $this->statusCode; + } + + /** + * returns the method + * + * @return string|null + */ + public function getMethod() { + return $this->method; + } + + /** + * returns the options + * + * @return array|null + */ + public function getOptions() { + return $this->options; + } } \ No newline at end of file diff --git a/Annotations/Routing.php b/Annotations/Routing.php index 2662234..ec61b9e 100644 --- a/Annotations/Routing.php +++ b/Annotations/Routing.php @@ -77,7 +77,7 @@ public function __construct($namespace) { /** * returns the post route * - * @return string|null + * @return \Circle\DoctrineRestDriver\Annotations\Insert|null */ public function post() { return $this->post; @@ -86,7 +86,7 @@ public function post() { /** * returns the get route * - * @return string|null + * @return \Circle\DoctrineRestDriver\Annotations\Select|null */ public function get() { return $this->get; @@ -95,7 +95,7 @@ public function get() { /** * returns the put route * - * @return string|null + * @return \Circle\DoctrineRestDriver\Annotations\Update|null */ public function put() { return $this->put; @@ -104,7 +104,7 @@ public function put() { /** * returns the delete route * - * @return string|null + * @return \Circle\DoctrineRestDriver\Annotations\Delete|null */ public function delete() { return $this->delete; @@ -113,7 +113,7 @@ public function delete() { /** * returns the get all route * - * @return string|null + * @return \Circle\DoctrineRestDriver\Annotations\Fetch|null */ public function getAll() { return $this->getAll; diff --git a/Annotations/Select.php b/Annotations/Select.php index c123868..b307886 100644 --- a/Annotations/Select.php +++ b/Annotations/Select.php @@ -29,6 +29,6 @@ * * @Annotation */ -class Select { +class Select implements DataSource { use Route; } \ No newline at end of file diff --git a/Annotations/Update.php b/Annotations/Update.php index 2067f44..52369db 100644 --- a/Annotations/Update.php +++ b/Annotations/Update.php @@ -29,6 +29,6 @@ * * @Annotation */ -class Update { +class Update implements DataSource { use Route; } \ No newline at end of file diff --git a/Exceptions/Exceptions.php b/Exceptions/Exceptions.php index 5f189bb..7ce298a 100644 --- a/Exceptions/Exceptions.php +++ b/Exceptions/Exceptions.php @@ -42,7 +42,7 @@ class Exceptions { * @throws InvalidTypeException */ public static function InvalidTypeException($expectedType, $key, $value) { - throw new InvalidTypeException($expectedType, $key, $value); + throw new InvalidTypeException($expectedType, $key, is_array($value) ? print_r($value) : $value); } /** diff --git a/Factory/RequestFactory.php b/Factory/RequestFactory.php index 6e9a639..60d40aa 100644 --- a/Factory/RequestFactory.php +++ b/Factory/RequestFactory.php @@ -19,13 +19,20 @@ namespace Circle\DoctrineRestDriver\Factory; use Circle\DoctrineRestDriver\Annotations\Routing; +use Circle\DoctrineRestDriver\Annotations\RoutingTable; use Circle\DoctrineRestDriver\Enums\HttpMethods; +use Circle\DoctrineRestDriver\Enums\SqlOperations; +use Circle\DoctrineRestDriver\Types\Annotation; use Circle\DoctrineRestDriver\Types\HttpHeader; use Circle\DoctrineRestDriver\Types\CurlOptions; +use Circle\DoctrineRestDriver\Types\HttpMethod; +use Circle\DoctrineRestDriver\Types\Id; use Circle\DoctrineRestDriver\Types\Payload; use Circle\DoctrineRestDriver\Types\HttpQuery; use Circle\DoctrineRestDriver\Types\Request; use Circle\DoctrineRestDriver\Types\SqlOperation; +use Circle\DoctrineRestDriver\Types\StatusCode; +use Circle\DoctrineRestDriver\Types\Table; use Circle\DoctrineRestDriver\Types\Url; /** @@ -34,26 +41,32 @@ * @author Tobias Hauck * @copyright 2015 TeeAge-Beatz UG * - * @SuppressWarnings("PHPMD.StaticAccess") + * @SuppressWarnings("PHPMD.CouplingBetweenObjects") */ class RequestFactory { /** * Creates a new Request with the given options * - * @param array $tokens - * @param string $apiUrl - * @param array $options + * @param array $tokens + * @param string $apiUrl + * @param array $options + * @param RoutingTable $routings * @return Request + * + * @SuppressWarnings("PHPMD.StaticAccess") */ - public function createOne(array $tokens, $apiUrl, array $options) { - $method = HttpMethods::ofSqlOperation(SqlOperation::create($tokens)); - $url = Url::create($tokens, $apiUrl); - $query = HttpQuery::create($tokens); - $payload = $method === HttpMethods::GET || $method === HttpMethods::DELETE ? null : Payload::create($tokens); + public function createOne(array $tokens, $apiUrl, array $options, RoutingTable $routings = null) { + $operation = SqlOperation::create($tokens); + $annotation = Annotation::get($routings, Table::create($tokens), HttpMethods::ofSqlOperation($operation)); - $options = array_merge($options, HttpHeader::create($options, $tokens)); + $method = HttpMethod::create($operation, $annotation); + $url = Url::createFromTokens($tokens, $apiUrl, $annotation); + $options = CurlOptions::create(array_merge($options, HttpHeader::create($options, $tokens))); + $query = HttpQuery::create($tokens); + $payload = Payload::create($tokens); + $statusCode = StatusCode::create($operation, $annotation); - return new Request($method, $url, CurlOptions::create($options), $query, $payload); + return new Request($method, $url, $options, $query, $payload, $statusCode); } } diff --git a/Security/HttpAuthentication.php b/Security/HttpAuthentication.php index 4396ac3..badf7de 100644 --- a/Security/HttpAuthentication.php +++ b/Security/HttpAuthentication.php @@ -52,6 +52,6 @@ public function transformRequest(Request $request) { array_push($headers, 'Authorization: Basic ' . base64_encode($this->config['user'] . ':' . $this->config['password'])); $options[CURLOPT_HTTPHEADER] = $headers; - return new Request($request->getMethod(), $request->getUrl(), $options, $request->getQuery(), $request->getPayload()); + return new Request($request->getMethod(), $request->getUrl(), $options, $request->getQuery(), $request->getPayload(), $request->getExpectedStatusCode()); } } \ No newline at end of file diff --git a/Statement.php b/Statement.php index b4e95ec..8c7d838 100644 --- a/Statement.php +++ b/Statement.php @@ -92,6 +92,11 @@ class Statement implements \IteratorAggregate, StatementInterface { */ private $authStrategy; + /** + * @var RoutingTable + */ + private $routings; + /** * Statement constructor * @@ -102,9 +107,10 @@ class Statement implements \IteratorAggregate, StatementInterface { * * @SuppressWarnings("PHPMD.StaticAccess") */ - public function __construct($query, array $options, RoutingTable $routings = null) { + public function __construct($query, array $options, RoutingTable $routings) { $this->query = $query; - $this->mysqlToRequest = new MysqlToRequest($options, $routings); + $this->routings = $routings; + $this->mysqlToRequest = new MysqlToRequest($options, $this->routings); $this->restClientFactory = new RestClientFactory(); $authenticatorClass = !empty($options['driverOptions']['authenticator_class']) ? $options['driverOptions']['authenticator_class'] : 'NoAuthentication'; @@ -157,7 +163,7 @@ public function execute($params = null) { $response = $method === HttpMethods::GET || $method === HttpMethods::DELETE ? $restClient->$method($request->getUrlAndQuery()) : $restClient->$method($request->getUrlAndQuery(), $request->getPayload()); $statusCode = $response->getStatusCode(); - return $statusCode === 200 || ($method === HttpMethods::DELETE && $statusCode === 204) ? $this->onSuccess($response, $method) : $this->onError($request, $response); + return $statusCode === $request->getExpectedStatusCode() ? $this->onSuccess($response, $method) : $this->onError($request, $response); } /** diff --git a/Tests/Annotations/DeleteTest.php b/Tests/Annotations/DeleteTest.php index 831c228..4670722 100644 --- a/Tests/Annotations/DeleteTest.php +++ b/Tests/Annotations/DeleteTest.php @@ -35,12 +35,21 @@ class DeleteTest extends \PHPUnit_Framework_TestCase { * @group unit * @covers ::__construct * @covers ::getRoute + * @covers ::getStatusCode + * @covers ::getMethod + * @covers ::getOptions */ public function getRoute() { $delete = new Delete([ - 'value' => 'http://www.mySite.com/delete' + 'value' => 'http://www.mySite.com/delete', + 'statusCode' => 201, + 'method' => 'DELETE', + 'options' => [] ]); $this->assertSame('http://www.mySite.com/delete', $delete->getRoute()); + $this->assertSame(201, $delete->getStatusCode()); + $this->assertSame('DELETE', $delete->getMethod()); + $this->assertEquals([], $delete->getOptions()); } } \ No newline at end of file diff --git a/Tests/Annotations/ReaderTest.php b/Tests/Annotations/ReaderTest.php index 8001949..bc7823b 100644 --- a/Tests/Annotations/ReaderTest.php +++ b/Tests/Annotations/ReaderTest.php @@ -19,6 +19,7 @@ namespace Circle\DoctrineRestDriver\Tests\Annotations; use Circle\DoctrineRestDriver\Annotations\Reader; +use Circle\DoctrineRestDriver\Annotations\Select; use Doctrine\Common\Annotations\AnnotationRegistry; /** @@ -58,9 +59,12 @@ public function setUp() { * @covers ::read */ public function getRoute() { - $reader = new Reader(); - $class = new \ReflectionClass('Circle\DoctrineRestDriver\Tests\Entity\TestEntity'); + $reader = new Reader(); + $class = new \ReflectionClass('Circle\DoctrineRestDriver\Tests\Entity\TestEntity'); + $expected = new Select([ + 'value' => 'http://127.0.0.1:3000/app_dev.php/mockapi/products' + ]); - $this->assertSame('http://127.0.0.1:3000/app_dev.php/mockapi/products', $reader->read($class, 'Circle\DoctrineRestDriver\Annotations\Select')); + $this->assertEquals($expected, $reader->read($class, 'Circle\DoctrineRestDriver\Annotations\Select')); } } \ No newline at end of file diff --git a/Tests/Controller/MockController.php b/Tests/Controller/MockController.php index 90f62e4..1b816b2 100644 --- a/Tests/Controller/MockController.php +++ b/Tests/Controller/MockController.php @@ -79,7 +79,7 @@ public function postAction(Request $request) { 'id' => 1, 'name' => $payload->name, 'value' => $payload->value, - ])); + ]), 201); } /** @@ -123,6 +123,6 @@ public function postCategoriesAction(Request $request) { 'id' => 1, 'name' => $payload->name, 'product_id' => $payload->product_id, - ])); + ]), 201); } } diff --git a/Tests/Exceptions/ExceptionsTest.php b/Tests/Exceptions/ExceptionsTest.php index b90995b..97e2498 100644 --- a/Tests/Exceptions/ExceptionsTest.php +++ b/Tests/Exceptions/ExceptionsTest.php @@ -89,7 +89,7 @@ public function methodNotImplementedExceptionTest() { * @SuppressWarnings("PHPMD.StaticAccess") */ public function requestFailedExceptionTest() { - Exceptions::requestFailedException(new Request('method', 'url', []), 1, 'errorMessage'); + Exceptions::requestFailedException(new Request('get', 'url', []), 1, 'errorMessage'); } /** diff --git a/Tests/Factory/RequestFactoryTest.php b/Tests/Factory/RequestFactoryTest.php index e577aaf..4e7fecd 100644 --- a/Tests/Factory/RequestFactoryTest.php +++ b/Tests/Factory/RequestFactoryTest.php @@ -69,6 +69,12 @@ public function createOne() { $factory = new RequestFactory(); $expected = new Request('get', 'http://circle.ai/products/1', $this->requestOptions); - $this->assertEquals($expected, $factory->createOne($parser->parse($query), 'http://circle.ai', $this->factoryOptions)); + $routings = $this->getMockBuilder('Circle\DoctrineRestDriver\Annotations\RoutingTable')->disableOriginalConstructor()->getMock(); + $routings + ->expects($this->any()) + ->method('get') + ->will($this->returnValue(null)); + + $this->assertEquals($expected, $factory->createOne($parser->parse($query), 'http://circle.ai', $this->factoryOptions, $routings)); } } \ No newline at end of file diff --git a/Tests/StatementTest.php b/Tests/StatementTest.php index dc621cc..92e5112 100644 --- a/Tests/StatementTest.php +++ b/Tests/StatementTest.php @@ -39,6 +39,12 @@ class StatementTest extends \PHPUnit_Framework_TestCase { * {@inheritdoc} */ public function setUp() { + $routings = $this->getMockBuilder('Circle\DoctrineRestDriver\Annotations\RoutingTable')->disableOriginalConstructor()->getMock(); + $routings + ->expects($this->any()) + ->method('get') + ->will($this->returnValue(null)); + $params = [ 'host' => 'http://www.circle.ai', 'user' => 'Aladdin', @@ -47,7 +53,7 @@ public function setUp() { 'authenticator_class' => 'HttpAuthentication' ] ]; - $this->statement = new Statement('SELECT name FROM product WHERE id=1', $params); + $this->statement = new Statement('SELECT name FROM product WHERE id=1', $params, $routings); } /** diff --git a/Tests/Transformers/MysqlToRequestTest.php b/Tests/Transformers/MysqlToRequestTest.php index 3364016..8afbd6c 100644 --- a/Tests/Transformers/MysqlToRequestTest.php +++ b/Tests/Transformers/MysqlToRequestTest.php @@ -59,6 +59,12 @@ class MysqlToRequestTest extends \PHPUnit_Framework_TestCase { * {@inheritdoc} */ public function setUp() { + $routings = $this->getMockBuilder('Circle\DoctrineRestDriver\Annotations\RoutingTable')->disableOriginalConstructor()->getMock(); + $routings + ->expects($this->any()) + ->method('get') + ->will($this->returnValue(null)); + $this->mysqlToRequest = new MysqlToRequest([ 'host' => 'http://www.test.de', 'driverOptions' => [ @@ -70,7 +76,7 @@ public function setUp() { 'CURLOPT_SSLVERSION' => 3, 'CURLOPT_FOLLOWLOCATION' => true, ] - ]); + ], $routings); } /** @@ -161,12 +167,12 @@ public function selectJoined() { * @covers :: */ public function insert() { - $query = 'INSERT INTO products ("name") VALUES ("myName")'; + $query = 'INSERT INTO products (name) VALUES ("myName")'; $expected = new Request('post', $this->apiUrl . '/products', $this->options, null, json_encode([ 'name' => 'myName' - ])); + ]), 201); - $this->assertEquals($expected, str_replace('\\"', '', $this->mysqlToRequest->transform($query))); + $this->assertEquals($expected, $this->mysqlToRequest->transform($query)); } /** @@ -185,7 +191,7 @@ public function update() { 'name' => 'myValue' ])); - $this->assertEquals($expected, str_replace('\\"', '', $this->mysqlToRequest->transform($query, $params))); + $this->assertEquals($expected, $this->mysqlToRequest->transform($query, $params)); } /** @@ -201,7 +207,7 @@ public function updateAll() { 'name' => 'myValue' ])); - $this->assertEquals($expected, str_replace('\\"', '', $this->mysqlToRequest->transform($query))); + $this->assertEquals($expected, $this->mysqlToRequest->transform($query)); } /** @@ -216,7 +222,7 @@ public function delete() { $params = [ 1 ]; - $expected = new Request('delete', $this->apiUrl . '/products/1', $this->options, null, null); + $expected = new Request('delete', $this->apiUrl . '/products/1', $this->options, null, null, 204); $this->assertEquals($expected, $this->mysqlToRequest->transform($query, $params)); } diff --git a/Tests/Types/AnnotationTest.php b/Tests/Types/AnnotationTest.php index f23e8ab..2b803ad 100644 --- a/Tests/Types/AnnotationTest.php +++ b/Tests/Types/AnnotationTest.php @@ -19,6 +19,7 @@ namespace Circle\DoctrineRestDriver\Tests\Types; use Circle\DoctrineRestDriver\Annotations\RoutingTable; +use Circle\DoctrineRestDriver\Annotations\Select; use Circle\DoctrineRestDriver\Types\Annotation; use PHPSQLParser\PHPSQLParser; @@ -45,4 +46,20 @@ public function exists() { $this->assertTrue(Annotation::exists($routings, 'products', 'get')); $this->assertFalse(Annotation::exists($routings, 'products', 'post')); } + + /** + * @test + * @group unit + * @covers ::get + * + * @SuppressWarnings("PHPMD.StaticAccess") + */ + public function get() { + $routings = new RoutingTable(['products' => 'Circle\DoctrineRestDriver\Tests\Entity\TestEntity']); + $annotation = new Select([ + 'value' => 'http://127.0.0.1:3000/app_dev.php/mockapi/products' + ]); + + $this->assertEquals($annotation, Annotation::get($routings, 'products', 'get')); + } } \ No newline at end of file diff --git a/Tests/Types/HttpMethodTest.php b/Tests/Types/HttpMethodTest.php new file mode 100644 index 0000000..04d2a54 --- /dev/null +++ b/Tests/Types/HttpMethodTest.php @@ -0,0 +1,68 @@ +. + */ + +namespace Circle\DoctrineRestDriver\Tests\Types; + +use Circle\DoctrineRestDriver\Enums\HttpMethods; +use Circle\DoctrineRestDriver\Enums\SqlOperations; +use Circle\DoctrineRestDriver\Types\HttpMethod; + +/** + * Tests the http method type + * + * @author Tobias Hauck + * @copyright 2015 TeeAge-Beatz UG + * + * @coversDefaultClass Circle\DoctrineRestDriver\Types\HttpMethod + */ +class HttpMethodTest extends \PHPUnit_Framework_TestCase { + + /** + * @test + * @group unit + * @covers ::create + * + * @SuppressWarnings("PHPMD.StaticAccess") + */ + public function create() { + $annotation = $this->getMockBuilder('Circle\DoctrineRestDriver\Annotations\DataSource')->getMock(); + $annotation + ->expects($this->exactly(2)) + ->method('getMethod') + ->will($this->returnValue(HttpMethods::PUT)); + + $this->assertSame(HttpMethods::PUT, HttpMethod::create(SqlOperations::INSERT, $annotation)); + } + + /** + * @test + * @group unit + * @covers ::create + * + * @SuppressWarnings("PHPMD.StaticAccess") + */ + public function createWithEmptyMethod() { + $annotation = $this->getMockBuilder('Circle\DoctrineRestDriver\Annotations\DataSource')->getMock(); + $annotation + ->expects($this->once()) + ->method('getMethod') + ->will($this->returnValue(null)); + + $this->assertSame(HttpMethods::POST, HttpMethod::create(SqlOperations::INSERT, $annotation)); + } +} \ No newline at end of file diff --git a/Tests/Types/InsertPayloadTest.php b/Tests/Types/InsertPayloadTest.php index 27b0e80..8c02da8 100644 --- a/Tests/Types/InsertPayloadTest.php +++ b/Tests/Types/InsertPayloadTest.php @@ -59,7 +59,7 @@ public function createWithRawValues() { */ public function createWithQuotedValues() { $parser = new PHPSQLParser(); - $tokens = $parser->parse('INSERT INTO products (name, value) VALUES ("testname", "testvalue")'); + $tokens = $parser->parse('INSERT INTO products (name, value) VALUES ("testname", `testvalue`)'); $expected = json_encode([ 'name' => 'testname', 'value' => 'testvalue', @@ -85,4 +85,34 @@ public function createWithIntValue() { $this->assertSame($expected, InsertPayload::create($tokens)); } + + /** + * @test + * @group unit + * @covers ::values + * + * @SuppressWarnings("PHPMD.StaticAccess") + */ + public function values() { + $parser = new PHPSQLParser(); + $tokens = $parser->parse('INSERT INTO products (name, value) VALUES (testname, testvalue)'); + $expected = ['testname', 'testvalue']; + + $this->assertEquals($expected, InsertPayload::values($tokens)); + } + + /** + * @test + * @group unit + * @covers ::columns + * + * @SuppressWarnings("PHPMD.StaticAccess") + */ + public function columns() { + $parser = new PHPSQLParser(); + $tokens = $parser->parse('INSERT INTO products (name, value) VALUES (testname, testvalue)'); + $expected = ['name', 'value']; + + $this->assertEquals($expected, InsertPayload::columns($tokens)); + } } \ No newline at end of file diff --git a/Tests/Types/RequestTest.php b/Tests/Types/RequestTest.php index c446ce1..dce6d2c 100644 --- a/Tests/Types/RequestTest.php +++ b/Tests/Types/RequestTest.php @@ -41,18 +41,20 @@ class RequestTest extends \PHPUnit_Framework_TestCase { * @covers ::getPayload * @covers ::getQuery * @covers ::getCurlOptions + * @covers ::getExpectedStatusCode * @covers ::__toString */ public function constructAndGetAll() { $options = []; - $request = new Request('GET', 'http://circle.ai', $options, 'genious=1'); - $this->assertSame('GET', $request->getMethod()); + $request = new Request('get', 'http://circle.ai', $options, 'genious=1'); + $this->assertSame('get', $request->getMethod()); $this->assertSame('http://circle.ai', $request->getUrl()); $this->assertSame('http://circle.ai?genious=1', $request->getUrlAndQuery()); $this->assertSame(null, $request->getPayload()); $this->assertSame('genious=1', $request->getQuery()); $this->assertSame('GET http://circle.ai?genious=1 HTTP/1.1', $request->__toString()); $this->assertEquals([], $request->getCurlOptions()); + $this->assertEquals(200, $request->getExpectedStatusCode()); } } \ No newline at end of file diff --git a/Tests/Types/StatusCodeTest.php b/Tests/Types/StatusCodeTest.php new file mode 100644 index 0000000..a354b56 --- /dev/null +++ b/Tests/Types/StatusCodeTest.php @@ -0,0 +1,67 @@ +. + */ + +namespace Circle\DoctrineRestDriver\Tests\Types; + +use Circle\DoctrineRestDriver\Enums\SqlOperations; +use Circle\DoctrineRestDriver\Types\StatusCode; + +/** + * Tests the status code type + * + * @author Tobias Hauck + * @copyright 2015 TeeAge-Beatz UG + * + * @coversDefaultClass Circle\DoctrineRestDriver\Types\StatusCode + */ +class StatusCodeTest extends \PHPUnit_Framework_TestCase { + + /** + * @test + * @group unit + * @covers ::create + * + * @SuppressWarnings("PHPMD.StaticAccess") + */ + public function create() { + $annotation = $this->getMockBuilder('Circle\DoctrineRestDriver\Annotations\DataSource')->getMock(); + $annotation + ->expects($this->exactly(2)) + ->method('getStatusCode') + ->will($this->returnValue(202)); + + $this->assertSame(202, StatusCode::create(SqlOperations::INSERT, $annotation)); + } + + /** + * @test + * @group unit + * @covers ::create + * + * @SuppressWarnings("PHPMD.StaticAccess") + */ + public function createWithEmptyStatusCode() { + $annotation = $this->getMockBuilder('Circle\DoctrineRestDriver\Annotations\DataSource')->getMock(); + $annotation + ->expects($this->once()) + ->method('getStatusCode') + ->will($this->returnValue(null)); + + $this->assertSame(201, StatusCode::create(SqlOperations::INSERT, $annotation)); + } +} \ No newline at end of file diff --git a/Tests/Types/TableTest.php b/Tests/Types/TableTest.php index 9aed8a4..8b15521 100644 --- a/Tests/Types/TableTest.php +++ b/Tests/Types/TableTest.php @@ -227,38 +227,4 @@ public function replace() { $tokens = $parser->parse('SELECT * FROM products'); $this->assertSame('http://www.circle.ai/get', Table::create(Table::replace($tokens, 'http://www.circle.ai/get'))); } - - /** - * @test - * @group unit - * @covers ::replaceWithAnnotation - * @covers :: - * - * @SuppressWarnings("PHPMD.StaticAccess") - */ - public function replaceWithAnnotation() { - $parser = new PHPSQLParser(); - $routing = new Routing('Circle\DoctrineRestDriver\Tests\Entity\TestEntity'); - - $annotations = $this->getMockBuilder('Circle\DoctrineRestDriver\Annotations\RoutingTable')->disableOriginalConstructor()->getMock(); - $annotations - ->expects($this->any()) - ->method('get') - ->will($this->returnValue($routing)); - - $tokens = $parser->parse('UPDATE products p0 set name="name"'); - $this->assertSame('products', Table::create(Table::replaceWithAnnotation($tokens, $annotations))); - - $tokens = $parser->parse('INSERT INTO products (test) VALUES ("test")'); - $this->assertSame('products', Table::create(Table::replaceWithAnnotation($tokens, $annotations))); - - $tokens = $parser->parse('SELECT * FROM products'); - $this->assertSame('products', Table::create(Table::replaceWithAnnotation($tokens, $annotations))); - - $tokens = $parser->parse('SELECT * FROM products WHERE id = 1'); - $this->assertSame('http://127.0.0.1:3000/app_dev.php/mockapi/products', Table::create(Table::replaceWithAnnotation($tokens, $annotations))); - - $tokens = $parser->parse('DELETE FROM products'); - $this->assertSame('products', Table::create(Table::replaceWithAnnotation($tokens, $annotations))); - } } \ No newline at end of file diff --git a/Tests/Types/UrlTest.php b/Tests/Types/UrlTest.php index 2a49145..44aaf15 100644 --- a/Tests/Types/UrlTest.php +++ b/Tests/Types/UrlTest.php @@ -39,10 +39,7 @@ class UrlTest extends \PHPUnit_Framework_TestCase { * @SuppressWarnings("PHPMD.StaticAccess") */ public function create() { - $parser = new PHPSQLParser(); - $tokens = $parser->parse('SELECT name FROM products WHERE id=1'); - - $this->assertSame('http://circle.ai/products/1', Url::create($tokens, 'http://circle.ai')); + $this->assertSame('http://circle.ai/products/1', Url::create('products', 'http://circle.ai', '1')); } /** @@ -53,10 +50,7 @@ public function create() { * @SuppressWarnings("PHPMD.StaticAccess") */ public function createWithUrl() { - $parser = new PHPSQLParser(); - $tokens = $parser->parse('SELECT name FROM "http://www.circle.ai/products/{id}" WHERE id=1'); - - $this->assertSame('http://www.circle.ai/products/1', Url::create($tokens, 'http://circle.ai')); + $this->assertSame('http://www.circle.ai/products/1', Url::create('http://www.circle.ai/products/{id}', 'http://circle.ai', '1')); } /** @@ -67,10 +61,7 @@ public function createWithUrl() { * @SuppressWarnings("PHPMD.StaticAccess") */ public function createWithUrlWithoutSetId() { - $parser = new PHPSQLParser(); - $tokens = $parser->parse('SELECT name FROM "http://www.circle.ai/products/{id}"'); - - $this->assertSame('http://www.circle.ai/products', Url::create($tokens, 'http://circle.ai')); + $this->assertSame('http://www.circle.ai/products', Url::create('http://www.circle.ai/products/{id}', 'http://circle.ai')); } /** @@ -81,9 +72,24 @@ public function createWithUrlWithoutSetId() { * @SuppressWarnings("PHPMD.StaticAccess") */ public function createWithoutAnyId() { - $parser = new PHPSQLParser(); - $tokens = $parser->parse('SELECT name FROM "http://www.circle.ai/products" WHERE id=1'); + $this->assertSame('http://www.circle.ai/products/1', Url::create('http://www.circle.ai/products', 'http://circle.ai', '1')); + } + + /** + * @test + * @group unit + * @covers ::createFromTokens + * + * @SuppressWarnings("PHPMD.StaticAccess") + */ + public function createFromTokens() { + $tokens = (new PHPSQLParser())->parse('SELECT name FROM products WHERE id=1'); + $annotation = $this->getMockBuilder('Circle\DoctrineRestDriver\Annotations\DataSource')->getMock(); + $annotation + ->expects($this->exactly(2)) + ->method('getRoute') + ->will($this->returnValue('http://circle.ai/products/{id}')); - $this->assertSame('http://www.circle.ai/products/1', Url::create($tokens, 'http://circle.ai')); + $this->assertSame('http://circle.ai/products/1', Url::createFromTokens($tokens, 'http://circle.ai', $annotation)); } } \ No newline at end of file diff --git a/Tests/Validation/AssertionsTest.php b/Tests/Validation/AssertionsTest.php index d71772c..38fec1c 100644 --- a/Tests/Validation/AssertionsTest.php +++ b/Tests/Validation/AssertionsTest.php @@ -28,6 +28,7 @@ * @copyright 2015 TeeAge-Beatz UG * * @coversDefaultClass Circle\DoctrineRestDriver\Validation\Assertions + * @SuppressWarnings("PHPMD.TooManyPublicMethods") */ class AssertionsTest extends \PHPUnit_Framework_TestCase { @@ -150,4 +151,102 @@ public function isNoUrlTest() { public function assertAuthStrategy() { $this->assertSame(null, Assertions::assertAuthStrategy(new HttpAuthentication([]))); } + + /** + * @test + * @group unit + * @covers ::assertMaybeList + * + * @SuppressWarnings("PHPMD.StaticAccess") + */ + public function assertMaybeList() { + $this->assertSame(null, Assertions::assertMaybeList('null', null)); + $this->assertSame(null, Assertions::assertMaybeList('list', [])); + } + + /** + * @test + * @group unit + * @covers ::assertMaybeList + * + * @SuppressWarnings("PHPMD.StaticAccess") + * @expectedException \Circle\DoctrineRestDriver\Validation\Exceptions\InvalidTypeException + */ + public function assertMaybeListOnException() { + Assertions::assertMaybeList('string', 'hello'); + } + + /** + * @test + * @group unit + * @covers ::assertMaybeString + * + * @SuppressWarnings("PHPMD.StaticAccess") + */ + public function assertMaybeString() { + $this->assertSame(null, Assertions::assertMaybeString('null', null)); + $this->assertSame(null, Assertions::assertMaybeString('string', 'value')); + } + + /** + * @test + * @group unit + * @covers ::assertMaybeString + * + * @SuppressWarnings("PHPMD.StaticAccess") + * @expectedException \Circle\DoctrineRestDriver\Validation\Exceptions\InvalidTypeException + */ + public function assertMaybeStringOnException() { + Assertions::assertMaybeString('array', []); + } + + /** + * @test + * @group unit + * @covers ::assertMaybeInt + * + * @SuppressWarnings("PHPMD.StaticAccess") + */ + public function assertMaybeInt() { + $this->assertSame(null, Assertions::assertMaybeInt('null', null)); + $this->assertSame(null, Assertions::assertMaybeInt('int', 123)); + } + + /** + * @test + * @group unit + * @covers ::assertMaybeInt + * + * @SuppressWarnings("PHPMD.StaticAccess") + * @expectedException \Circle\DoctrineRestDriver\Validation\Exceptions\InvalidTypeException + */ + public function assertMaybeIntOnException() { + Assertions::assertMaybeInt('float', 3.2); + } + + /** + * @test + * @group unit + * @covers ::assertUrl + * + * @SuppressWarnings("PHPMD.StaticAccess") + */ + public function assertUrl() { + $this->assertSame(null, Assertions::assertUrl('Url', 'http://www.test.com')); + $this->assertSame(null, Assertions::assertUrl('Url', 'http://www.test.com?filter=1')); + $this->assertSame(null, Assertions::assertUrl('Url', 'http://circle.ai')); + $this->assertSame(null, Assertions::assertUrl('Url', 'http://circle.ai/test?test=test')); + } + + /** + * @test + * @group unit + * @covers ::assertUrl + * + * @SuppressWarnings("PHPMD.StaticAccess") + * @expectedException \Circle\DoctrineRestDriver\Validation\Exceptions\InvalidTypeException + */ + public function assertUrlOnException() { + Assertions::assertUrl('Url', 'localhost:3000'); + } } \ No newline at end of file diff --git a/Transformers/MysqlToRequest.php b/Transformers/MysqlToRequest.php index ca91e2f..9b69ed9 100644 --- a/Transformers/MysqlToRequest.php +++ b/Transformers/MysqlToRequest.php @@ -67,7 +67,7 @@ class MysqlToRequest { * @param array $options * @param RoutingTable $routings */ - public function __construct(array $options, RoutingTable $routings = null) { + public function __construct(array $options, RoutingTable $routings) { $this->apiUrl = $options['host']; $this->options = $options['driverOptions']; $this->parser = new PHPSQLParser(); @@ -94,6 +94,8 @@ public function transform($query, array $params = []) { return $carry . (Assertions::isUrl($part) ? ('"' . $part . '" ') : ($part . ' ')); }); - return $this->requestFactory->createOne(Table::replaceWithAnnotation($this->parser->parse($transformedQuery), $this->routings), $this->apiUrl, $this->options); + $tokens = $this->parser->parse($transformedQuery); + + return $this->requestFactory->createOne($tokens, $this->apiUrl, $this->options, $this->routings); } } \ No newline at end of file diff --git a/Types/Annotation.php b/Types/Annotation.php index b3d8b73..a7a5602 100644 --- a/Types/Annotation.php +++ b/Types/Annotation.php @@ -18,6 +18,7 @@ namespace Circle\DoctrineRestDriver\Types; +use Circle\DoctrineRestDriver\Annotations\DataSource; use Circle\DoctrineRestDriver\Annotations\RoutingTable; /** @@ -28,6 +29,20 @@ */ class Annotation { + /** + * returns the corresponding data source annotation if exists + * + * @param RoutingTable $annotations + * @param string $entityAlias + * @param string $method + * @return DataSource|null + */ + public static function get(RoutingTable $annotations, $entityAlias, $method) { + if (!self::exists($annotations, $entityAlias, $method)) return null; + + return $annotations->get($entityAlias)->$method(); + } + /** * checks if the annotation exists * diff --git a/Types/HttpMethod.php b/Types/HttpMethod.php new file mode 100644 index 0000000..1b1ff23 --- /dev/null +++ b/Types/HttpMethod.php @@ -0,0 +1,46 @@ +. + */ + +namespace Circle\DoctrineRestDriver\Types; + +use Circle\DoctrineRestDriver\Annotations\DataSource; +use Circle\DoctrineRestDriver\Enums\HttpMethods; +use Circle\DoctrineRestDriver\Validation\Assertions; + +/** + * Type for HTTP method + * + * @author Tobias Hauck + * @copyright 2015 TeeAge-Beatz UG + */ +class HttpMethod { + + /** + * Returns the right HTTP method + * + * @param string $sqlOperation + * @param DataSource $annotation + * @return string + * + * @SuppressWarnings("PHPMD.StaticAccess") + */ + public static function create($sqlOperation, DataSource $annotation = null) { + Assertions::assertString('sqlOperation', $sqlOperation); + return empty($annotation) || $annotation->getMethod() === null ? HttpMethods::ofSqlOperation($sqlOperation) : $annotation->getMethod(); + } +} \ No newline at end of file diff --git a/Types/HttpQuery.php b/Types/HttpQuery.php index 2e969d8..30af5f1 100644 --- a/Types/HttpQuery.php +++ b/Types/HttpQuery.php @@ -34,7 +34,7 @@ class HttpQuery { * clause of the parsed sql tokens * * @param array $tokens - * @return string + * @return string|null * * @SuppressWarnings("PHPMD.StaticAccess") */ @@ -42,7 +42,7 @@ public static function create(array $tokens) { Assertions::assertHashMap('tokens', $tokens); $operation = SqlOperation::create($tokens); - if ($operation !== SqlOperations::SELECT || empty($tokens['WHERE'])) return ''; + if ($operation !== SqlOperations::SELECT || empty($tokens['WHERE'])) return null; $tableAlias = Table::alias($tokens); $query = array_reduce($tokens['WHERE'], function($query, $token) use ($tableAlias) { diff --git a/Types/InsertPayload.php b/Types/InsertPayload.php index ba41291..65a2c69 100644 --- a/Types/InsertPayload.php +++ b/Types/InsertPayload.php @@ -40,15 +40,38 @@ class InsertPayload { public static function create(array $tokens) { Assertions::assertHashMap('tokens', $tokens); + return json_encode(array_combine(self::columns($tokens), self::values($tokens))); + } + + /** + * returns the columns as list + * + * @param array $tokens + * @return array + */ + public static function columns(array $tokens) { $columns = array_filter($tokens['INSERT'], function($token) { return $token['expr_type'] === 'column-list'; }); - $columns = explode(',', str_replace(['(', ')', ' '], '', end($columns)['base_expr'])); - $values = explode(',', str_replace(['(', ')', ' '], '', end($tokens['VALUES'])['base_expr'])); + return array_map(function($column) { + return end($column['no_quotes']['parts']); + }, end($columns)['sub_tree']); + } + + /** + * returns the values as list + * + * @param array $tokens + * @return array + * + * @SuppressWarnings("PHPMD.StaticAccess") + */ + public static function values(array $tokens) { + $values = explode(',', preg_replace('/\)$/', '', preg_replace('/^\(/', '', str_replace(', ', ',', end($tokens['VALUES'])['base_expr'])))); - return json_encode(array_combine($columns, array_map(function($value) { + return array_map(function($value) { return Value::create($value); - }, $values))); + }, $values); } } \ No newline at end of file diff --git a/Types/Request.php b/Types/Request.php index 277654f..7f0ea56 100644 --- a/Types/Request.php +++ b/Types/Request.php @@ -51,6 +51,11 @@ class Request { */ private $query; + /** + * @var int + */ + private $expectedStatusCode; + /** * Request constructor * @@ -59,13 +64,15 @@ class Request { * @param array $curlOptions * @param string|null $query * @param string|null $payload + * @param int|null $expectedStatusCode */ - public function __construct($method, $url, array $curlOptions, $query = null, $payload = null) { - $this->method = $method; - $this->url = $url; - $this->payload = $payload; - $this->curlOptions = $curlOptions; - $this->query = $query; + public function __construct($method, $url, array $curlOptions, $query = null, $payload = null, $expectedStatusCode = 200) { + $this->method = strtolower($method); + $this->url = $url; + $this->payload = $payload; + $this->curlOptions = $curlOptions; + $this->query = $query; + $this->expectedStatusCode = $expectedStatusCode; } /** @@ -122,10 +129,19 @@ public function getUrlAndQuery() { return $this->url . '?' . $this->query; } + /** + * returns the expected response http code + * + * @return int + */ + public function getExpectedStatusCode() { + return $this->expectedStatusCode; + } + /** * {@inheritdoc} */ public function __toString() { - return $this->method . ' ' . $this->getUrlAndQuery() . ' HTTP/1.1' . (!empty($this->payload) ? ' ' . $this->payload : ''); + return strtoupper($this->method) . ' ' . $this->getUrlAndQuery() . ' HTTP/1.1' . (!empty($this->payload) ? ' ' . $this->payload : ''); } } \ No newline at end of file diff --git a/Types/StatusCode.php b/Types/StatusCode.php new file mode 100644 index 0000000..a2bbc4c --- /dev/null +++ b/Types/StatusCode.php @@ -0,0 +1,57 @@ +. + */ + +namespace Circle\DoctrineRestDriver\Types; + +use Circle\DoctrineRestDriver\Annotations\DataSource; +use Circle\DoctrineRestDriver\Validation\Assertions; + +/** + * Type class for status codes + * + * @author Tobias Hauck + * @copyright 2015 TeeAge-Beatz UG + */ +class StatusCode { + + /** + * @var array + */ + private static $expectedStatusCodes = [ + 'select' => 200, + 'update' => 200, + 'insert' => 201, + 'delete' => 204 + ]; + + /** + * returns the status code depending on its input + * + * @param string $operation + * @param DataSource $annotation + * @return string + * + * @SuppressWarnings("PHPMD.StaticAccess") + */ + public static function create($operation, DataSource $annotation = null) { + Assertions::assertString('operation', $operation); + $code = empty($annotation) || $annotation->getStatusCode() === null ? null : $annotation->getStatusCode(); + + return empty($code) ? self::$expectedStatusCodes[$operation] : $code; + } +} \ No newline at end of file diff --git a/Types/Table.php b/Types/Table.php index 1fe8a08..0b418c0 100644 --- a/Types/Table.php +++ b/Types/Table.php @@ -83,22 +83,4 @@ public static function replace(array $tokens, $newTable) { return $tokens; } - - /** - * replaces the table name with the related annotation - * - * @param array $tokens - * @param RoutingTable $annotations - * @return array - */ - public static function replaceWithAnnotation(array $tokens, RoutingTable $annotations = null) { - if (empty($annotations)) return $tokens; - - $table = Table::create($tokens); - $method = HttpMethods::ofSqlOperation(SqlOperation::create($tokens)); - $id = Id::create($tokens); - $methodToCall = $method === HttpMethods::GET && empty($id) ? $method . 'All' : $method; - - return Annotation::exists($annotations, $table, $methodToCall) ? Table::replace($tokens, $annotations->get($table)->$methodToCall()) : $tokens; - } } \ No newline at end of file diff --git a/Types/UpdatePayload.php b/Types/UpdatePayload.php index 340adaa..e58a6be 100644 --- a/Types/UpdatePayload.php +++ b/Types/UpdatePayload.php @@ -47,7 +47,7 @@ public static function create(array $tokens) { $values = array_map(function($token) { $segments = explode('=', $token['base_expr']); - return str_replace('"', '', $segments[1]); + return Value::create($segments[1]); }, $tokens['SET']); return json_encode(array_combine($columns, $values)); diff --git a/Types/Url.php b/Types/Url.php index c6e775e..5b27d73 100644 --- a/Types/Url.php +++ b/Types/Url.php @@ -18,6 +18,7 @@ namespace Circle\DoctrineRestDriver\Types; +use Circle\DoctrineRestDriver\Annotations\DataSource; use Circle\DoctrineRestDriver\Validation\Assertions; /** @@ -29,23 +30,42 @@ class Url { /** - * Returns an url depending on the given sql tokens + * returns an url depending on the given route, apiUrl + * and id * - * @param array $tokens - * @param string $apiUrl + * @param string $route + * @param string $apiUrl + * @param string|null $id * @return string * * @SuppressWarnings("PHPMD.StaticAccess") */ - public static function create(array $tokens, $apiUrl) { - Assertions::assertHashMap('tokens', $tokens); + public static function create($route, $apiUrl, $id = null) { + Assertions::assertString('route', $route); + Assertions::assertString('apiUrl', $apiUrl); + Assertions::assertMaybeString('id', $id); - $table = Table::create($tokens); - $id = Id::create($tokens); $idPath = empty($id) ? '' : '/' . $id; - if (!Assertions::isUrl($table)) return $apiUrl . '/' . $table . $idPath; - if (!preg_match('/\{id\}/', $table)) return $table . $idPath; - return !empty($id) ? str_replace('{id}', $id, $table) : str_replace('/{id}', '', $table); + if (!Assertions::isUrl($route)) return $apiUrl . '/' . $route . $idPath; + if (!preg_match('/\{id\}/', $route)) return $route . $idPath; + return !empty($id) ? str_replace('{id}', $id, $route) : str_replace('/{id}', '', $route); + } + + /** + * returns an url depending on the given tokens + * + * @param array $tokens + * @param string $apiUrl + * @param DataSource $annotation + * @return string + * + * @SuppressWarnings("PHPMD.StaticAccess") + */ + public static function createFromTokens(array $tokens, $apiUrl, DataSource $annotation = null) { + $id = Id::create($tokens); + $route = empty($annotation) || $annotation->getRoute() === null ? Table::create($tokens) : $annotation->getRoute(); + + return self::create($route, $apiUrl, $id); } } \ No newline at end of file diff --git a/Types/Value.php b/Types/Value.php index 1527299..07fb575 100644 --- a/Types/Value.php +++ b/Types/Value.php @@ -40,8 +40,9 @@ class Value { */ public static function create($value) { Assertions::assertString('value', $value); + if (empty($value)) return null; - $return = preg_replace('/\"$/', '', preg_replace('/^\"/', '', $value)); + $return = preg_replace('/\"|\\\'|\`$/', '', preg_replace('/^\"|\\\'|\`/', '', $value)); if (!is_numeric($return)) return $return; return ((string) intval($return) === $return) ? intval($return) : floatval($return); diff --git a/Validation/Assertions.php b/Validation/Assertions.php index 15e4a5d..eb4df1d 100644 --- a/Validation/Assertions.php +++ b/Validation/Assertions.php @@ -33,6 +33,7 @@ * @copyright 2015 TeeAge-Beatz UG * * @SuppressWarnings("PHPMD.StaticAccess") + * @SuppressWarnings("PHPMD.TooManyPublicMethods") */ class Assertions { @@ -62,6 +63,45 @@ public static function assertString($varName, $value) { return !is_string($value) ? Exceptions::InvalidTypeException('string', $varName, $value) : null; } + /** + * Asserts if the given value is a maybe list + * + * @param string $varName + * @param mixed $value + * @return null + * @throws InvalidTypeException + * @throws NotNilException + */ + public static function assertMaybeList($varName, $value) { + return !is_array($value) && $value !== null ? Exceptions::InvalidTypeException('MaybeList', $varName, $value) : null; + } + + /** + * Asserts if the given value is a maybe string + * + * @param string $varName + * @param mixed $value + * @return null + * @throws InvalidTypeException + * @throws NotNilException + */ + public static function assertMaybeString($varName, $value) { + return !is_string($value) && $value !== null ? Exceptions::InvalidTypeException('MaybeString', $varName, $value) : null; + } + + /** + * Asserts if the given value is a maybe int + * + * @param string $varName + * @param mixed $value + * @return null + * @throws InvalidTypeException + * @throws NotNilException + */ + public static function assertMaybeInt($varName, $value) { + return !is_int($value) && $value !== null ? Exceptions::InvalidTypeException('MaybeInt', $varName, $value) : null; + } + /** * Asserts if the given value is a hash map * @@ -106,6 +146,17 @@ public static function assertHashMapEntryExists($varName, $hashMap, $entryName) return array_key_exists($entryName, $hashMap) ? null : Exceptions::InvalidTypeException('HashMapEntry', $varName . '[\'' . $entryName . '\']', 'undefined'); } + /** + * Asserts if the given value is an url + * + * @param string $varName + * @param mixed $value + * @throws InvalidTypeException + */ + public static function assertUrl($varName, $value) { + if (!self::isUrl($value)) return Exceptions::InvalidTypeException('Url', $varName, $value); + } + /** * Checks if the given value is a url * From 687999a63871768b4f735edccd6fafc968a3f605 Mon Sep 17 00:00:00 2001 From: TobiasHauck Date: Thu, 4 Aug 2016 12:06:02 +0200 Subject: [PATCH 02/15] removed unnecessary uses in request factory --- Factory/RequestFactory.php | 3 --- 1 file changed, 3 deletions(-) diff --git a/Factory/RequestFactory.php b/Factory/RequestFactory.php index 60d40aa..2094d72 100644 --- a/Factory/RequestFactory.php +++ b/Factory/RequestFactory.php @@ -18,15 +18,12 @@ namespace Circle\DoctrineRestDriver\Factory; -use Circle\DoctrineRestDriver\Annotations\Routing; use Circle\DoctrineRestDriver\Annotations\RoutingTable; use Circle\DoctrineRestDriver\Enums\HttpMethods; -use Circle\DoctrineRestDriver\Enums\SqlOperations; use Circle\DoctrineRestDriver\Types\Annotation; use Circle\DoctrineRestDriver\Types\HttpHeader; use Circle\DoctrineRestDriver\Types\CurlOptions; use Circle\DoctrineRestDriver\Types\HttpMethod; -use Circle\DoctrineRestDriver\Types\Id; use Circle\DoctrineRestDriver\Types\Payload; use Circle\DoctrineRestDriver\Types\HttpQuery; use Circle\DoctrineRestDriver\Types\Request; From 59da2a42c9e681a4e3d9eb53276a704ed5ad0c00 Mon Sep 17 00:00:00 2001 From: TobiasHauck Date: Thu, 4 Aug 2016 21:30:14 +0200 Subject: [PATCH 03/15] added format --- Annotations/Route.php | 15 ++----- Exceptions/Exceptions.php | 12 +++++- Exceptions/InvalidFormatException.php | 39 +++++++++++++++++++ Factory/RequestFactory.php | 2 +- Formatters/Formatter.php | 44 +++++++++++++++++++++ Formatters/Json.php | 48 +++++++++++++++++++++++ Statement.php | 20 ++++++---- Tests/Exceptions/ExceptionsTest.php | 13 +++++++ Tests/Formatters/JsonTest.php | 56 +++++++++++++++++++++++++++ Tests/Types/AuthenticationTest.php | 54 ++++++++++++++++++++++++++ Tests/Types/FormatTest.php | 54 ++++++++++++++++++++++++++ Tests/Types/InsertPayloadTest.php | 15 ++++--- Tests/Types/PayloadTest.php | 4 +- Tests/Types/UpdatePayloadTest.php | 4 +- Tests/Validation/AssertionsTest.php | 26 +++++++++---- Types/Authentication.php | 49 +++++++++++++++++++++++ Types/Format.php | 49 +++++++++++++++++++++++ Types/InsertPayload.php | 25 +++++++++++- Types/Payload.php | 7 +++- Types/UpdatePayload.php | 2 +- Types/Url.php | 1 + Validation/Assertions.php | 27 +++++++++---- 22 files changed, 516 insertions(+), 50 deletions(-) create mode 100644 Exceptions/InvalidFormatException.php create mode 100644 Formatters/Formatter.php create mode 100644 Formatters/Json.php create mode 100644 Tests/Formatters/JsonTest.php create mode 100644 Tests/Types/AuthenticationTest.php create mode 100644 Tests/Types/FormatTest.php create mode 100644 Types/Authentication.php create mode 100644 Types/Format.php diff --git a/Annotations/Route.php b/Annotations/Route.php index 96c4b37..c1a93ef 100644 --- a/Annotations/Route.php +++ b/Annotations/Route.php @@ -62,17 +62,10 @@ trait Route { public function __construct(array $values) { $settings = new ArrayCollection($values); - $this->route = $settings->get('value'); - Assertions::assertUrl('value', $this->route); - - $this->statusCode = $settings->get('statusCode'); - Assertions::assertMaybeInt('statusCode', $this->statusCode); - - $this->method = $settings->get('method'); - Assertions::assertMaybeString('method', $this->method); - - $this->options = $settings->get('options'); - Assertions::assertMaybeList('options', $this->options); + $this->route = Assertions::assertUrl('value', $settings->get('value')); + $this->statusCode = Assertions::assertMaybeInt('statusCode', $settings->get('statusCode')); + $this->method = Assertions::assertMaybeString('method', $settings->get('method')); + $this->options = Assertions::assertMaybeList('options', $settings->get('options')); } /** diff --git a/Exceptions/Exceptions.php b/Exceptions/Exceptions.php index 7ce298a..383ee3c 100644 --- a/Exceptions/Exceptions.php +++ b/Exceptions/Exceptions.php @@ -42,7 +42,7 @@ class Exceptions { * @throws InvalidTypeException */ public static function InvalidTypeException($expectedType, $key, $value) { - throw new InvalidTypeException($expectedType, $key, is_array($value) ? print_r($value) : $value); + throw new InvalidTypeException($expectedType, $key, is_array($value) ? serialize($value) : $value); } /** @@ -85,6 +85,16 @@ public static function InvalidAuthStrategyException($class) { throw new InvalidAuthStrategyException($class); } + /** + * throws an invalid format exception + * + * @param string $class + * @throws InvalidFormatException + */ + public static function InvalidFormatException($class) { + throw new InvalidFormatException($class); + } + /** * throws a method not implemented exception * diff --git a/Exceptions/InvalidFormatException.php b/Exceptions/InvalidFormatException.php new file mode 100644 index 0000000..787f84f --- /dev/null +++ b/Exceptions/InvalidFormatException.php @@ -0,0 +1,39 @@ +. + */ + +namespace Circle\DoctrineRestDriver\Exceptions; + +/** + * Exception class for invalid format + * + * @author Tobias Hauck + * @copyright 2015 TeeAge-Beatz UG + * + * @SuppressWarnings("PHPMD.StaticAccess") + */ +class InvalidFormatException extends \Exception { + + /** + * InvalidFormatException constructor + * + * @param string $class + */ + public function __construct($class) { + parent::__construct('Class ' . $class . ' must implement Circle\DoctrineRestDriver\Formatters\Formatter to act as formatter'); + } +} diff --git a/Factory/RequestFactory.php b/Factory/RequestFactory.php index 2094d72..add8445 100644 --- a/Factory/RequestFactory.php +++ b/Factory/RequestFactory.php @@ -61,7 +61,7 @@ public function createOne(array $tokens, $apiUrl, array $options, RoutingTable $ $url = Url::createFromTokens($tokens, $apiUrl, $annotation); $options = CurlOptions::create(array_merge($options, HttpHeader::create($options, $tokens))); $query = HttpQuery::create($tokens); - $payload = Payload::create($tokens); + $payload = Payload::create($tokens, $options); $statusCode = StatusCode::create($operation, $annotation); return new Request($method, $url, $options, $query, $payload, $statusCode); diff --git a/Formatters/Formatter.php b/Formatters/Formatter.php new file mode 100644 index 0000000..6656340 --- /dev/null +++ b/Formatters/Formatter.php @@ -0,0 +1,44 @@ +. + */ + +namespace Circle\DoctrineRestDriver\Formatters; + +/** + * Contract for formatters + * + * @author Tobias Hauck + * @copyright 2015 TeeAge-Beatz UG + */ +interface Formatter { + + /** + * encodes the given values into json + * + * @param array $values + * @return string + */ + public function encode(array $values); + + /** + * decodes the given json string into an array + * + * @param string $json + * @return array + */ + public function decode($json); +} \ No newline at end of file diff --git a/Formatters/Json.php b/Formatters/Json.php new file mode 100644 index 0000000..50d172a --- /dev/null +++ b/Formatters/Json.php @@ -0,0 +1,48 @@ +. + */ + +namespace Circle\DoctrineRestDriver\Formatters; + +/** + * Encodes and decodes into json + * + * @author Tobias Hauck + * @copyright 2015 TeeAge-Beatz UG + */ +class Json implements Formatter { + + /** + * encodes the given values into json + * + * @param array $values + * @return string + */ + public function encode(array $values) { + return json_encode($values); + } + + /** + * decodes the given json string into an array + * + * @param string $json + * @return array + */ + public function decode($json) { + return json_decode($json, true); + } +} \ No newline at end of file diff --git a/Statement.php b/Statement.php index 8c7d838..0c571cc 100644 --- a/Statement.php +++ b/Statement.php @@ -22,15 +22,16 @@ use Circle\DoctrineRestDriver\Enums\HttpMethods; use Circle\DoctrineRestDriver\Exceptions\Exceptions; use Circle\DoctrineRestDriver\Factory\RestClientFactory; -use Circle\DoctrineRestDriver\Factory\ResultSetFactory; use Circle\DoctrineRestDriver\Security\AuthStrategy; use Circle\DoctrineRestDriver\Transformers\MysqlToRequest; +use Circle\DoctrineRestDriver\Types\Authentication; +use Circle\DoctrineRestDriver\Types\Format; use Circle\DoctrineRestDriver\Types\Request; use Circle\DoctrineRestDriver\Types\Result; use Circle\DoctrineRestDriver\Validation\Assertions; use Doctrine\DBAL\Driver\Statement as StatementInterface; -use Symfony\Component\EventDispatcher\EventDispatcher; use Symfony\Component\HttpFoundation\Response; +use Circle\DoctrineRestDriver\Formatters\Formatter; /** * Executes the statement - sends requests to an api @@ -39,6 +40,7 @@ * @copyright 2015 TeeAge-Beatz UG * * @SuppressWarnings("PHPMD.TooManyPublicMethods") + * @SuppressWarnings("PHPMD.CouplingBetweenObjects") */ class Statement implements \IteratorAggregate, StatementInterface { @@ -97,6 +99,11 @@ class Statement implements \IteratorAggregate, StatementInterface { */ private $routings; + /** + * @var Formatter + */ + private $formatter; + /** * Statement constructor * @@ -113,11 +120,8 @@ public function __construct($query, array $options, RoutingTable $routings) { $this->mysqlToRequest = new MysqlToRequest($options, $this->routings); $this->restClientFactory = new RestClientFactory(); - $authenticatorClass = !empty($options['driverOptions']['authenticator_class']) ? $options['driverOptions']['authenticator_class'] : 'NoAuthentication'; - $className = preg_match('/\\\\/', $authenticatorClass) ? $authenticatorClass : 'Circle\DoctrineRestDriver\Security\\' . $authenticatorClass; - Assertions::assertClassExists($className); - $this->authStrategy = new $className($options); - Assertions::assertAuthStrategy($this->authStrategy); + $this->authStrategy = Authentication::create($options); + $this->formatter = Format::create($options); } /** @@ -255,7 +259,7 @@ public function getId() { * @SuppressWarnings("PHPMD.StaticAccess") */ private function onSuccess(Response $response, $method) { - $this->result = Result::create($this->query, json_decode($response->getContent(), true)); + $this->result = Result::create($this->query, $this->formatter->decode($response->getContent())); $this->id = $method === HttpMethods::POST ? $this->result['id'] : null; krsort($this->result); diff --git a/Tests/Exceptions/ExceptionsTest.php b/Tests/Exceptions/ExceptionsTest.php index 97e2498..5b7bc84 100644 --- a/Tests/Exceptions/ExceptionsTest.php +++ b/Tests/Exceptions/ExceptionsTest.php @@ -117,4 +117,17 @@ public function invalidAuthStrategyExceptionTest() { public function invalidSqlOperationExceptionTest() { Exceptions::invalidSqlOperationException('operation'); } + + /** + * @test + * @group unit + * @covers ::invalidFormatException + * @covers Circle\DoctrineRestDriver\Exceptions\InvalidFormatException::__construct + * @expectedException \Circle\DoctrineRestDriver\Exceptions\InvalidFormatException + * + * @SuppressWarnings("PHPMD.StaticAccess") + */ + public function invalidFormatExceptionTest() { + Exceptions::invalidFormatException('class'); + } } \ No newline at end of file diff --git a/Tests/Formatters/JsonTest.php b/Tests/Formatters/JsonTest.php new file mode 100644 index 0000000..29488e5 --- /dev/null +++ b/Tests/Formatters/JsonTest.php @@ -0,0 +1,56 @@ +. + */ + +namespace Circle\DoctrineRestDriver\Tests\Formatters; + +use Circle\DoctrineRestDriver\Formatters\Json; + +/** + * Tests the json formatter + * + * @author Tobias Hauck + * @copyright 2015 TeeAge-Beatz UG + * + * @coversDefaultClass Circle\DoctrineRestDriver\Formatters\Json + */ +class JsonTest extends \PHPUnit_Framework_TestCase { + + /** + * @test + * @group unit + * @covers ::encode + * + * @SuppressWarnings("PHPMD.StaticAccess") + */ + public function encode() { + $json = new Json(); + $this->assertSame('{"test":"test"}', $json->encode(['test' => 'test'])); + } + + /** + * @test + * @group unit + * @covers ::decode + * + * @SuppressWarnings("PHPMD.StaticAccess") + */ + public function decode() { + $json = new Json(); + $this->assertEquals(['test' => 'test'], $json->decode('{"test": "test"}')); + } +} \ No newline at end of file diff --git a/Tests/Types/AuthenticationTest.php b/Tests/Types/AuthenticationTest.php new file mode 100644 index 0000000..91bc393 --- /dev/null +++ b/Tests/Types/AuthenticationTest.php @@ -0,0 +1,54 @@ +. + */ + +namespace Circle\DoctrineRestDriver\Tests\Types; + +use Circle\DoctrineRestDriver\Types\Authentication; + +/** + * Tests the authentication type + * + * @author Tobias Hauck + * @copyright 2015 TeeAge-Beatz UG + * + * @coversDefaultClass Circle\DoctrineRestDriver\Types\Authentication + */ +class AuthenticationTest extends \PHPUnit_Framework_TestCase { + + /** + * @test + * @group unit + * @covers ::create + * + * @SuppressWarnings("PHPMD.StaticAccess") + */ + public function create() { + $this->assertInstanceOf('Circle\DoctrineRestDriver\Security\AuthStrategy', Authentication::create([])); + } + + /** + * @test + * @group unit + * @covers ::create + * + * @SuppressWarnings("PHPMD.StaticAccess") + */ + public function createWithOptions() { + $this->assertInstanceOf('Circle\DoctrineRestDriver\Security\HttpAuthentication', Authentication::create(['driverOptions' => ['authenticator_class' => 'HttpAuthentication']])); + } +} \ No newline at end of file diff --git a/Tests/Types/FormatTest.php b/Tests/Types/FormatTest.php new file mode 100644 index 0000000..9b8f3f0 --- /dev/null +++ b/Tests/Types/FormatTest.php @@ -0,0 +1,54 @@ +. + */ + +namespace Circle\DoctrineRestDriver\Tests\Types; + +use Circle\DoctrineRestDriver\Types\Format; + +/** + * Tests the format type + * + * @author Tobias Hauck + * @copyright 2015 TeeAge-Beatz UG + * + * @coversDefaultClass Circle\DoctrineRestDriver\Types\Format + */ +class FormatTest extends \PHPUnit_Framework_TestCase { + + /** + * @test + * @group unit + * @covers ::create + * + * @SuppressWarnings("PHPMD.StaticAccess") + */ + public function create() { + $this->assertInstanceOf('Circle\DoctrineRestDriver\Formatters\Formatter', Format::create([])); + } + + /** + * @test + * @group unit + * @covers ::create + * + * @SuppressWarnings("PHPMD.StaticAccess") + */ + public function createWithOptions() { + $this->assertInstanceOf('Circle\DoctrineRestDriver\Formatters\Json', Format::create(['driverOptions' => ['format' => 'json']])); + } +} \ No newline at end of file diff --git a/Tests/Types/InsertPayloadTest.php b/Tests/Types/InsertPayloadTest.php index 8c02da8..a01470d 100644 --- a/Tests/Types/InsertPayloadTest.php +++ b/Tests/Types/InsertPayloadTest.php @@ -36,16 +36,17 @@ class InsertPayloadTest extends \PHPUnit_Framework_TestCase { * @test * @group unit * @covers ::create + * @covers :: * * @SuppressWarnings("PHPMD.StaticAccess") */ public function createWithRawValues() { $parser = new PHPSQLParser(); $tokens = $parser->parse('INSERT INTO products (name, value) VALUES (testname, testvalue)'); - $expected = json_encode([ + $expected = [ 'name' => 'testname', 'value' => 'testvalue', - ]); + ]; $this->assertSame($expected, InsertPayload::create($tokens)); } @@ -54,16 +55,17 @@ public function createWithRawValues() { * @test * @group unit * @covers ::create + * @covers :: * * @SuppressWarnings("PHPMD.StaticAccess") */ public function createWithQuotedValues() { $parser = new PHPSQLParser(); $tokens = $parser->parse('INSERT INTO products (name, value) VALUES ("testname", `testvalue`)'); - $expected = json_encode([ + $expected = [ 'name' => 'testname', 'value' => 'testvalue', - ]); + ]; $this->assertSame($expected, InsertPayload::create($tokens)); } @@ -72,16 +74,17 @@ public function createWithQuotedValues() { * @test * @group unit * @covers ::create + * @covers :: * * @SuppressWarnings("PHPMD.StaticAccess") */ public function createWithIntValue() { $parser = new PHPSQLParser(); $tokens = $parser->parse('INSERT INTO products (name, value) VALUES (testname, 1)'); - $expected = json_encode([ + $expected = [ 'name' => 'testname', 'value' => 1, - ]); + ]; $this->assertSame($expected, InsertPayload::create($tokens)); } diff --git a/Tests/Types/PayloadTest.php b/Tests/Types/PayloadTest.php index b9d51e7..cbfc754 100644 --- a/Tests/Types/PayloadTest.php +++ b/Tests/Types/PayloadTest.php @@ -46,7 +46,7 @@ public function createInsert() { 'value' => 'testvalue', ]); - $this->assertSame($expected, Payload::create($tokens)); + $this->assertSame($expected, Payload::create($tokens, [])); } /** @@ -64,6 +64,6 @@ public function createUpdate() { 'value' => 'testvalue', ]); - $this->assertSame($expected, Payload::create($tokens)); + $this->assertSame($expected, Payload::create($tokens, [])); } } \ No newline at end of file diff --git a/Tests/Types/UpdatePayloadTest.php b/Tests/Types/UpdatePayloadTest.php index e57a611..33385b4 100644 --- a/Tests/Types/UpdatePayloadTest.php +++ b/Tests/Types/UpdatePayloadTest.php @@ -41,10 +41,10 @@ class UpdatePayloadTest extends \PHPUnit_Framework_TestCase { public function create() { $parser = new PHPSQLParser(); $tokens = $parser->parse('UPDATE products set name="testname", value="testvalue" WHERE id=1'); - $expected = json_encode([ + $expected = [ 'name' => 'testname', 'value' => 'testvalue', - ]); + ]; $this->assertSame($expected, UpdatePayload::create($tokens)); } diff --git a/Tests/Validation/AssertionsTest.php b/Tests/Validation/AssertionsTest.php index 38fec1c..250e9f5 100644 --- a/Tests/Validation/AssertionsTest.php +++ b/Tests/Validation/AssertionsTest.php @@ -161,7 +161,7 @@ public function assertAuthStrategy() { */ public function assertMaybeList() { $this->assertSame(null, Assertions::assertMaybeList('null', null)); - $this->assertSame(null, Assertions::assertMaybeList('list', [])); + $this->assertSame([], Assertions::assertMaybeList('list', [])); } /** @@ -185,7 +185,7 @@ public function assertMaybeListOnException() { */ public function assertMaybeString() { $this->assertSame(null, Assertions::assertMaybeString('null', null)); - $this->assertSame(null, Assertions::assertMaybeString('string', 'value')); + $this->assertSame('value', Assertions::assertMaybeString('string', 'value')); } /** @@ -209,7 +209,7 @@ public function assertMaybeStringOnException() { */ public function assertMaybeInt() { $this->assertSame(null, Assertions::assertMaybeInt('null', null)); - $this->assertSame(null, Assertions::assertMaybeInt('int', 123)); + $this->assertSame(123, Assertions::assertMaybeInt('int', 123)); } /** @@ -232,10 +232,10 @@ public function assertMaybeIntOnException() { * @SuppressWarnings("PHPMD.StaticAccess") */ public function assertUrl() { - $this->assertSame(null, Assertions::assertUrl('Url', 'http://www.test.com')); - $this->assertSame(null, Assertions::assertUrl('Url', 'http://www.test.com?filter=1')); - $this->assertSame(null, Assertions::assertUrl('Url', 'http://circle.ai')); - $this->assertSame(null, Assertions::assertUrl('Url', 'http://circle.ai/test?test=test')); + $this->assertSame('http://www.test.com', Assertions::assertUrl('Url', 'http://www.test.com')); + $this->assertSame('http://www.test.com?filter=1', Assertions::assertUrl('Url', 'http://www.test.com?filter=1')); + $this->assertSame('http://circle.ai', Assertions::assertUrl('Url', 'http://circle.ai')); + $this->assertSame('http://circle.ai/test?test=test', Assertions::assertUrl('Url', 'http://circle.ai/test?test=test')); } /** @@ -249,4 +249,16 @@ public function assertUrl() { public function assertUrlOnException() { Assertions::assertUrl('Url', 'localhost:3000'); } + + /** + * @test + * @group unit + * @covers ::assertFormatter + * + * @SuppressWarnings("PHPMD.StaticAccess") + */ + public function assertFormatter() { + $formatter = $this->getMockBuilder('Circle\DoctrineRestDriver\Formatters\Formatter')->getMock(); + $this->assertSame(null, Assertions::assertFormatter($formatter)); + } } \ No newline at end of file diff --git a/Types/Authentication.php b/Types/Authentication.php new file mode 100644 index 0000000..6dd0bbe --- /dev/null +++ b/Types/Authentication.php @@ -0,0 +1,49 @@ +. + */ + +namespace Circle\DoctrineRestDriver\Types; + +use Circle\DoctrineRestDriver\Security\AuthStrategy; +use Circle\DoctrineRestDriver\Validation\Assertions; + +/** + * Type for Authentication + * + * @author Tobias Hauck + * @copyright 2015 TeeAge-Beatz UG + */ +class Authentication { + + /** + * Returns the right HTTP method + * + * @param array $options + * @return AuthStrategy + * + * @SuppressWarnings("PHPMD.StaticAccess") + */ + public static function create(array $options) { + $authenticatorClass = !empty($options['driverOptions']['authenticator_class']) ? $options['driverOptions']['authenticator_class'] : 'NoAuthentication'; + $className = preg_match('/\\\\/', $authenticatorClass) ? $authenticatorClass : 'Circle\DoctrineRestDriver\Security\\' . $authenticatorClass; + Assertions::assertClassExists($className); + $authStrategy = new $className($options); + Assertions::assertAuthStrategy($authStrategy); + + return $authStrategy; + } +} \ No newline at end of file diff --git a/Types/Format.php b/Types/Format.php new file mode 100644 index 0000000..2b6f02f --- /dev/null +++ b/Types/Format.php @@ -0,0 +1,49 @@ +. + */ + +namespace Circle\DoctrineRestDriver\Types; + +use Circle\DoctrineRestDriver\Formatters\Formatter; +use Circle\DoctrineRestDriver\Validation\Assertions; + +/** + * Type for Format + * + * @author Tobias Hauck + * @copyright 2015 TeeAge-Beatz UG + */ +class Format { + + /** + * Returns the right format + * + * @param array $options + * @return Formatter + * + * @SuppressWarnings("PHPMD.StaticAccess") + */ + public static function create(array $options) { + $formatterClass = ucfirst(!empty($options['driverOptions']['format']) ? $options['driverOptions']['format'] : 'json'); + $className = preg_match('/\\\\/', $formatterClass) ? $formatterClass : 'Circle\DoctrineRestDriver\Formatters\\' . $formatterClass; + Assertions::assertClassExists($className); + $formatter = new $className($options); + Assertions::assertFormatter($formatter); + + return $formatter; + } +} \ No newline at end of file diff --git a/Types/InsertPayload.php b/Types/InsertPayload.php index 65a2c69..79feb1a 100644 --- a/Types/InsertPayload.php +++ b/Types/InsertPayload.php @@ -40,7 +40,7 @@ class InsertPayload { public static function create(array $tokens) { Assertions::assertHashMap('tokens', $tokens); - return json_encode(array_combine(self::columns($tokens), self::values($tokens))); + return array_combine(self::columns($tokens), self::values($tokens)); } /** @@ -68,10 +68,31 @@ public static function columns(array $tokens) { * @SuppressWarnings("PHPMD.StaticAccess") */ public static function values(array $tokens) { - $values = explode(',', preg_replace('/\)$/', '', preg_replace('/^\(/', '', str_replace(', ', ',', end($tokens['VALUES'])['base_expr'])))); + $values = explode(',', self::removeBrackets(self::removeSpacesBetweenComma(end($tokens['VALUES'])['base_expr']))); return array_map(function($value) { return Value::create($value); }, $values); } + + /** + * removes spaces between commas + * + * @param string $string + * @return string + */ + private static function removeSpacesBetweenComma($string) { + return str_replace(', ', ',', $string); + } + + /** + * removes beginning and ending brackets + * + * @param string $string + * @return string + */ + private static function removeBrackets($string) { + $return = preg_replace('/^\(/', '', $string); + return preg_replace('/\)$/', '', $return); + } } \ No newline at end of file diff --git a/Types/Payload.php b/Types/Payload.php index 09449d8..5afb569 100644 --- a/Types/Payload.php +++ b/Types/Payload.php @@ -34,15 +34,18 @@ class Payload { * result or null depending on the given tokens array * * @param array $tokens + * @param array $options * @return null|string * * @SuppressWarnings("PHPMD.StaticAccess") */ - public static function create(array $tokens) { + public static function create(array $tokens, array $options) { Assertions::assertHashMap('tokens', $tokens); + $formatter = Format::create($options); $operation = SqlOperation::create($tokens); + if ($operation === SqlOperations::SELECT || $operation === SqlOperations::DELETE) return null; - return $operation === SqlOperations::INSERT ? InsertPayload::create($tokens) : UpdatePayload::create($tokens); + return $formatter->encode($operation === SqlOperations::INSERT ? InsertPayload::create($tokens) : UpdatePayload::create($tokens)); } } \ No newline at end of file diff --git a/Types/UpdatePayload.php b/Types/UpdatePayload.php index e58a6be..d661271 100644 --- a/Types/UpdatePayload.php +++ b/Types/UpdatePayload.php @@ -50,6 +50,6 @@ public static function create(array $tokens) { return Value::create($segments[1]); }, $tokens['SET']); - return json_encode(array_combine($columns, $values)); + return array_combine($columns, $values); } } \ No newline at end of file diff --git a/Types/Url.php b/Types/Url.php index 5b27d73..5f6451f 100644 --- a/Types/Url.php +++ b/Types/Url.php @@ -49,6 +49,7 @@ public static function create($route, $apiUrl, $id = null) { if (!Assertions::isUrl($route)) return $apiUrl . '/' . $route . $idPath; if (!preg_match('/\{id\}/', $route)) return $route . $idPath; + return !empty($id) ? str_replace('{id}', $id, $route) : str_replace('/{id}', '', $route); } diff --git a/Validation/Assertions.php b/Validation/Assertions.php index eb4df1d..9c0fe45 100644 --- a/Validation/Assertions.php +++ b/Validation/Assertions.php @@ -20,6 +20,7 @@ use Circle\DoctrineRestDriver\Exceptions\InvalidAuthStrategyException; use Circle\DoctrineRestDriver\Exceptions\UnsupportedFetchModeException; +use Circle\DoctrineRestDriver\Formatters\Formatter; use Circle\DoctrineRestDriver\Security\AuthStrategy; use Circle\DoctrineRestDriver\Validation\Exceptions\InvalidTypeException; use Circle\DoctrineRestDriver\Validation\Exceptions\NotNilException; @@ -68,12 +69,12 @@ public static function assertString($varName, $value) { * * @param string $varName * @param mixed $value - * @return null + * @return array|null * @throws InvalidTypeException * @throws NotNilException */ public static function assertMaybeList($varName, $value) { - return !is_array($value) && $value !== null ? Exceptions::InvalidTypeException('MaybeList', $varName, $value) : null; + return !is_array($value) && $value !== null ? Exceptions::InvalidTypeException('MaybeList', $varName, $value) : $value; } /** @@ -81,12 +82,12 @@ public static function assertMaybeList($varName, $value) { * * @param string $varName * @param mixed $value - * @return null + * @return string|null * @throws InvalidTypeException * @throws NotNilException */ public static function assertMaybeString($varName, $value) { - return !is_string($value) && $value !== null ? Exceptions::InvalidTypeException('MaybeString', $varName, $value) : null; + return !is_string($value) && $value !== null ? Exceptions::InvalidTypeException('MaybeString', $varName, $value) : $value; } /** @@ -94,12 +95,12 @@ public static function assertMaybeString($varName, $value) { * * @param string $varName * @param mixed $value - * @return null + * @return int|null * @throws InvalidTypeException * @throws NotNilException */ public static function assertMaybeInt($varName, $value) { - return !is_int($value) && $value !== null ? Exceptions::InvalidTypeException('MaybeInt', $varName, $value) : null; + return !is_int($value) && $value !== null ? Exceptions::InvalidTypeException('MaybeInt', $varName, $value) : $value; } /** @@ -151,10 +152,11 @@ public static function assertHashMapEntryExists($varName, $hashMap, $entryName) * * @param string $varName * @param mixed $value + * @return string * @throws InvalidTypeException */ public static function assertUrl($varName, $value) { - if (!self::isUrl($value)) return Exceptions::InvalidTypeException('Url', $varName, $value); + return !self::isUrl($value) ? Exceptions::InvalidTypeException('Url', $varName, $value) : $value; } /** @@ -201,4 +203,15 @@ public static function assertClassExists($className) { public static function assertAuthStrategy($instance) { return !$instance instanceof AuthStrategy ? Exceptions::invalidAuthStrategyException(get_class($instance)) : null; } + + /** + * Checks if the given instance is instanceof Formatter + * + * @param object $instance + * @return null + * @throws InvalidAuthStrategyException + */ + public static function assertFormatter($instance) { + return !$instance instanceof Formatter ? Exceptions::invalidFormatException(get_class($instance)) : null; + } } \ No newline at end of file From 8963937e4801a6187e78f867fe4f3d4a9793828c Mon Sep 17 00:00:00 2001 From: T Date: Fri, 5 Aug 2016 10:23:34 +0200 Subject: [PATCH 04/15] Update README.md --- README.md | 37 ++++++++++++++++++++++--------------- 1 file changed, 22 insertions(+), 15 deletions(-) diff --git a/README.md b/README.md index 631d25c..30090a8 100644 --- a/README.md +++ b/README.md @@ -10,9 +10,6 @@ And because we have absolutely no idea how to write a programming language, we'r # Prerequisites - You need composer to download the library -- Your REST API has to return JSON -- GET, PUT and POST requests must be answered with 200 if successful -- A response for a DELETE request needs to contain a status code of 204 if successful # Installation @@ -33,7 +30,8 @@ doctrine: user: "%default_api_username%" password: "%default_api_password%" options: - authentication_class: "HttpAuthentication" | "YourOwnNamespaceName" | if not specified no authentication will be used + format: "json" + authenticator_class: "HttpAuthentication" | "YourOwnNamespaceName" | if not specified no authentication will be used ``` Additionally you can add CURL-specific options: @@ -47,7 +45,8 @@ doctrine: user: "%default_api_username%" password: "%default_api_password%" options: - authentication_class: "HttpAuthentication" + format: "json" + authenticator_class: "HttpAuthentication" CURLOPT_CURLOPT_FOLLOWLOCATION: true CURLOPT_HEADER: true ``` @@ -116,7 +115,7 @@ Afterwards, you are able to use the created entity as if you were using a databa By using this setting, the driver is performing a lot of magic under the hood: - It generally uses the request body to send data in JSON format -- It automatically maps the response into a valid entity +- It automatically maps the response into a valid entity if the status code matches the default expected status codes (200 for GET and PUT, 201 for POST 204 for DELETE) - It saves the entity as managed doctrine entity - It translates INSERT queries into POST requests to create new data - Urls have the following format: ```{apiHost}/{pathToApi}/{tableName}``` @@ -145,7 +144,7 @@ class UserController extends Controller { * {"name": "Circle"} * * Let's assume the API responded with: - * HTTP/1.1 200 OK + * HTTP/1.1 201 Created * {"id": 1, "name": "Circle"} * * Response body is "1" @@ -241,7 +240,15 @@ class UserController extends Controller { ``` ## If your API doesn't follow our conventions -Now it's time to introduce you to some annotations, which help you to configure your own routes. Be sure to use them only with ```Doctrine``` entities. To demonstrate their capabilities, let's customize some parts of the previous chapter with the ```DataSource``` annotation: +Now it's time to introduce you to some annotations, which help you to configure your own routes. Be sure to use them only with ```Doctrine``` entities. All these annotations have the same structure so we will call them ```DataSource``` annotation: + +```php +@DataSource\SomeName("http://www.myRoute.com", method="POST", statusCode=200) +``` + +The ```ROUTE``` value is mandatory, method and statusCode are optional. + +To demonstrate their capabilities, let's customize some parts of the previous chapter with the ```DataSource``` annotation: ```php namespace CircleBundle\Entity; @@ -256,9 +263,9 @@ use Circle\DoctrineRestDriver\Annotations as DataSource; * @ORM\Table("products") * @DataSource\Select("http://www.yourSite.com/api/products/findOne/{id}") * @DataSource\Fetch("http://www.yourSite.com/api/products/findAll") - * @DataSource\Insert("http://www.yourSite.com/api/products/insert") - * @DataSource\Update("http://www.yourSite.com/api/products/update/{id}") - * @DataSource\Delete("http://www.yourSite.com/api/products/remove/{id}") + * @DataSource\Insert("http://www.yourSite.com/api/products/insert", statusCode=200) + * @DataSource\Update("http://www.yourSite.com/api/products/update/{id}", method="POST") + * @DataSource\Delete("http://www.yourSite.com/api/products/remove/{id}", method="POST", statusCode=200) */ class Product { @@ -359,14 +366,14 @@ class UserController extends Controller { /** * After sending a GET request (readAction) it sends the following * request to the API by default: - * PUT http://www.yourSite.com/api/products/update/1 HTTP/1.1 + * POST http://www.yourSite.com/api/products/update/1 HTTP/1.1 * {"name": "myName"} * * Let's assume the API responded the GET request with: * HTTP/1.1 200 OK * {"id": 1, "name": "Circle"} * - * and the PUT request with: + * and the POST request with: * HTTP/1.1 200 OK * {"id": 1, "name": "myName"} * @@ -384,10 +391,10 @@ class UserController extends Controller { /** * After sending a GET request (readAction) it sends the following * request to the API by default: - * DELETE http://www.yourSite.com/api/products/remove/1 HTTP/1.1 + * POST http://www.yourSite.com/api/products/remove/1 HTTP/1.1 * * If the response is: - * HTTP/1.1 204 No Content + * HTTP/1.1 200 OK * * the response body is "" */ From ea6dc3c203eddb46a2bb0d8abe3fe3ad3b14ea49 Mon Sep 17 00:00:00 2001 From: T Date: Fri, 5 Aug 2016 10:26:03 +0200 Subject: [PATCH 05/15] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 30090a8..b384690 100644 --- a/README.md +++ b/README.md @@ -30,7 +30,7 @@ doctrine: user: "%default_api_username%" password: "%default_api_password%" options: - format: "json" + format: "json" | "YourOwnNamespaceName" | if not specified json will be used authenticator_class: "HttpAuthentication" | "YourOwnNamespaceName" | if not specified no authentication will be used ``` From 820c4adcca485bc18d3af5f4f40f3ea9d733adb2 Mon Sep 17 00:00:00 2001 From: TobiasHauck Date: Mon, 8 Aug 2016 00:16:05 +0200 Subject: [PATCH 06/15] everything besides Assertions --- Factory/RequestFactory.php | 37 +++++------- MetaData.php | 2 - RestClient.php | 64 +++++++++++++++++++++ Security/HttpAuthentication.php | 2 +- Statement.php | 54 ++++-------------- Tests/Exceptions/ExceptionsTest.php | 2 +- Tests/Factory/RequestFactoryTest.php | 31 ++++++----- Tests/RestClientTest.php | 68 +++++++++++++++++++++++ Tests/Security/HttpAuthenticationTest.php | 12 +++- Tests/Security/NoAuthenticationTest.php | 12 +++- Tests/Transformers/MysqlToRequestTest.php | 68 ++++++++++++++++++----- Tests/Types/HttpMethodTest.php | 5 +- Tests/Types/RequestTest.php | 36 +++++++++++- Tests/Types/StatusCodeTest.php | 6 +- Transformers/MysqlToRequest.php | 17 +++--- Types/HttpMethod.php | 8 +-- Types/InsertPayload.php | 3 +- Types/Request.php | 46 +++++++++------ Types/StatusCode.php | 15 +++-- Types/Value.php | 6 +- 20 files changed, 341 insertions(+), 153 deletions(-) create mode 100644 RestClient.php create mode 100644 Tests/RestClientTest.php diff --git a/Factory/RequestFactory.php b/Factory/RequestFactory.php index add8445..84eb6da 100644 --- a/Factory/RequestFactory.php +++ b/Factory/RequestFactory.php @@ -18,18 +18,14 @@ namespace Circle\DoctrineRestDriver\Factory; -use Circle\DoctrineRestDriver\Annotations\RoutingTable; -use Circle\DoctrineRestDriver\Enums\HttpMethods; -use Circle\DoctrineRestDriver\Types\Annotation; +use Circle\DoctrineRestDriver\Annotations\DataSource; use Circle\DoctrineRestDriver\Types\HttpHeader; use Circle\DoctrineRestDriver\Types\CurlOptions; use Circle\DoctrineRestDriver\Types\HttpMethod; use Circle\DoctrineRestDriver\Types\Payload; use Circle\DoctrineRestDriver\Types\HttpQuery; use Circle\DoctrineRestDriver\Types\Request; -use Circle\DoctrineRestDriver\Types\SqlOperation; use Circle\DoctrineRestDriver\Types\StatusCode; -use Circle\DoctrineRestDriver\Types\Table; use Circle\DoctrineRestDriver\Types\Url; /** @@ -37,33 +33,28 @@ * * @author Tobias Hauck * @copyright 2015 TeeAge-Beatz UG - * - * @SuppressWarnings("PHPMD.CouplingBetweenObjects") */ class RequestFactory { /** * Creates a new Request with the given options * - * @param array $tokens - * @param string $apiUrl - * @param array $options - * @param RoutingTable $routings + * @param string $method + * @param array $tokens + * @param array $options + * @param DataSource $annotation * @return Request * * @SuppressWarnings("PHPMD.StaticAccess") */ - public function createOne(array $tokens, $apiUrl, array $options, RoutingTable $routings = null) { - $operation = SqlOperation::create($tokens); - $annotation = Annotation::get($routings, Table::create($tokens), HttpMethods::ofSqlOperation($operation)); - - $method = HttpMethod::create($operation, $annotation); - $url = Url::createFromTokens($tokens, $apiUrl, $annotation); - $options = CurlOptions::create(array_merge($options, HttpHeader::create($options, $tokens))); - $query = HttpQuery::create($tokens); - $payload = Payload::create($tokens, $options); - $statusCode = StatusCode::create($operation, $annotation); - - return new Request($method, $url, $options, $query, $payload, $statusCode); + public function createOne($method, array $tokens, array $options, DataSource $annotation = null) { + return new Request([ + 'method' => HttpMethod::create($method, $annotation), + 'url' => Url::createFromTokens($tokens, $options['host'], $annotation), + 'curlOptions' => CurlOptions::create(array_merge($options['driverOptions'], HttpHeader::create($options['driverOptions'], $tokens))), + 'query' => HttpQuery::create($tokens), + 'payload' => Payload::create($tokens, $options), + 'expectedStatusCode' => StatusCode::create($method, $annotation) + ]); } } diff --git a/MetaData.php b/MetaData.php index 330a187..1c6c8d6 100644 --- a/MetaData.php +++ b/MetaData.php @@ -18,8 +18,6 @@ namespace Circle\DoctrineRestDriver; -use Circle\DoctrineRestDriver\Annotations\Loader; -use Doctrine\Common\Annotations\AnnotationRegistry; use Doctrine\Common\Persistence\ObjectManager; /** diff --git a/RestClient.php b/RestClient.php new file mode 100644 index 0000000..d854281 --- /dev/null +++ b/RestClient.php @@ -0,0 +1,64 @@ +. + */ + +namespace Circle\DoctrineRestDriver; + +use Circle\DoctrineRestDriver\Enums\HttpMethods; +use Circle\DoctrineRestDriver\Exceptions\Exceptions; +use Circle\DoctrineRestDriver\Factory\RestClientFactory; +use Circle\DoctrineRestDriver\Types\Request; +use Symfony\Component\HttpFoundation\Response; +use Circle\RestClientBundle\Services\RestClient as CiRestClient; +use Circle\DoctrineRestDriver\Exceptions\RequestFailedException; + +/** + * Rest client to send requests and map responses + * + * @author Tobias Hauck + * @copyright 2015 TeeAge-Beatz UG + */ +class RestClient { + + /** + * @var CiRestClient + */ + private $restClient; + + /** + * RestClient constructor + */ + public function __construct() { + $this->restClient = (new RestClientFactory())->createOne([]); + } + + /** + * sends the request + * + * @param Request $request + * @return Response + * @throws RequestFailedException + * + * @SuppressWarnings("PHPMD.StaticAccess") + */ + public function send(Request $request) { + $method = strtolower($request->getMethod()); + $response = $method === HttpMethods::GET || $method === HttpMethods::DELETE ? $this->restClient->$method($request->getUrlAndQuery(), $request->getCurlOptions()) : $this->restClient->$method($request->getUrlAndQuery(), $request->getPayload(), $request->getCurlOptions()); + + return $response->getStatusCode() === $request->getExpectedStatusCode() ? $response : Exceptions::RequestFailedException($request, $response->getStatusCode(), $response->getContent()); + } +} \ No newline at end of file diff --git a/Security/HttpAuthentication.php b/Security/HttpAuthentication.php index badf7de..9070c1e 100644 --- a/Security/HttpAuthentication.php +++ b/Security/HttpAuthentication.php @@ -52,6 +52,6 @@ public function transformRequest(Request $request) { array_push($headers, 'Authorization: Basic ' . base64_encode($this->config['user'] . ':' . $this->config['password'])); $options[CURLOPT_HTTPHEADER] = $headers; - return new Request($request->getMethod(), $request->getUrl(), $options, $request->getQuery(), $request->getPayload(), $request->getExpectedStatusCode()); + return $request->setCurlOptions($options); } } \ No newline at end of file diff --git a/Statement.php b/Statement.php index 0c571cc..abf832a 100644 --- a/Statement.php +++ b/Statement.php @@ -21,7 +21,6 @@ use Circle\DoctrineRestDriver\Annotations\RoutingTable; use Circle\DoctrineRestDriver\Enums\HttpMethods; use Circle\DoctrineRestDriver\Exceptions\Exceptions; -use Circle\DoctrineRestDriver\Factory\RestClientFactory; use Circle\DoctrineRestDriver\Security\AuthStrategy; use Circle\DoctrineRestDriver\Transformers\MysqlToRequest; use Circle\DoctrineRestDriver\Types\Authentication; @@ -40,7 +39,6 @@ * @copyright 2015 TeeAge-Beatz UG * * @SuppressWarnings("PHPMD.TooManyPublicMethods") - * @SuppressWarnings("PHPMD.CouplingBetweenObjects") */ class Statement implements \IteratorAggregate, StatementInterface { @@ -60,9 +58,9 @@ class Statement implements \IteratorAggregate, StatementInterface { private $params = []; /** - * @var \Circle\DoctrineRestDriver\Factory\RestClientFactory + * @var RestClient */ - private $restClientFactory; + private $restClient; /** * @var array @@ -118,7 +116,7 @@ public function __construct($query, array $options, RoutingTable $routings) { $this->query = $query; $this->routings = $routings; $this->mysqlToRequest = new MysqlToRequest($options, $this->routings); - $this->restClientFactory = new RestClientFactory(); + $this->restClient = new RestClient(); $this->authStrategy = Authentication::create($options); $this->formatter = Format::create($options); @@ -157,17 +155,20 @@ public function errorInfo() { /** * {@inheritdoc} + * + * @SuppressWarnings("PHPMD.StaticAccess") */ public function execute($params = null) { $rawRequest = $this->mysqlToRequest->transform($this->query, $this->params); $request = $this->authStrategy->transformRequest($rawRequest); - $restClient = $this->restClientFactory->createOne($request->getCurlOptions()); - $method = strtolower($request->getMethod()); - $response = $method === HttpMethods::GET || $method === HttpMethods::DELETE ? $restClient->$method($request->getUrlAndQuery()) : $restClient->$method($request->getUrlAndQuery(), $request->getPayload()); - $statusCode = $response->getStatusCode(); + $response = $this->restClient->send($request); - return $statusCode === $request->getExpectedStatusCode() ? $this->onSuccess($response, $method) : $this->onError($request, $response); + $this->result = Result::create($this->query, $this->formatter->decode($response->getContent())); + $this->id = !empty($this->result['id']) ? $this->result['id'] : null; + krsort($this->result); + + return true; } /** @@ -248,37 +249,4 @@ public function getIterator() { public function getId() { return $this->id; } - - /** - * Handles the statement if the execution succeeded - * - * @param Response $response - * @param string $method - * @return bool - * - * @SuppressWarnings("PHPMD.StaticAccess") - */ - private function onSuccess(Response $response, $method) { - $this->result = Result::create($this->query, $this->formatter->decode($response->getContent())); - $this->id = $method === HttpMethods::POST ? $this->result['id'] : null; - krsort($this->result); - - return true; - } - - /** - * Handles the statement if the execution failed - * - * @param Request $request - * @param Response $response - * @throws \Exception - * - * @SuppressWarnings("PHPMD.StaticAccess") - */ - private function onError(Request $request, Response $response) { - $this->errorCode = $response->getStatusCode(); - $this->errorMessage = $response->getContent(); - - return Exceptions::RequestFailedException($request, $response->getStatusCode(), $response->getContent()); - } } \ No newline at end of file diff --git a/Tests/Exceptions/ExceptionsTest.php b/Tests/Exceptions/ExceptionsTest.php index 5b7bc84..2e1fdf8 100644 --- a/Tests/Exceptions/ExceptionsTest.php +++ b/Tests/Exceptions/ExceptionsTest.php @@ -89,7 +89,7 @@ public function methodNotImplementedExceptionTest() { * @SuppressWarnings("PHPMD.StaticAccess") */ public function requestFailedExceptionTest() { - Exceptions::requestFailedException(new Request('get', 'url', []), 1, 'errorMessage'); + Exceptions::requestFailedException(new Request(['method' => 'get', 'url' => 'url']), 1, 'errorMessage'); } /** diff --git a/Tests/Factory/RequestFactoryTest.php b/Tests/Factory/RequestFactoryTest.php index 4e7fecd..2f4b058 100644 --- a/Tests/Factory/RequestFactoryTest.php +++ b/Tests/Factory/RequestFactoryTest.php @@ -49,13 +49,16 @@ class RequestFactoryTest extends \PHPUnit_Framework_TestCase { * @var array */ private $factoryOptions = [ - 'CURLOPT_HTTPHEADER' => 'Content-Type: application/json', - 'CURLOPT_MAXREDIRS' => 25, - 'CURLOPT_TIMEOUT' => 25, - 'CURLOPT_CONNECTTIMEOUT' => 25, - 'CURLOPT_CRLF' => true, - 'CURLOPT_SSLVERSION' => 3, - 'CURLOPT_FOLLOWLOCATION' => true, + 'host' => 'http://circle.ai', + 'driverOptions' => [ + 'CURLOPT_HTTPHEADER' => 'Content-Type: application/json', + 'CURLOPT_MAXREDIRS' => 25, + 'CURLOPT_TIMEOUT' => 25, + 'CURLOPT_CONNECTTIMEOUT' => 25, + 'CURLOPT_CRLF' => true, + 'CURLOPT_SSLVERSION' => 3, + 'CURLOPT_FOLLOWLOCATION' => true, + ] ]; /** @@ -67,14 +70,14 @@ public function createOne() { $query = 'SELECT name FROM products WHERE id=1'; $parser = new PHPSQLParser(); $factory = new RequestFactory(); - $expected = new Request('get', 'http://circle.ai/products/1', $this->requestOptions); + $expected = new Request([ + 'method' => 'get', + 'url' => 'http://circle.ai/products/1', + 'curlOptions' => $this->requestOptions + ]); - $routings = $this->getMockBuilder('Circle\DoctrineRestDriver\Annotations\RoutingTable')->disableOriginalConstructor()->getMock(); - $routings - ->expects($this->any()) - ->method('get') - ->will($this->returnValue(null)); + $routings = $this->getMockBuilder('Circle\DoctrineRestDriver\Annotations\DataSource')->getMock(); - $this->assertEquals($expected, $factory->createOne($parser->parse($query), 'http://circle.ai', $this->factoryOptions, $routings)); + $this->assertEquals($expected, $factory->createOne('get', $parser->parse($query), $this->factoryOptions, $routings)); } } \ No newline at end of file diff --git a/Tests/RestClientTest.php b/Tests/RestClientTest.php new file mode 100644 index 0000000..3bb997d --- /dev/null +++ b/Tests/RestClientTest.php @@ -0,0 +1,68 @@ +. + */ + +namespace Circle\DoctrineRestDriver\Tests; + +use Circle\DoctrineRestDriver\Enums\HttpMethods; +use Circle\DoctrineRestDriver\RestClient; +use Circle\DoctrineRestDriver\Types\Request; +use Symfony\Component\HttpFoundation\Response; + +/** + * Tests the rest client + * + * @author Tobias Hauck + * @copyright 2015 TeeAge-Beatz UG + * + * @coversDefaultClass Circle\DoctrineRestDriver\RestClient + */ +class RestClientTest extends \PHPUnit_Framework_TestCase { + + /** + * @var RestClient + */ + private $restClient; + + /** + * {@inheritdoc} + */ + public function setUp() { + $this->restClient = new RestClient(); + } + + /** + * @test + * @group unit + * @covers ::__construct + * @covers ::send + */ + public function send() { + $request = new Request([ + 'method' => HttpMethods::GET, + 'url' => 'http://127.0.0.1:3000/app_dev.php/mockapi/products/1' + ]); + + $response = new Response(json_encode([ + 'id' => 1, + 'name' => 'MyName', + 'value' => 'MyValue' + ])); + + $this->assertEquals($response->getContent(), $this->restClient->send($request)->getContent()); + } +} \ No newline at end of file diff --git a/Tests/Security/HttpAuthenticationTest.php b/Tests/Security/HttpAuthenticationTest.php index 79cdd98..21923ac 100644 --- a/Tests/Security/HttpAuthenticationTest.php +++ b/Tests/Security/HttpAuthenticationTest.php @@ -62,8 +62,16 @@ public function transformRequest() { ] ]; - $request = new Request(HttpMethods::GET, 'http://circle.ai', []); - $expected = new Request(HttpMethods::GET, 'http://circle.ai', $expectedOptions); + $request = new Request([ + 'method' => HttpMethods::GET, + 'url' => 'http://circle.ai' + ]); + + $expected = new Request([ + 'method' => HttpMethods::GET, + 'url' => 'http://circle.ai', + 'curlOptions' => $expectedOptions + ]); $this->assertEquals($expected, $this->authentication->transformRequest($request)); } diff --git a/Tests/Security/NoAuthenticationTest.php b/Tests/Security/NoAuthenticationTest.php index 6bbe63b..c5ddfa0 100644 --- a/Tests/Security/NoAuthenticationTest.php +++ b/Tests/Security/NoAuthenticationTest.php @@ -57,8 +57,16 @@ public function setUp() { public function transformRequest() { $expectedOptions = []; - $request = new Request(HttpMethods::GET, 'http://circle.ai', []); - $expected = new Request(HttpMethods::GET, 'http://circle.ai', $expectedOptions); + $request = new Request([ + 'method' => HttpMethods::GET, + 'url' => 'http://circle.ai' + ]); + + $expected = new Request([ + 'method' => HttpMethods::GET, + 'url' => 'http://circle.ai', + 'curlOptions' => $expectedOptions + ]); $this->assertEquals($expected, $this->authentication->transformRequest($request)); } diff --git a/Tests/Transformers/MysqlToRequestTest.php b/Tests/Transformers/MysqlToRequestTest.php index 8afbd6c..a84645e 100644 --- a/Tests/Transformers/MysqlToRequestTest.php +++ b/Tests/Transformers/MysqlToRequestTest.php @@ -91,7 +91,11 @@ public function selectOne() { $params = [ 1 ]; - $expected = new Request('get', $this->apiUrl . '/products/1', $this->options, null, null); + $expected = new Request([ + 'method' => 'get', + 'url' => $this->apiUrl . '/products/1', + 'curlOptions' => $this->options + ]); $this->assertEquals($expected, $this->mysqlToRequest->transform($query, $params)); } @@ -109,7 +113,12 @@ public function selectOneBy() { 1, 'myName' ]; - $expected = new Request('get', $this->apiUrl . '/products/1', $this->options, 'name=myName', null); + $expected = new Request([ + 'method' => 'get', + 'url' => $this->apiUrl . '/products/1', + 'curlOptions' => $this->options, + 'query' => 'name=myName' + ]); $this->assertEquals($expected, $this->mysqlToRequest->transform($query, $params)); } @@ -126,7 +135,12 @@ public function selectBy() { $params = [ 'myName' ]; - $expected = new Request('get', $this->apiUrl . '/products', $this->options, 'name=myName', null); + $expected = new Request([ + 'method' => 'get', + 'url' => $this->apiUrl . '/products', + 'curlOptions' => $this->options, + 'query' => 'name=myName' + ]); $this->assertEquals($expected, $this->mysqlToRequest->transform($query, $params)); } @@ -140,7 +154,11 @@ public function selectBy() { */ public function selectAll() { $query = 'SELECT name FROM products'; - $expected = new Request('get', $this->apiUrl . '/products', $this->options, null, null); + $expected = new Request([ + 'method' => 'get', + 'url' => $this->apiUrl . '/products', + 'curlOptions' => $this->options + ]); $this->assertEquals($expected, $this->mysqlToRequest->transform($query)); } @@ -154,7 +172,11 @@ public function selectAll() { */ public function selectJoined() { $query = 'SELECT p.name FROM products p JOIN product.categories c ON c.id = p.categories_id'; - $expected = new Request('get', $this->apiUrl . '/products', $this->options, null, null); + $expected = new Request([ + 'method' => 'get', + 'url' => $this->apiUrl . '/products', + 'curlOptions' => $this->options + ]); $this->assertEquals($expected, $this->mysqlToRequest->transform($query)); } @@ -168,9 +190,14 @@ public function selectJoined() { */ public function insert() { $query = 'INSERT INTO products (name) VALUES ("myName")'; - $expected = new Request('post', $this->apiUrl . '/products', $this->options, null, json_encode([ - 'name' => 'myName' - ]), 201); + + $expected = new Request([ + 'method' => 'post', + 'url' => $this->apiUrl . '/products', + 'curlOptions' => $this->options, + 'payload' => json_encode(['name' => 'myName']), + 'expectedStatusCode' => 201 + ]); $this->assertEquals($expected, $this->mysqlToRequest->transform($query)); } @@ -187,9 +214,12 @@ public function update() { $params = [ 1 ]; - $expected = new Request('put', $this->apiUrl . '/products/1', $this->options, null, json_encode([ - 'name' => 'myValue' - ])); + $expected = new Request([ + 'method' => 'put', + 'url' => $this->apiUrl . '/products/1', + 'curlOptions' => $this->options, + 'payload' => json_encode(['name' => 'myValue']) + ]); $this->assertEquals($expected, $this->mysqlToRequest->transform($query, $params)); } @@ -203,9 +233,12 @@ public function update() { */ public function updateAll() { $query = 'UPDATE products SET name="myValue"'; - $expected = new Request('put', $this->apiUrl . '/products', $this->options, null, json_encode([ - 'name' => 'myValue' - ])); + $expected = new Request([ + 'method' => 'put', + 'url' => $this->apiUrl . '/products', + 'curlOptions' => $this->options, + 'payload' => json_encode(['name' => 'myValue']) + ]); $this->assertEquals($expected, $this->mysqlToRequest->transform($query)); } @@ -222,7 +255,12 @@ public function delete() { $params = [ 1 ]; - $expected = new Request('delete', $this->apiUrl . '/products/1', $this->options, null, null, 204); + $expected = new Request([ + 'method' => 'delete', + 'url' => $this->apiUrl . '/products/1', + 'curlOptions' => $this->options, + 'expectedStatusCode' => 204 + ]); $this->assertEquals($expected, $this->mysqlToRequest->transform($query, $params)); } diff --git a/Tests/Types/HttpMethodTest.php b/Tests/Types/HttpMethodTest.php index 04d2a54..3dc5389 100644 --- a/Tests/Types/HttpMethodTest.php +++ b/Tests/Types/HttpMethodTest.php @@ -19,7 +19,6 @@ namespace Circle\DoctrineRestDriver\Tests\Types; use Circle\DoctrineRestDriver\Enums\HttpMethods; -use Circle\DoctrineRestDriver\Enums\SqlOperations; use Circle\DoctrineRestDriver\Types\HttpMethod; /** @@ -46,7 +45,7 @@ public function create() { ->method('getMethod') ->will($this->returnValue(HttpMethods::PUT)); - $this->assertSame(HttpMethods::PUT, HttpMethod::create(SqlOperations::INSERT, $annotation)); + $this->assertSame(HttpMethods::PUT, HttpMethod::create(HttpMethods::POST, $annotation)); } /** @@ -63,6 +62,6 @@ public function createWithEmptyMethod() { ->method('getMethod') ->will($this->returnValue(null)); - $this->assertSame(HttpMethods::POST, HttpMethod::create(SqlOperations::INSERT, $annotation)); + $this->assertSame(HttpMethods::POST, HttpMethod::create(HttpMethods::POST, $annotation)); } } \ No newline at end of file diff --git a/Tests/Types/RequestTest.php b/Tests/Types/RequestTest.php index dce6d2c..1e11cf5 100644 --- a/Tests/Types/RequestTest.php +++ b/Tests/Types/RequestTest.php @@ -47,7 +47,13 @@ class RequestTest extends \PHPUnit_Framework_TestCase { public function constructAndGetAll() { $options = []; - $request = new Request('get', 'http://circle.ai', $options, 'genious=1'); + $request = new Request([ + 'method' => 'get', + 'url' => 'http://circle.ai', + 'curlOptions' => $options, + 'query' => 'genious=1' + ]); + $this->assertSame('get', $request->getMethod()); $this->assertSame('http://circle.ai', $request->getUrl()); $this->assertSame('http://circle.ai?genious=1', $request->getUrlAndQuery()); @@ -57,4 +63,32 @@ public function constructAndGetAll() { $this->assertEquals([], $request->getCurlOptions()); $this->assertEquals(200, $request->getExpectedStatusCode()); } + + /** + * @test + * @group unit + * @covers ::__construct + * @covers ::setCurlOptions + */ + public function setCurlOptions() { + $options = [ + 'CURLOPT_HEADER' => true + ]; + + $expected = new Request([ + 'method' => 'get', + 'url' => 'http://circle.ai', + 'curlOptions' => $options, + 'query' => 'genious=1' + ]); + + $request = new Request([ + 'method' => 'get', + 'url' => 'http://circle.ai', + 'curlOptions' => [], + 'query' => 'genious=1' + ]); + + $this->assertEquals($expected, $request->setCurlOptions($options)); + } } \ No newline at end of file diff --git a/Tests/Types/StatusCodeTest.php b/Tests/Types/StatusCodeTest.php index a354b56..1bea61d 100644 --- a/Tests/Types/StatusCodeTest.php +++ b/Tests/Types/StatusCodeTest.php @@ -18,7 +18,7 @@ namespace Circle\DoctrineRestDriver\Tests\Types; -use Circle\DoctrineRestDriver\Enums\SqlOperations; +use Circle\DoctrineRestDriver\Enums\HttpMethods; use Circle\DoctrineRestDriver\Types\StatusCode; /** @@ -45,7 +45,7 @@ public function create() { ->method('getStatusCode') ->will($this->returnValue(202)); - $this->assertSame(202, StatusCode::create(SqlOperations::INSERT, $annotation)); + $this->assertSame(202, StatusCode::create(HttpMethods::POST, $annotation)); } /** @@ -62,6 +62,6 @@ public function createWithEmptyStatusCode() { ->method('getStatusCode') ->will($this->returnValue(null)); - $this->assertSame(201, StatusCode::create(SqlOperations::INSERT, $annotation)); + $this->assertSame(201, StatusCode::create(HttpMethods::POST, $annotation)); } } \ No newline at end of file diff --git a/Transformers/MysqlToRequest.php b/Transformers/MysqlToRequest.php index 9b69ed9..f4837ca 100644 --- a/Transformers/MysqlToRequest.php +++ b/Transformers/MysqlToRequest.php @@ -21,6 +21,7 @@ use Circle\DoctrineRestDriver\Annotations\RoutingTable; use Circle\DoctrineRestDriver\Enums\HttpMethods; use Circle\DoctrineRestDriver\Factory\RequestFactory; +use Circle\DoctrineRestDriver\Types\Annotation; use Circle\DoctrineRestDriver\Types\Id; use Circle\DoctrineRestDriver\Types\Request; use Circle\DoctrineRestDriver\Types\SqlOperation; @@ -36,11 +37,6 @@ */ class MysqlToRequest { - /** - * @var string - */ - private $apiUrl; - /** * @var PHPSQLParser */ @@ -52,7 +48,7 @@ class MysqlToRequest { private $requestFactory; /** - * @var string + * @var array */ private $options; @@ -68,8 +64,7 @@ class MysqlToRequest { * @param RoutingTable $routings */ public function __construct(array $options, RoutingTable $routings) { - $this->apiUrl = $options['host']; - $this->options = $options['driverOptions']; + $this->options = $options; $this->parser = new PHPSQLParser(); $this->requestFactory = new RequestFactory(); $this->routings = $routings; @@ -94,8 +89,10 @@ public function transform($query, array $params = []) { return $carry . (Assertions::isUrl($part) ? ('"' . $part . '" ') : ($part . ' ')); }); - $tokens = $this->parser->parse($transformedQuery); + $tokens = $this->parser->parse($transformedQuery); + $method = HttpMethods::ofSqlOperation(SqlOperation::create($tokens)); + $annotation = Annotation::get($this->routings, Table::create($tokens), $method); - return $this->requestFactory->createOne($tokens, $this->apiUrl, $this->options, $this->routings); + return $this->requestFactory->createOne($method, $tokens, $this->options, $annotation); } } \ No newline at end of file diff --git a/Types/HttpMethod.php b/Types/HttpMethod.php index 1b1ff23..afa7001 100644 --- a/Types/HttpMethod.php +++ b/Types/HttpMethod.php @@ -33,14 +33,14 @@ class HttpMethod { /** * Returns the right HTTP method * - * @param string $sqlOperation + * @param string $method * @param DataSource $annotation * @return string * * @SuppressWarnings("PHPMD.StaticAccess") */ - public static function create($sqlOperation, DataSource $annotation = null) { - Assertions::assertString('sqlOperation', $sqlOperation); - return empty($annotation) || $annotation->getMethod() === null ? HttpMethods::ofSqlOperation($sqlOperation) : $annotation->getMethod(); + public static function create($method, DataSource $annotation = null) { + Assertions::assertString('method', $method); + return empty($annotation) || $annotation->getMethod() === null ? $method : $annotation->getMethod(); } } \ No newline at end of file diff --git a/Types/InsertPayload.php b/Types/InsertPayload.php index 79feb1a..c2d72fe 100644 --- a/Types/InsertPayload.php +++ b/Types/InsertPayload.php @@ -92,7 +92,6 @@ private static function removeSpacesBetweenComma($string) { * @return string */ private static function removeBrackets($string) { - $return = preg_replace('/^\(/', '', $string); - return preg_replace('/\)$/', '', $return); + return preg_replace('/\)$/', '', preg_replace('/^\(/', '', $string)); } } \ No newline at end of file diff --git a/Types/Request.php b/Types/Request.php index 7f0ea56..2fd25d3 100644 --- a/Types/Request.php +++ b/Types/Request.php @@ -17,6 +17,7 @@ */ namespace Circle\DoctrineRestDriver\Types; +use Circle\DoctrineRestDriver\Validation\Assertions; /** * Request type @@ -44,7 +45,7 @@ class Request { /** * @var array */ - private $curlOptions; + private $curlOptions = []; /** * @var string @@ -54,25 +55,38 @@ class Request { /** * @var int */ - private $expectedStatusCode; + private $expectedStatusCode = 200; /** * Request constructor * - * @param string $method - * @param string $url - * @param array $curlOptions - * @param string|null $query - * @param string|null $payload - * @param int|null $expectedStatusCode - */ - public function __construct($method, $url, array $curlOptions, $query = null, $payload = null, $expectedStatusCode = 200) { - $this->method = strtolower($method); - $this->url = $url; - $this->payload = $payload; - $this->curlOptions = $curlOptions; - $this->query = $query; - $this->expectedStatusCode = $expectedStatusCode; + * @param array $options + * + * @SuppressWarnings("PHPMD.StaticAccess") + */ + public function __construct(array $options) { + Assertions::assertHashMap('options', $options); + Assertions::assertHashMapEntryExists('options.method', $options, 'method'); + Assertions::assertHashMapEntryExists('options.url', $options, 'url'); + + foreach ($options as $key => $value) $this->$key = $value; + } + + /** + * sets the curl options + * + * @param array $options + * @return Request + */ + public function setCurlOptions(array $options) { + return new Request([ + 'method' => $this->method, + 'url' => $this->url, + 'curlOptions' => $options, + 'query' => $this->query, + 'payload' => $this->payload, + 'expectedStatusCode' => $this->expectedStatusCode + ]); } /** diff --git a/Types/StatusCode.php b/Types/StatusCode.php index a2bbc4c..0ad1f54 100644 --- a/Types/StatusCode.php +++ b/Types/StatusCode.php @@ -33,25 +33,24 @@ class StatusCode { * @var array */ private static $expectedStatusCodes = [ - 'select' => 200, - 'update' => 200, - 'insert' => 201, + 'get' => 200, + 'put' => 200, + 'post' => 201, 'delete' => 204 ]; /** * returns the status code depending on its input * - * @param string $operation + * @param string $method * @param DataSource $annotation * @return string * * @SuppressWarnings("PHPMD.StaticAccess") */ - public static function create($operation, DataSource $annotation = null) { - Assertions::assertString('operation', $operation); - $code = empty($annotation) || $annotation->getStatusCode() === null ? null : $annotation->getStatusCode(); + public static function create($method, DataSource $annotation = null) { + Assertions::assertString('method', $method); - return empty($code) ? self::$expectedStatusCodes[$operation] : $code; + return !empty($annotation) && $annotation->getStatusCode() !== null ? $annotation->getStatusCode() : self::$expectedStatusCodes[$method]; } } \ No newline at end of file diff --git a/Types/Value.php b/Types/Value.php index 07fb575..a4c6537 100644 --- a/Types/Value.php +++ b/Types/Value.php @@ -42,9 +42,9 @@ public static function create($value) { Assertions::assertString('value', $value); if (empty($value)) return null; - $return = preg_replace('/\"|\\\'|\`$/', '', preg_replace('/^\"|\\\'|\`/', '', $value)); - if (!is_numeric($return)) return $return; + $unquoted = preg_replace('/\"|\\\'|\`$/', '', preg_replace('/^\"|\\\'|\`/', '', $value)); + if (!is_numeric($unquoted)) return $unquoted; - return ((string) intval($return) === $return) ? intval($return) : floatval($return); + return ((string) intval($unquoted) === $unquoted) ? intval($unquoted) : floatval($unquoted); } } \ No newline at end of file From b2bfa254d0c08e1d170190b2b7423803578f1aeb Mon Sep 17 00:00:00 2001 From: TobiasHauck Date: Tue, 9 Aug 2016 11:34:44 +0200 Subject: [PATCH 07/15] id annotation lookup --- MetaData.php | 27 ++++++++++++++++---------- Tests/FunctionalTest.php | 13 ------------- Tests/Types/IdTest.php | 30 +++++++++++++++++++++++++++++ Tests/Validation/AssertionsTest.php | 22 +++++++++++---------- Types/Authentication.php | 4 +--- Types/Format.php | 4 +--- Types/Id.php | 25 +++++++++++++++++++++++- Validation/Assertions.php | 20 ++++++++++--------- 8 files changed, 96 insertions(+), 49 deletions(-) diff --git a/MetaData.php b/MetaData.php index 1c6c8d6..35b7286 100644 --- a/MetaData.php +++ b/MetaData.php @@ -28,15 +28,27 @@ */ class MetaData { + /** + * @var ObjectManager + */ + private $em; + + /** + * MetaData constructor + */ + public function __construct() { + $this->em = array_filter(debug_backtrace(), function($trace) { + return isset($trace['object']) && $trace['object'] instanceof ObjectManager; + }); + } + /** * returns all namespaces of managed entities * * @return array */ public function getEntityNamespaces() { - $meta = $this->getMetaData(debug_backtrace()); - - return array_reduce($meta, function($carry, $item) { + return array_reduce($this->get(), function($carry, $item) { $carry[$item->table['name']] = $item->getName(); return $carry; }, []); @@ -45,14 +57,9 @@ public function getEntityNamespaces() { /** * returns all entity meta data if existing * - * @param array $traces * @return array */ - private function getMetaData(array $traces) { - $em = array_filter($traces, function($trace) { - return isset($trace['object']) && $trace['object'] instanceof ObjectManager; - }); - - return empty($em) ? [] : array_pop($em)['object']->getMetaDataFactory()->getAllMetaData(); + public function get() { + return empty($this->em) ? [] : array_pop($this->em)['object']->getMetaDataFactory()->getAllMetaData(); } } \ No newline at end of file diff --git a/Tests/FunctionalTest.php b/Tests/FunctionalTest.php index c3bfbea..e4d14e1 100644 --- a/Tests/FunctionalTest.php +++ b/Tests/FunctionalTest.php @@ -57,7 +57,6 @@ public function setUp() { * @covers Circle\DoctrineRestDriver\Statement * @covers Circle\DoctrineRestDriver\Statement:: * @covers Circle\DoctrineRestDriver\MetaData - * @covers Circle\DoctrineRestDriver\MetaData:: */ public function find() { $entity = $this->em->find('Circle\DoctrineRestDriver\Tests\Entity\TestEntity', 1); @@ -74,7 +73,6 @@ public function find() { * @covers Circle\DoctrineRestDriver\Statement * @covers Circle\DoctrineRestDriver\Statement:: * @covers Circle\DoctrineRestDriver\MetaData - * @covers Circle\DoctrineRestDriver\MetaData:: * @expectedException \Exception */ public function findNonExisting() { @@ -89,7 +87,6 @@ public function findNonExisting() { * @covers Circle\DoctrineRestDriver\Statement * @covers Circle\DoctrineRestDriver\Statement:: * @covers Circle\DoctrineRestDriver\MetaData - * @covers Circle\DoctrineRestDriver\MetaData:: */ public function findOneBy() { $entity = $this->em->getRepository('Circle\DoctrineRestDriver\Tests\Entity\TestEntity')->findOneBy(['id' => 1]); @@ -106,7 +103,6 @@ public function findOneBy() { * @covers Circle\DoctrineRestDriver\Statement * @covers Circle\DoctrineRestDriver\Statement:: * @covers Circle\DoctrineRestDriver\MetaData - * @covers Circle\DoctrineRestDriver\MetaData:: */ public function findBy() { $entity = $this->em->getRepository('Circle\DoctrineRestDriver\Tests\Entity\TestEntity')->findBy(['id' => 1]); @@ -124,7 +120,6 @@ public function findBy() { * @covers Circle\DoctrineRestDriver\Statement * @covers Circle\DoctrineRestDriver\Statement:: * @covers Circle\DoctrineRestDriver\MetaData - * @covers Circle\DoctrineRestDriver\MetaData:: */ public function findAll() { $entity = $this->em->getRepository('Circle\DoctrineRestDriver\Tests\Entity\TestEntity')->findAll(); @@ -147,7 +142,6 @@ public function findAll() { * @covers Circle\DoctrineRestDriver\Statement * @covers Circle\DoctrineRestDriver\Statement:: * @covers Circle\DoctrineRestDriver\MetaData - * @covers Circle\DoctrineRestDriver\MetaData:: */ public function persistAndFlush() { $entity = new TestEntity(); @@ -175,7 +169,6 @@ public function persistAndFlush() { * @covers Circle\DoctrineRestDriver\Statement * @covers Circle\DoctrineRestDriver\Statement:: * @covers Circle\DoctrineRestDriver\MetaData - * @covers Circle\DoctrineRestDriver\MetaData:: */ public function updateAndFlush() { $entity = $this->em->find('Circle\DoctrineRestDriver\Tests\Entity\TestEntity', 1); @@ -195,7 +188,6 @@ public function updateAndFlush() { * @covers Circle\DoctrineRestDriver\Statement * @covers Circle\DoctrineRestDriver\Statement:: * @covers Circle\DoctrineRestDriver\MetaData - * @covers Circle\DoctrineRestDriver\MetaData:: */ public function remove() { $entity = $this->em->find('Circle\DoctrineRestDriver\Tests\Entity\TestEntity', 1); @@ -211,7 +203,6 @@ public function remove() { * @covers Circle\DoctrineRestDriver\Statement * @covers Circle\DoctrineRestDriver\Statement:: * @covers Circle\DoctrineRestDriver\MetaData - * @covers Circle\DoctrineRestDriver\MetaData:: */ public function dql() { $entity = $this->em @@ -231,7 +222,6 @@ public function dql() { * @covers Circle\DoctrineRestDriver\Statement * @covers Circle\DoctrineRestDriver\Statement:: * @covers Circle\DoctrineRestDriver\MetaData - * @covers Circle\DoctrineRestDriver\MetaData:: */ public function nativeQuery() { $mapping = new ResultSetMapping(); @@ -257,7 +247,6 @@ public function nativeQuery() { * @covers Circle\DoctrineRestDriver\Statement * @covers Circle\DoctrineRestDriver\Statement:: * @covers Circle\DoctrineRestDriver\MetaData - * @covers Circle\DoctrineRestDriver\MetaData:: */ public function dqlWithOrderBy() { $entity = $this->em @@ -281,7 +270,6 @@ public function dqlWithOrderBy() { * @covers Circle\DoctrineRestDriver\Statement * @covers Circle\DoctrineRestDriver\Statement:: * @covers Circle\DoctrineRestDriver\MetaData - * @covers Circle\DoctrineRestDriver\MetaData:: */ public function dqlWithObjectParameter() { $entity = $this->em @@ -300,7 +288,6 @@ public function dqlWithObjectParameter() { * @covers Circle\DoctrineRestDriver\Statement * @covers Circle\DoctrineRestDriver\Statement:: * @covers Circle\DoctrineRestDriver\MetaData - * @covers Circle\DoctrineRestDriver\MetaData:: * @expectedException \Exception */ public function nonImplementedEntity() { diff --git a/Tests/Types/IdTest.php b/Tests/Types/IdTest.php index 366678f..fa2c2ce 100644 --- a/Tests/Types/IdTest.php +++ b/Tests/Types/IdTest.php @@ -72,4 +72,34 @@ public function alias() { $this->assertSame('id', Id::alias($tokens)); } + + /** + * @test + * @group unit + * @covers ::column + * + * @SuppressWarnings("PHPMD.StaticAccess") + */ + public function column() { + $parser = new PHPSQLParser(); + $tokens = $parser->parse('SELECT name FROM products WHERE id=1'); + + $metaDataEntry = $this->getMockBuilder('Doctrine\ORM\Mapping\ClassMetadataInfo')->disableOriginalConstructor()->getMock(); + $metaDataEntry + ->expects($this->once()) + ->method('getTableName') + ->will($this->returnValue('products')); + $metaDataEntry + ->expects($this->once()) + ->method('getIdentifierColumnNames') + ->will($this->returnValue(['testId'])); + + $metaData = $this->getMockBuilder('Circle\DoctrineRestDriver\MetaData')->disableOriginalConstructor()->getMock(); + $metaData + ->expects($this->once()) + ->method('get') + ->will($this->returnValue([$metaDataEntry])); + + $this->assertSame('testId', Id::column($tokens, $metaData)); + } } \ No newline at end of file diff --git a/Tests/Validation/AssertionsTest.php b/Tests/Validation/AssertionsTest.php index 250e9f5..88091f6 100644 --- a/Tests/Validation/AssertionsTest.php +++ b/Tests/Validation/AssertionsTest.php @@ -18,7 +18,6 @@ namespace Circle\DoctrineRestDriver\Tests\Validation; -use Circle\DoctrineRestDriver\Security\HttpAuthentication; use Circle\DoctrineRestDriver\Validation\Assertions; /** @@ -40,7 +39,7 @@ class AssertionsTest extends \PHPUnit_Framework_TestCase { * @SuppressWarnings("PHPMD.StaticAccess") */ public function assertNotNilTest() { - $this->assertSame(null, Assertions::assertNotNil('test', 'test')); + $this->assertSame('test', Assertions::assertNotNil('test', 'test')); } /** @@ -51,7 +50,7 @@ public function assertNotNilTest() { * @SuppressWarnings("PHPMD.StaticAccess") */ public function assertStringTest() { - $this->assertSame(null, Assertions::assertString('test', 'test')); + $this->assertSame('test', Assertions::assertString('test', 'test')); } /** @@ -63,9 +62,10 @@ public function assertStringTest() { * @SuppressWarnings("PHPMD.StaticAccess") */ public function assertHashMapTest() { - $this->assertSame(null, Assertions::assertHashMap('test', [ + $hashMap = [ 'test' => 'test' - ])); + ]; + $this->assertSame($hashMap, Assertions::assertHashMap('test', $hashMap)); } /** @@ -76,9 +76,10 @@ public function assertHashMapTest() { * @SuppressWarnings("PHPMD.StaticAccess") */ public function assertHashMapEntryExistsTest() { - $this->assertSame(null, Assertions::assertHashMapEntryExists('test', [ + $hashMap = [ 'test' => 'test' - ], 'test')); + ]; + $this->assertSame($hashMap, Assertions::assertHashMapEntryExists('test', $hashMap, 'test')); } /** @@ -100,7 +101,7 @@ public function assertClassExistsTest() { * @SuppressWarnings("PHPMD.StaticAccess") */ public function assertSupportedFetchModeTest() { - $this->assertSame(null, Assertions::assertSupportedFetchMode(\PDO::FETCH_ASSOC)); + $this->assertSame(\PDO::FETCH_ASSOC, Assertions::assertSupportedFetchMode(\PDO::FETCH_ASSOC)); } /** @@ -149,7 +150,8 @@ public function isNoUrlTest() { * @SuppressWarnings("PHPMD.StaticAccess") */ public function assertAuthStrategy() { - $this->assertSame(null, Assertions::assertAuthStrategy(new HttpAuthentication([]))); + $authStrategy = $this->getMockBuilder('Circle\DoctrineRestDriver\Security\HttpAuthentication')->disableOriginalConstructor()->getMock(); + $this->assertSame($authStrategy, Assertions::assertAuthStrategy($authStrategy)); } /** @@ -259,6 +261,6 @@ public function assertUrlOnException() { */ public function assertFormatter() { $formatter = $this->getMockBuilder('Circle\DoctrineRestDriver\Formatters\Formatter')->getMock(); - $this->assertSame(null, Assertions::assertFormatter($formatter)); + $this->assertSame($formatter, Assertions::assertFormatter($formatter)); } } \ No newline at end of file diff --git a/Types/Authentication.php b/Types/Authentication.php index 6dd0bbe..2016df9 100644 --- a/Types/Authentication.php +++ b/Types/Authentication.php @@ -41,9 +41,7 @@ public static function create(array $options) { $authenticatorClass = !empty($options['driverOptions']['authenticator_class']) ? $options['driverOptions']['authenticator_class'] : 'NoAuthentication'; $className = preg_match('/\\\\/', $authenticatorClass) ? $authenticatorClass : 'Circle\DoctrineRestDriver\Security\\' . $authenticatorClass; Assertions::assertClassExists($className); - $authStrategy = new $className($options); - Assertions::assertAuthStrategy($authStrategy); - return $authStrategy; + return Assertions::assertAuthStrategy(new $className($options)); } } \ No newline at end of file diff --git a/Types/Format.php b/Types/Format.php index 2b6f02f..08515f4 100644 --- a/Types/Format.php +++ b/Types/Format.php @@ -41,9 +41,7 @@ public static function create(array $options) { $formatterClass = ucfirst(!empty($options['driverOptions']['format']) ? $options['driverOptions']['format'] : 'json'); $className = preg_match('/\\\\/', $formatterClass) ? $formatterClass : 'Circle\DoctrineRestDriver\Formatters\\' . $formatterClass; Assertions::assertClassExists($className); - $formatter = new $className($options); - Assertions::assertFormatter($formatter); - return $formatter; + return Assertions::assertFormatter(new $className($options)); } } \ No newline at end of file diff --git a/Types/Id.php b/Types/Id.php index 1ced05f..c23861a 100644 --- a/Types/Id.php +++ b/Types/Id.php @@ -18,6 +18,7 @@ namespace Circle\DoctrineRestDriver\Types; +use Circle\DoctrineRestDriver\MetaData; use Circle\DoctrineRestDriver\Validation\Assertions; /** @@ -59,7 +60,29 @@ public static function create(array $tokens) { * @SuppressWarnings("PHPMD.StaticAccess") */ public static function alias(array $tokens) { + $column = self::column($tokens, new MetaData()); $tableAlias = Table::alias($tokens); - return empty($tableAlias) ? 'id' : $tableAlias . '.id'; + + return empty($tableAlias) ? $column : $tableAlias . '.' . $column; + } + + /** + * returns the column of the id + * + * @param array $tokens + * @param MetaData $metaData + * @return string + * + * @SuppressWarnings("PHPMD.StaticAccess") + */ + public static function column(array $tokens, MetaData $metaData) { + $table = Table::create($tokens); + $meta = array_filter($metaData->get(), function($meta) use ($table) { + return $meta->getTableName() === $table; + }); + + $idColumns = !empty($meta) ? end($meta)->getIdentifierColumnNames() : []; + + return !empty($idColumns) ? end($idColumns) : 'id'; } } \ No newline at end of file diff --git a/Validation/Assertions.php b/Validation/Assertions.php index 9c0fe45..88b3486 100644 --- a/Validation/Assertions.php +++ b/Validation/Assertions.php @@ -28,7 +28,7 @@ use Prophecy\Exception\Doubler\ClassNotFoundException; /** - * Trait including assertions + * Assertions * * @author Tobias Hauck * @copyright 2015 TeeAge-Beatz UG @@ -43,11 +43,11 @@ class Assertions { * * @param string $varName * @param mixed $value - * @return null + * @return mixed * @throws NotNilException */ public static function assertNotNil($varName, $value) { - return $value === null ? Exceptions::NotNilException($varName) : null; + return $value === null ? Exceptions::NotNilException($varName) : $value; } /** @@ -55,13 +55,13 @@ public static function assertNotNil($varName, $value) { * * @param string $varName * @param mixed $value - * @return null + * @return mixed * @throws InvalidTypeException * @throws NotNilException */ public static function assertString($varName, $value) { self::assertNotNil($varName, $value); - return !is_string($value) ? Exceptions::InvalidTypeException('string', $varName, $value) : null; + return !is_string($value) ? Exceptions::InvalidTypeException('string', $varName, $value) : $value; } /** @@ -114,6 +114,8 @@ public static function assertMaybeInt($varName, $value) { public static function assertHashMap($varName, $value) { if(!is_array($value)) return Exceptions::InvalidTypeException('HashMap', $varName, $value); foreach($value as $key => $v) self::assertHashMapEntry($varName, [$key => $v]); + + return $value; } /** @@ -144,7 +146,7 @@ public static function assertHashMapEntry($varName, $value) { */ public static function assertHashMapEntryExists($varName, $hashMap, $entryName) { self::assertHashMap($varName, $hashMap); - return array_key_exists($entryName, $hashMap) ? null : Exceptions::InvalidTypeException('HashMapEntry', $varName . '[\'' . $entryName . '\']', 'undefined'); + return array_key_exists($entryName, $hashMap) ? $hashMap : Exceptions::InvalidTypeException('HashMapEntry', $varName . '[\'' . $entryName . '\']', 'undefined'); } /** @@ -179,7 +181,7 @@ public static function isUrl($value) { * @SuppressWarnings("PHPMD.StaticAccess") */ public static function assertSupportedFetchMode($fetchMode) { - return $fetchMode !== \PDO::FETCH_ASSOC ? Exceptions::UnsupportedFetchModeException($fetchMode) : null; + return $fetchMode !== \PDO::FETCH_ASSOC ? Exceptions::UnsupportedFetchModeException($fetchMode) : $fetchMode; } /** @@ -201,7 +203,7 @@ public static function assertClassExists($className) { * @throws InvalidAuthStrategyException */ public static function assertAuthStrategy($instance) { - return !$instance instanceof AuthStrategy ? Exceptions::invalidAuthStrategyException(get_class($instance)) : null; + return !$instance instanceof AuthStrategy ? Exceptions::invalidAuthStrategyException(get_class($instance)) : $instance; } /** @@ -212,6 +214,6 @@ public static function assertAuthStrategy($instance) { * @throws InvalidAuthStrategyException */ public static function assertFormatter($instance) { - return !$instance instanceof Formatter ? Exceptions::invalidFormatException(get_class($instance)) : null; + return !$instance instanceof Formatter ? Exceptions::invalidFormatException(get_class($instance)) : $instance; } } \ No newline at end of file From 2d9f633176a87d9fee4d98d409f52223eb1a4bf7 Mon Sep 17 00:00:00 2001 From: TobiasHauck Date: Tue, 9 Aug 2016 12:07:34 +0200 Subject: [PATCH 08/15] moved assertions --- Annotations/Route.php | 3 +- Tests/Types/AuthenticationTest.php | 12 ++++ Tests/Types/FormatTest.php | 12 ++++ Tests/Types/UrlTest.php | 64 +++++++++++++++++++++ Tests/Validation/AssertionsTest.php | 88 ----------------------------- Transformers/MysqlToRequest.php | 3 +- Types/Authentication.php | 17 +++++- Types/Format.php | 17 +++++- Types/Url.php | 30 +++++++++- Validation/Assertions.php | 59 +++---------------- phpmd.xml | 6 +- 11 files changed, 165 insertions(+), 146 deletions(-) diff --git a/Annotations/Route.php b/Annotations/Route.php index c1a93ef..ac04516 100644 --- a/Annotations/Route.php +++ b/Annotations/Route.php @@ -19,6 +19,7 @@ namespace Circle\DoctrineRestDriver\Annotations; use Circle\DoctrineRestDriver\Exceptions\Exceptions; +use Circle\DoctrineRestDriver\Types\Url; use Circle\DoctrineRestDriver\Validation\Assertions; use Doctrine\Common\Collections\ArrayCollection; @@ -62,7 +63,7 @@ trait Route { public function __construct(array $values) { $settings = new ArrayCollection($values); - $this->route = Assertions::assertUrl('value', $settings->get('value')); + $this->route = Url::assert($settings->get('value'), 'value'); $this->statusCode = Assertions::assertMaybeInt('statusCode', $settings->get('statusCode')); $this->method = Assertions::assertMaybeString('method', $settings->get('method')); $this->options = Assertions::assertMaybeList('options', $settings->get('options')); diff --git a/Tests/Types/AuthenticationTest.php b/Tests/Types/AuthenticationTest.php index 91bc393..217b5be 100644 --- a/Tests/Types/AuthenticationTest.php +++ b/Tests/Types/AuthenticationTest.php @@ -51,4 +51,16 @@ public function create() { public function createWithOptions() { $this->assertInstanceOf('Circle\DoctrineRestDriver\Security\HttpAuthentication', Authentication::create(['driverOptions' => ['authenticator_class' => 'HttpAuthentication']])); } + + /** + * @test + * @group unit + * @covers ::assert + * + * @SuppressWarnings("PHPMD.StaticAccess") + */ + public function assert() { + $authStrategy = $this->getMockBuilder('Circle\DoctrineRestDriver\Security\HttpAuthentication')->disableOriginalConstructor()->getMock(); + $this->assertSame($authStrategy, Authentication::assert($authStrategy)); + } } \ No newline at end of file diff --git a/Tests/Types/FormatTest.php b/Tests/Types/FormatTest.php index 9b8f3f0..c8fc724 100644 --- a/Tests/Types/FormatTest.php +++ b/Tests/Types/FormatTest.php @@ -51,4 +51,16 @@ public function create() { public function createWithOptions() { $this->assertInstanceOf('Circle\DoctrineRestDriver\Formatters\Json', Format::create(['driverOptions' => ['format' => 'json']])); } + + /** + * @test + * @group unit + * @covers ::assert + * + * @SuppressWarnings("PHPMD.StaticAccess") + */ + public function assert() { + $formatter = $this->getMockBuilder('Circle\DoctrineRestDriver\Formatters\Formatter')->getMock(); + $this->assertSame($formatter, Format::assert($formatter)); + } } \ No newline at end of file diff --git a/Tests/Types/UrlTest.php b/Tests/Types/UrlTest.php index 44aaf15..5132410 100644 --- a/Tests/Types/UrlTest.php +++ b/Tests/Types/UrlTest.php @@ -92,4 +92,68 @@ public function createFromTokens() { $this->assertSame('http://circle.ai/products/1', Url::createFromTokens($tokens, 'http://circle.ai', $annotation)); } + + /** + * @test + * @group unit + * @covers ::is + * + * @SuppressWarnings("PHPMD.StaticAccess") + */ + public function isTest() { + $this->assertTrue(Url::is('http://www.circle.ai')); + } + + /** + * @test + * @group unit + * @covers ::is + * + * @SuppressWarnings("PHPMD.StaticAccess") + */ + public function isUrlLocalhostTest() { + $this->assertTrue(Url::is('http://localhost:3000')); + $this->assertTrue(Url::is('http://localhost:3000/api?filter=true')); + } + + /** + * @test + * @group unit + * @covers ::is + * + * @SuppressWarnings("PHPMD.StaticAccess") + */ + public function isNoUrlTest() { + $this->assertFalse(Url::is('http:/localhost:3000')); + $this->assertFalse(Url::is('localhost:3000')); + $this->assertFalse(Url::is('www.circle.ai')); + $this->assertFalse(Url::is('noUrl')); + $this->assertFalse(Url::is(1)); + } + + /** + * @test + * @group unit + * @covers ::assert + * + * @SuppressWarnings("PHPMD.StaticAccess") + */ + public function assert() { + $this->assertSame('http://www.test.com', Url::assert('http://www.test.com', 'Url')); + $this->assertSame('http://www.test.com?filter=1', Url::assert('http://www.test.com?filter=1', 'Url')); + $this->assertSame('http://circle.ai', Url::assert('http://circle.ai', 'Url')); + $this->assertSame('http://circle.ai/test?test=test', Url::assert('http://circle.ai/test?test=test', 'Url')); + } + + /** + * @test + * @group unit + * @covers ::assert + * + * @SuppressWarnings("PHPMD.StaticAccess") + * @expectedException \Circle\DoctrineRestDriver\Validation\Exceptions\InvalidTypeException + */ + public function assertUrlOnException() { + Url::assert('localhost:3000', 'Url'); + } } \ No newline at end of file diff --git a/Tests/Validation/AssertionsTest.php b/Tests/Validation/AssertionsTest.php index 88091f6..08eb58f 100644 --- a/Tests/Validation/AssertionsTest.php +++ b/Tests/Validation/AssertionsTest.php @@ -104,56 +104,6 @@ public function assertSupportedFetchModeTest() { $this->assertSame(\PDO::FETCH_ASSOC, Assertions::assertSupportedFetchMode(\PDO::FETCH_ASSOC)); } - /** - * @test - * @group unit - * @covers ::isUrl - * - * @SuppressWarnings("PHPMD.StaticAccess") - */ - public function isUrlTest() { - $this->assertTrue(Assertions::isUrl('http://www.circle.ai')); - } - - /** - * @test - * @group unit - * @covers ::isUrl - * - * @SuppressWarnings("PHPMD.StaticAccess") - */ - public function isUrlLocalhostTest() { - $this->assertTrue(Assertions::isUrl('http://localhost:3000')); - $this->assertTrue(Assertions::isUrl('http://localhost:3000/api?filter=true')); - } - - /** - * @test - * @group unit - * @covers ::isUrl - * - * @SuppressWarnings("PHPMD.StaticAccess") - */ - public function isNoUrlTest() { - $this->assertFalse(Assertions::isUrl('http:/localhost:3000')); - $this->assertFalse(Assertions::isUrl('localhost:3000')); - $this->assertFalse(Assertions::isUrl('www.circle.ai')); - $this->assertFalse(Assertions::isUrl('noUrl')); - $this->assertFalse(Assertions::isUrl(1)); - } - - /** - * @test - * @group unit - * @covers ::assertAuthStrategy - * - * @SuppressWarnings("PHPMD.StaticAccess") - */ - public function assertAuthStrategy() { - $authStrategy = $this->getMockBuilder('Circle\DoctrineRestDriver\Security\HttpAuthentication')->disableOriginalConstructor()->getMock(); - $this->assertSame($authStrategy, Assertions::assertAuthStrategy($authStrategy)); - } - /** * @test * @group unit @@ -225,42 +175,4 @@ public function assertMaybeInt() { public function assertMaybeIntOnException() { Assertions::assertMaybeInt('float', 3.2); } - - /** - * @test - * @group unit - * @covers ::assertUrl - * - * @SuppressWarnings("PHPMD.StaticAccess") - */ - public function assertUrl() { - $this->assertSame('http://www.test.com', Assertions::assertUrl('Url', 'http://www.test.com')); - $this->assertSame('http://www.test.com?filter=1', Assertions::assertUrl('Url', 'http://www.test.com?filter=1')); - $this->assertSame('http://circle.ai', Assertions::assertUrl('Url', 'http://circle.ai')); - $this->assertSame('http://circle.ai/test?test=test', Assertions::assertUrl('Url', 'http://circle.ai/test?test=test')); - } - - /** - * @test - * @group unit - * @covers ::assertUrl - * - * @SuppressWarnings("PHPMD.StaticAccess") - * @expectedException \Circle\DoctrineRestDriver\Validation\Exceptions\InvalidTypeException - */ - public function assertUrlOnException() { - Assertions::assertUrl('Url', 'localhost:3000'); - } - - /** - * @test - * @group unit - * @covers ::assertFormatter - * - * @SuppressWarnings("PHPMD.StaticAccess") - */ - public function assertFormatter() { - $formatter = $this->getMockBuilder('Circle\DoctrineRestDriver\Formatters\Formatter')->getMock(); - $this->assertSame($formatter, Assertions::assertFormatter($formatter)); - } } \ No newline at end of file diff --git a/Transformers/MysqlToRequest.php b/Transformers/MysqlToRequest.php index f4837ca..7ab7303 100644 --- a/Transformers/MysqlToRequest.php +++ b/Transformers/MysqlToRequest.php @@ -26,6 +26,7 @@ use Circle\DoctrineRestDriver\Types\Request; use Circle\DoctrineRestDriver\Types\SqlOperation; use Circle\DoctrineRestDriver\Types\Table; +use Circle\DoctrineRestDriver\Types\Url; use Circle\DoctrineRestDriver\Validation\Assertions; use PHPSQLParser\PHPSQLParser; @@ -86,7 +87,7 @@ public function transform($query, array $params = []) { $queryParts = explode(' ', $query); $transformedQuery = array_reduce($queryParts, function($carry, $part) { - return $carry . (Assertions::isUrl($part) ? ('"' . $part . '" ') : ($part . ' ')); + return $carry . (Url::is($part) ? ('"' . $part . '" ') : ($part . ' ')); }); $tokens = $this->parser->parse($transformedQuery); diff --git a/Types/Authentication.php b/Types/Authentication.php index 2016df9..4e122ba 100644 --- a/Types/Authentication.php +++ b/Types/Authentication.php @@ -18,6 +18,8 @@ namespace Circle\DoctrineRestDriver\Types; +use Circle\DoctrineRestDriver\Exceptions\Exceptions; +use Circle\DoctrineRestDriver\Exceptions\InvalidAuthStrategyException; use Circle\DoctrineRestDriver\Security\AuthStrategy; use Circle\DoctrineRestDriver\Validation\Assertions; @@ -42,6 +44,19 @@ public static function create(array $options) { $className = preg_match('/\\\\/', $authenticatorClass) ? $authenticatorClass : 'Circle\DoctrineRestDriver\Security\\' . $authenticatorClass; Assertions::assertClassExists($className); - return Assertions::assertAuthStrategy(new $className($options)); + return self::assert(new $className($options)); + } + + /** + * Checks if the given instance is instanceof AuthStrategy + * + * @param object $instance + * @return null + * @throws InvalidAuthStrategyException + * + * @SuppressWarnings("PHPMD.StaticAccess") + */ + public static function assert($instance) { + return !$instance instanceof AuthStrategy ? Exceptions::invalidAuthStrategyException(get_class($instance)) : $instance; } } \ No newline at end of file diff --git a/Types/Format.php b/Types/Format.php index 08515f4..5026603 100644 --- a/Types/Format.php +++ b/Types/Format.php @@ -18,6 +18,8 @@ namespace Circle\DoctrineRestDriver\Types; +use Circle\DoctrineRestDriver\Exceptions\Exceptions; +use Circle\DoctrineRestDriver\Exceptions\InvalidAuthStrategyException; use Circle\DoctrineRestDriver\Formatters\Formatter; use Circle\DoctrineRestDriver\Validation\Assertions; @@ -42,6 +44,19 @@ public static function create(array $options) { $className = preg_match('/\\\\/', $formatterClass) ? $formatterClass : 'Circle\DoctrineRestDriver\Formatters\\' . $formatterClass; Assertions::assertClassExists($className); - return Assertions::assertFormatter(new $className($options)); + return self::assert(new $className($options)); + } + + /** + * Checks if the given instance is instanceof Formatter + * + * @param object $instance + * @return null + * @throws InvalidAuthStrategyException + * + * @SuppressWarnings("PHPMD.StaticAccess") + */ + public static function assert($instance) { + return !$instance instanceof Formatter ? Exceptions::invalidFormatException(get_class($instance)) : $instance; } } \ No newline at end of file diff --git a/Types/Url.php b/Types/Url.php index 5f6451f..9aca225 100644 --- a/Types/Url.php +++ b/Types/Url.php @@ -19,7 +19,9 @@ namespace Circle\DoctrineRestDriver\Types; use Circle\DoctrineRestDriver\Annotations\DataSource; +use Circle\DoctrineRestDriver\Exceptions\Exceptions; use Circle\DoctrineRestDriver\Validation\Assertions; +use Circle\DoctrineRestDriver\Validation\Exceptions\InvalidTypeException; /** * Url type @@ -47,7 +49,7 @@ public static function create($route, $apiUrl, $id = null) { $idPath = empty($id) ? '' : '/' . $id; - if (!Assertions::isUrl($route)) return $apiUrl . '/' . $route . $idPath; + if (!self::is($route)) return $apiUrl . '/' . $route . $idPath; if (!preg_match('/\{id\}/', $route)) return $route . $idPath; return !empty($id) ? str_replace('{id}', $id, $route) : str_replace('/{id}', '', $route); @@ -69,4 +71,30 @@ public static function createFromTokens(array $tokens, $apiUrl, DataSource $anno return self::create($route, $apiUrl, $id); } + + /** + * Checks if the given value is an url + * + * @param $value + * @return bool + * + * @SuppressWarnings("PHPMD.StaticAccess") + */ + public static function is($value) { + return (bool) (preg_match('/^(http|ftp|https):\/\/([0-9a-zA-Z_-]+(\.[0-9a-zA-Z_-]+)+|localhost)([0-9a-zA-Z_\-.,@?^=%&:\/~+#-]*[0-9a-zA-Z_\-@?^=%&\/~+#-])?/', $value)); + } + + /** + * Asserts if the given value is an url + * + * @param mixed $value + * @param string $varName + * @return string + * @throws InvalidTypeException + * + * @SuppressWarnings("PHPMD.StaticAccess") + */ + public static function assert($value, $varName) { + return !self::is($value) ? Exceptions::InvalidTypeException('Url', $varName, $value) : $value; + } } \ No newline at end of file diff --git a/Validation/Assertions.php b/Validation/Assertions.php index 88b3486..b6422ca 100644 --- a/Validation/Assertions.php +++ b/Validation/Assertions.php @@ -34,7 +34,6 @@ * @copyright 2015 TeeAge-Beatz UG * * @SuppressWarnings("PHPMD.StaticAccess") - * @SuppressWarnings("PHPMD.TooManyPublicMethods") */ class Assertions { @@ -108,7 +107,7 @@ public static function assertMaybeInt($varName, $value) { * * @param string $varName * @param mixed $value - * @return void + * @return mixed * @throws InvalidTypeException */ public static function assertHashMap($varName, $value) { @@ -123,7 +122,7 @@ public static function assertHashMap($varName, $value) { * * @param string $varName * @param mixed $value - * @return void + * @return mixed * @throws InvalidTypeException */ public static function assertHashMapEntry($varName, $value) { @@ -141,7 +140,7 @@ public static function assertHashMapEntry($varName, $value) { * @param string $varName * @param array $hashMap * @param string $entryName - * @return null + * @return array * @throws InvalidTypeException */ public static function assertHashMapEntryExists($varName, $hashMap, $entryName) { @@ -149,33 +148,11 @@ public static function assertHashMapEntryExists($varName, $hashMap, $entryName) return array_key_exists($entryName, $hashMap) ? $hashMap : Exceptions::InvalidTypeException('HashMapEntry', $varName . '[\'' . $entryName . '\']', 'undefined'); } - /** - * Asserts if the given value is an url - * - * @param string $varName - * @param mixed $value - * @return string - * @throws InvalidTypeException - */ - public static function assertUrl($varName, $value) { - return !self::isUrl($value) ? Exceptions::InvalidTypeException('Url', $varName, $value) : $value; - } - - /** - * Checks if the given value is a url - * - * @param mixed $value - * @return bool - */ - public static function isUrl($value) { - return (bool) (preg_match('/^(http|ftp|https):\/\/([0-9a-zA-Z_-]+(\.[0-9a-zA-Z_-]+)+|localhost)([0-9a-zA-Z_\-.,@?^=%&:\/~+#-]*[0-9a-zA-Z_\-@?^=%&\/~+#-])?/', $value)); - } - /** * Checks if the given fetch mode is supported * - * @param int $fetchMode - * @return null + * @param int $fetchMode + * @return int * @throws UnsupportedFetchModeException * * @SuppressWarnings("PHPMD.StaticAccess") @@ -187,33 +164,11 @@ public static function assertSupportedFetchMode($fetchMode) { /** * Checks if the given class exists * - * @param string $className - * @return void + * @param string $className + * @return string * @throws ClassNotFoundException */ public static function assertClassExists($className) { if (!empty($className) && !class_exists($className)) throw new ClassNotFoundException('Class not found', $className); } - - /** - * Checks if the given instance is instanceof AuthStrategy - * - * @param object $instance - * @return null - * @throws InvalidAuthStrategyException - */ - public static function assertAuthStrategy($instance) { - return !$instance instanceof AuthStrategy ? Exceptions::invalidAuthStrategyException(get_class($instance)) : $instance; - } - - /** - * Checks if the given instance is instanceof Formatter - * - * @param object $instance - * @return null - * @throws InvalidAuthStrategyException - */ - public static function assertFormatter($instance) { - return !$instance instanceof Formatter ? Exceptions::invalidFormatException(get_class($instance)) : $instance; - } } \ No newline at end of file diff --git a/phpmd.xml b/phpmd.xml index 970a16b..eec134c 100644 --- a/phpmd.xml +++ b/phpmd.xml @@ -17,9 +17,13 @@ + + + + + - \ No newline at end of file From b99c001725ed7c2972c38d79387fe229e620e35c Mon Sep 17 00:00:00 2001 From: TobiasHauck Date: Tue, 9 Aug 2016 12:46:53 +0200 Subject: [PATCH 09/15] hashmap assertions moved --- Annotations/RoutingTable.php | 5 +-- Tests/Types/HashMapEntryTest.php | 60 +++++++++++++++++++++++++ Tests/Types/HashMapTest.php | 46 +++++++++++++++++++ Tests/Validation/AssertionsTest.php | 29 ------------ Types/CurlOptions.php | 4 +- Types/HashMap.php | 49 ++++++++++++++++++++ Types/HashMapEntry.php | 70 +++++++++++++++++++++++++++++ Types/HttpQuery.php | 2 +- Types/Id.php | 2 +- Types/InsertPayload.php | 4 +- Types/OrderingHeaders.php | 5 +-- Types/PaginationHeaders.php | 5 +-- Types/Payload.php | 3 +- Types/Request.php | 7 ++- Types/SelectSingleResult.php | 1 + Types/SqlOperation.php | 4 +- Types/Table.php | 9 ++-- Types/UpdatePayload.php | 4 +- Validation/Assertions.php | 47 +------------------ 19 files changed, 244 insertions(+), 112 deletions(-) create mode 100644 Tests/Types/HashMapEntryTest.php create mode 100644 Tests/Types/HashMapTest.php create mode 100644 Types/HashMap.php create mode 100644 Types/HashMapEntry.php diff --git a/Annotations/RoutingTable.php b/Annotations/RoutingTable.php index 3c49181..ad2a019 100644 --- a/Annotations/RoutingTable.php +++ b/Annotations/RoutingTable.php @@ -18,8 +18,7 @@ namespace Circle\DoctrineRestDriver\Annotations; -use Circle\DoctrineRestDriver\Validation\Assertions; -use Doctrine\Common\Annotations\AnnotationReader; +use Circle\DoctrineRestDriver\Types\HashMap; /** * Contains all routing information about all entities @@ -42,7 +41,7 @@ class RoutingTable { * @SuppressWarnings("PHPMD.StaticAccess") */ public function __construct(array $entities) { - Assertions::assertHashMap('entities', $entities); + HashMap::assert($entities, 'entities'); $aliases = array_flip($entities); $this->routingTable = array_reduce($entities, function ($carry, $namespace) use ($aliases) { diff --git a/Tests/Types/HashMapEntryTest.php b/Tests/Types/HashMapEntryTest.php new file mode 100644 index 0000000..e23e4ec --- /dev/null +++ b/Tests/Types/HashMapEntryTest.php @@ -0,0 +1,60 @@ +. + */ + +namespace Circle\DoctrineRestDriver\Tests\Types; + +use Circle\DoctrineRestDriver\Types\HashMapEntry; + +/** + * Tests the hash map type + * + * @author Tobias Hauck + * @copyright 2015 TeeAge-Beatz UG + * + * @coversDefaultClass Circle\DoctrineRestDriver\Types\HashMapEntry + */ +class HashMapEntryTest extends \PHPUnit_Framework_TestCase { + + /** + * @test + * @group unit + * @covers ::assert + * + * @SuppressWarnings("PHPMD.StaticAccess") + */ + public function assert() { + $hashMap = [ + 'test' => 'test' + ]; + $this->assertSame($hashMap, HashMapEntry::assert($hashMap, 'test')); + } + + /** + * @test + * @group unit + * @covers ::assertExists + * + * @SuppressWarnings("PHPMD.StaticAccess") + */ + public function assertExists() { + $hashMap = [ + 'test' => 'test' + ]; + $this->assertSame($hashMap, HashMapEntry::assertExists($hashMap, 'test', 'test')); + } +} \ No newline at end of file diff --git a/Tests/Types/HashMapTest.php b/Tests/Types/HashMapTest.php new file mode 100644 index 0000000..f29846a --- /dev/null +++ b/Tests/Types/HashMapTest.php @@ -0,0 +1,46 @@ +. + */ + +namespace Circle\DoctrineRestDriver\Tests\Types; + +use Circle\DoctrineRestDriver\Types\HashMap; + +/** + * Tests the hash map type + * + * @author Tobias Hauck + * @copyright 2015 TeeAge-Beatz UG + * + * @coversDefaultClass Circle\DoctrineRestDriver\Types\HashMap + */ +class HashMapTest extends \PHPUnit_Framework_TestCase { + + /** + * @test + * @group unit + * @covers ::assert + * + * @SuppressWarnings("PHPMD.StaticAccess") + */ + public function assert() { + $hashMap = [ + 'test' => 'test' + ]; + $this->assertSame($hashMap, HashMap::assert($hashMap, 'test')); + } +} \ No newline at end of file diff --git a/Tests/Validation/AssertionsTest.php b/Tests/Validation/AssertionsTest.php index 08eb58f..0045ea9 100644 --- a/Tests/Validation/AssertionsTest.php +++ b/Tests/Validation/AssertionsTest.php @@ -53,35 +53,6 @@ public function assertStringTest() { $this->assertSame('test', Assertions::assertString('test', 'test')); } - /** - * @test - * @group unit - * @covers ::assertHashMap - * @covers ::assertHashMapEntry - * - * @SuppressWarnings("PHPMD.StaticAccess") - */ - public function assertHashMapTest() { - $hashMap = [ - 'test' => 'test' - ]; - $this->assertSame($hashMap, Assertions::assertHashMap('test', $hashMap)); - } - - /** - * @test - * @group unit - * @covers ::assertHashMapEntryExists - * - * @SuppressWarnings("PHPMD.StaticAccess") - */ - public function assertHashMapEntryExistsTest() { - $hashMap = [ - 'test' => 'test' - ]; - $this->assertSame($hashMap, Assertions::assertHashMapEntryExists('test', $hashMap, 'test')); - } - /** * @test * @group unit diff --git a/Types/CurlOptions.php b/Types/CurlOptions.php index 80867ae..85e350b 100644 --- a/Types/CurlOptions.php +++ b/Types/CurlOptions.php @@ -18,8 +18,6 @@ namespace Circle\DoctrineRestDriver\Types; -use Circle\DoctrineRestDriver\Validation\Assertions; - /** * Converts a given options set into a valid array * containing CURLOPT options that can be added to @@ -53,7 +51,7 @@ class CurlOptions extends \ArrayObject { * @SuppressWarnings("PHPMD.StaticAccess") */ public static function create(array $options) { - Assertions::assertHashMap('options', $options); + HashMap::assert($options, 'options'); $filteredKeys = array_filter(array_keys($options), function ($key) { return strpos($key, 'CURLOPT_') === 0; diff --git a/Types/HashMap.php b/Types/HashMap.php new file mode 100644 index 0000000..2586a19 --- /dev/null +++ b/Types/HashMap.php @@ -0,0 +1,49 @@ +. + */ + +namespace Circle\DoctrineRestDriver\Types; + +use Circle\DoctrineRestDriver\Exceptions\Exceptions; +use Circle\DoctrineRestDriver\Validation\Assertions; +use Circle\DoctrineRestDriver\Validation\Exceptions\InvalidTypeException; + +/** + * HashMap type + * + * @author Tobias Hauck + * @copyright 2015 TeeAge-Beatz UG + */ +class HashMap { + + /** + * Asserts if the given value is a hash map + * + * @param mixed $value + * @param string $varName + * @return mixed + * @throws InvalidTypeException + * + * @SuppressWarnings("PHPMD.StaticAccess") + */ + public static function assert($value, $varName) { + if(!is_array($value)) return Exceptions::InvalidTypeException('HashMap', $varName, $value); + foreach($value as $key => $v) HashMapEntry::assert([$key => $v], $varName); + + return $value; + } +} \ No newline at end of file diff --git a/Types/HashMapEntry.php b/Types/HashMapEntry.php new file mode 100644 index 0000000..849bf8c --- /dev/null +++ b/Types/HashMapEntry.php @@ -0,0 +1,70 @@ +. + */ + +namespace Circle\DoctrineRestDriver\Types; + +use Circle\DoctrineRestDriver\Exceptions\Exceptions; +use Circle\DoctrineRestDriver\Validation\Assertions; +use Circle\DoctrineRestDriver\Validation\Exceptions\InvalidTypeException; + +/** + * HashMapEntry type + * + * @author Tobias Hauck + * @copyright 2015 TeeAge-Beatz UG + */ +class HashMapEntry { + + /** + * Asserts if the given value is a hash map entry + * + * @param mixed $value + * @param string $varName + * @return mixed + * @throws InvalidTypeException + * + * @SuppressWarnings("PHPMD.StaticAccess") + */ + public static function assert($value, $varName) { + if(!is_array($value)) return Exceptions::InvalidTypeException('HashMapEntry', $varName, $value); + if(count($value) > 1) return Exceptions::InvalidTypeException('HashMapEntry', $varName, $value); + + $keys = array_keys($value); + $key = end($keys); + + Assertions::assertString('HashMapEntry of "' . $varName . '": "' . $key . '"', $key); + + return $value; + } + + /** + * Asserts if the given hash map entry exists + * + * @param array $hashMap + * @param string $entryName + * @param string $varName + * @return array + * @throws InvalidTypeException + * + * @SuppressWarnings("PHPMD.StaticAccess") + */ + public static function assertExists($hashMap, $entryName, $varName) { + HashMap::assert($hashMap, $varName); + return array_key_exists($entryName, $hashMap) ? $hashMap : Exceptions::InvalidTypeException('HashMapEntry', $varName . '[\'' . $entryName . '\']', 'undefined'); + } +} \ No newline at end of file diff --git a/Types/HttpQuery.php b/Types/HttpQuery.php index 30af5f1..dd36d04 100644 --- a/Types/HttpQuery.php +++ b/Types/HttpQuery.php @@ -39,7 +39,7 @@ class HttpQuery { * @SuppressWarnings("PHPMD.StaticAccess") */ public static function create(array $tokens) { - Assertions::assertHashMap('tokens', $tokens); + HashMap::assert($tokens, 'tokens'); $operation = SqlOperation::create($tokens); if ($operation !== SqlOperations::SELECT || empty($tokens['WHERE'])) return null; diff --git a/Types/Id.php b/Types/Id.php index c23861a..224a843 100644 --- a/Types/Id.php +++ b/Types/Id.php @@ -38,7 +38,7 @@ class Id { * @SuppressWarnings("PHPMD.StaticAccess") */ public static function create(array $tokens) { - Assertions::assertHashMap('tokens', $tokens); + HashMap::assert($tokens, 'tokens'); if (empty($tokens['WHERE'])) return ''; diff --git a/Types/InsertPayload.php b/Types/InsertPayload.php index c2d72fe..7f7c34d 100644 --- a/Types/InsertPayload.php +++ b/Types/InsertPayload.php @@ -18,8 +18,6 @@ namespace Circle\DoctrineRestDriver\Types; -use Circle\DoctrineRestDriver\Validation\Assertions; - /** * InsertPayload type * @@ -38,7 +36,7 @@ class InsertPayload { * @SuppressWarnings("PHPMD.StaticAccess") */ public static function create(array $tokens) { - Assertions::assertHashMap('tokens', $tokens); + HashMap::assert($tokens, 'tokens'); return array_combine(self::columns($tokens), self::values($tokens)); } diff --git a/Types/OrderingHeaders.php b/Types/OrderingHeaders.php index e665636..e46d9f6 100644 --- a/Types/OrderingHeaders.php +++ b/Types/OrderingHeaders.php @@ -18,9 +18,6 @@ namespace Circle\DoctrineRestDriver\Types; -use Circle\DoctrineRestDriver\Enums\SqlOperations; -use Circle\DoctrineRestDriver\Validation\Assertions; - /** * Handles creation http headers for ordering/sorting * @@ -38,7 +35,7 @@ class OrderingHeaders { * @SuppressWarnings("PHPMD.StaticAccess") */ public static function create(array $tokens) { - Assertions::assertHashMap('tokens', $tokens); + HashMap::assert($tokens, 'tokens'); if (empty($tokens['ORDER'])) return []; diff --git a/Types/PaginationHeaders.php b/Types/PaginationHeaders.php index 1f7d626..ed473d5 100644 --- a/Types/PaginationHeaders.php +++ b/Types/PaginationHeaders.php @@ -18,9 +18,6 @@ namespace Circle\DoctrineRestDriver\Types; -use Circle\DoctrineRestDriver\Enums\SqlOperations; -use Circle\DoctrineRestDriver\Validation\Assertions; - /** * Handles creation of pagination related http headers * @@ -38,7 +35,7 @@ class PaginationHeaders { * @SuppressWarnings("PHPMD.StaticAccess") */ public static function create(array $tokens) { - Assertions::assertHashMap('tokens', $tokens); + HashMap::assert($tokens, 'tokens'); if (empty($tokens['LIMIT'])) return []; diff --git a/Types/Payload.php b/Types/Payload.php index 5afb569..912d8f1 100644 --- a/Types/Payload.php +++ b/Types/Payload.php @@ -19,7 +19,6 @@ namespace Circle\DoctrineRestDriver\Types; use Circle\DoctrineRestDriver\Enums\SqlOperations; -use Circle\DoctrineRestDriver\Validation\Assertions; /** * Payload type: Union type for UpdatePayload and InsertPayload @@ -40,7 +39,7 @@ class Payload { * @SuppressWarnings("PHPMD.StaticAccess") */ public static function create(array $tokens, array $options) { - Assertions::assertHashMap('tokens', $tokens); + HashMap::assert($tokens, 'tokens'); $formatter = Format::create($options); $operation = SqlOperation::create($tokens); diff --git a/Types/Request.php b/Types/Request.php index 2fd25d3..8b484f0 100644 --- a/Types/Request.php +++ b/Types/Request.php @@ -17,7 +17,6 @@ */ namespace Circle\DoctrineRestDriver\Types; -use Circle\DoctrineRestDriver\Validation\Assertions; /** * Request type @@ -65,9 +64,9 @@ class Request { * @SuppressWarnings("PHPMD.StaticAccess") */ public function __construct(array $options) { - Assertions::assertHashMap('options', $options); - Assertions::assertHashMapEntryExists('options.method', $options, 'method'); - Assertions::assertHashMapEntryExists('options.url', $options, 'url'); + HashMap::assert($options, 'options'); + HashMapEntry::assertExists($options, 'method', 'options.method'); + HashMapEntry::assertExists($options, 'url', 'options.url'); foreach ($options as $key => $value) $this->$key = $value; } diff --git a/Types/SelectSingleResult.php b/Types/SelectSingleResult.php index 1d768ce..56e47a6 100644 --- a/Types/SelectSingleResult.php +++ b/Types/SelectSingleResult.php @@ -37,6 +37,7 @@ class SelectSingleResult { * @SuppressWarnings("PHPMD.StaticAccess") */ public static function create(array $tokens, $content) { + HashMap::assert($tokens, 'tokens'); $tableAlias = Table::alias($tokens); $attributeValueMap = array_map(function($token) use ($content, $tableAlias) { diff --git a/Types/SqlOperation.php b/Types/SqlOperation.php index 0403a9c..dc2374e 100644 --- a/Types/SqlOperation.php +++ b/Types/SqlOperation.php @@ -18,8 +18,6 @@ namespace Circle\DoctrineRestDriver\Types; -use Circle\DoctrineRestDriver\Validation\Assertions; - /** * SqlOperation type * @@ -37,7 +35,7 @@ class SqlOperation { * @SuppressWarnings("PHPMD.StaticAccess") */ public static function create(array $tokens) { - Assertions::assertHashMap('tokens', $tokens); + HashMap::assert($tokens, 'tokens'); return strtolower(array_keys($tokens)[0]); } diff --git a/Types/Table.php b/Types/Table.php index 0b418c0..e388399 100644 --- a/Types/Table.php +++ b/Types/Table.php @@ -18,11 +18,8 @@ namespace Circle\DoctrineRestDriver\Types; -use Circle\DoctrineRestDriver\Annotations\RoutingTable; -use Circle\DoctrineRestDriver\Enums\HttpMethods; use Circle\DoctrineRestDriver\Enums\SqlOperations; use Circle\DoctrineRestDriver\Exceptions\Exceptions; -use Circle\DoctrineRestDriver\Validation\Assertions; /** * Table type @@ -41,7 +38,7 @@ class Table { * @return string */ public static function create(array $tokens) { - Assertions::assertHashMap('tokens', $tokens); + HashMap::assert($tokens, 'tokens'); if (empty($tokens['FROM']) && empty($tokens['INSERT']) && empty($tokens['UPDATE'])) return Exceptions::InvalidTypeException('array', 'tokens', null); @@ -58,7 +55,7 @@ public static function create(array $tokens) { * @return null|string */ public static function alias(array $tokens) { - Assertions::assertHashMap('tokens', $tokens); + HashMap::assert($tokens, 'tokens'); $operation = SqlOperation::create($tokens); if ($operation === SqlOperations::INSERT) return null; @@ -74,7 +71,7 @@ public static function alias(array $tokens) { * @return array */ public static function replace(array $tokens, $newTable) { - Assertions::assertHashMap('tokens', $tokens); + HashMap::assert($tokens, 'tokens'); $operation = SqlOperation::create($tokens); $firstKey = $operation === SqlOperations::DELETE || $operation === SqlOperations::SELECT ? 'FROM' : strtoupper($operation); diff --git a/Types/UpdatePayload.php b/Types/UpdatePayload.php index d661271..a82c738 100644 --- a/Types/UpdatePayload.php +++ b/Types/UpdatePayload.php @@ -18,8 +18,6 @@ namespace Circle\DoctrineRestDriver\Types; -use Circle\DoctrineRestDriver\Validation\Assertions; - /** * UpdatePayload type * @@ -38,7 +36,7 @@ class UpdatePayload { * @SuppressWarnings("PHPMD.StaticAccess") */ public static function create(array $tokens) { - Assertions::assertHashMap('tokens', $tokens); + HashMap::assert($tokens, 'tokens'); $columns = array_map(function($token) { $segments = explode('=', $token['base_expr']); diff --git a/Validation/Assertions.php b/Validation/Assertions.php index b6422ca..31b4437 100644 --- a/Validation/Assertions.php +++ b/Validation/Assertions.php @@ -22,6 +22,7 @@ use Circle\DoctrineRestDriver\Exceptions\UnsupportedFetchModeException; use Circle\DoctrineRestDriver\Formatters\Formatter; use Circle\DoctrineRestDriver\Security\AuthStrategy; +use Circle\DoctrineRestDriver\Types\HashMap; use Circle\DoctrineRestDriver\Validation\Exceptions\InvalidTypeException; use Circle\DoctrineRestDriver\Validation\Exceptions\NotNilException; use Circle\DoctrineRestDriver\Exceptions\Exceptions; @@ -102,52 +103,6 @@ public static function assertMaybeInt($varName, $value) { return !is_int($value) && $value !== null ? Exceptions::InvalidTypeException('MaybeInt', $varName, $value) : $value; } - /** - * Asserts if the given value is a hash map - * - * @param string $varName - * @param mixed $value - * @return mixed - * @throws InvalidTypeException - */ - public static function assertHashMap($varName, $value) { - if(!is_array($value)) return Exceptions::InvalidTypeException('HashMap', $varName, $value); - foreach($value as $key => $v) self::assertHashMapEntry($varName, [$key => $v]); - - return $value; - } - - /** - * Asserts if the given value is a hash map entry - * - * @param string $varName - * @param mixed $value - * @return mixed - * @throws InvalidTypeException - */ - public static function assertHashMapEntry($varName, $value) { - if(!is_array($value)) return Exceptions::InvalidTypeException('HashMapEntry', $varName, $value); - if(count($value) > 1) return Exceptions::InvalidTypeException('HashMapEntry', $varName, $value); - - $keys = array_keys($value); - $key = end($keys); - self::assertString('HashMapEntry of "' . $varName . '": "' . $key . '"', $key); - } - - /** - * Asserts if the given hash map entry exists - * - * @param string $varName - * @param array $hashMap - * @param string $entryName - * @return array - * @throws InvalidTypeException - */ - public static function assertHashMapEntryExists($varName, $hashMap, $entryName) { - self::assertHashMap($varName, $hashMap); - return array_key_exists($entryName, $hashMap) ? $hashMap : Exceptions::InvalidTypeException('HashMapEntry', $varName . '[\'' . $entryName . '\']', 'undefined'); - } - /** * Checks if the given fetch mode is supported * From 0b0a3242b489e72531ad4019a781b99d11f589f4 Mon Sep 17 00:00:00 2001 From: TobiasHauck Date: Tue, 9 Aug 2016 23:01:32 +0200 Subject: [PATCH 10/15] added all missing types --- Annotations/Route.php | 11 ++-- Tests/Types/HashMapEntryTest.php | 2 +- Tests/Types/MaybeIntTest.php | 56 +++++++++++++++++ Tests/Types/MaybeListTest.php | 56 +++++++++++++++++ Tests/Types/MaybeStringTest.php | 56 +++++++++++++++++ Tests/Types/NotNilTest.php | 43 +++++++++++++ Tests/Types/StrTest.php | 55 +++++++++++++++++ Tests/Validation/AssertionsTest.php | 94 ----------------------------- Types/HashMapEntry.php | 3 +- Types/HttpMethod.php | 2 +- Types/MaybeInt.php | 45 ++++++++++++++ Types/MaybeList.php | 45 ++++++++++++++ Types/MaybeString.php | 45 ++++++++++++++ Types/NotNil.php | 45 ++++++++++++++ Types/StatusCode.php | 2 +- Types/Str.php | 48 +++++++++++++++ Types/Url.php | 6 +- Types/Value.php | 2 +- Validation/Assertions.php | 71 ---------------------- 19 files changed, 508 insertions(+), 179 deletions(-) create mode 100644 Tests/Types/MaybeIntTest.php create mode 100644 Tests/Types/MaybeListTest.php create mode 100644 Tests/Types/MaybeStringTest.php create mode 100644 Tests/Types/NotNilTest.php create mode 100644 Tests/Types/StrTest.php create mode 100644 Types/MaybeInt.php create mode 100644 Types/MaybeList.php create mode 100644 Types/MaybeString.php create mode 100644 Types/NotNil.php create mode 100644 Types/Str.php diff --git a/Annotations/Route.php b/Annotations/Route.php index ac04516..0b37cbd 100644 --- a/Annotations/Route.php +++ b/Annotations/Route.php @@ -18,9 +18,10 @@ namespace Circle\DoctrineRestDriver\Annotations; -use Circle\DoctrineRestDriver\Exceptions\Exceptions; +use Circle\DoctrineRestDriver\Types\MaybeInt; +use Circle\DoctrineRestDriver\Types\MaybeList; +use Circle\DoctrineRestDriver\Types\MaybeString; use Circle\DoctrineRestDriver\Types\Url; -use Circle\DoctrineRestDriver\Validation\Assertions; use Doctrine\Common\Collections\ArrayCollection; /** @@ -64,9 +65,9 @@ public function __construct(array $values) { $settings = new ArrayCollection($values); $this->route = Url::assert($settings->get('value'), 'value'); - $this->statusCode = Assertions::assertMaybeInt('statusCode', $settings->get('statusCode')); - $this->method = Assertions::assertMaybeString('method', $settings->get('method')); - $this->options = Assertions::assertMaybeList('options', $settings->get('options')); + $this->statusCode = MaybeInt::assert($settings->get('statusCode'), 'statusCode'); + $this->method = MaybeString::assert($settings->get('method'), 'method'); + $this->options = MaybeList::assert($settings->get('options'), 'options'); } /** diff --git a/Tests/Types/HashMapEntryTest.php b/Tests/Types/HashMapEntryTest.php index e23e4ec..b9820e9 100644 --- a/Tests/Types/HashMapEntryTest.php +++ b/Tests/Types/HashMapEntryTest.php @@ -21,7 +21,7 @@ use Circle\DoctrineRestDriver\Types\HashMapEntry; /** - * Tests the hash map type + * Tests the hash map entry type * * @author Tobias Hauck * @copyright 2015 TeeAge-Beatz UG diff --git a/Tests/Types/MaybeIntTest.php b/Tests/Types/MaybeIntTest.php new file mode 100644 index 0000000..b1d4612 --- /dev/null +++ b/Tests/Types/MaybeIntTest.php @@ -0,0 +1,56 @@ +. + */ + +namespace Circle\DoctrineRestDriver\Tests\Types; + +use Circle\DoctrineRestDriver\Types\MaybeInt; + +/** + * Tests the maybe int type + * + * @author Tobias Hauck + * @copyright 2015 TeeAge-Beatz UG + * + * @coversDefaultClass Circle\DoctrineRestDriver\Types\MaybeInt + */ +class MaybeIntTest extends \PHPUnit_Framework_TestCase { + + /** + * @test + * @group unit + * @covers ::assert + * + * @SuppressWarnings("PHPMD.StaticAccess") + */ + public function assert() { + $this->assertSame(1, MaybeInt::assert(1, 'test')); + $this->assertSame(null, MaybeInt::assert(null, 'test')); + } + + /** + * @test + * @group unit + * @covers ::assert + * + * @SuppressWarnings("PHPMD.StaticAccess") + * @expectedException \Circle\DoctrineRestDriver\Validation\Exceptions\InvalidTypeException + */ + public function assertOnException() { + MaybeInt::assert([], 'array'); + } +} \ No newline at end of file diff --git a/Tests/Types/MaybeListTest.php b/Tests/Types/MaybeListTest.php new file mode 100644 index 0000000..45df840 --- /dev/null +++ b/Tests/Types/MaybeListTest.php @@ -0,0 +1,56 @@ +. + */ + +namespace Circle\DoctrineRestDriver\Tests\Types; + +use Circle\DoctrineRestDriver\Types\MaybeList; + +/** + * Tests the maybe list type + * + * @author Tobias Hauck + * @copyright 2015 TeeAge-Beatz UG + * + * @coversDefaultClass Circle\DoctrineRestDriver\Types\MaybeList + */ +class MaybeListTest extends \PHPUnit_Framework_TestCase { + + /** + * @test + * @group unit + * @covers ::assert + * + * @SuppressWarnings("PHPMD.StaticAccess") + */ + public function assert() { + $this->assertSame(null, MaybeList::assert(null, 'null')); + $this->assertSame([], MaybeList::assert([], 'list')); + } + + /** + * @test + * @group unit + * @covers ::assert + * + * @SuppressWarnings("PHPMD.StaticAccess") + * @expectedException \Circle\DoctrineRestDriver\Validation\Exceptions\InvalidTypeException + */ + public function assertOnException() { + MaybeList::assert('hello', 'string'); + } +} \ No newline at end of file diff --git a/Tests/Types/MaybeStringTest.php b/Tests/Types/MaybeStringTest.php new file mode 100644 index 0000000..9254cd3 --- /dev/null +++ b/Tests/Types/MaybeStringTest.php @@ -0,0 +1,56 @@ +. + */ + +namespace Circle\DoctrineRestDriver\Tests\Types; + +use Circle\DoctrineRestDriver\Types\MaybeString; + +/** + * Tests the maybe string type + * + * @author Tobias Hauck + * @copyright 2015 TeeAge-Beatz UG + * + * @coversDefaultClass Circle\DoctrineRestDriver\Types\MaybeString + */ +class MaybeStringTest extends \PHPUnit_Framework_TestCase { + + /** + * @test + * @group unit + * @covers ::assert + * + * @SuppressWarnings("PHPMD.StaticAccess") + */ + public function assert() { + $this->assertSame('test', MaybeString::assert('test', 'test')); + $this->assertSame(null, MaybeString::assert(null, 'test')); + } + + /** + * @test + * @group unit + * @covers ::assert + * + * @SuppressWarnings("PHPMD.StaticAccess") + * @expectedException \Circle\DoctrineRestDriver\Validation\Exceptions\InvalidTypeException + */ + public function assertOnException() { + MaybeString::assert([], 'array'); + } +} \ No newline at end of file diff --git a/Tests/Types/NotNilTest.php b/Tests/Types/NotNilTest.php new file mode 100644 index 0000000..7f0719c --- /dev/null +++ b/Tests/Types/NotNilTest.php @@ -0,0 +1,43 @@ +. + */ + +namespace Circle\DoctrineRestDriver\Tests\Types; + +use Circle\DoctrineRestDriver\Types\NotNil; + +/** + * Tests the not nil type + * + * @author Tobias Hauck + * @copyright 2015 TeeAge-Beatz UG + * + * @coversDefaultClass Circle\DoctrineRestDriver\Types\NotNil + */ +class NotNilTest extends \PHPUnit_Framework_TestCase { + + /** + * @test + * @group unit + * @covers ::assert + * + * @SuppressWarnings("PHPMD.StaticAccess") + */ + public function assert() { + $this->assertSame('test', NotNil::assert('test', 'test')); + } +} \ No newline at end of file diff --git a/Tests/Types/StrTest.php b/Tests/Types/StrTest.php new file mode 100644 index 0000000..87ec497 --- /dev/null +++ b/Tests/Types/StrTest.php @@ -0,0 +1,55 @@ +. + */ + +namespace Circle\DoctrineRestDriver\Tests\Types; + +use Circle\DoctrineRestDriver\Types\Str; + +/** + * Tests the string type + * + * @author Tobias Hauck + * @copyright 2015 TeeAge-Beatz UG + * + * @coversDefaultClass Circle\DoctrineRestDriver\Types\Str + */ +class StrTest extends \PHPUnit_Framework_TestCase { + + /** + * @test + * @group unit + * @covers ::assert + * + * @SuppressWarnings("PHPMD.StaticAccess") + */ + public function assert() { + $this->assertSame('test', Str::assert('test', 'test')); + } + + /** + * @test + * @group unit + * @covers ::assert + * + * @SuppressWarnings("PHPMD.StaticAccess") + * @expectedException \Circle\DoctrineRestDriver\Validation\Exceptions\InvalidTypeException + */ + public function assertOnException() { + Str::assert([], 'array'); + } +} \ No newline at end of file diff --git a/Tests/Validation/AssertionsTest.php b/Tests/Validation/AssertionsTest.php index 0045ea9..b455d82 100644 --- a/Tests/Validation/AssertionsTest.php +++ b/Tests/Validation/AssertionsTest.php @@ -31,28 +31,6 @@ */ class AssertionsTest extends \PHPUnit_Framework_TestCase { - /** - * @test - * @group unit - * @covers ::assertNotNil - * - * @SuppressWarnings("PHPMD.StaticAccess") - */ - public function assertNotNilTest() { - $this->assertSame('test', Assertions::assertNotNil('test', 'test')); - } - - /** - * @test - * @group unit - * @covers ::assertString - * - * @SuppressWarnings("PHPMD.StaticAccess") - */ - public function assertStringTest() { - $this->assertSame('test', Assertions::assertString('test', 'test')); - } - /** * @test * @group unit @@ -74,76 +52,4 @@ public function assertClassExistsTest() { public function assertSupportedFetchModeTest() { $this->assertSame(\PDO::FETCH_ASSOC, Assertions::assertSupportedFetchMode(\PDO::FETCH_ASSOC)); } - - /** - * @test - * @group unit - * @covers ::assertMaybeList - * - * @SuppressWarnings("PHPMD.StaticAccess") - */ - public function assertMaybeList() { - $this->assertSame(null, Assertions::assertMaybeList('null', null)); - $this->assertSame([], Assertions::assertMaybeList('list', [])); - } - - /** - * @test - * @group unit - * @covers ::assertMaybeList - * - * @SuppressWarnings("PHPMD.StaticAccess") - * @expectedException \Circle\DoctrineRestDriver\Validation\Exceptions\InvalidTypeException - */ - public function assertMaybeListOnException() { - Assertions::assertMaybeList('string', 'hello'); - } - - /** - * @test - * @group unit - * @covers ::assertMaybeString - * - * @SuppressWarnings("PHPMD.StaticAccess") - */ - public function assertMaybeString() { - $this->assertSame(null, Assertions::assertMaybeString('null', null)); - $this->assertSame('value', Assertions::assertMaybeString('string', 'value')); - } - - /** - * @test - * @group unit - * @covers ::assertMaybeString - * - * @SuppressWarnings("PHPMD.StaticAccess") - * @expectedException \Circle\DoctrineRestDriver\Validation\Exceptions\InvalidTypeException - */ - public function assertMaybeStringOnException() { - Assertions::assertMaybeString('array', []); - } - - /** - * @test - * @group unit - * @covers ::assertMaybeInt - * - * @SuppressWarnings("PHPMD.StaticAccess") - */ - public function assertMaybeInt() { - $this->assertSame(null, Assertions::assertMaybeInt('null', null)); - $this->assertSame(123, Assertions::assertMaybeInt('int', 123)); - } - - /** - * @test - * @group unit - * @covers ::assertMaybeInt - * - * @SuppressWarnings("PHPMD.StaticAccess") - * @expectedException \Circle\DoctrineRestDriver\Validation\Exceptions\InvalidTypeException - */ - public function assertMaybeIntOnException() { - Assertions::assertMaybeInt('float', 3.2); - } } \ No newline at end of file diff --git a/Types/HashMapEntry.php b/Types/HashMapEntry.php index 849bf8c..a01fd91 100644 --- a/Types/HashMapEntry.php +++ b/Types/HashMapEntry.php @@ -19,7 +19,6 @@ namespace Circle\DoctrineRestDriver\Types; use Circle\DoctrineRestDriver\Exceptions\Exceptions; -use Circle\DoctrineRestDriver\Validation\Assertions; use Circle\DoctrineRestDriver\Validation\Exceptions\InvalidTypeException; /** @@ -47,7 +46,7 @@ public static function assert($value, $varName) { $keys = array_keys($value); $key = end($keys); - Assertions::assertString('HashMapEntry of "' . $varName . '": "' . $key . '"', $key); + Str::assert($key, 'HashMapEntry of "' . $varName . '": "' . $key . '"'); return $value; } diff --git a/Types/HttpMethod.php b/Types/HttpMethod.php index afa7001..2d0dcac 100644 --- a/Types/HttpMethod.php +++ b/Types/HttpMethod.php @@ -40,7 +40,7 @@ class HttpMethod { * @SuppressWarnings("PHPMD.StaticAccess") */ public static function create($method, DataSource $annotation = null) { - Assertions::assertString('method', $method); + Str::assert($method, 'method'); return empty($annotation) || $annotation->getMethod() === null ? $method : $annotation->getMethod(); } } \ No newline at end of file diff --git a/Types/MaybeInt.php b/Types/MaybeInt.php new file mode 100644 index 0000000..0293aae --- /dev/null +++ b/Types/MaybeInt.php @@ -0,0 +1,45 @@ +. + */ + +namespace Circle\DoctrineRestDriver\Types; + +use Circle\DoctrineRestDriver\Exceptions\Exceptions; +use Symfony\Component\Config\Definition\Exception\InvalidTypeException; + +/** + * MaybeInt type + * + * @author Tobias Hauck + * @copyright 2015 TeeAge-Beatz UG + */ +class MaybeInt { + + /** + * Asserts if the given value is a maybe int + * + * @param mixed $value + * @param string $varName + * @return int|null + * @throws InvalidTypeException + * + * @SuppressWarnings("PHPMD.StaticAccess") + */ + public static function assert($value, $varName) { + return !is_int($value) && $value !== null ? Exceptions::InvalidTypeException('MaybeInt', $varName, $value) : $value; + } +} \ No newline at end of file diff --git a/Types/MaybeList.php b/Types/MaybeList.php new file mode 100644 index 0000000..4129085 --- /dev/null +++ b/Types/MaybeList.php @@ -0,0 +1,45 @@ +. + */ + +namespace Circle\DoctrineRestDriver\Types; + +use Circle\DoctrineRestDriver\Exceptions\Exceptions; +use Symfony\Component\Config\Definition\Exception\InvalidTypeException; + +/** + * MaybeList type + * + * @author Tobias Hauck + * @copyright 2015 TeeAge-Beatz UG + */ +class MaybeList { + + /** + * Asserts if the given value is a maybe list + * + * @param mixed $value + * @param string $varName + * @return array|null + * @throws InvalidTypeException + * + * @SuppressWarnings("PHPMD.StaticAccess") + */ + public static function assert($value, $varName) { + return !is_array($value) && $value !== null ? Exceptions::InvalidTypeException('MaybeList', $varName, $value) : $value; + } +} \ No newline at end of file diff --git a/Types/MaybeString.php b/Types/MaybeString.php new file mode 100644 index 0000000..6a7bfc7 --- /dev/null +++ b/Types/MaybeString.php @@ -0,0 +1,45 @@ +. + */ + +namespace Circle\DoctrineRestDriver\Types; + +use Circle\DoctrineRestDriver\Exceptions\Exceptions; +use Symfony\Component\Config\Definition\Exception\InvalidTypeException; + +/** + * MaybeString type + * + * @author Tobias Hauck + * @copyright 2015 TeeAge-Beatz UG + */ +class MaybeString { + + /** + * Asserts if the given value is a maybe string + * + * @param mixed $value + * @param string $varName + * @return string|null + * @throws InvalidTypeException + * + * @SuppressWarnings("PHPMD.StaticAccess") + */ + public static function assert($value, $varName) { + return !is_string($value) && $value !== null ? Exceptions::InvalidTypeException('MaybeString', $varName, $value) : $value; + } +} \ No newline at end of file diff --git a/Types/NotNil.php b/Types/NotNil.php new file mode 100644 index 0000000..3c811a8 --- /dev/null +++ b/Types/NotNil.php @@ -0,0 +1,45 @@ +. + */ + +namespace Circle\DoctrineRestDriver\Types; + +use Circle\DoctrineRestDriver\Exceptions\Exceptions; +use Circle\DoctrineRestDriver\Validation\Exceptions\NotNilException; + +/** + * NotNil type + * + * @author Tobias Hauck + * @copyright 2015 TeeAge-Beatz UG + */ +class NotNil { + + /** + * Asserts if the given value is not nil + * + * @param string $varName + * @param mixed $value + * @return mixed + * @throws NotNilException + * + * @SuppressWarnings("PHPMD.StaticAccess") + */ + public static function assert($value, $varName) { + return $value === null ? Exceptions::NotNilException($varName) : $value; + } +} \ No newline at end of file diff --git a/Types/StatusCode.php b/Types/StatusCode.php index 0ad1f54..6df205e 100644 --- a/Types/StatusCode.php +++ b/Types/StatusCode.php @@ -49,7 +49,7 @@ class StatusCode { * @SuppressWarnings("PHPMD.StaticAccess") */ public static function create($method, DataSource $annotation = null) { - Assertions::assertString('method', $method); + Str::assert($method, 'method'); return !empty($annotation) && $annotation->getStatusCode() !== null ? $annotation->getStatusCode() : self::$expectedStatusCodes[$method]; } diff --git a/Types/Str.php b/Types/Str.php new file mode 100644 index 0000000..40ba04b --- /dev/null +++ b/Types/Str.php @@ -0,0 +1,48 @@ +. + */ + +namespace Circle\DoctrineRestDriver\Types; + +use Circle\DoctrineRestDriver\Exceptions\Exceptions; +use Circle\DoctrineRestDriver\Validation\Exceptions\NotNilException; +use Symfony\Component\Config\Definition\Exception\InvalidTypeException; + +/** + * String type + * + * @author Tobias Hauck + * @copyright 2015 TeeAge-Beatz UG + */ +class Str { + + /** + * Asserts if the given value is a string + * + * @param mixed $value + * @param string $varName + * @return string + * @throws InvalidTypeException + * @throws NotNilException + * + * @SuppressWarnings("PHPMD.StaticAccess") + */ + public static function assert($value, $varName) { + NotNil::assert($value, $varName); + return !is_string($value) ? Exceptions::InvalidTypeException('string', $varName, $value) : $value; + } +} \ No newline at end of file diff --git a/Types/Url.php b/Types/Url.php index 9aca225..ba9daca 100644 --- a/Types/Url.php +++ b/Types/Url.php @@ -43,9 +43,9 @@ class Url { * @SuppressWarnings("PHPMD.StaticAccess") */ public static function create($route, $apiUrl, $id = null) { - Assertions::assertString('route', $route); - Assertions::assertString('apiUrl', $apiUrl); - Assertions::assertMaybeString('id', $id); + Str::assert($route, 'route'); + Str::assert($apiUrl, 'apiUrl'); + MaybeString::assert($id, 'id'); $idPath = empty($id) ? '' : '/' . $id; diff --git a/Types/Value.php b/Types/Value.php index a4c6537..9a22048 100644 --- a/Types/Value.php +++ b/Types/Value.php @@ -39,7 +39,7 @@ class Value { * @SuppressWarnings("PHPMD.StaticAccess") */ public static function create($value) { - Assertions::assertString('value', $value); + Str::assert($value, 'value'); if (empty($value)) return null; $unquoted = preg_replace('/\"|\\\'|\`$/', '', preg_replace('/^\"|\\\'|\`/', '', $value)); diff --git a/Validation/Assertions.php b/Validation/Assertions.php index 31b4437..f6afabd 100644 --- a/Validation/Assertions.php +++ b/Validation/Assertions.php @@ -18,13 +18,7 @@ namespace Circle\DoctrineRestDriver\Validation; -use Circle\DoctrineRestDriver\Exceptions\InvalidAuthStrategyException; use Circle\DoctrineRestDriver\Exceptions\UnsupportedFetchModeException; -use Circle\DoctrineRestDriver\Formatters\Formatter; -use Circle\DoctrineRestDriver\Security\AuthStrategy; -use Circle\DoctrineRestDriver\Types\HashMap; -use Circle\DoctrineRestDriver\Validation\Exceptions\InvalidTypeException; -use Circle\DoctrineRestDriver\Validation\Exceptions\NotNilException; use Circle\DoctrineRestDriver\Exceptions\Exceptions; use Prophecy\Exception\Doubler\ClassNotFoundException; @@ -38,71 +32,6 @@ */ class Assertions { - /** - * Asserts if the given value is not nil - * - * @param string $varName - * @param mixed $value - * @return mixed - * @throws NotNilException - */ - public static function assertNotNil($varName, $value) { - return $value === null ? Exceptions::NotNilException($varName) : $value; - } - - /** - * Asserts if the given value is a string - * - * @param string $varName - * @param mixed $value - * @return mixed - * @throws InvalidTypeException - * @throws NotNilException - */ - public static function assertString($varName, $value) { - self::assertNotNil($varName, $value); - return !is_string($value) ? Exceptions::InvalidTypeException('string', $varName, $value) : $value; - } - - /** - * Asserts if the given value is a maybe list - * - * @param string $varName - * @param mixed $value - * @return array|null - * @throws InvalidTypeException - * @throws NotNilException - */ - public static function assertMaybeList($varName, $value) { - return !is_array($value) && $value !== null ? Exceptions::InvalidTypeException('MaybeList', $varName, $value) : $value; - } - - /** - * Asserts if the given value is a maybe string - * - * @param string $varName - * @param mixed $value - * @return string|null - * @throws InvalidTypeException - * @throws NotNilException - */ - public static function assertMaybeString($varName, $value) { - return !is_string($value) && $value !== null ? Exceptions::InvalidTypeException('MaybeString', $varName, $value) : $value; - } - - /** - * Asserts if the given value is a maybe int - * - * @param string $varName - * @param mixed $value - * @return int|null - * @throws InvalidTypeException - * @throws NotNilException - */ - public static function assertMaybeInt($varName, $value) { - return !is_int($value) && $value !== null ? Exceptions::InvalidTypeException('MaybeInt', $varName, $value) : $value; - } - /** * Checks if the given fetch mode is supported * From bec198bbf2699a05754cfc7546017680d542365e Mon Sep 17 00:00:00 2001 From: TobiasHauck Date: Wed, 10 Aug 2016 00:01:33 +0200 Subject: [PATCH 11/15] added sql query type --- Statement.php | 8 ++- Tests/Transformers/MysqlToRequestTest.php | 43 ++++---------- Tests/Types/SqlQueryTest.php | 62 +++++++++++++++++++++ Transformers/MysqlToRequest.php | 15 +---- Types/SqlQuery.php | 68 +++++++++++++++++++++++ 5 files changed, 150 insertions(+), 46 deletions(-) create mode 100644 Tests/Types/SqlQueryTest.php create mode 100644 Types/SqlQuery.php diff --git a/Statement.php b/Statement.php index abf832a..26ae869 100644 --- a/Statement.php +++ b/Statement.php @@ -27,6 +27,7 @@ use Circle\DoctrineRestDriver\Types\Format; use Circle\DoctrineRestDriver\Types\Request; use Circle\DoctrineRestDriver\Types\Result; +use Circle\DoctrineRestDriver\Types\SqlQuery; use Circle\DoctrineRestDriver\Validation\Assertions; use Doctrine\DBAL\Driver\Statement as StatementInterface; use Symfony\Component\HttpFoundation\Response; @@ -159,12 +160,13 @@ public function errorInfo() { * @SuppressWarnings("PHPMD.StaticAccess") */ public function execute($params = null) { - $rawRequest = $this->mysqlToRequest->transform($this->query, $this->params); - $request = $this->authStrategy->transformRequest($rawRequest); + $transformedQuery = SqlQuery::quoteUrl(SqlQuery::setParams($this->query, $params !== null ? $params : $this->params)); + $rawRequest = $this->mysqlToRequest->transform($transformedQuery); + $request = $this->authStrategy->transformRequest($rawRequest); $response = $this->restClient->send($request); - $this->result = Result::create($this->query, $this->formatter->decode($response->getContent())); + $this->result = Result::create($transformedQuery, $this->formatter->decode($response->getContent())); $this->id = !empty($this->result['id']) ? $this->result['id'] : null; krsort($this->result); diff --git a/Tests/Transformers/MysqlToRequestTest.php b/Tests/Transformers/MysqlToRequestTest.php index a84645e..cc5ead8 100644 --- a/Tests/Transformers/MysqlToRequestTest.php +++ b/Tests/Transformers/MysqlToRequestTest.php @@ -87,17 +87,14 @@ public function setUp() { * @covers :: */ public function selectOne() { - $query = 'SELECT name FROM products WHERE id = ?'; - $params = [ - 1 - ]; + $query = 'SELECT name FROM products WHERE id = 1'; $expected = new Request([ 'method' => 'get', 'url' => $this->apiUrl . '/products/1', 'curlOptions' => $this->options ]); - $this->assertEquals($expected, $this->mysqlToRequest->transform($query, $params)); + $this->assertEquals($expected, $this->mysqlToRequest->transform($query)); } /** @@ -108,11 +105,7 @@ public function selectOne() { * @covers :: */ public function selectOneBy() { - $query = 'SELECT name FROM products WHERE id=? AND name=?'; - $params = [ - 1, - 'myName' - ]; + $query = 'SELECT name FROM products WHERE id=1 AND name=myName'; $expected = new Request([ 'method' => 'get', 'url' => $this->apiUrl . '/products/1', @@ -120,7 +113,7 @@ public function selectOneBy() { 'query' => 'name=myName' ]); - $this->assertEquals($expected, $this->mysqlToRequest->transform($query, $params)); + $this->assertEquals($expected, $this->mysqlToRequest->transform($query)); } /** @@ -131,10 +124,7 @@ public function selectOneBy() { * @covers :: */ public function selectBy() { - $query = 'SELECT name FROM products WHERE name=?'; - $params = [ - 'myName' - ]; + $query = 'SELECT name FROM products WHERE name=myName'; $expected = new Request([ 'method' => 'get', 'url' => $this->apiUrl . '/products', @@ -142,7 +132,7 @@ public function selectBy() { 'query' => 'name=myName' ]); - $this->assertEquals($expected, $this->mysqlToRequest->transform($query, $params)); + $this->assertEquals($expected, $this->mysqlToRequest->transform($query)); } /** @@ -210,10 +200,7 @@ public function insert() { * @covers :: */ public function update() { - $query = 'UPDATE products SET name="myValue" WHERE id=?'; - $params = [ - 1 - ]; + $query = 'UPDATE products SET name="myValue" WHERE id=1'; $expected = new Request([ 'method' => 'put', 'url' => $this->apiUrl . '/products/1', @@ -221,7 +208,7 @@ public function update() { 'payload' => json_encode(['name' => 'myValue']) ]); - $this->assertEquals($expected, $this->mysqlToRequest->transform($query, $params)); + $this->assertEquals($expected, $this->mysqlToRequest->transform($query)); } /** @@ -251,10 +238,7 @@ public function updateAll() { * @covers :: */ public function delete() { - $query = 'DELETE FROM products WHERE id=?'; - $params = [ - 1 - ]; + $query = 'DELETE FROM products WHERE id=1'; $expected = new Request([ 'method' => 'delete', 'url' => $this->apiUrl . '/products/1', @@ -262,7 +246,7 @@ public function delete() { 'expectedStatusCode' => 204 ]); - $this->assertEquals($expected, $this->mysqlToRequest->transform($query, $params)); + $this->assertEquals($expected, $this->mysqlToRequest->transform($query)); } /** @@ -274,10 +258,7 @@ public function delete() { * @expectedException \Exception */ public function brokenQuery() { - $query = 'SHIT products WHERE dirt=?'; - $params = [ - 1 - ]; - $this->mysqlToRequest->transform($query, $params); + $query = 'SHIT products WHERE dirt=1'; + $this->mysqlToRequest->transform($query); } } \ No newline at end of file diff --git a/Tests/Types/SqlQueryTest.php b/Tests/Types/SqlQueryTest.php new file mode 100644 index 0000000..bc09d96 --- /dev/null +++ b/Tests/Types/SqlQueryTest.php @@ -0,0 +1,62 @@ +. + */ + +namespace Circle\DoctrineRestDriver\Tests\Types; + +use Circle\DoctrineRestDriver\Types\SqlQuery; + +/** + * Tests the sql query type + * + * @author Tobias Hauck + * @copyright 2015 TeeAge-Beatz UG + * + * @coversDefaultClass Circle\DoctrineRestDriver\Types\SqlQuery + */ +class SqlQueryTest extends \PHPUnit_Framework_TestCase { + + /** + * @test + * @group unit + * @covers ::setParams + * + * @SuppressWarnings("PHPMD.StaticAccess") + */ + public function setParams() { + $query = 'SELECT name FROM products WHERE id=? AND name=?'; + $params = [ + 1, + 'myName' + ]; + $expected = 'SELECT name FROM products WHERE id=1 AND name=myName'; + $this->assertSame($expected, SqlQuery::setParams($query, $params)); + } + + /** + * @test + * @group unit + * @covers ::quoteUrl + * + * @SuppressWarnings("PHPMD.StaticAccess") + */ + public function quoteUrl() { + $query = 'SELECT name FROM http://www.circle.ai'; + $expected = 'SELECT name FROM "http://www.circle.ai"'; + $this->assertSame($expected, SqlQuery::quoteUrl($query)); + } +} \ No newline at end of file diff --git a/Transformers/MysqlToRequest.php b/Transformers/MysqlToRequest.php index 7ab7303..ff3a1d9 100644 --- a/Transformers/MysqlToRequest.php +++ b/Transformers/MysqlToRequest.php @@ -25,6 +25,7 @@ use Circle\DoctrineRestDriver\Types\Id; use Circle\DoctrineRestDriver\Types\Request; use Circle\DoctrineRestDriver\Types\SqlOperation; +use Circle\DoctrineRestDriver\Types\SqlQuery; use Circle\DoctrineRestDriver\Types\Table; use Circle\DoctrineRestDriver\Types\Url; use Circle\DoctrineRestDriver\Validation\Assertions; @@ -75,22 +76,12 @@ public function __construct(array $options, RoutingTable $routings) { * Transforms the given query into a request object * * @param string $query - * @param array $params * @return Request * * @SuppressWarnings("PHPMD.StaticAccess") */ - public function transform($query, array $params = []) { - $query = array_reduce($params, function($query, $param) { - return strpos($query, '?') ? substr_replace($query, $param, strpos($query, '?'), strlen('?')) : $query; - }, $query); - - $queryParts = explode(' ', $query); - $transformedQuery = array_reduce($queryParts, function($carry, $part) { - return $carry . (Url::is($part) ? ('"' . $part . '" ') : ($part . ' ')); - }); - - $tokens = $this->parser->parse($transformedQuery); + public function transform($query) { + $tokens = $this->parser->parse($query); $method = HttpMethods::ofSqlOperation(SqlOperation::create($tokens)); $annotation = Annotation::get($this->routings, Table::create($tokens), $method); diff --git a/Types/SqlQuery.php b/Types/SqlQuery.php new file mode 100644 index 0000000..077ef08 --- /dev/null +++ b/Types/SqlQuery.php @@ -0,0 +1,68 @@ +. + */ + +namespace Circle\DoctrineRestDriver\Types; + +use Circle\DoctrineRestDriver\Validation\Exceptions\NotNilException; +use Symfony\Component\Config\Definition\Exception\InvalidTypeException; + +/** + * SqlQuery type + * + * @author Tobias Hauck + * @copyright 2015 TeeAge-Beatz UG + */ +class SqlQuery { + + /** + * replaces param placeholders with corresponding params + * + * @param string $query + * @param array $params + * @return string + * @throws InvalidTypeException + * @throws NotNilException + * + * @SuppressWarnings("PHPMD.StaticAccess") + */ + public static function setParams($query, array $params = []) { + Str::assert($query, 'query'); + + return array_reduce($params, function($query, $param) { + return strpos($query, '?') ? substr_replace($query, $param, strpos($query, '?'), strlen('?')) : $query; + }, $query); + } + + /** + * quotes the table if it's an url + * + * @param string $query + * @return string + * @throws InvalidTypeException + * @throws NotNilException + * + * @SuppressWarnings("PHPMD.StaticAccess") + */ + public static function quoteUrl($query) { + $queryParts = explode(' ', Str::assert($query, 'query')); + + return trim(array_reduce($queryParts, function($carry, $part) { + return $carry . (Url::is($part) ? ('"' . $part . '" ') : ($part . ' ')); + })); + } +} \ No newline at end of file From 05ced02a3802d2b32e2c7dcaf1cfac393de53e43 Mon Sep 17 00:00:00 2001 From: TobiasHauck Date: Wed, 10 Aug 2016 23:29:04 +0200 Subject: [PATCH 12/15] everything besides change set and statement execute --- Exceptions/RequestFailedException.php | 2 +- Statement.php | 16 +++--- Tests/Transformers/MysqlToRequestTest.php | 13 ++--- Tests/Types/ResultTest.php | 28 ++++++---- Tests/Validation/AssertionsTest.php | 1 - Types/Payload.php | 4 +- Types/Result.php | 67 ++++++++++++++++++++--- Types/Url.php | 5 +- Types/Value.php | 5 +- 9 files changed, 100 insertions(+), 41 deletions(-) diff --git a/Exceptions/RequestFailedException.php b/Exceptions/RequestFailedException.php index ae3062f..d6fcb2a 100644 --- a/Exceptions/RequestFailedException.php +++ b/Exceptions/RequestFailedException.php @@ -39,6 +39,6 @@ class RequestFailedException extends \Exception { * @param string $errorMessage */ public function __construct(Request $request, $errorCode, $errorMessage) { - parent::__construct('Execution failed for request: ' . $request . ': HTTPCode ' . $errorCode . ', body ' . $errorMessage); + parent::__construct('Execution failed for request: ' . $request . ': HTTPCode ' . $errorCode . ', body ' . $errorMessage, $errorCode); } } diff --git a/Statement.php b/Statement.php index 26ae869..ba8b7cc 100644 --- a/Statement.php +++ b/Statement.php @@ -21,6 +21,7 @@ use Circle\DoctrineRestDriver\Annotations\RoutingTable; use Circle\DoctrineRestDriver\Enums\HttpMethods; use Circle\DoctrineRestDriver\Exceptions\Exceptions; +use Circle\DoctrineRestDriver\Exceptions\RequestFailedException; use Circle\DoctrineRestDriver\Security\AuthStrategy; use Circle\DoctrineRestDriver\Transformers\MysqlToRequest; use Circle\DoctrineRestDriver\Types\Authentication; @@ -114,10 +115,10 @@ class Statement implements \IteratorAggregate, StatementInterface { * @SuppressWarnings("PHPMD.StaticAccess") */ public function __construct($query, array $options, RoutingTable $routings) { - $this->query = $query; - $this->routings = $routings; - $this->mysqlToRequest = new MysqlToRequest($options, $this->routings); - $this->restClient = new RestClient(); + $this->query = $query; + $this->routings = $routings; + $this->mysqlToRequest = new MysqlToRequest($options, $this->routings); + $this->restClient = new RestClient(); $this->authStrategy = Authentication::create($options); $this->formatter = Format::create($options); @@ -156,6 +157,7 @@ public function errorInfo() { /** * {@inheritdoc} + * @throws RequestFailedException * * @SuppressWarnings("PHPMD.StaticAccess") */ @@ -165,10 +167,10 @@ public function execute($params = null) { $request = $this->authStrategy->transformRequest($rawRequest); $response = $this->restClient->send($request); + $result = new Result($transformedQuery, $this->formatter->decode($response->getContent())); - $this->result = Result::create($transformedQuery, $this->formatter->decode($response->getContent())); - $this->id = !empty($this->result['id']) ? $this->result['id'] : null; - krsort($this->result); + $this->result = $result->get(); + $this->id = $result->id(); return true; } diff --git a/Tests/Transformers/MysqlToRequestTest.php b/Tests/Transformers/MysqlToRequestTest.php index cc5ead8..a25f4ca 100644 --- a/Tests/Transformers/MysqlToRequestTest.php +++ b/Tests/Transformers/MysqlToRequestTest.php @@ -87,7 +87,7 @@ public function setUp() { * @covers :: */ public function selectOne() { - $query = 'SELECT name FROM products WHERE id = 1'; + $query = 'SELECT name FROM products WHERE id = 1'; $expected = new Request([ 'method' => 'get', 'url' => $this->apiUrl . '/products/1', @@ -105,7 +105,7 @@ public function selectOne() { * @covers :: */ public function selectOneBy() { - $query = 'SELECT name FROM products WHERE id=1 AND name=myName'; + $query = 'SELECT name FROM products WHERE id=1 AND name=myName'; $expected = new Request([ 'method' => 'get', 'url' => $this->apiUrl . '/products/1', @@ -124,7 +124,7 @@ public function selectOneBy() { * @covers :: */ public function selectBy() { - $query = 'SELECT name FROM products WHERE name=myName'; + $query = 'SELECT name FROM products WHERE name=myName'; $expected = new Request([ 'method' => 'get', 'url' => $this->apiUrl . '/products', @@ -180,7 +180,6 @@ public function selectJoined() { */ public function insert() { $query = 'INSERT INTO products (name) VALUES ("myName")'; - $expected = new Request([ 'method' => 'post', 'url' => $this->apiUrl . '/products', @@ -200,7 +199,7 @@ public function insert() { * @covers :: */ public function update() { - $query = 'UPDATE products SET name="myValue" WHERE id=1'; + $query = 'UPDATE products SET name="myValue" WHERE id=1'; $expected = new Request([ 'method' => 'put', 'url' => $this->apiUrl . '/products/1', @@ -238,7 +237,7 @@ public function updateAll() { * @covers :: */ public function delete() { - $query = 'DELETE FROM products WHERE id=1'; + $query = 'DELETE FROM products WHERE id=1'; $expected = new Request([ 'method' => 'delete', 'url' => $this->apiUrl . '/products/1', @@ -258,7 +257,7 @@ public function delete() { * @expectedException \Exception */ public function brokenQuery() { - $query = 'SHIT products WHERE dirt=1'; + $query = 'SHIT products WHERE dirt=1'; $this->mysqlToRequest->transform($query); } } \ No newline at end of file diff --git a/Tests/Types/ResultTest.php b/Tests/Types/ResultTest.php index 08913ca..d75545c 100644 --- a/Tests/Types/ResultTest.php +++ b/Tests/Types/ResultTest.php @@ -33,11 +33,12 @@ class ResultTest extends \PHPUnit_Framework_TestCase { /** * @test * @group unit - * @covers ::create + * @covers ::get + * @covers :: * * @SuppressWarnings("PHPMD.StaticAccess") */ - public function createWithSelect() { + public function getWithSelect() { $content = [ 'name' => 'testname' ]; @@ -48,34 +49,36 @@ public function createWithSelect() { ] ]; - $this->assertEquals($expected, Result::create('SELECT name FROM products WHERE id=1', $content)); + $this->assertEquals($expected, (new Result('SELECT name FROM products WHERE id=1', $content))->get()); } /** * @test * @group unit - * @covers ::create + * @covers ::get + * @covers :: * * @SuppressWarnings("PHPMD.StaticAccess") */ - public function createWithDelete() { + public function getWithDelete() { $content = [ 'name' => 'testname' ]; $expected = []; - $this->assertEquals($expected, Result::create('DELETE FROM products WHERE id=1', $content)); + $this->assertEquals($expected, (new Result('DELETE FROM products WHERE id=1', $content))->get()); } /** * @test * @group unit - * @covers ::create + * @covers ::get + * @covers :: * * @SuppressWarnings("PHPMD.StaticAccess") */ - public function createWithInsert() { + public function getWithInsert() { $content = [ 'name' => 'testname' ]; @@ -84,17 +87,18 @@ public function createWithInsert() { 'name' => 'testname' ]; - $this->assertEquals($expected, Result::create('INSERT INTO products (name) VALUES ("testname")', $content)); + $this->assertEquals($expected, (new Result('INSERT INTO products (name) VALUES ("testname")', $content))->get()); } /** * @test * @group unit - * @covers ::create + * @covers ::get + * @covers :: * * @SuppressWarnings("PHPMD.StaticAccess") */ - public function createWithUpdate() { + public function getWithUpdate() { $content = [ 'name' => 'testname' ]; @@ -103,6 +107,6 @@ public function createWithUpdate() { 'name' => 'testname' ]; - $this->assertEquals($expected, Result::create('UPDATE products SET name = "testname" WHERE id=1', $content)); + $this->assertEquals($expected, (new Result('UPDATE products SET name = "testname" WHERE id=1', $content))->get()); } } \ No newline at end of file diff --git a/Tests/Validation/AssertionsTest.php b/Tests/Validation/AssertionsTest.php index b455d82..f97ba17 100644 --- a/Tests/Validation/AssertionsTest.php +++ b/Tests/Validation/AssertionsTest.php @@ -27,7 +27,6 @@ * @copyright 2015 TeeAge-Beatz UG * * @coversDefaultClass Circle\DoctrineRestDriver\Validation\Assertions - * @SuppressWarnings("PHPMD.TooManyPublicMethods") */ class AssertionsTest extends \PHPUnit_Framework_TestCase { diff --git a/Types/Payload.php b/Types/Payload.php index 912d8f1..7ca1ba1 100644 --- a/Types/Payload.php +++ b/Types/Payload.php @@ -41,10 +41,10 @@ class Payload { public static function create(array $tokens, array $options) { HashMap::assert($tokens, 'tokens'); - $formatter = Format::create($options); + $format = Format::create($options); $operation = SqlOperation::create($tokens); if ($operation === SqlOperations::SELECT || $operation === SqlOperations::DELETE) return null; - return $formatter->encode($operation === SqlOperations::INSERT ? InsertPayload::create($tokens) : UpdatePayload::create($tokens)); + return $format->encode($operation === SqlOperations::INSERT ? InsertPayload::create($tokens) : UpdatePayload::create($tokens)); } } \ No newline at end of file diff --git a/Types/Result.php b/Types/Result.php index 9fd141f..84fadfd 100644 --- a/Types/Result.php +++ b/Types/Result.php @@ -18,6 +18,7 @@ namespace Circle\DoctrineRestDriver\Types; use Circle\DoctrineRestDriver\Enums\SqlOperations; +use Circle\DoctrineRestDriver\MetaData; use PHPSQLParser\PHPSQLParser; /** @@ -29,21 +30,73 @@ */ class Result { + /** + * @var array + */ + private $result; + + /** + * @var mixed + */ + private $id; + + /** + * Result constructor + * + * @param string $query + * @param array $content + */ + public function __construct($query, array $content = null) { + $tokens = (new PHPSQLParser())->parse($query); + $this->result = $this->createResult($tokens, $content); + $this->id = $this->createId($tokens); + } + /** * Returns a valid Doctrine result * - * @param string $query - * @param array $content - * @return string + * @return array + */ + public function get() { + return $this->result; + } + + /** + * returns the id of the result + */ + public function id() { + return $this->id; + } + + /** + * returns the id + * + * @param array $tokens + * @return mixed + * + * @SuppressWarnings("PHPMD.StaticAccess") + */ + private function createId(array $tokens) { + $idColumn = Id::column($tokens, new MetaData()); + return empty($this->result[$idColumn]) ? null : $this->result[$idColumn]; + } + + /** + * returns the result + * + * @param array $tokens + * @param array|null $content + * @return array * * @SuppressWarnings("PHPMD.StaticAccess") */ - public static function create($query, $content) { - $parser = new PHPSQLParser(); - $tokens = $parser->parse($query); + private function createResult(array $tokens, array $content = null) { $operator = strtolower(array_keys($tokens)[0]); if ($operator === SqlOperations::DELETE) return []; - return $operator === SqlOperations::SELECT ? SelectResult::create($tokens, $content) : $content; + $result = $operator === SqlOperations::SELECT ? SelectResult::create($tokens, $content) : $content; + krsort($result); + + return $result; } } \ No newline at end of file diff --git a/Types/Url.php b/Types/Url.php index ba9daca..4b5215d 100644 --- a/Types/Url.php +++ b/Types/Url.php @@ -49,10 +49,11 @@ public static function create($route, $apiUrl, $id = null) { $idPath = empty($id) ? '' : '/' . $id; - if (!self::is($route)) return $apiUrl . '/' . $route . $idPath; + if (!self::is($route)) return $apiUrl . '/' . $route . $idPath; if (!preg_match('/\{id\}/', $route)) return $route . $idPath; + if (!empty($id)) return str_replace('{id}', $id, $route); - return !empty($id) ? str_replace('{id}', $id, $route) : str_replace('/{id}', '', $route); + return str_replace('/{id}', '', $route); } /** diff --git a/Types/Value.php b/Types/Value.php index 9a22048..6547828 100644 --- a/Types/Value.php +++ b/Types/Value.php @@ -43,8 +43,9 @@ public static function create($value) { if (empty($value)) return null; $unquoted = preg_replace('/\"|\\\'|\`$/', '', preg_replace('/^\"|\\\'|\`/', '', $value)); - if (!is_numeric($unquoted)) return $unquoted; + if (!is_numeric($unquoted)) return $unquoted; + if ((string) intval($unquoted) === $unquoted) return intval($unquoted); - return ((string) intval($unquoted) === $unquoted) ? intval($unquoted) : floatval($unquoted); + return floatval($unquoted); } } \ No newline at end of file From 81a025420752310a4fd119ef6a675a50048ddc89 Mon Sep 17 00:00:00 2001 From: TobiasHauck Date: Thu, 11 Aug 2016 00:48:44 +0200 Subject: [PATCH 13/15] added suggestions --- Exceptions/DoctrineRestDriverException.php | 27 ++++++++++ Statement.php | 41 ++++++++-------- .../Types/{IdTest.php => IdentifierTest.php} | 16 +++--- ...ayloadTest.php => InsertChangeSetTest.php} | 19 ++++--- Tests/Types/ResultTest.php | 49 ++++++++++++++----- ...ayloadTest.php => UpdateChangeSetTest.php} | 10 ++-- Types/{Id.php => Identifier.php} | 2 +- ...{InsertPayload.php => InsertChangeSet.php} | 4 +- Types/Payload.php | 6 +-- Types/Result.php | 17 +++++-- ...{UpdatePayload.php => UpdateChangeSet.php} | 4 +- Types/Url.php | 2 +- composer.json | 2 +- 13 files changed, 129 insertions(+), 70 deletions(-) create mode 100644 Exceptions/DoctrineRestDriverException.php rename Tests/Types/{IdTest.php => IdentifierTest.php} (85%) rename Tests/Types/{InsertPayloadTest.php => InsertChangeSetTest.php} (83%) rename Tests/Types/{UpdatePayloadTest.php => UpdateChangeSetTest.php} (81%) rename Types/{Id.php => Identifier.php} (99%) rename Types/{InsertPayload.php => InsertChangeSet.php} (98%) rename Types/{UpdatePayload.php => UpdateChangeSet.php} (97%) diff --git a/Exceptions/DoctrineRestDriverException.php b/Exceptions/DoctrineRestDriverException.php new file mode 100644 index 0000000..6ff7d4f --- /dev/null +++ b/Exceptions/DoctrineRestDriverException.php @@ -0,0 +1,27 @@ +. + */ + +namespace Circle\DoctrineRestDriver\Exceptions; + +/** + * Generic driver exception + * + * @author Tobias Hauck + * @copyright 2015 TeeAge-Beatz UG + */ +class DoctrineRestDriverException extends \Exception {} diff --git a/Statement.php b/Statement.php index ba8b7cc..585e776 100644 --- a/Statement.php +++ b/Statement.php @@ -19,20 +19,16 @@ namespace Circle\DoctrineRestDriver; use Circle\DoctrineRestDriver\Annotations\RoutingTable; -use Circle\DoctrineRestDriver\Enums\HttpMethods; +use Circle\DoctrineRestDriver\Exceptions\DoctrineRestDriverException; use Circle\DoctrineRestDriver\Exceptions\Exceptions; use Circle\DoctrineRestDriver\Exceptions\RequestFailedException; use Circle\DoctrineRestDriver\Security\AuthStrategy; use Circle\DoctrineRestDriver\Transformers\MysqlToRequest; use Circle\DoctrineRestDriver\Types\Authentication; -use Circle\DoctrineRestDriver\Types\Format; -use Circle\DoctrineRestDriver\Types\Request; use Circle\DoctrineRestDriver\Types\Result; use Circle\DoctrineRestDriver\Types\SqlQuery; use Circle\DoctrineRestDriver\Validation\Assertions; use Doctrine\DBAL\Driver\Statement as StatementInterface; -use Symfony\Component\HttpFoundation\Response; -use Circle\DoctrineRestDriver\Formatters\Formatter; /** * Executes the statement - sends requests to an api @@ -100,9 +96,9 @@ class Statement implements \IteratorAggregate, StatementInterface { private $routings; /** - * @var Formatter + * @var array */ - private $formatter; + private $options; /** * Statement constructor @@ -115,13 +111,13 @@ class Statement implements \IteratorAggregate, StatementInterface { * @SuppressWarnings("PHPMD.StaticAccess") */ public function __construct($query, array $options, RoutingTable $routings) { - $this->query = $query; + $this->query = SqlQuery::quoteUrl($query); $this->routings = $routings; $this->mysqlToRequest = new MysqlToRequest($options, $this->routings); $this->restClient = new RestClient(); $this->authStrategy = Authentication::create($options); - $this->formatter = Format::create($options); + $this->options = $options; } /** @@ -162,17 +158,22 @@ public function errorInfo() { * @SuppressWarnings("PHPMD.StaticAccess") */ public function execute($params = null) { - $transformedQuery = SqlQuery::quoteUrl(SqlQuery::setParams($this->query, $params !== null ? $params : $this->params)); - $rawRequest = $this->mysqlToRequest->transform($transformedQuery); - $request = $this->authStrategy->transformRequest($rawRequest); - - $response = $this->restClient->send($request); - $result = new Result($transformedQuery, $this->formatter->decode($response->getContent())); - - $this->result = $result->get(); - $this->id = $result->id(); - - return true; + $query = SqlQuery::setParams($this->query, $params !== null ? $params : $this->params); + $request = $this->authStrategy->transformRequest($this->mysqlToRequest->transform($query)); + + try { + $response = $this->restClient->send($request); + $result = new Result($query, $response, $this->options); + $this->result = $result->get(); + $this->id = $result->id(); + + return true; + } catch(RequestFailedException $e) { + // as the error handling proposed by doctrine + // does not work, we use the way of PDO_mysql + // which just throws the possible errors + throw new DoctrineRestDriverException($e->getMessage(), $e->getCode()); + } } /** diff --git a/Tests/Types/IdTest.php b/Tests/Types/IdentifierTest.php similarity index 85% rename from Tests/Types/IdTest.php rename to Tests/Types/IdentifierTest.php index fa2c2ce..1122ef8 100644 --- a/Tests/Types/IdTest.php +++ b/Tests/Types/IdentifierTest.php @@ -18,18 +18,18 @@ namespace Circle\DoctrineRestDriver\Tests\Types; -use Circle\DoctrineRestDriver\Types\Id; +use Circle\DoctrineRestDriver\Types\Identifier; use PHPSQLParser\PHPSQLParser; /** - * Tests the id type + * Tests the identifier type * * @author Tobias Hauck * @copyright 2015 TeeAge-Beatz UG * - * @coversDefaultClass Circle\DoctrineRestDriver\Types\Id + * @coversDefaultClass Circle\DoctrineRestDriver\Types\Identifier */ -class IdTest extends \PHPUnit_Framework_TestCase { +class IdentifierTest extends \PHPUnit_Framework_TestCase { /** * @test @@ -42,7 +42,7 @@ public function create() { $parser = new PHPSQLParser(); $tokens = $parser->parse('SELECT name FROM products WHERE id=1'); - $this->assertSame('1', Id::create($tokens)); + $this->assertSame('1', Identifier::create($tokens)); } /** @@ -56,7 +56,7 @@ public function createWithEmptyId() { $parser = new PHPSQLParser(); $tokens = $parser->parse('SELECT name FROM products WHERE name="test"'); - $this->assertSame('', Id::create($tokens)); + $this->assertSame('', Identifier::create($tokens)); } /** @@ -70,7 +70,7 @@ public function alias() { $parser = new PHPSQLParser(); $tokens = $parser->parse('SELECT name FROM products WHERE id=1'); - $this->assertSame('id', Id::alias($tokens)); + $this->assertSame('id', Identifier::alias($tokens)); } /** @@ -100,6 +100,6 @@ public function column() { ->method('get') ->will($this->returnValue([$metaDataEntry])); - $this->assertSame('testId', Id::column($tokens, $metaData)); + $this->assertSame('testId', Identifier::column($tokens, $metaData)); } } \ No newline at end of file diff --git a/Tests/Types/InsertPayloadTest.php b/Tests/Types/InsertChangeSetTest.php similarity index 83% rename from Tests/Types/InsertPayloadTest.php rename to Tests/Types/InsertChangeSetTest.php index a01470d..7edf560 100644 --- a/Tests/Types/InsertPayloadTest.php +++ b/Tests/Types/InsertChangeSetTest.php @@ -18,19 +18,18 @@ namespace Circle\DoctrineRestDriver\Tests\Types; -use Circle\DoctrineRestDriver\Types\Id; -use Circle\DoctrineRestDriver\Types\InsertPayload; +use Circle\DoctrineRestDriver\Types\InsertChangeSet; use PHPSQLParser\PHPSQLParser; /** - * Tests the insert payload type + * Tests the insert change set type * * @author Tobias Hauck * @copyright 2015 TeeAge-Beatz UG * - * @coversDefaultClass Circle\DoctrineRestDriver\Types\InsertPayload + * @coversDefaultClass Circle\DoctrineRestDriver\Types\InsertChangeSet */ -class InsertPayloadTest extends \PHPUnit_Framework_TestCase { +class InsertChangeSetTest extends \PHPUnit_Framework_TestCase { /** * @test @@ -48,7 +47,7 @@ public function createWithRawValues() { 'value' => 'testvalue', ]; - $this->assertSame($expected, InsertPayload::create($tokens)); + $this->assertSame($expected, InsertChangeSet::create($tokens)); } /** @@ -67,7 +66,7 @@ public function createWithQuotedValues() { 'value' => 'testvalue', ]; - $this->assertSame($expected, InsertPayload::create($tokens)); + $this->assertSame($expected, InsertChangeSet::create($tokens)); } /** @@ -86,7 +85,7 @@ public function createWithIntValue() { 'value' => 1, ]; - $this->assertSame($expected, InsertPayload::create($tokens)); + $this->assertSame($expected, InsertChangeSet::create($tokens)); } /** @@ -101,7 +100,7 @@ public function values() { $tokens = $parser->parse('INSERT INTO products (name, value) VALUES (testname, testvalue)'); $expected = ['testname', 'testvalue']; - $this->assertEquals($expected, InsertPayload::values($tokens)); + $this->assertEquals($expected, InsertChangeSet::values($tokens)); } /** @@ -116,6 +115,6 @@ public function columns() { $tokens = $parser->parse('INSERT INTO products (name, value) VALUES (testname, testvalue)'); $expected = ['name', 'value']; - $this->assertEquals($expected, InsertPayload::columns($tokens)); + $this->assertEquals($expected, InsertChangeSet::columns($tokens)); } } \ No newline at end of file diff --git a/Tests/Types/ResultTest.php b/Tests/Types/ResultTest.php index d75545c..8507c38 100644 --- a/Tests/Types/ResultTest.php +++ b/Tests/Types/ResultTest.php @@ -19,6 +19,7 @@ namespace Circle\DoctrineRestDriver\Tests\Types; use Circle\DoctrineRestDriver\Types\Result; +use Symfony\Component\HttpFoundation\Response; /** * Tests the result type @@ -33,15 +34,16 @@ class ResultTest extends \PHPUnit_Framework_TestCase { /** * @test * @group unit + * @covers ::__construct * @covers ::get * @covers :: * * @SuppressWarnings("PHPMD.StaticAccess") */ public function getWithSelect() { - $content = [ + $response = new Response(json_encode([ 'name' => 'testname' - ]; + ])); $expected = [ [ @@ -49,64 +51,87 @@ public function getWithSelect() { ] ]; - $this->assertEquals($expected, (new Result('SELECT name FROM products WHERE id=1', $content))->get()); + $this->assertEquals($expected, (new Result('SELECT name FROM products WHERE id=1', $response))->get()); } /** * @test * @group unit + * @covers ::__construct * @covers ::get * @covers :: * * @SuppressWarnings("PHPMD.StaticAccess") */ public function getWithDelete() { - $content = [ + $response = new Response(json_encode([ 'name' => 'testname' - ]; + ])); $expected = []; - $this->assertEquals($expected, (new Result('DELETE FROM products WHERE id=1', $content))->get()); + $this->assertEquals($expected, (new Result('DELETE FROM products WHERE id=1', $response))->get()); } /** * @test * @group unit + * @covers ::__construct * @covers ::get * @covers :: * * @SuppressWarnings("PHPMD.StaticAccess") */ public function getWithInsert() { - $content = [ + $response = new Response(json_encode([ 'name' => 'testname' - ]; + ])); $expected = [ 'name' => 'testname' ]; - $this->assertEquals($expected, (new Result('INSERT INTO products (name) VALUES ("testname")', $content))->get()); + $this->assertEquals($expected, (new Result('INSERT INTO products (name) VALUES ("testname")', $response))->get()); } /** * @test * @group unit + * @covers ::__construct * @covers ::get * @covers :: * * @SuppressWarnings("PHPMD.StaticAccess") */ public function getWithUpdate() { - $content = [ + $response = new Response(json_encode([ 'name' => 'testname' - ]; + ])); $expected = [ 'name' => 'testname' ]; - $this->assertEquals($expected, (new Result('UPDATE products SET name = "testname" WHERE id=1', $content))->get()); + $this->assertEquals($expected, (new Result('UPDATE products SET name = "testname" WHERE id=1', $response))->get()); + } + + /** + * @test + * @group unit + * @covers ::__construct + * @covers ::id + * @covers :: + * + * @SuppressWarnings("PHPMD.StaticAccess") + */ + public function id() { + $response = new Response(json_encode([ + 'name' => 'testname', + 'id' => 1 + ])); + + $expected = 1; + + $this->assertEquals($expected, (new Result('UPDATE products SET name = "testname" WHERE id=1', $response))->id()); } } \ No newline at end of file diff --git a/Tests/Types/UpdatePayloadTest.php b/Tests/Types/UpdateChangeSetTest.php similarity index 81% rename from Tests/Types/UpdatePayloadTest.php rename to Tests/Types/UpdateChangeSetTest.php index 33385b4..670b7e6 100644 --- a/Tests/Types/UpdatePayloadTest.php +++ b/Tests/Types/UpdateChangeSetTest.php @@ -18,18 +18,18 @@ namespace Circle\DoctrineRestDriver\Tests\Types; -use Circle\DoctrineRestDriver\Types\UpdatePayload; +use Circle\DoctrineRestDriver\Types\UpdateChangeSet; use PHPSQLParser\PHPSQLParser; /** - * Tests the UpdatePayload type + * Tests the UpdateChangeSet type * * @author Tobias Hauck * @copyright 2015 TeeAge-Beatz UG * - * @coversDefaultClass Circle\DoctrineRestDriver\Types\UpdatePayload + * @coversDefaultClass Circle\DoctrineRestDriver\Types\UpdateChangeSet */ -class UpdatePayloadTest extends \PHPUnit_Framework_TestCase { +class UpdateChangeSetTest extends \PHPUnit_Framework_TestCase { /** * @test @@ -46,6 +46,6 @@ public function create() { 'value' => 'testvalue', ]; - $this->assertSame($expected, UpdatePayload::create($tokens)); + $this->assertSame($expected, UpdateChangeSet::create($tokens)); } } \ No newline at end of file diff --git a/Types/Id.php b/Types/Identifier.php similarity index 99% rename from Types/Id.php rename to Types/Identifier.php index 224a843..69a4422 100644 --- a/Types/Id.php +++ b/Types/Identifier.php @@ -27,7 +27,7 @@ * @author Tobias Hauck * @copyright 2015 TeeAge-Beatz UG */ -class Id { +class Identifier { /** * Returns the id in the WHERE clause if exists diff --git a/Types/InsertPayload.php b/Types/InsertChangeSet.php similarity index 98% rename from Types/InsertPayload.php rename to Types/InsertChangeSet.php index 7f7c34d..bafe2a8 100644 --- a/Types/InsertPayload.php +++ b/Types/InsertChangeSet.php @@ -19,12 +19,12 @@ namespace Circle\DoctrineRestDriver\Types; /** - * InsertPayload type + * InsertChangeSet type * * @author Tobias Hauck * @copyright 2015 TeeAge-Beatz UG */ -class InsertPayload { +class InsertChangeSet { /** * Converts the string with format (key) VALUES (value) diff --git a/Types/Payload.php b/Types/Payload.php index 7ca1ba1..7600faf 100644 --- a/Types/Payload.php +++ b/Types/Payload.php @@ -21,7 +21,7 @@ use Circle\DoctrineRestDriver\Enums\SqlOperations; /** - * Payload type: Union type for UpdatePayload and InsertPayload + * Payload type: Union type for InsertChangeSet and InsertChangeSet * * @author Tobias Hauck * @copyright 2015 TeeAge-Beatz UG @@ -29,7 +29,7 @@ class Payload { /** - * Returns an InsertPayload::create or UpdatePayload::create + * Returns an InsertChangeSet::create or InsertChangeSet::create * result or null depending on the given tokens array * * @param array $tokens @@ -45,6 +45,6 @@ public static function create(array $tokens, array $options) { $operation = SqlOperation::create($tokens); if ($operation === SqlOperations::SELECT || $operation === SqlOperations::DELETE) return null; - return $format->encode($operation === SqlOperations::INSERT ? InsertPayload::create($tokens) : UpdatePayload::create($tokens)); + return $format->encode($operation === SqlOperations::INSERT ? InsertChangeSet::create($tokens) : UpdateChangeSet::create($tokens)); } } \ No newline at end of file diff --git a/Types/Result.php b/Types/Result.php index 84fadfd..5e8d0d2 100644 --- a/Types/Result.php +++ b/Types/Result.php @@ -17,9 +17,11 @@ */ namespace Circle\DoctrineRestDriver\Types; + use Circle\DoctrineRestDriver\Enums\SqlOperations; use Circle\DoctrineRestDriver\MetaData; use PHPSQLParser\PHPSQLParser; +use Symfony\Component\HttpFoundation\Response; /** * Maps the response content of any query to a valid @@ -43,11 +45,16 @@ class Result { /** * Result constructor * - * @param string $query - * @param array $content + * @param string $query + * @param Response $response + * @param array $options + * + * @SuppressWarnings("PHPMD.StaticAccess") */ - public function __construct($query, array $content = null) { - $tokens = (new PHPSQLParser())->parse($query); + public function __construct($query, Response $response, array $options = []) { + $tokens = (new PHPSQLParser())->parse($query); + $content = Format::create($options)->decode($response->getContent()); + $this->result = $this->createResult($tokens, $content); $this->id = $this->createId($tokens); } @@ -77,7 +84,7 @@ public function id() { * @SuppressWarnings("PHPMD.StaticAccess") */ private function createId(array $tokens) { - $idColumn = Id::column($tokens, new MetaData()); + $idColumn = Identifier::column($tokens, new MetaData()); return empty($this->result[$idColumn]) ? null : $this->result[$idColumn]; } diff --git a/Types/UpdatePayload.php b/Types/UpdateChangeSet.php similarity index 97% rename from Types/UpdatePayload.php rename to Types/UpdateChangeSet.php index a82c738..501c3c0 100644 --- a/Types/UpdatePayload.php +++ b/Types/UpdateChangeSet.php @@ -19,12 +19,12 @@ namespace Circle\DoctrineRestDriver\Types; /** - * UpdatePayload type + * UpdateChangeSet type * * @author Tobias Hauck * @copyright 2015 TeeAge-Beatz UG */ -class UpdatePayload { +class UpdateChangeSet { /** * Converts the string with format key="value",[key2="value2",]* diff --git a/Types/Url.php b/Types/Url.php index 4b5215d..6e4854e 100644 --- a/Types/Url.php +++ b/Types/Url.php @@ -67,7 +67,7 @@ public static function create($route, $apiUrl, $id = null) { * @SuppressWarnings("PHPMD.StaticAccess") */ public static function createFromTokens(array $tokens, $apiUrl, DataSource $annotation = null) { - $id = Id::create($tokens); + $id = Identifier::create($tokens); $route = empty($annotation) || $annotation->getRoute() === null ? Table::create($tokens) : $annotation->getRoute(); return self::create($route, $apiUrl, $id); diff --git a/composer.json b/composer.json index f2f3c19..0a3cfbb 100644 --- a/composer.json +++ b/composer.json @@ -39,7 +39,7 @@ "target-dir": "Circle/DoctrineRestDriver", "extra": { "branch-alias": { - "dev-master": "0.3-dev" + "dev-master": "1.0-dev" } }, "require": { From d0ec753d1b5ac9244af87dd59aa28369f1e65203 Mon Sep 17 00:00:00 2001 From: TobiasHauck Date: Thu, 11 Aug 2016 10:52:52 +0200 Subject: [PATCH 14/15] exceptions extend doctrine rest driver exception --- Exceptions/InvalidAuthStrategyException.php | 2 +- Exceptions/InvalidFormatException.php | 2 +- Exceptions/InvalidSqlOperationException.php | 2 +- Exceptions/MethodNotImplementedException.php | 2 +- Exceptions/RequestFailedException.php | 2 +- Exceptions/UnsupportedFetchModeException.php | 2 +- Tests/Transformers/MysqlToRequestTest.php | 10 +++++----- 7 files changed, 11 insertions(+), 11 deletions(-) diff --git a/Exceptions/InvalidAuthStrategyException.php b/Exceptions/InvalidAuthStrategyException.php index fc157c3..f422496 100644 --- a/Exceptions/InvalidAuthStrategyException.php +++ b/Exceptions/InvalidAuthStrategyException.php @@ -26,7 +26,7 @@ * * @SuppressWarnings("PHPMD.StaticAccess") */ -class InvalidAuthStrategyException extends \Exception { +class InvalidAuthStrategyException extends DoctrineRestDriverException { /** * InvalidAuthStrategyException constructor diff --git a/Exceptions/InvalidFormatException.php b/Exceptions/InvalidFormatException.php index 787f84f..c61c71b 100644 --- a/Exceptions/InvalidFormatException.php +++ b/Exceptions/InvalidFormatException.php @@ -26,7 +26,7 @@ * * @SuppressWarnings("PHPMD.StaticAccess") */ -class InvalidFormatException extends \Exception { +class InvalidFormatException extends DoctrineRestDriverException { /** * InvalidFormatException constructor diff --git a/Exceptions/InvalidSqlOperationException.php b/Exceptions/InvalidSqlOperationException.php index f39fe82..04a56b0 100644 --- a/Exceptions/InvalidSqlOperationException.php +++ b/Exceptions/InvalidSqlOperationException.php @@ -26,7 +26,7 @@ * * @SuppressWarnings("PHPMD.StaticAccess") */ -class InvalidSqlOperationException extends \Exception { +class InvalidSqlOperationException extends DoctrineRestDriverException { /** * InvalidSqlOperationException constructor diff --git a/Exceptions/MethodNotImplementedException.php b/Exceptions/MethodNotImplementedException.php index 73cfe1c..fe1d481 100644 --- a/Exceptions/MethodNotImplementedException.php +++ b/Exceptions/MethodNotImplementedException.php @@ -28,7 +28,7 @@ * * @SuppressWarnings("PHPMD.StaticAccess") */ -class MethodNotImplementedException extends \Exception { +class MethodNotImplementedException extends DoctrineRestDriverException { /** * InvalidSqlOperationException constructor diff --git a/Exceptions/RequestFailedException.php b/Exceptions/RequestFailedException.php index d6fcb2a..bb19fc8 100644 --- a/Exceptions/RequestFailedException.php +++ b/Exceptions/RequestFailedException.php @@ -29,7 +29,7 @@ * * @SuppressWarnings("PHPMD.StaticAccess") */ -class RequestFailedException extends \Exception { +class RequestFailedException extends DoctrineRestDriverException { /** * RequestFailedException constructor diff --git a/Exceptions/UnsupportedFetchModeException.php b/Exceptions/UnsupportedFetchModeException.php index 8972254..18e39ff 100644 --- a/Exceptions/UnsupportedFetchModeException.php +++ b/Exceptions/UnsupportedFetchModeException.php @@ -27,7 +27,7 @@ * * @SuppressWarnings("PHPMD.StaticAccess") */ -class UnsupportedFetchModeException extends \Exception { +class UnsupportedFetchModeException extends DoctrineRestDriverException { /** * UnsupportedFetchMode constructor diff --git a/Tests/Transformers/MysqlToRequestTest.php b/Tests/Transformers/MysqlToRequestTest.php index a25f4ca..585b829 100644 --- a/Tests/Transformers/MysqlToRequestTest.php +++ b/Tests/Transformers/MysqlToRequestTest.php @@ -181,11 +181,11 @@ public function selectJoined() { public function insert() { $query = 'INSERT INTO products (name) VALUES ("myName")'; $expected = new Request([ - 'method' => 'post', - 'url' => $this->apiUrl . '/products', - 'curlOptions' => $this->options, - 'payload' => json_encode(['name' => 'myName']), - 'expectedStatusCode' => 201 + 'method' => 'post', + 'url' => $this->apiUrl . '/products', + 'curlOptions' => $this->options, + 'payload' => json_encode(['name' => 'myName']), + 'expectedStatusCode' => 201 ]); $this->assertEquals($expected, $this->mysqlToRequest->transform($query)); From b4fa00a77f2b96399d67448dc7d519604bbf0eaf Mon Sep 17 00:00:00 2001 From: TobiasHauck Date: Thu, 11 Aug 2016 12:29:20 +0200 Subject: [PATCH 15/15] fixed suggestions --- Tests/Types/PayloadTest.php | 14 ++++++++++++++ Types/Payload.php | 6 ++++-- Types/Request.php | 2 +- 3 files changed, 19 insertions(+), 3 deletions(-) diff --git a/Tests/Types/PayloadTest.php b/Tests/Types/PayloadTest.php index cbfc754..67834e9 100644 --- a/Tests/Types/PayloadTest.php +++ b/Tests/Types/PayloadTest.php @@ -66,4 +66,18 @@ public function createUpdate() { $this->assertSame($expected, Payload::create($tokens, [])); } + + /** + * @test + * @group unit + * @covers ::create + * + * @SuppressWarnings("PHPMD.StaticAccess") + */ + public function createSelect() { + $parser = new PHPSQLParser(); + $tokens = $parser->parse('SELECT name FROM products WHERE id=1'); + + $this->assertSame(null, Payload::create($tokens, [])); + } } \ No newline at end of file diff --git a/Types/Payload.php b/Types/Payload.php index 7600faf..09eb91c 100644 --- a/Types/Payload.php +++ b/Types/Payload.php @@ -44,7 +44,9 @@ public static function create(array $tokens, array $options) { $format = Format::create($options); $operation = SqlOperation::create($tokens); - if ($operation === SqlOperations::SELECT || $operation === SqlOperations::DELETE) return null; - return $format->encode($operation === SqlOperations::INSERT ? InsertChangeSet::create($tokens) : UpdateChangeSet::create($tokens)); + if ($operation === SqlOperations::INSERT) return $format->encode(InsertChangeSet::create($tokens)); + if ($operation === SqlOperations::UPDATE) return $format->encode(UpdateChangeSet::create($tokens)); + + return null; } } \ No newline at end of file diff --git a/Types/Request.php b/Types/Request.php index 8b484f0..1772218 100644 --- a/Types/Request.php +++ b/Types/Request.php @@ -68,7 +68,7 @@ public function __construct(array $options) { HashMapEntry::assertExists($options, 'method', 'options.method'); HashMapEntry::assertExists($options, 'url', 'options.url'); - foreach ($options as $key => $value) $this->$key = $value; + foreach($options as $key => $value) $this->$key = $value; } /**