From 1e98f8db05114b72ba8139bb2687baecc402ca4c Mon Sep 17 00:00:00 2001 From: Nathanael Esayeas Date: Thu, 8 Jun 2023 10:17:39 -0500 Subject: [PATCH 01/37] Update HalResourceTest.php Signed-off-by: Nathanael Esayeas --- test/HalResourceTest.php | 71 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 71 insertions(+) diff --git a/test/HalResourceTest.php b/test/HalResourceTest.php index de4c53f..6e0dedd 100644 --- a/test/HalResourceTest.php +++ b/test/HalResourceTest.php @@ -11,6 +11,8 @@ use RuntimeException; use function array_values; +use function file_get_contents; +use function json_decode; class HalResourceTest extends TestCase { @@ -636,4 +638,73 @@ public function testAllowsForcingLinkToAggregateAsACollection(): void $this->assertEquals($expected, $resource->toArray()); } + + private function fixture(string $file): array + { + $contents = file_get_contents(__DIR__ . '/Fixture/' . $file); + + if ($contents === false) { + throw new RuntimeException('Failed to read fixture file: ' . $file); + } + + return json_decode($contents, true); + } + + public static function nonEmptyCollectionDataProvider(): iterable + { + yield from [ + 'collection' => [ + [ + (new HalResource())->withElements([ + 'id' => 1, + 'name' => 'John', + 'email' => 'john@example.com', + ]), + (new HalResource())->withElements([ + 'id' => 2, + 'name' => 'Jane', + 'email' => 'jane@example.com', + ]), + ], + ], + ]; + } + + public static function emptyCollectionDataProvider(): iterable + { + yield from [ + 'null' => [null], + 'array' => [[]], + ]; + } + + /** + * @dataProvider emptyCollectionDataProvider + */ + public function testEmptyCollection(mixed $collection): void + { + $resource = (new HalResource()) + ->withLink(new Link('self', '/api/contacts')) + ->withElements(['contacts' => $collection]); + + self::assertSame( + $this->fixture('empty-contacts-collection.json'), + $resource->toArray() + ); + } + + /** + * @dataProvider nonEmptyCollectionDataProvider + */ + public function testNonEmptyCollection(mixed $collection): void + { + $resource = (new HalResource()) + ->withLink(new Link('self', '/api/contacts')) + ->withElements(['contacts' => $collection]); + + self::assertSame( + $this->fixture('non-empty-contacts-collection.json'), + $resource->toArray() + ); + } } From ec0ef25eddc35977b39cd7d205e6f2a1967ef948 Mon Sep 17 00:00:00 2001 From: Nathanael Esayeas Date: Thu, 8 Jun 2023 10:17:50 -0500 Subject: [PATCH 02/37] Create empty-contacts-collection.json Signed-off-by: Nathanael Esayeas --- test/Fixture/empty-contacts-collection.json | 10 ++++++++++ 1 file changed, 10 insertions(+) create mode 100644 test/Fixture/empty-contacts-collection.json diff --git a/test/Fixture/empty-contacts-collection.json b/test/Fixture/empty-contacts-collection.json new file mode 100644 index 0000000..51f4231 --- /dev/null +++ b/test/Fixture/empty-contacts-collection.json @@ -0,0 +1,10 @@ +{ + "_links": { + "self": { + "href": "/api/contacts" + } + }, + "_embedded": { + "contacts": [] + } +} From a664f13ec4f65884b559994dd68fae673ac40983 Mon Sep 17 00:00:00 2001 From: Nathanael Esayeas Date: Thu, 8 Jun 2023 10:19:56 -0500 Subject: [PATCH 03/37] Create non-empty-contacts-collection.json Signed-off-by: Nathanael Esayeas --- .../non-empty-contacts-collection.json | 21 +++++++++++++++++++ 1 file changed, 21 insertions(+) create mode 100644 test/Fixture/non-empty-contacts-collection.json diff --git a/test/Fixture/non-empty-contacts-collection.json b/test/Fixture/non-empty-contacts-collection.json new file mode 100644 index 0000000..9864e3b --- /dev/null +++ b/test/Fixture/non-empty-contacts-collection.json @@ -0,0 +1,21 @@ +{ + "_links": { + "self": { + "href": "/api/contacts" + } + }, + "_embedded": { + "contacts": [ + { + "id": 1, + "name": "John", + "email": "john@example.com" + }, + { + "id": 2, + "name": "Jane", + "email": "jane@example.com" + } + ] + } +} From a77e5bcd6c50e26bbb8fb477add22a1a8d0eacc0 Mon Sep 17 00:00:00 2001 From: Nathanael Esayeas Date: Thu, 8 Jun 2023 10:20:19 -0500 Subject: [PATCH 04/37] Update HalResource.php Signed-off-by: Nathanael Esayeas --- src/HalResource.php | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/HalResource.php b/src/HalResource.php index 929a41e..89b0383 100644 --- a/src/HalResource.php +++ b/src/HalResource.php @@ -141,6 +141,10 @@ public function withElement(string $name, $value): HalResource { $this->validateElementName($name, __METHOD__); + if ($value === null || $value === []) { + return $this->embed($name, []); + } + if ( ! empty($value) && ($value instanceof self || $this->isResourceCollection($value)) From 39b7a356be286f89e84d85b730d7dab43d6b7c09 Mon Sep 17 00:00:00 2001 From: Nathanael Esayeas Date: Thu, 8 Jun 2023 10:21:52 -0500 Subject: [PATCH 05/37] Update HalResourceTest.php Signed-off-by: Nathanael Esayeas --- test/HalResourceTest.php | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/test/HalResourceTest.php b/test/HalResourceTest.php index 6e0dedd..5affc11 100644 --- a/test/HalResourceTest.php +++ b/test/HalResourceTest.php @@ -237,13 +237,22 @@ public function testWithElementProxiesToEmbedIfResourceCollectionValueProvided() $this->assertEquals(['foo' => $collection], $new->getElements()); } - public function testWithElementDoesNotProxyToEmbedIfAnEmptyArrayValueIsProvided(): void + public function testWithElementWillEmbedAnEmptyArrayIfAnEmptyArrayValueIsProvided(): void { $resource = new HalResource(['foo' => 'bar']); $new = $resource->withElement('bar', []); $representation = $new->toArray(); - $this->assertEquals(['foo' => 'bar', 'bar' => []], $representation); + self::assertSame(['foo' => 'bar', '_embedded' => ['bar' => []]], $representation); + } + + public function testWithElementWillEmbedAnEmptyArrayIfNullValueIsProvided(): void + { + $resource = new HalResource(['foo' => 'bar']); + $new = $resource->withElement('bar', null); + + $representation = $new->toArray(); + self::assertSame(['foo' => 'bar', '_embedded' => ['bar' => []]], $representation); } /** From aa29f66f740a34e070f8971168ad1c46648d3835 Mon Sep 17 00:00:00 2001 From: Nathanael Esayeas Date: Wed, 28 Jun 2023 17:02:18 -0500 Subject: [PATCH 06/37] Fix Psalm issue Signed-off-by: Nathanael Esayeas --- test/HalResourceTest.php | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/test/HalResourceTest.php b/test/HalResourceTest.php index 5affc11..69c1157 100644 --- a/test/HalResourceTest.php +++ b/test/HalResourceTest.php @@ -4,6 +4,7 @@ namespace MezzioTest\Hal; +use Generator; use InvalidArgumentException; use Mezzio\Hal\HalResource; use Mezzio\Hal\Link; @@ -659,7 +660,10 @@ private function fixture(string $file): array return json_decode($contents, true); } - public static function nonEmptyCollectionDataProvider(): iterable + /** + * @return Generator>> + */ + public static function nonEmptyCollectionDataProvider(): Generator { yield from [ 'collection' => [ @@ -679,7 +683,10 @@ public static function nonEmptyCollectionDataProvider(): iterable ]; } - public static function emptyCollectionDataProvider(): iterable + /** + * @return Generator<'array'|'null',list{array|null},mixed,void> + */ + public static function emptyCollectionDataProvider(): Generator { yield from [ 'null' => [null], From 588faf529d78722a83914f637e431eeb77160e32 Mon Sep 17 00:00:00 2001 From: Nathanael Esayeas Date: Wed, 28 Jun 2023 17:10:30 -0500 Subject: [PATCH 07/37] Guard against invalid json decoding Signed-off-by: Nathanael Esayeas --- test/HalResourceTest.php | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/test/HalResourceTest.php b/test/HalResourceTest.php index 69c1157..5f3e8ac 100644 --- a/test/HalResourceTest.php +++ b/test/HalResourceTest.php @@ -657,7 +657,12 @@ private function fixture(string $file): array throw new RuntimeException('Failed to read fixture file: ' . $file); } - return json_decode($contents, true); + $json = json_decode($contents, true); + if (!is_array($json)) { + throw new RuntimeException('Failed to json_decode fixture file: ' . $file); + } + + return $json; } /** From 3b01dbc8cc9be91b7941e5a4536fbd61e6979197 Mon Sep 17 00:00:00 2001 From: Nathanael Esayeas Date: Wed, 28 Jun 2023 17:12:43 -0500 Subject: [PATCH 08/37] Fix Phpcs issue Signed-off-by: Nathanael Esayeas --- test/HalResourceTest.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/test/HalResourceTest.php b/test/HalResourceTest.php index 5f3e8ac..2288e26 100644 --- a/test/HalResourceTest.php +++ b/test/HalResourceTest.php @@ -13,6 +13,7 @@ use function array_values; use function file_get_contents; +use function is_array; use function json_decode; class HalResourceTest extends TestCase @@ -658,7 +659,7 @@ private function fixture(string $file): array } $json = json_decode($contents, true); - if (!is_array($json)) { + if (! is_array($json)) { throw new RuntimeException('Failed to json_decode fixture file: ' . $file); } From 67fa194510fa52b1261b1926b5ba4219ca211d79 Mon Sep 17 00:00:00 2001 From: Nathanael Esayeas Date: Fri, 14 Jul 2023 18:31:00 -0500 Subject: [PATCH 09/37] Update ConfigProvider.php Signed-off-by: Nathanael Esayeas --- src/ConfigProvider.php | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/ConfigProvider.php b/src/ConfigProvider.php index 8eaeacc..f24e189 100644 --- a/src/ConfigProvider.php +++ b/src/ConfigProvider.php @@ -69,6 +69,13 @@ public function getDependencies(): array public function getHalConfig(): array { return [ + /** + * Whether or not to include empty collections within the _embedded section of the response, + * + * See: https://github.com/mezzio/mezzio-hal/pull/80 + */ + 'embed-empty-collections' => false, + 'resource-generator' => [ 'strategies' => [ // The registered strategies and their metadata types RouteBasedCollectionMetadata::class => RouteBasedCollectionStrategy::class, From 96327a452dc1f80c03961155463728d2a2d3e832 Mon Sep 17 00:00:00 2001 From: Nathanael Esayeas Date: Fri, 14 Jul 2023 18:33:19 -0500 Subject: [PATCH 10/37] Fix CS issue Signed-off-by: Nathanael Esayeas --- src/ConfigProvider.php | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/ConfigProvider.php b/src/ConfigProvider.php index f24e189..b0178fb 100644 --- a/src/ConfigProvider.php +++ b/src/ConfigProvider.php @@ -69,14 +69,13 @@ public function getDependencies(): array public function getHalConfig(): array { return [ - /** + /** * Whether or not to include empty collections within the _embedded section of the response, * * See: https://github.com/mezzio/mezzio-hal/pull/80 */ 'embed-empty-collections' => false, - - 'resource-generator' => [ + 'resource-generator' => [ 'strategies' => [ // The registered strategies and their metadata types RouteBasedCollectionMetadata::class => RouteBasedCollectionStrategy::class, RouteBasedResourceMetadata::class => RouteBasedResourceStrategy::class, @@ -84,7 +83,7 @@ public function getHalConfig(): array UrlBasedResourceMetadata::class => UrlBasedResourceStrategy::class, ], ], - 'metadata-factories' => [ // The factories for the metadata types + 'metadata-factories' => [ // The factories for the metadata types RouteBasedCollectionMetadata::class => RouteBasedCollectionMetadataFactory::class, RouteBasedResourceMetadata::class => RouteBasedResourceMetadataFactory::class, UrlBasedCollectionMetadata::class => UrlBasedCollectionMetadataFactory::class, From 88d9f067b2f2d3682dc43bad606efd9c438452a2 Mon Sep 17 00:00:00 2001 From: Nathanael Esayeas Date: Fri, 14 Jul 2023 18:39:09 -0500 Subject: [PATCH 11/37] Update HalResource.php Signed-off-by: Nathanael Esayeas --- src/HalResource.php | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/src/HalResource.php b/src/HalResource.php index 89b0383..2b88240 100644 --- a/src/HalResource.php +++ b/src/HalResource.php @@ -42,20 +42,21 @@ class HalResource implements EvolvableLinkProviderInterface, JsonSerializable /** @var array> */ private $embedded = []; + private bool $embedEmptyCollections; + /** * @param array $data * @param LinkInterface[] $links * @param HalResource[][] $embedded */ - public function __construct(array $data = [], array $links = [], array $embedded = []) + public function __construct(array $data = [], array $links = [], array $embedded = [], bool $embedEmptyCollections = false) { + $this->embedEmptyCollections = $embedEmptyCollections; + $context = self::class; array_walk($data, function ($value, $name) use ($context) { $this->validateElementName($name, $context); - if ( - ! empty($value) - && ($value instanceof self || $this->isResourceCollection($value)) - ) { + if ($value instanceof self || $this->isResourceCollection($value)) { $this->embedded[$name] = $value; return; } @@ -141,13 +142,8 @@ public function withElement(string $name, $value): HalResource { $this->validateElementName($name, __METHOD__); - if ($value === null || $value === []) { - return $this->embed($name, []); - } - if ( - ! empty($value) - && ($value instanceof self || $this->isResourceCollection($value)) + $value instanceof self || $this->isResourceCollection($value) ) { return $this->embed($name, $value); } @@ -399,6 +395,10 @@ private function isResourceCollection($value): bool return false; } + if ($this->embedEmptyCollections && $value === []) { + return true; + } + return array_reduce($value, static function ($isResource, $item) { return $isResource && $item instanceof self; }, true); From 2538c2bca336cdccd07fa11de2dfda19f097056a Mon Sep 17 00:00:00 2001 From: Nathanael Esayeas Date: Sat, 15 Jul 2023 05:43:15 -0500 Subject: [PATCH 12/37] Update ResourceGenerator.php Signed-off-by: Nathanael Esayeas --- src/ResourceGenerator.php | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/ResourceGenerator.php b/src/ResourceGenerator.php index e441b9a..3a1785d 100644 --- a/src/ResourceGenerator.php +++ b/src/ResourceGenerator.php @@ -94,7 +94,12 @@ public function getStrategies(): array public function fromArray(array $data, ?string $uri = null): HalResource { - $resource = new HalResource($data); + $embedEmptyCollections = + $this->hydrators->has('config') && + $this->hydrators->get('config')['mezzio-hal']['embed-empty-collections'] ?? + false; + + $resource = new HalResource($data, [], [], $embedEmptyCollections); if (null !== $uri) { return $resource->withLink(new Link('self', $uri)); From 78c2bf5983fe135e64b33c88dbf78e3d485f816e Mon Sep 17 00:00:00 2001 From: Nathanael Esayeas Date: Sat, 15 Jul 2023 05:43:19 -0500 Subject: [PATCH 13/37] Create null-contacts-collection.json Signed-off-by: Nathanael Esayeas --- test/Fixture/null-contacts-collection.json | 8 ++++++++ 1 file changed, 8 insertions(+) create mode 100644 test/Fixture/null-contacts-collection.json diff --git a/test/Fixture/null-contacts-collection.json b/test/Fixture/null-contacts-collection.json new file mode 100644 index 0000000..7768a7c --- /dev/null +++ b/test/Fixture/null-contacts-collection.json @@ -0,0 +1,8 @@ +{ + "contacts": null, + "_links": { + "self": { + "href": "/api/contacts" + } + } +} From f170e24615990ebf615c4f72f4a6b85a8106cc17 Mon Sep 17 00:00:00 2001 From: Nathanael Esayeas Date: Sat, 15 Jul 2023 05:46:31 -0500 Subject: [PATCH 14/37] Update ResourceGeneratorTest.php Signed-off-by: Nathanael Esayeas --- test/ResourceGeneratorTest.php | 3 +++ 1 file changed, 3 insertions(+) diff --git a/test/ResourceGeneratorTest.php b/test/ResourceGeneratorTest.php index b87e78a..65a284c 100644 --- a/test/ResourceGeneratorTest.php +++ b/test/ResourceGeneratorTest.php @@ -109,6 +109,9 @@ public function testCanGenerateResourceWithSelfLinkFromArrayData(): void 'foo' => 'bar', 'bar' => 'baz', ]; + + $this->hydrators->has('config')->willReturn(false); + $this->linkGenerator->fromRoute()->shouldNotBeCalled(); $this->metadataMap->has()->shouldNotBeCalled(); From b0f6d89e423f93b980e1e69c5cb41ad76332f8e5 Mon Sep 17 00:00:00 2001 From: Nathanael Esayeas Date: Sat, 15 Jul 2023 05:47:41 -0500 Subject: [PATCH 15/37] Update HalResourceTest.php Signed-off-by: Nathanael Esayeas --- test/HalResourceTest.php | 38 +++++++++++++++++++++++++++++++------- 1 file changed, 31 insertions(+), 7 deletions(-) diff --git a/test/HalResourceTest.php b/test/HalResourceTest.php index 2288e26..c818ed1 100644 --- a/test/HalResourceTest.php +++ b/test/HalResourceTest.php @@ -241,20 +241,20 @@ public function testWithElementProxiesToEmbedIfResourceCollectionValueProvided() public function testWithElementWillEmbedAnEmptyArrayIfAnEmptyArrayValueIsProvided(): void { - $resource = new HalResource(['foo' => 'bar']); + $resource = new HalResource(['foo' => 'bar'], [], [], true); $new = $resource->withElement('bar', []); $representation = $new->toArray(); self::assertSame(['foo' => 'bar', '_embedded' => ['bar' => []]], $representation); } - public function testWithElementWillEmbedAnEmptyArrayIfNullValueIsProvided(): void + public function testWithElementDoesNotProxyToEmbedIfNullValueIsProvided(): void { - $resource = new HalResource(['foo' => 'bar']); + $resource = new HalResource(['foo' => 'bar'], [], [], true); $new = $resource->withElement('bar', null); $representation = $new->toArray(); - self::assertSame(['foo' => 'bar', '_embedded' => ['bar' => []]], $representation); + self::assertSame(['foo' => 'bar', 'bar' => null], $representation); } /** @@ -690,12 +690,11 @@ public static function nonEmptyCollectionDataProvider(): Generator } /** - * @return Generator<'array'|'null',list{array|null},mixed,void> + * @return Generator<'array',list{array},mixed,void> */ public static function emptyCollectionDataProvider(): Generator { yield from [ - 'null' => [null], 'array' => [[]], ]; } @@ -705,7 +704,7 @@ public static function emptyCollectionDataProvider(): Generator */ public function testEmptyCollection(mixed $collection): void { - $resource = (new HalResource()) + $resource = (new HalResource([], [], [], true)) ->withLink(new Link('self', '/api/contacts')) ->withElements(['contacts' => $collection]); @@ -729,4 +728,29 @@ public function testNonEmptyCollection(mixed $collection): void $resource->toArray() ); } + + /** + * @return Generator<'null',list{null},mixed,void> + */ + public static function nullCollectionDataProvider(): Generator + { + yield from [ + 'null' => [null], + ]; + } + + /** + * @dataProvider nullCollectionDataProvider + */ + public function testNullCollection(mixed $collection): void + { + $resource = (new HalResource([], [], [], true)) + ->withLink(new Link('self', '/api/contacts')) + ->withElements(['contacts' => $collection]); + + self::assertSame( + $this->fixture('null-contacts-collection.json'), + $resource->toArray() + ); + } } From 0baf7dc9657987e71ff9a3f27570371783421d94 Mon Sep 17 00:00:00 2001 From: Nathanael Esayeas Date: Sat, 15 Jul 2023 05:50:10 -0500 Subject: [PATCH 16/37] Update HalResource.php Signed-off-by: Nathanael Esayeas --- src/HalResource.php | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/HalResource.php b/src/HalResource.php index 2b88240..8fb8477 100644 --- a/src/HalResource.php +++ b/src/HalResource.php @@ -49,8 +49,12 @@ class HalResource implements EvolvableLinkProviderInterface, JsonSerializable * @param LinkInterface[] $links * @param HalResource[][] $embedded */ - public function __construct(array $data = [], array $links = [], array $embedded = [], bool $embedEmptyCollections = false) - { + public function __construct( + array $data = [], + array $links = [], + array $embedded = [], + bool $embedEmptyCollections = false + ) { $this->embedEmptyCollections = $embedEmptyCollections; $context = self::class; From bad20ad00a85145d228a634810cf9e9a0d67eafa Mon Sep 17 00:00:00 2001 From: Nathanael Esayeas Date: Sat, 15 Jul 2023 05:58:07 -0500 Subject: [PATCH 17/37] Suppress Psalm issue Signed-off-by: Nathanael Esayeas --- src/ResourceGenerator.php | 1 + 1 file changed, 1 insertion(+) diff --git a/src/ResourceGenerator.php b/src/ResourceGenerator.php index 3a1785d..bcd672b 100644 --- a/src/ResourceGenerator.php +++ b/src/ResourceGenerator.php @@ -94,6 +94,7 @@ public function getStrategies(): array public function fromArray(array $data, ?string $uri = null): HalResource { + /** @psalm-suppress MixedArrayAccess */ $embedEmptyCollections = $this->hydrators->has('config') && $this->hydrators->get('config')['mezzio-hal']['embed-empty-collections'] ?? From 11ffa3b42942918b8087e9c817633e9a660b0228 Mon Sep 17 00:00:00 2001 From: Nathanael Esayeas Date: Tue, 18 Jul 2023 06:25:39 -0500 Subject: [PATCH 18/37] Remove doc comment Signed-off-by: Nathanael Esayeas --- src/ConfigProvider.php | 5 ----- 1 file changed, 5 deletions(-) diff --git a/src/ConfigProvider.php b/src/ConfigProvider.php index b0178fb..708da08 100644 --- a/src/ConfigProvider.php +++ b/src/ConfigProvider.php @@ -69,11 +69,6 @@ public function getDependencies(): array public function getHalConfig(): array { return [ - /** - * Whether or not to include empty collections within the _embedded section of the response, - * - * See: https://github.com/mezzio/mezzio-hal/pull/80 - */ 'embed-empty-collections' => false, 'resource-generator' => [ 'strategies' => [ // The registered strategies and their metadata types From ca2b505e920e8be80aa0f732f56d1ca399a89422 Mon Sep 17 00:00:00 2001 From: Nathanael Esayeas Date: Tue, 18 Jul 2023 06:26:06 -0500 Subject: [PATCH 19/37] Add documentation Signed-off-by: Nathanael Esayeas --- docs/book/v2/links-and-resources.md | 38 +++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) diff --git a/docs/book/v2/links-and-resources.md b/docs/book/v2/links-and-resources.md index f5da3cf..30304c6 100644 --- a/docs/book/v2/links-and-resources.md +++ b/docs/book/v2/links-and-resources.md @@ -198,4 +198,42 @@ $resource = $resource->withLink($link); $resource = $resource->withoutLink($link); ``` +To maintain consistency in the structure of the response, you may choose to embed both non-empty and empty collections within the `_embedded` section. This can be achieved by enabling the `embed-empty-collections` configuration option. + +To enable this feature, modify the configuration file as follows: + +```php +return [ + 'mezzio-hal' => [ + 'embed-empty-collections' => false, // (default: false for compatibility reasons) + 'metadata-factories' => [...], + 'resource-generator' => [...], + ], +]; +``` + +The default setting of `false` ensures compatibility with existing API endpoints and prevents potential test failures. + +When `embed-empty-collections` is set to `false`, the representation will be as follows: + +**`empty-contacts-collection-not-embedded.json`** + +```json +{ + "contacts": [] +} +``` + +However, when `embed-empty-collections` is set to `true`, the representation will be as follows: + +**`empty-contacts-collection-embedded.json`** + +``` json +{ + "_embedded": { + "contacts": [] + } +} +``` + With these tools, you can describe any resource you want to represent. From 28b572f0576a68656e96532c3f6f39f20b25cea1 Mon Sep 17 00:00:00 2001 From: Nathanael Esayeas Date: Tue, 18 Jul 2023 06:33:00 -0500 Subject: [PATCH 20/37] Update links-and-resources.md Signed-off-by: Nathanael Esayeas --- docs/book/v2/links-and-resources.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/book/v2/links-and-resources.md b/docs/book/v2/links-and-resources.md index 30304c6..011d669 100644 --- a/docs/book/v2/links-and-resources.md +++ b/docs/book/v2/links-and-resources.md @@ -228,7 +228,7 @@ However, when `embed-empty-collections` is set to `true`, the representation wil **`empty-contacts-collection-embedded.json`** -``` json +```json { "_embedded": { "contacts": [] From e0ddb0e6e6b74f21d3021ce41885d152bb672945 Mon Sep 17 00:00:00 2001 From: Nathanael Esayeas Date: Tue, 18 Jul 2023 06:38:38 -0500 Subject: [PATCH 21/37] Fix unrelated cs issue Signed-off-by: Nathanael Esayeas --- README.md | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index 743a7d7..def2cc4 100644 --- a/README.md +++ b/README.md @@ -3,19 +3,19 @@ [![Build Status](https://github.com/mezzio/mezzio-hal/actions/workflows/continuous-integration.yml/badge.svg)](https://github.com/mezzio/mezzio-hal/actions/workflows/continuous-integration.yml) > ## πŸ‡·πŸ‡Ί Русским Π³Ρ€Π°ΠΆΠ΄Π°Π½Π°ΠΌ -> +> > ΠœΡ‹, участники Laminas, Ρ€ΠΎΠ΄ΠΈΠ»ΠΈΡΡŒ ΠΈ ΠΆΠΈΠ²Π΅ΠΌ Π² Ρ€Π°Π·Π½Ρ‹Ρ… странах. Π£ ΠΌΠ½ΠΎΠ³ΠΈΡ… ΠΈΠ· нас Π΅ΡΡ‚ΡŒ Π΄Ρ€ΡƒΠ·ΡŒΡ, родствСнники ΠΈ ΠΊΠΎΠ»Π»Π΅Π³ΠΈ ΠΊΠ°ΠΊ Π² России, Ρ‚Π°ΠΊ ΠΈ Π² Π£ΠΊΡ€Π°ΠΈΠ½Π΅. НСкоторыС ΠΈΠ· нас Ρ€ΠΎΠ΄ΠΈΠ»ΠΈΡΡŒ Π² России. НСкоторыС ΠΈΠ· нас ΠΆΠΈΠ²ΡƒΡ‚ Π² России. Π£ Π½Π΅ΠΊΠΎΡ‚ΠΎΡ€Ρ‹Ρ… Π±Π°Π±ΡƒΡˆΠΊΠΈ ΠΈ Π΄Π΅Π΄ΡƒΡˆΠΊΠΈ ΡΡ€Π°ΠΆΠ°Π»ΠΈΡΡŒ с Ρ„Π°ΡˆΠΈΡΡ‚Π°ΠΌΠΈ Π²ΠΎ Π’Ρ‚ΠΎΡ€ΠΎΠΉ ΠΌΠΈΡ€ΠΎΠ²ΠΎΠΉ Π²ΠΎΠΉΠ½Π΅. Π—Π΄Π΅ΡΡŒ Π½ΠΈΠΊΡ‚ΠΎ Π½Π΅ ΠΏΠΎΠ΄Π΄Π΅Ρ€ΠΆΠΈΠ²Π°Π΅Ρ‚ Ρ„Π°ΡˆΠΈΠ·ΠΌ. -> +> > Π£ ΠΎΠ΄Π½ΠΎΠ³ΠΎ ΠΈΠ· нас Π΅ΡΡ‚ΡŒ украинская родствСнница, которая спаслась ΠΈΠ· Π΄ΠΎΠΌΠ° вмСстС с сыном. ПоСзд задСрТался ΠΈΠ·-Π·Π° Π±ΠΎΠΌΠ±Π΅ΠΆΠΊΠΈ Π½Π° Π΄ΠΎΡ€ΠΎΠ³Π΅ Π²ΠΏΠ΅Ρ€Π΅Π΄ΠΈ. Π£ нас Π΅ΡΡ‚ΡŒ Π΄Ρ€ΡƒΠ·ΡŒΡ, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹Π΅ прячутся Π² Π±ΠΎΠΌΠ±ΠΎΡƒΠ±Π΅ΠΆΠΈΡ‰Π°Ρ…. ΠœΡ‹ с Ρ‚Ρ€Π΅Π²ΠΎΠ³ΠΎΠΉ ΠΆΠ΄Π΅ΠΌ вСсточки ΠΎΡ‚ Π½ΠΈΡ… послС Π²ΠΎΠ·Π΄ΡƒΡˆΠ½Ρ‹Ρ… Π½Π°Π»Π΅Ρ‚ΠΎΠ², ΠΊΠΎΡ‚ΠΎΡ€Ρ‹Π΅ бСспорядочно наносят ΡƒΠ΄Π°Ρ€Ρ‹ ΠΈ ΠΏΠΎΠΏΠ°Π΄Π°ΡŽΡ‚ ΠΏΠΎ Π±ΠΎΠ»ΡŒΠ½ΠΈΡ†Π°ΠΌ, школам, дСтским садам ΠΈ Π΄ΠΎΠΌΠ°ΠΌ. ΠœΡ‹ Π½Π΅ Π±Π΅Ρ€Π΅ΠΌ это ΠΈΠ· ΠΊΠ°ΠΊΠΈΡ…-Π»ΠΈΠ±ΠΎ БМИ. ΠœΡ‹ наблюдаСм это Π½Π°ΠΏΡ€ΡΠΌΡƒΡŽ. -> +> > Π’Ρ‹ довСряСтС Π½Π°ΠΌ достаточно, Ρ‡Ρ‚ΠΎΠ± ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚ΡŒ наши ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΡ‹, ΠΈ ΠΌΡ‹ просим вас Π΄ΠΎΠ²Π΅Ρ€ΠΈΡ‚ΡŒΡΡ Π½Π°ΠΌ вновь. ΠœΡ‹ нуТдаСмся Π² ΠΏΠΎΠΌΠΎΡ‰ΠΈ. Π’Ρ‹Ρ…ΠΎΠ΄ΠΈΡ‚Π΅ ΠΈ протСстуйтС ΠΏΡ€ΠΎΡ‚ΠΈΠ² этой бСсполСзной Π²ΠΎΠΉΠ½Ρ‹. ΠžΡΡ‚Π°Π½ΠΎΠ²ΠΈΡ‚Π΅ ΠΊΡ€ΠΎΠ²ΠΎΠΏΡ€ΠΎΠ»ΠΈΡ‚ΠΈΠ΅. Π‘ΠΊΠ°ΠΆΠΈΡ‚Π΅ "НСт Π²ΠΎΠΉΠ½Π΅!" -> +> > ## πŸ‡ΊπŸ‡Έ To Citizens of Russia -> +> > We at Laminas come from all over the world. Many of us have friends, family and colleagues in both Russia and Ukraine. Some of us were born in Russia. Some of us currently live in Russia. Some have grandparents who fought Nazis in World War II. Nobody here supports fascism. -> +> > One team member has a Ukrainian relative who fled her home with her son. The train was delayed due to bombing on the road ahead. We have friends who are hiding in bomb shelters. We anxiously follow up on them after the air raids, which indiscriminately fire at hospitals, schools, kindergartens and houses. We're not taking this from any media. These are our actual experiences. -> +> > You trust us enough to use our software. We ask that you trust us to say the truth on this. We need your help. Go out and protest this unnecessary war. Stop the bloodshed. Say "stop the war!" This library provides utilities for modeling HAL resources with links and generating [PSR-7](https://www.php-fig.org/psr/psr-7/) responses representing both JSON and XML serializations of them. From 0c2aa962632f6bca17f1785951086d2a29978056 Mon Sep 17 00:00:00 2001 From: Nathanael Esayeas Date: Tue, 18 Jul 2023 07:16:01 -0500 Subject: [PATCH 22/37] Specify configuration file path Signed-off-by: Nathanael Esayeas --- docs/book/v2/links-and-resources.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/book/v2/links-and-resources.md b/docs/book/v2/links-and-resources.md index 011d669..ef73b33 100644 --- a/docs/book/v2/links-and-resources.md +++ b/docs/book/v2/links-and-resources.md @@ -200,7 +200,7 @@ $resource = $resource->withoutLink($link); To maintain consistency in the structure of the response, you may choose to embed both non-empty and empty collections within the `_embedded` section. This can be achieved by enabling the `embed-empty-collections` configuration option. -To enable this feature, modify the configuration file as follows: +To enable this feature, modify the configuration file `config/autoload/hal.global.php` as follows: ```php return [ From 5a24772884028ce3969c70daa30a0a88e377c4a7 Mon Sep 17 00:00:00 2001 From: Nathanael Esayeas Date: Mon, 31 Jul 2023 11:17:45 -0500 Subject: [PATCH 23/37] Update src/ResourceGenerator.php Commit suggestion: The above makes the order of operations more clear. Additionally, our CS has us put operators on the next line. Co-authored-by: Matthew Weier O'Phinney Signed-off-by: Nathanael Esayeas --- src/ResourceGenerator.php | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/ResourceGenerator.php b/src/ResourceGenerator.php index bcd672b..4dcfd61 100644 --- a/src/ResourceGenerator.php +++ b/src/ResourceGenerator.php @@ -96,9 +96,8 @@ public function fromArray(array $data, ?string $uri = null): HalResource { /** @psalm-suppress MixedArrayAccess */ $embedEmptyCollections = - $this->hydrators->has('config') && - $this->hydrators->get('config')['mezzio-hal']['embed-empty-collections'] ?? - false; + $this->hydrators->has('config') + && $this->hydrators->get('config')['mezzio-hal']['embed-empty-collections'] ?? false; $resource = new HalResource($data, [], [], $embedEmptyCollections); From e7e825d040c3cb0b9528fcd25363e8bfbc488e74 Mon Sep 17 00:00:00 2001 From: Nathanael Esayeas Date: Mon, 31 Jul 2023 11:18:10 -0500 Subject: [PATCH 24/37] Update test/HalResourceTest.php Co-authored-by: Matthew Weier O'Phinney Signed-off-by: Nathanael Esayeas --- test/HalResourceTest.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/HalResourceTest.php b/test/HalResourceTest.php index c818ed1..6530ee4 100644 --- a/test/HalResourceTest.php +++ b/test/HalResourceTest.php @@ -742,7 +742,7 @@ public static function nullCollectionDataProvider(): Generator /** * @dataProvider nullCollectionDataProvider */ - public function testNullCollection(mixed $collection): void + public function testNullCollectionWhenEmbedEmtpyEnabled(mixed $collection): void { $resource = (new HalResource([], [], [], true)) ->withLink(new Link('self', '/api/contacts')) From 93301262b2bd89dbb5dd0cbade44d3ed59af01ec Mon Sep 17 00:00:00 2001 From: Nathanael Esayeas Date: Mon, 31 Jul 2023 11:18:18 -0500 Subject: [PATCH 25/37] Update test/HalResourceTest.php Co-authored-by: Matthew Weier O'Phinney Signed-off-by: Nathanael Esayeas --- test/HalResourceTest.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/HalResourceTest.php b/test/HalResourceTest.php index 6530ee4..91f0e8c 100644 --- a/test/HalResourceTest.php +++ b/test/HalResourceTest.php @@ -702,7 +702,7 @@ public static function emptyCollectionDataProvider(): Generator /** * @dataProvider emptyCollectionDataProvider */ - public function testEmptyCollection(mixed $collection): void + public function testEmptyCollectionWhenEmbedEmptyEnabled(mixed $collection): void { $resource = (new HalResource([], [], [], true)) ->withLink(new Link('self', '/api/contacts')) From 228c4e7884401a91892e9e98de35d96615d32192 Mon Sep 17 00:00:00 2001 From: Nathanael Esayeas Date: Mon, 31 Jul 2023 11:18:25 -0500 Subject: [PATCH 26/37] Update test/HalResourceTest.php Co-authored-by: Matthew Weier O'Phinney Signed-off-by: Nathanael Esayeas --- test/HalResourceTest.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/HalResourceTest.php b/test/HalResourceTest.php index 91f0e8c..2de7899 100644 --- a/test/HalResourceTest.php +++ b/test/HalResourceTest.php @@ -248,7 +248,7 @@ public function testWithElementWillEmbedAnEmptyArrayIfAnEmptyArrayValueIsProvide self::assertSame(['foo' => 'bar', '_embedded' => ['bar' => []]], $representation); } - public function testWithElementDoesNotProxyToEmbedIfNullValueIsProvided(): void + public function testWithElementDoesNotProxyToEmbedIfNullValueIsProvidedAndEmbedEmptyCollectionsEnabled(): void { $resource = new HalResource(['foo' => 'bar'], [], [], true); $new = $resource->withElement('bar', null); From 27bae41a40db208612ec9355bf295cf581e45910 Mon Sep 17 00:00:00 2001 From: Nathanael Esayeas Date: Mon, 31 Jul 2023 11:23:32 -0500 Subject: [PATCH 27/37] Update test/HalResourceTest.php Commit suggestion: Since the default behavior remains unchanged, we should note in the test that the tested behavior is specifically for when the embed empty collections option is toggled on. Co-authored-by: Matthew Weier O'Phinney Signed-off-by: Nathanael Esayeas --- test/HalResourceTest.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/HalResourceTest.php b/test/HalResourceTest.php index 2de7899..e533171 100644 --- a/test/HalResourceTest.php +++ b/test/HalResourceTest.php @@ -239,7 +239,7 @@ public function testWithElementProxiesToEmbedIfResourceCollectionValueProvided() $this->assertEquals(['foo' => $collection], $new->getElements()); } - public function testWithElementWillEmbedAnEmptyArrayIfAnEmptyArrayValueIsProvided(): void + public function testWithElementWillEmbedAnEmptyArrayIfAnEmptyArrayValueIsProvidedAndConfiguredToEmbedEmptyCollections(): void { $resource = new HalResource(['foo' => 'bar'], [], [], true); $new = $resource->withElement('bar', []); From ba594cc8f07f3b9b03fbb080d552f4163e9a8948 Mon Sep 17 00:00:00 2001 From: Nathanael Esayeas Date: Mon, 31 Jul 2023 11:24:00 -0500 Subject: [PATCH 28/37] Update links-and-resources.md Add a note here that this feature is available since version 2.7.0. Signed-off-by: Nathanael Esayeas --- docs/book/v2/links-and-resources.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/docs/book/v2/links-and-resources.md b/docs/book/v2/links-and-resources.md index ef73b33..0caf2e0 100644 --- a/docs/book/v2/links-and-resources.md +++ b/docs/book/v2/links-and-resources.md @@ -198,6 +198,10 @@ $resource = $resource->withLink($link); $resource = $resource->withoutLink($link); ``` +> INFO: Available since 2.7.0 +> +> The `embed-empty-collections` configuration option is available starting with version 2.7.0. + To maintain consistency in the structure of the response, you may choose to embed both non-empty and empty collections within the `_embedded` section. This can be achieved by enabling the `embed-empty-collections` configuration option. To enable this feature, modify the configuration file `config/autoload/hal.global.php` as follows: From 188caec9fa506bfcedb263a1b5997a9bc8590b68 Mon Sep 17 00:00:00 2001 From: Nathanael Esayeas Date: Mon, 31 Jul 2023 11:25:06 -0500 Subject: [PATCH 29/37] Update HalResource.php Use constructor property promotion here Signed-off-by: Nathanael Esayeas --- src/HalResource.php | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/HalResource.php b/src/HalResource.php index 8fb8477..45d727a 100644 --- a/src/HalResource.php +++ b/src/HalResource.php @@ -42,8 +42,6 @@ class HalResource implements EvolvableLinkProviderInterface, JsonSerializable /** @var array> */ private $embedded = []; - private bool $embedEmptyCollections; - /** * @param array $data * @param LinkInterface[] $links @@ -53,7 +51,7 @@ public function __construct( array $data = [], array $links = [], array $embedded = [], - bool $embedEmptyCollections = false + private bool $embedEmptyCollections = false ) { $this->embedEmptyCollections = $embedEmptyCollections; From adb411dff5e383dedd30f01e4adc95ec181e322f Mon Sep 17 00:00:00 2001 From: Nathanael Esayeas Date: Mon, 31 Jul 2023 11:31:43 -0500 Subject: [PATCH 30/37] Reinstate removed tests Signed-off-by: Nathanael Esayeas --- src/HalResource.php | 30 +++++++++++++++++++++--------- test/HalResourceTest.php | 11 ++++++++++- 2 files changed, 31 insertions(+), 10 deletions(-) diff --git a/src/HalResource.php b/src/HalResource.php index 45d727a..f8940bc 100644 --- a/src/HalResource.php +++ b/src/HalResource.php @@ -19,6 +19,7 @@ use function array_shift; use function array_walk; use function count; +use function get_debug_type; use function gettype; use function in_array; use function is_array; @@ -56,26 +57,37 @@ public function __construct( $this->embedEmptyCollections = $embedEmptyCollections; $context = self::class; + array_walk($data, function ($value, $name) use ($context) { $this->validateElementName($name, $context); + if ($value instanceof self || $this->isResourceCollection($value)) { $this->embedded[$name] = $value; return; } + $this->data[$name] = $value; }); array_walk($embedded, function ($resource, $name) use ($context) { $this->validateElementName($name, $context); $this->detectCollisionWithData($name, $context); - if (! ($resource instanceof self || $this->isResourceCollection($resource))) { - throw new InvalidArgumentException(sprintf( - 'Invalid embedded resource provided to %s constructor with name "%s"', - $context, - $name - )); + + if ( + $resource instanceof self || + $resource === [] || + $this->isResourceCollection($resource) + ) { + $this->embedded[$name] = $resource; + return; } - $this->embedded[$name] = $resource; + + throw new InvalidArgumentException(sprintf( + 'Invalid embedded resource provided to %s constructor with name "%s":"%s"', + $context, + $name, + get_debug_type($resource) + )); }); if ( @@ -397,8 +409,8 @@ private function isResourceCollection($value): bool return false; } - if ($this->embedEmptyCollections && $value === []) { - return true; + if ($value === []) { + return $this->embedEmptyCollections; } return array_reduce($value, static function ($isResource, $item) { diff --git a/test/HalResourceTest.php b/test/HalResourceTest.php index e533171..7078e9f 100644 --- a/test/HalResourceTest.php +++ b/test/HalResourceTest.php @@ -239,9 +239,18 @@ public function testWithElementProxiesToEmbedIfResourceCollectionValueProvided() $this->assertEquals(['foo' => $collection], $new->getElements()); } + public function testWithElementDoesNotProxyToEmbedIfAnEmptyArrayValueIsProvided(): void + { + $resource = new HalResource(['foo' => 'bar'], embedEmptyCollections: false); + $new = $resource->withElement('bar', []); + + $representation = $new->toArray(); + self::assertSame(['foo' => 'bar', 'bar' => []], $representation); + } + public function testWithElementWillEmbedAnEmptyArrayIfAnEmptyArrayValueIsProvidedAndConfiguredToEmbedEmptyCollections(): void { - $resource = new HalResource(['foo' => 'bar'], [], [], true); + $resource = new HalResource(['foo' => 'bar'], embedEmptyCollections: true); $new = $resource->withElement('bar', []); $representation = $new->toArray(); From 6be416cf2db4f387d500714c57ddfb6cc1d0c17f Mon Sep 17 00:00:00 2001 From: Nathanael Esayeas Date: Mon, 31 Jul 2023 11:39:16 -0500 Subject: [PATCH 31/37] Add phpcs:ignore Signed-off-by: Nathanael Esayeas --- test/HalResourceTest.php | 1 + 1 file changed, 1 insertion(+) diff --git a/test/HalResourceTest.php b/test/HalResourceTest.php index 7078e9f..eb520c6 100644 --- a/test/HalResourceTest.php +++ b/test/HalResourceTest.php @@ -248,6 +248,7 @@ public function testWithElementDoesNotProxyToEmbedIfAnEmptyArrayValueIsProvided( self::assertSame(['foo' => 'bar', 'bar' => []], $representation); } + // phpcs:ignore public function testWithElementWillEmbedAnEmptyArrayIfAnEmptyArrayValueIsProvidedAndConfiguredToEmbedEmptyCollections(): void { $resource = new HalResource(['foo' => 'bar'], embedEmptyCollections: true); From a7b9f9e5d899fc7dbc2e38cf69a7a7f391a1b856 Mon Sep 17 00:00:00 2001 From: Nathanael Esayeas Date: Mon, 31 Jul 2023 12:27:05 -0500 Subject: [PATCH 32/37] Fix pslam issue Signed-off-by: Nathanael Esayeas --- psalm-baseline.xml | 3 --- src/ResourceGenerator/UrlBasedCollectionStrategy.php | 2 +- 2 files changed, 1 insertion(+), 4 deletions(-) diff --git a/psalm-baseline.xml b/psalm-baseline.xml index 0f2ee51..9fd5442 100644 --- a/psalm-baseline.xml +++ b/psalm-baseline.xml @@ -448,9 +448,6 @@ - - $page - protected function generateSelfLink( diff --git a/src/ResourceGenerator/UrlBasedCollectionStrategy.php b/src/ResourceGenerator/UrlBasedCollectionStrategy.php index 0847f9a..8fbf67d 100644 --- a/src/ResourceGenerator/UrlBasedCollectionStrategy.php +++ b/src/ResourceGenerator/UrlBasedCollectionStrategy.php @@ -73,7 +73,7 @@ protected function generateLinkForPage( switch ($paginationType) { case Metadata\AbstractCollectionMetadata::TYPE_PLACEHOLDER: - $url = str_replace($url, $paginationParam, $page); + $url = str_replace($url, $paginationParam, (string) $page); break; case Metadata\AbstractCollectionMetadata::TYPE_QUERY: // fall-through From b65df9aa881b263c26da07c1505a0982ad3e20e4 Mon Sep 17 00:00:00 2001 From: Nathanael Esayeas Date: Tue, 1 Aug 2023 05:27:39 -0500 Subject: [PATCH 33/37] Update docs/book/v2/links-and-resources.md MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit commit suggestion Co-authored-by: Frank BrΓΌckner Signed-off-by: Nathanael Esayeas --- docs/book/v2/links-and-resources.md | 1 - 1 file changed, 1 deletion(-) diff --git a/docs/book/v2/links-and-resources.md b/docs/book/v2/links-and-resources.md index 0caf2e0..3e5e27d 100644 --- a/docs/book/v2/links-and-resources.md +++ b/docs/book/v2/links-and-resources.md @@ -220,7 +220,6 @@ The default setting of `false` ensures compatibility with existing API endpoints When `embed-empty-collections` is set to `false`, the representation will be as follows: -**`empty-contacts-collection-not-embedded.json`** ```json { From a2f1bbf236bd0295c81207037ee44efda1ea07ae Mon Sep 17 00:00:00 2001 From: Nathanael Esayeas Date: Tue, 1 Aug 2023 05:27:57 -0500 Subject: [PATCH 34/37] Update docs/book/v2/links-and-resources.md MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit commit suggestion Co-authored-by: Frank BrΓΌckner Signed-off-by: Nathanael Esayeas --- docs/book/v2/links-and-resources.md | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/docs/book/v2/links-and-resources.md b/docs/book/v2/links-and-resources.md index 3e5e27d..6c48f64 100644 --- a/docs/book/v2/links-and-resources.md +++ b/docs/book/v2/links-and-resources.md @@ -198,9 +198,10 @@ $resource = $resource->withLink($link); $resource = $resource->withoutLink($link); ``` -> INFO: Available since 2.7.0 -> -> The `embed-empty-collections` configuration option is available starting with version 2.7.0. +### Embed Empty Collection + +> INFO: **New Feature** +> Available since version 2.7.0. To maintain consistency in the structure of the response, you may choose to embed both non-empty and empty collections within the `_embedded` section. This can be achieved by enabling the `embed-empty-collections` configuration option. From c155d75cc5fe2929f42e48b697e89d89c5d28b2d Mon Sep 17 00:00:00 2001 From: Nathanael Esayeas Date: Tue, 1 Aug 2023 05:28:06 -0500 Subject: [PATCH 35/37] Update docs/book/v2/links-and-resources.md MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit commit suggestion Co-authored-by: Frank BrΓΌckner Signed-off-by: Nathanael Esayeas --- docs/book/v2/links-and-resources.md | 1 - 1 file changed, 1 deletion(-) diff --git a/docs/book/v2/links-and-resources.md b/docs/book/v2/links-and-resources.md index 6c48f64..92affad 100644 --- a/docs/book/v2/links-and-resources.md +++ b/docs/book/v2/links-and-resources.md @@ -230,7 +230,6 @@ When `embed-empty-collections` is set to `false`, the representation will be as However, when `embed-empty-collections` is set to `true`, the representation will be as follows: -**`empty-contacts-collection-embedded.json`** ```json { From e82ee831787ed2e53d8ecb0586b54bb850851c15 Mon Sep 17 00:00:00 2001 From: Nathanael Esayeas Date: Tue, 1 Aug 2023 05:31:25 -0500 Subject: [PATCH 36/37] Update links-and-resources.md Fix Documentation Linting issues Signed-off-by: Nathanael Esayeas --- docs/book/v2/links-and-resources.md | 2 -- 1 file changed, 2 deletions(-) diff --git a/docs/book/v2/links-and-resources.md b/docs/book/v2/links-and-resources.md index 92affad..c7db6ae 100644 --- a/docs/book/v2/links-and-resources.md +++ b/docs/book/v2/links-and-resources.md @@ -221,7 +221,6 @@ The default setting of `false` ensures compatibility with existing API endpoints When `embed-empty-collections` is set to `false`, the representation will be as follows: - ```json { "contacts": [] @@ -230,7 +229,6 @@ When `embed-empty-collections` is set to `false`, the representation will be as However, when `embed-empty-collections` is set to `true`, the representation will be as follows: - ```json { "_embedded": { From b432dfdb35c5d5904b3b540e7cbb04fddb3c556c Mon Sep 17 00:00:00 2001 From: Matthew Weier O'Phinney Date: Tue, 1 Aug 2023 16:02:14 -0500 Subject: [PATCH 37/37] Update test/HalResourceTest.php Signed-off-by: Matthew Weier O'Phinney --- test/HalResourceTest.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/HalResourceTest.php b/test/HalResourceTest.php index eb520c6..005ddeb 100644 --- a/test/HalResourceTest.php +++ b/test/HalResourceTest.php @@ -752,7 +752,7 @@ public static function nullCollectionDataProvider(): Generator /** * @dataProvider nullCollectionDataProvider */ - public function testNullCollectionWhenEmbedEmtpyEnabled(mixed $collection): void + public function testNullCollectionWhenEmbedEmptyEnabled(mixed $collection): void { $resource = (new HalResource([], [], [], true)) ->withLink(new Link('self', '/api/contacts'))