From fe5feb4eb771e556b8efeac4a0b7fe7ab52abceb Mon Sep 17 00:00:00 2001 From: Mohammad Alavi Date: Fri, 6 Dec 2024 17:44:18 +0330 Subject: [PATCH 1/2] fix: empty param bag --- src/Fractal.php | 2 +- tests/ScopeTest.php | 52 +++++++++++++++++++++++++++++++++++++-------- 2 files changed, 44 insertions(+), 10 deletions(-) diff --git a/src/Fractal.php b/src/Fractal.php index e6393e2..4b8dda0 100644 --- a/src/Fractal.php +++ b/src/Fractal.php @@ -405,7 +405,7 @@ public function createData() $this->manager->parseFieldsets($this->fieldsets); } - return $this->manager->createData($this->getResource(), $this->resourceName); + return $this->manager->createData($this->getResource()); } /** diff --git a/tests/ScopeTest.php b/tests/ScopeTest.php index 6cba108..babf89c 100644 --- a/tests/ScopeTest.php +++ b/tests/ScopeTest.php @@ -1,13 +1,47 @@ fractal - ->collection($this->testBooks, new TestTransformer(), 'books') - ->parseIncludes('characters') - ->createData(); +it('can parse include parameters', function ($resourceName, string $include, string $includeWithParams, ParamBag $expected): void { + $fractal = Fractal::create(getTestPublishers(), new PublisherTransformer()) + ->withResourceName($resourceName) + ->parseIncludes($includeWithParams); - assertEquals('books', $scope->getIdentifier()); -}); + $scope = $fractal->createData(); + + $identifier = $scope->getIdentifier($include); + $actualParams = $scope->getManager()->getIncludeParams($identifier); + expect($actualParams)->toEqual($expected); +})->with([ + [ + 'resource name: string' => 'Publisher', + ], + [ + 'resource name: null' => null, + ], +])->with([ + [ + 'include' => 'books', + 'include_with_params' => 'books:test(2|value)', + 'expected' => new ParamBag([ + 'test' => ['2', 'value'], + ]), + ], + [ + 'include' => 'books', + 'include_with_params' => 'books:test(another_value|3):another(1|2|3)', + 'expected' => new ParamBag([ + 'test' => ['another_value', '3'], + 'another' => ['1', '2', '3'], + ]), + ], + [ + 'include' => 'books.author', + 'include_with_params' => 'books.author:test(test|value)', + 'expected' => new ParamBag([ + 'test' => ['test', 'value'], + ]), + ], +]); From 2cea8a6404fcfc469aa9738f01711c2a9a071a56 Mon Sep 17 00:00:00 2001 From: Mohammad Alavi Date: Fri, 6 Dec 2024 18:15:54 +0330 Subject: [PATCH 2/2] test: access scope in transformer this test demonstrates that scopes can be accessed in the transformers --- tests/Pest.php | 14 +++ tests/ScopeTest.php | 121 +++++++++++++++++++++ tests/TestClasses/Author.php | 7 ++ tests/TestClasses/AuthorTransformer.php | 6 + tests/TestClasses/Book.php | 10 ++ tests/TestClasses/BookTransformer.php | 7 ++ tests/TestClasses/Character.php | 19 ++++ tests/TestClasses/CharacterTransformer.php | 40 +++++++ 8 files changed, 224 insertions(+) create mode 100644 tests/TestClasses/Character.php create mode 100644 tests/TestClasses/CharacterTransformer.php diff --git a/tests/Pest.php b/tests/Pest.php index 5a31aa1..2279fe8 100644 --- a/tests/Pest.php +++ b/tests/Pest.php @@ -9,6 +9,7 @@ use Spatie\Fractalistic\Fractal; use Spatie\Fractalistic\Test\TestClasses\Author; use Spatie\Fractalistic\Test\TestClasses\Book; +use Spatie\Fractalistic\Test\TestClasses\Character; use Spatie\Fractalistic\Test\TestClasses\Publisher; uses() @@ -56,6 +57,11 @@ function getTestPublishers(): array $authorA = new Author('Philip K Dick', 'philip@example.org'); $authorB = new Author('George R. R. Satan', 'george@example.org'); + $charA = new Character('Death'); + $charB = new Character('Hex'); + $charC = new Character('Ned Stark'); + $charD = new Character('Tywin Lannister'); + $bookA = new Book( '1', 'Hogfather', @@ -78,11 +84,19 @@ function getTestPublishers(): array $bookA->author = $authorA; $bookA->publisher = $publisherA; + $bookA->characters = [$charA, $charB]; + $authorA->characters = [$charA, $charB]; + $charA->book = $bookA; + $charB->book = $bookA; $publisherA->books = [$bookA]; $authorA->books = [$bookA]; $bookB->author = $authorB; $bookB->publisher = $publisherB; + $bookB->characters = [$charC, $charD]; + $authorB->characters = [$charC, $charD]; + $charC->book = $bookB; + $charD->book = $bookB; $publisherB->books = [$bookB]; $authorB->books = [$bookB]; diff --git a/tests/ScopeTest.php b/tests/ScopeTest.php index babf89c..ebf6a89 100644 --- a/tests/ScopeTest.php +++ b/tests/ScopeTest.php @@ -45,3 +45,124 @@ ]), ], ]); + +it('can access scope in transformer', function (): void { + $fractal = Fractal::create(getTestPublishers(), new PublisherTransformer()) + ->parseIncludes('books.characters,books.author.characters'); + + $result = $fractal->toArray(); + + expect($result)->toEqual([ + 'data' => [ + [ + 'name' => 'Elephant books', + 'address' => 'Amazon rainforests, near the river', + 'books' => + [ + 'data' => [ + [ + 'id' => 1, + 'title' => 'Hogfather', + 'characters' => [ + 'data' => [ + [ + 'name' => 'Death', + 'current_scope' => 'characters', + 'parent_scope' => 'books', + 'scope_identifier' => 'books.characters', + 'called_by_book' => 'yes!', + ], + [ + 'name' => 'Hex', + 'current_scope' => 'characters', + 'parent_scope' => 'books', + 'scope_identifier' => 'books.characters', + 'called_by_book' => 'yes!', + ], + ] + ], + 'author' => [ + 'data' => [ + 'name' => 'Philip K Dick', + 'email' => 'philip@example.org', + 'characters' => [ + 'data' => [ + [ + 'name' => 'Death', + 'current_scope' => 'characters', + 'parent_scope' => 'author', + 'scope_identifier' => 'books.author.characters', + 'called_by_author' => 'indeed!', + ], + [ + 'name' => 'Hex', + 'current_scope' => 'characters', + 'parent_scope' => 'author', + 'scope_identifier' => 'books.author.characters', + 'called_by_author' => 'indeed!', + ], + ] + ], + ] + ], + ], + ], + ], + ], + [ + 'name' => 'Bloody Fantasy inc.', + 'address' => 'Diagon Alley, before the bank, to the left', + 'books' => [ + 'data' => [ + [ + 'id' => 2, + 'title' => 'Game Of Kill Everyone', + 'characters' => [ + 'data' => [ + [ + 'name' => 'Ned Stark', + 'current_scope' => 'characters', + 'parent_scope' => 'books', + 'scope_identifier' => 'books.characters', + 'called_by_book' => 'yes!', + ], + [ + 'name' => 'Tywin Lannister', + 'current_scope' => 'characters', + 'parent_scope' => 'books', + 'scope_identifier' => 'books.characters', + 'called_by_book' => 'yes!', + ], + ] + ], + 'author' => [ + 'data' => [ + 'name' => 'George R. R. Satan', + 'email' => 'george@example.org', + 'characters' => [ + 'data' => [ + [ + 'name' => 'Ned Stark', + 'current_scope' => 'characters', + 'parent_scope' => 'author', + 'scope_identifier' => 'books.author.characters', + 'called_by_author' => 'indeed!', + ], + [ + 'name' => 'Tywin Lannister', + 'current_scope' => 'characters', + 'parent_scope' => 'author', + 'scope_identifier' => 'books.author.characters', + 'called_by_author' => 'indeed!', + ], + ] + ], + ], + ] + ], + ], + ], + ], + ], + ]); +}); diff --git a/tests/TestClasses/Author.php b/tests/TestClasses/Author.php index bcdadd1..c78eb42 100644 --- a/tests/TestClasses/Author.php +++ b/tests/TestClasses/Author.php @@ -8,6 +8,8 @@ class Author public string $email; /** @var Book[] */ public ?array $books = []; + /** @var Character[] */ + public array $characters = []; public function __construct(string $name, string $email) { @@ -19,4 +21,9 @@ public function books(): array { return $this->books; } + + public function characters(): array + { + return $this->characters; + } } diff --git a/tests/TestClasses/AuthorTransformer.php b/tests/TestClasses/AuthorTransformer.php index d4379c4..5065a9a 100644 --- a/tests/TestClasses/AuthorTransformer.php +++ b/tests/TestClasses/AuthorTransformer.php @@ -9,6 +9,7 @@ class AuthorTransformer extends TransformerAbstract { protected array $availableIncludes = [ 'books', + 'characters' ]; public function transform(Author $author): array @@ -23,4 +24,9 @@ public function includeBooks(Author $author): Collection { return $this->collection($author->books(), new BookTransformer()); } + + public function includeCharacters(Author $author): Collection + { + return $this->collection($author->characters(), new CharacterTransformer()); + } } diff --git a/tests/TestClasses/Book.php b/tests/TestClasses/Book.php index 8473e21..ab6b340 100644 --- a/tests/TestClasses/Book.php +++ b/tests/TestClasses/Book.php @@ -7,6 +7,8 @@ class Book public string $id; public string $title; public string $yr; + /** @var Character[] */ + public array $characters = []; public ?Publisher $publisher = null; public ?Author $author = null; @@ -25,6 +27,14 @@ public function publisher(): ?Publisher return $this->publisher; } + /** + * @return Character[] + */ + public function characters(): array + { + return $this->characters; + } + public function author(): ?Author { return $this->author; diff --git a/tests/TestClasses/BookTransformer.php b/tests/TestClasses/BookTransformer.php index 754ee6c..81846f5 100644 --- a/tests/TestClasses/BookTransformer.php +++ b/tests/TestClasses/BookTransformer.php @@ -2,6 +2,7 @@ namespace Spatie\Fractalistic\Test\TestClasses; +use League\Fractal\Resource\Collection; use League\Fractal\Resource\Item; use League\Fractal\TransformerAbstract; @@ -9,6 +10,7 @@ class BookTransformer extends TransformerAbstract { protected array $availableIncludes = [ 'publisher', + 'characters', 'author', ]; @@ -25,6 +27,11 @@ public function includePublisher(Book $book): Item return $this->item($book->publisher(), new PublisherTransformer()); } + public function includeCharacters(Book $book): Collection + { + return $this->collection($book->characters(), new CharacterTransformer()); + } + public function includeAuthor(Book $book): Item { return $this->item($book->author(), new AuthorTransformer()); diff --git a/tests/TestClasses/Character.php b/tests/TestClasses/Character.php new file mode 100644 index 0000000..905fe0e --- /dev/null +++ b/tests/TestClasses/Character.php @@ -0,0 +1,19 @@ +name = $name; + } + + public function book(): ?Book + { + return $this->book; + } +} diff --git a/tests/TestClasses/CharacterTransformer.php b/tests/TestClasses/CharacterTransformer.php new file mode 100644 index 0000000..df0a9aa --- /dev/null +++ b/tests/TestClasses/CharacterTransformer.php @@ -0,0 +1,40 @@ +getCurrentScope()->getParentScopes()); + $data = [ + 'name' => $character->name, + 'current_scope' => $this->getCurrentScope()->getScopeIdentifier(), + 'parent_scope' => $parentScope, + 'scope_identifier' => $this->getCurrentScope()->getIdentifier(), + ]; + + if ($parentScope === 'author') { + $data['called_by_author'] = 'indeed!'; + } + + if ($parentScope === 'books') { + $data['called_by_book'] = 'yes!'; + } + + return $data; + } + + public function includeBook(Character $character): Item + { + return $this->item($character->book(), new BookTransformer()); + } +}