From 5d27482a3e3e331b58ed1b6480e8db498cd61cb7 Mon Sep 17 00:00:00 2001 From: Xenofon Spafaridis Date: Tue, 25 Oct 2016 14:59:34 +0200 Subject: [PATCH] Test promise solution for #45 Use callable to return the ResourceModel instead of using resource model as argument at Relationship constructor Fixes #45 --- src/Directive/FilterAttribute.php | 2 +- src/Relationship.php | 20 ++++--- src/Resource.php | 3 +- tests/APP/Models/A.php | 56 +++++++++++++++++++ tests/APP/Models/Article.php | 71 ++++++++++++++++++++++++ tests/APP/Models/Tag.php | 22 +++++++- tests/APP/Models/User.php | 12 +++- tests/bootstrap.php | 24 +++++++- tests/src/Directive/FilterTest.php | 67 +++++++++++----------- tests/src/RelationshipDependencyTest.php | 40 +++++++++++++ tests/src/RelationshipTest.php | 66 ++++++++++++++++------ 11 files changed, 320 insertions(+), 63 deletions(-) create mode 100644 tests/APP/Models/A.php create mode 100644 tests/APP/Models/Article.php create mode 100644 tests/src/RelationshipDependencyTest.php diff --git a/src/Directive/FilterAttribute.php b/src/Directive/FilterAttribute.php index de94d7a..48e849a 100644 --- a/src/Directive/FilterAttribute.php +++ b/src/Directive/FilterAttribute.php @@ -118,7 +118,7 @@ public static function parse($filterKey, $filterValue) } //@todo is this required? - $singleFilterValue = urldecode($singleFilterValue); + $singleFilterValue = urldecode((string) $singleFilterValue); list($operator, $operand) = Operator::parse($singleFilterValue); diff --git a/src/Relationship.php b/src/Relationship.php index 769e40a..5da1e89 100644 --- a/src/Relationship.php +++ b/src/Relationship.php @@ -48,11 +48,6 @@ class Relationship */ const TYPE_TO_MANY = 2; - /** - * @var ResourceModel - */ - protected $resourceModel; - /** * The type of relationship from the resource to relationship resource * @var int @@ -77,6 +72,8 @@ class Relationship */ protected $flags; + protected $modelPromise; + /** * @param ResourceModel $model Class path of relationship resource resourceModel * @param int $type *[Optional] Relationship type @@ -103,7 +100,7 @@ class Relationship * ``` */ public function __construct( - ResourceModel $model, + callable $modelPromise, int $type = Relationship::TYPE_TO_ONE, string $recordDataAttribute = null, \stdClass $callbacks = null, @@ -131,7 +128,7 @@ public function __construct( $this->callbacks = $callbacks; } - $this->resourceModel = $model; + $this->modelPromise = $modelPromise; $this->type = $type; $this->recordDataAttribute = $recordDataAttribute; $this->flags = $flags; @@ -142,7 +139,14 @@ public function __construct( */ public function getResourceModel() { - return $this->resourceModel; + $promise = $this->getModelPromise(); + + return $promise(); + } + + public function getModelPromise() : callable + { + return $this->modelPromise; } /** diff --git a/src/Resource.php b/src/Resource.php index 73b39a1..6555499 100644 --- a/src/Resource.php +++ b/src/Resource.php @@ -221,6 +221,7 @@ public static function parseFromRecords( * ); * ``` * @todo what about getRelationshipData method ? + * @todo restore links */ public static function parseFromRecord( \stdClass $record, @@ -238,7 +239,6 @@ public static function parseFromRecord( $flagRelationshipLinks = ($flags & Resource::PARSE_RELATIONSHIP_LINKS) != 0; $flagRelationshipData = ($flags & Resource::PARSE_RELATIONSHIP_DATA) != 0; - $idAttribute = $model->getIdAttribute(); if (!isset($record->{$idAttribute})) { @@ -328,6 +328,7 @@ public static function parseFromRecord( * @var ResourceModel */ $relationshipModel = $relationshipObject->getResourceModel(); + $relationshipType = $relationshipObject->getType(); $recordDataAttribute = $relationshipObject->getRecordDataAttribute(); diff --git a/tests/APP/Models/A.php b/tests/APP/Models/A.php new file mode 100644 index 0000000..519ef0f --- /dev/null +++ b/tests/APP/Models/A.php @@ -0,0 +1,56 @@ + + */ +class A extends Model +{ + use ModelTrait; + + /** + * @inheritDoc + */ + protected static function defineModel() : ResourceModel + { + $model = (new ResourceModel('A', new MemoryDataSource())) + ->addVariable('table', 'user') + ->setRelationships((object) [ + 'A' => new Relationship( + function () + { + return A::getResourceModel(); + }, + Relationship::TYPE_TO_ONE, + 'referrer-user_id' + ) + ]); + + return $model; + } +} diff --git a/tests/APP/Models/Article.php b/tests/APP/Models/Article.php new file mode 100644 index 0000000..3169961 --- /dev/null +++ b/tests/APP/Models/Article.php @@ -0,0 +1,71 @@ + + */ +class Article extends Model +{ + use ModelTrait; + + protected static function defineModel() : ResourceModel + { + return (new ResourceModel('article', new MemoryDataSource())) + ->addVariable('table', 'article') + ->setRelationships( + (object) [ + 'author' => new Relationship( + function () { + return User::getResourceModel(); + }, + Relationship::TYPE_TO_ONE, + 'creator-user_id' + ), + 'tag' => new Relationship( + function () { + return Tag::getResourceModel(); + }, + Relationship::TYPE_TO_MANY, + null,//'tag_id' + (object) [ + /** + * @param string $articleId + * @return string[] + */ + 'GET' => function (string $articleId) { + $ids = []; + return $ids; + } + ] + ) + ] + ); + } +} +{ + +} diff --git a/tests/APP/Models/Tag.php b/tests/APP/Models/Tag.php index 7c16b01..921f3df 100644 --- a/tests/APP/Models/Tag.php +++ b/tests/APP/Models/Tag.php @@ -19,6 +19,7 @@ use Phramework\JSONAPI\APP\DataSource\MemoryDataSource; use Phramework\JSONAPI\Directive\Directive; +use Phramework\JSONAPI\Relationship; use Phramework\JSONAPI\ResourceModel; use Phramework\JSONAPI\Model; use Phramework\JSONAPI\ModelTrait; @@ -38,7 +39,26 @@ class Tag extends Model protected static function defineModel() : ResourceModel { $model = (new ResourceModel('tag', new MemoryDataSource())) - ->addVariable('table', 'tag'); + ->addVariable('table', 'tag') + ->setRelationships((object) [ + 'article' => new Relationship( + function () { + return Article::getResourceModel(); + }, + Relationship::TYPE_TO_MANY, + null, + (object) [ + /** + * @param string $tagId + * @return string[] + */ + 'GET' => function (string $tagId) { + $ids = []; + return $ids; + } + ] + ) + ]); return $model; } diff --git a/tests/APP/Models/User.php b/tests/APP/Models/User.php index 7b09adb..d90a715 100644 --- a/tests/APP/Models/User.php +++ b/tests/APP/Models/User.php @@ -45,17 +45,23 @@ protected static function defineModel() : ResourceModel ) ->setRelationships((object) [ 'group' => new Relationship( - Group::getResourceModel(), + function () { + return Group::getResourceModel(); + }, Relationship::TYPE_TO_ONE, 'group_id' ), 'tag' => new Relationship( - Tag::getResourceModel(), + function () { + return Tag::getResourceModel(); + }, Relationship::TYPE_TO_MANY, 'tag_id' ), 'company' => new Relationship( - Company::getResourceModel(), + function () { + return Company::getResourceModel(); + }, Relationship::TYPE_TO_MANY, null, (object) [ diff --git a/tests/bootstrap.php b/tests/bootstrap.php index add71ad..3a08fc9 100644 --- a/tests/bootstrap.php +++ b/tests/bootstrap.php @@ -87,6 +87,24 @@ ] ); +/** + * company + */ + +MemoryDataSource::addTable('article'); + +MemoryDataSource::insert( + 'article', + (object) [ + 'id' => '1', + 'title' => 'Hello world', + 'body' => 'Lorem ipsum', + 'creator-user_id' => '1', + 'tag_id' => ['1', '2'] + ] +); + + /** * user */ @@ -100,7 +118,8 @@ 'username' => 'nohponex', 'email' => 'nohponex@gmail.com', 'group_id' => '1', - 'tag_id' => ['1', '2'] + 'tag_id' => ['1', '2'], + 'referrer-user_id' => '1' ] ); @@ -111,7 +130,8 @@ 'username' => 'nohponex2', 'email' => 'nohponex+2@gmail.com', 'group_id' => '2', - 'tag_id' => [] + 'tag_id' => [], + 'referrer-user_id' => '2' ] ); diff --git a/tests/src/Directive/FilterTest.php b/tests/src/Directive/FilterTest.php index 451bb04..78799e5 100644 --- a/tests/src/Directive/FilterTest.php +++ b/tests/src/Directive/FilterTest.php @@ -52,7 +52,7 @@ public function setUp() new ObjectValidator() ))->setFilterValidator(new ObjectValidator((object) [ 'id' => new UnsignedIntegerValidator(0, 10), - 'meta' => new ObjectValidator((object) [ + 'meta' => new ObjectValidator((object) [ 'timestamp' => new UnsignedIntegerValidator(), 'keywords' => new StringValidator() ]), @@ -76,26 +76,31 @@ public function setUp() | Operator::CLASS_NULLABLE, ])->setRelationships((object) [ 'creator' => new Relationship( - (new ResourceModel('user')) - ->setValidationModel(new ValidationModel( - new ObjectValidator( - ) - )), + function () { + return (new ResourceModel('user')) + ->setValidationModel(new ValidationModel( + new ObjectValidator() + )); + }, Relationship::TYPE_TO_ONE, 'creator-user_id' ), - 'tag' => new Relationship( - (new ResourceModel('tag')) - ->setValidationModel(new ValidationModel( - new ObjectValidator( - ) - )), + 'tag' => new Relationship( + function () { + return (new ResourceModel('tag')) + ->setValidationModel(new ValidationModel( + new ObjectValidator() + )); + }, Relationship::TYPE_TO_MANY, null, (object) [ - 'GET' => function () {}, - 'POST' => function () {}, - 'PATCH' => function () {} + 'GET' => function () { + }, + 'POST' => function () { + }, + 'PATCH' => function () { + } ] ) ]); @@ -228,15 +233,15 @@ public function testParseFromRequest() $filter = Filter::parseFromRequest( $this->request->withQueryParams([ 'filter' => [ - 'article' => '1, 2', - 'tag' => '4, 5, 7', - 'creator' => '1', - 'status' => [true, false], - 'title' => [ + 'article' => '1, 2', + 'tag' => '4, 5, 7', + 'creator' => '1', + 'status' => [true, false], + 'title' => [ Operator::LIKE . 'blog', Operator::NOT_LIKE . 'welcome' ], - 'updated' => Operator::NOT_ISNULL, + 'updated' => Operator::NOT_ISNULL, 'meta.keywords' => 'blog' ] ]), @@ -325,7 +330,7 @@ public function testParseFromRequestFailurePrimaryNotString() Filter::parseFromRequest( $this->request->withQueryParams([ 'filter' => [ - 'article' => [1, 2] + 'article' => [1, 2] ] ]), $this->articleModel @@ -358,7 +363,7 @@ public function testParseFromRequestFailureRelationshipNotString() Filter::parseFromRequest( $this->request->withQueryParams([ 'filter' => [ - 'tag' => [1, 2] + 'tag' => [1, 2] ] ]), $this->articleModel @@ -374,7 +379,7 @@ public function testParseFromRequestFailureNotAllowedAttribute() Filter::parseFromRequest( $this->request->withQueryParams([ 'filter' => [ - 'not-found' => 1 + 'not-found' => 1 ] ]), $this->articleModel @@ -390,7 +395,7 @@ public function testParseFromRequestFailureAttributeWithoutValidator() Filter::parseFromRequest( $this->request->withQueryParams([ 'filter' => [ - 'no-validator' => 1 + 'no-validator' => 1 ] ]), $this->articleModel @@ -406,7 +411,7 @@ public function testParseFromRequestFailureAttributeIsArray() Filter::parseFromRequest( $this->request->withQueryParams([ 'filter' => [ - 'updated' => [[Operator::ISNULL]] + 'updated' => [[Operator::ISNULL]] ] ]), $this->articleModel @@ -422,7 +427,7 @@ public function testParseFromRequestFailureAttributeToParse() Filter::parseFromRequest( $this->request->withQueryParams([ 'filter' => [ - 'updated' => 'qwerty' + 'updated' => 'qwerty' ] ]), $this->articleModel @@ -438,7 +443,7 @@ public function testParseFromRequestFailureAttributeNotAllowedOperator() Filter::parseFromRequest( $this->request->withQueryParams([ 'filter' => [ - 'status' => Operator::GREATER_EQUAL . '1' + 'status' => Operator::GREATER_EQUAL . '1' ] ]), $this->articleModel @@ -454,7 +459,7 @@ public function testParseFromRequestFailureAttributeNotAcceptingJSONOperator() Filter::parseFromRequest( $this->request->withQueryParams([ 'filter' => [ - 'status.ok' => true + 'status.ok' => true ] ]), $this->articleModel @@ -470,7 +475,7 @@ public function testParseFromRequestFailureAttributeUsingJSONPropertyValidator() $filter = Filter::parseFromRequest( $this->request->withQueryParams([ 'filter' => [ - 'meta.timestamp' => 'xsadas' + 'meta.timestamp' => 'xsadas' ] ]), $this->articleModel @@ -488,7 +493,7 @@ public function testParseFromRequestFailureAttributeJSONSecondLevel() $filter = Filter::parseFromRequest( $this->request->withQueryParams([ 'filter' => [ - 'meta.timestamp.time' => 123456789 + 'meta.timestamp.time' => 123456789 ] ]), $this->articleModel diff --git a/tests/src/RelationshipDependencyTest.php b/tests/src/RelationshipDependencyTest.php new file mode 100644 index 0000000..cfaf005 --- /dev/null +++ b/tests/src/RelationshipDependencyTest.php @@ -0,0 +1,40 @@ + + * @coversDefaultClass \Phramework\JSONAPI\Relationship + */ +class RelationshipDependencyTest extends \PHPUnit_Framework_TestCase +{ + /** + * @covers ::getFlags + */ + public function testGetFlags() + { + $g = A::get(); + + $article = Article::get(); + } +} diff --git a/tests/src/RelationshipTest.php b/tests/src/RelationshipTest.php index 877bb97..775683e 100644 --- a/tests/src/RelationshipTest.php +++ b/tests/src/RelationshipTest.php @@ -29,7 +29,7 @@ class RelationshipTest extends \PHPUnit_Framework_TestCase /** * @var $model */ - protected $model; + protected $model; /** * @var Relationship @@ -38,10 +38,12 @@ class RelationshipTest extends \PHPUnit_Framework_TestCase public function setUp() { - $this->model = new ResourceModel('user'); + $this->model = $model = new ResourceModel('user'); $this->relationship = new Relationship( - $this->model + function () use ($model) { + return $model; + } ); } @@ -50,8 +52,12 @@ public function setUp() */ public function testConstruct() { + $model = $this->model; + new Relationship( - $this->model, + function () use ($model) { + return $model; + }, Relationship::TYPE_TO_ONE, 'tag-id' ); @@ -62,18 +68,24 @@ public function testConstruct() */ public function testConstruct3() { + $model = $this->model; + $relationship = new Relationship( - $this->model, + function () use ($model) { + return $model; + }, Relationship::TYPE_TO_ONE, 'tag-id', (object) [ - 'GET' => function () {} + 'GET' => function () { + } ] ); $this->assertEquals( (object) [ - 'GET' => function () {} + 'GET' => function () { + } ], $relationship->getCallbacks() ); @@ -85,8 +97,12 @@ public function testConstruct3() */ public function testConstructFailure2() { + $model = $this->model; + new Relationship( - $this->model, + function () use ($model) { + return $model; + }, Relationship::TYPE_TO_ONE, null, (object) ['inv'] //Not callable @@ -99,11 +115,16 @@ public function testConstructFailure2() */ public function testConstructFailureCallbackMethodUnset() { + $model = $this->model; + new Relationship( - $this->model, + function () use ($model) { + return $model; + }, Relationship::TYPE_TO_ONE, null, - (object) [function() {}] //Not callable + (object) [function () { + }] //Not callable ); } @@ -113,8 +134,12 @@ public function testConstructFailureCallbackMethodUnset() */ public function testConstructFailureInvalidCallbackMethod() { + $model = $this->model; + new Relationship( - $this->model, + function () use ($model) { + return $model; + }, Relationship::TYPE_TO_ONE, null, (object) [ @@ -132,8 +157,12 @@ public function testConstructFailureInvalidCallbackMethod() */ public function testConstructFailureInvalidMethodNotCallable() { + $model = $this->model; + new Relationship( - $this->model, + function () use ($model) { + return $model; + }, Relationship::TYPE_TO_ONE, null, (object) [ @@ -167,7 +196,9 @@ public function testGetType() ); $relationship = new Relationship( - User::getResourceModel(), + function () { + return User::getResourceModel(); + }, Relationship::TYPE_TO_MANY, 'group_id' ); @@ -189,7 +220,9 @@ public function testGetRecordDataAttribute() ); $relationship = new Relationship( - User::getResourceModel(), + function () { + return User::getResourceModel(); + }, Relationship::TYPE_TO_MANY, 'group_id' ); @@ -211,12 +244,13 @@ public function testGetCallbacks() ); $relationship = new Relationship( - User::getResourceModel(), + function () { + return User::getResourceModel(); + }, Relationship::TYPE_TO_MANY, null, (object) [ 'GET' => function () { - } ] );