From da2aa260178092c610471732025859620f82a78a Mon Sep 17 00:00:00 2001 From: Vic GUTT Date: Wed, 29 May 2024 12:35:34 +0200 Subject: [PATCH 1/3] fix: resolving response arrayable properties --- src/Response.php | 44 +++++++++++-------------------------- tests/ResponseTest.php | 29 ++++++++++++++++++++++++ tests/Stubs/AsArrayable.php | 31 ++++++++++++++++++++++++++ 3 files changed, 73 insertions(+), 31 deletions(-) create mode 100644 tests/Stubs/AsArrayable.php diff --git a/src/Response.php b/src/Response.php index 7e1373a9..995da79e 100644 --- a/src/Response.php +++ b/src/Response.php @@ -119,7 +119,7 @@ public function resolveProperties(Request $request, array $props): array }); } - $props = $this->resolveArrayableProperties($props, $request); + $props = $this->resolvePropertyInstances($props, $request); if($isPartial && $request->hasHeader(Header::PARTIAL_ONLY)) { $props = $this->resolveOnly($request, $props); @@ -129,33 +129,6 @@ public function resolveProperties(Request $request, array $props): array $props = $this->resolveExcept($request, $props); } - $props = $this->resolvePropertyInstances($props, $request); - - return $props; - } - - /** - * Resolve all arrayables properties into an array. - */ - public function resolveArrayableProperties(array $props, Request $request, bool $unpackDotProps = true): array - { - foreach ($props as $key => $value) { - if ($value instanceof Arrayable) { - $value = $value->toArray(); - } - - if (is_array($value)) { - $value = $this->resolveArrayableProperties($value, $request, false); - } - - if ($unpackDotProps && str_contains($key, '.')) { - Arr::set($props, $key, $value); - unset($props[$key]); - } else { - $props[$key] = $value; - } - } - return $props; } @@ -193,7 +166,7 @@ public function resolveExcept(Request $request, array $props): array /** * Resolve all necessary class instances in the given props. */ - public function resolvePropertyInstances(array $props, Request $request): array + public function resolvePropertyInstances(array $props, Request $request, bool $unpackDotProps = true): array { foreach ($props as $key => $value) { if ($value instanceof Closure) { @@ -212,11 +185,20 @@ public function resolvePropertyInstances(array $props, Request $request): array $value = $value->toResponse($request)->getData(true); } + if ($value instanceof Arrayable) { + $value = $value->toArray(); + } + if (is_array($value)) { - $value = $this->resolvePropertyInstances($value, $request); + $value = $this->resolvePropertyInstances($value, $request, false); } - $props[$key] = $value; + if ($unpackDotProps && str_contains($key, '.')) { + Arr::set($props, $key, $value); + unset($props[$key]); + } else { + $props[$key] = $value; + } } return $props; diff --git a/tests/ResponseTest.php b/tests/ResponseTest.php index eb925cbc..6cad8895 100644 --- a/tests/ResponseTest.php +++ b/tests/ResponseTest.php @@ -11,6 +11,7 @@ use Illuminate\Support\Fluent; use Illuminate\Http\JsonResponse; use Illuminate\Support\Collection; +use Inertia\Tests\Stubs\AsArrayable; use Inertia\Tests\Stubs\FakeResource; use Illuminate\Http\Response as BaseResponse; use Illuminate\Pagination\LengthAwarePaginator; @@ -210,6 +211,34 @@ public function test_arrayable_prop_response(): void $this->assertSame('123', $page->version); } + public function test_nested_arrayable_prop_response(): void + { + $request = Request::create('/auth', 'GET'); + $request->headers->add(['X-Inertia' => 'true']); + + $data = AsArrayable::make([ + 'user' => fn () => [ + 'full_name' => 'Victor Gutt', + 'organizations' => [ + fn () => AsArrayable::make([ + 'name' => 'Transl.me', + ]), + ], + ], + ]); + + $response = new Response('Auth/Index', ['data' => $data], 'app', '123'); + $response = $response->toResponse($request); + $page = $response->getData(); + + $this->assertInstanceOf(JsonResponse::class, $response); + $this->assertSame('Auth/Index', $page->component); + $this->assertSame('Victor Gutt', $page->props->data->user->full_name); + $this->assertSame('Transl.me', $page->props->data->user->organizations[0]->name); + $this->assertSame('/auth', $page->url); + $this->assertSame('123', $page->version); + } + public function test_promise_props_are_resolved(): void { $request = Request::create('/user/123', 'GET'); diff --git a/tests/Stubs/AsArrayable.php b/tests/Stubs/AsArrayable.php new file mode 100644 index 00000000..18f2517e --- /dev/null +++ b/tests/Stubs/AsArrayable.php @@ -0,0 +1,31 @@ + + */ +class AsArrayable implements Arrayable { + /** + * @var array + */ + protected $data = []; + + public function __construct(array $data) + { + $this->data = $data; + } + + public static function make(array $data): self { + return new self($data); + } + + /** + * Get the instance as an array. + */ + public function toArray(): array { + return $this->data; + } +} From fee2b1caa269f268a41c3627567368204d88e06d Mon Sep 17 00:00:00 2001 From: Vic GUTT Date: Wed, 29 May 2024 13:14:02 +0200 Subject: [PATCH 2/3] fix: test for PHP 7.3 - use regular closure --- tests/ResponseTest.php | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/tests/ResponseTest.php b/tests/ResponseTest.php index 6cad8895..eb371fd8 100644 --- a/tests/ResponseTest.php +++ b/tests/ResponseTest.php @@ -217,14 +217,18 @@ public function test_nested_arrayable_prop_response(): void $request->headers->add(['X-Inertia' => 'true']); $data = AsArrayable::make([ - 'user' => fn () => [ - 'full_name' => 'Victor Gutt', - 'organizations' => [ - fn () => AsArrayable::make([ - 'name' => 'Transl.me', - ]), - ], - ], + 'user' => function () { + return [ + 'full_name' => 'Victor Gutt', + 'organizations' => [ + function () { + return AsArrayable::make([ + 'name' => 'Transl.me', + ]); + }, + ], + ]; + }, ]); $response = new Response('Auth/Index', ['data' => $data], 'app', '123'); From 18d80d119173ef7e8300263c68f915484c6d9434 Mon Sep 17 00:00:00 2001 From: Vic GUTT Date: Thu, 13 Jun 2024 10:02:39 +0200 Subject: [PATCH 3/3] feat: test homogenization --- tests/ResponseTest.php | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/tests/ResponseTest.php b/tests/ResponseTest.php index 36ae9eff..d5d953d8 100644 --- a/tests/ResponseTest.php +++ b/tests/ResponseTest.php @@ -213,7 +213,7 @@ public function test_arrayable_prop_response(): void public function test_nested_arrayable_prop_response(): void { - $request = Request::create('/auth', 'GET'); + $request = Request::create('/user/123', 'GET'); $request->headers->add(['X-Inertia' => 'true']); $data = AsArrayable::make([ @@ -231,15 +231,15 @@ function () { }, ]); - $response = new Response('Auth/Index', ['data' => $data], 'app', '123'); + $response = new Response('User/Edit', ['data' => $data], 'app', '123'); $response = $response->toResponse($request); $page = $response->getData(); $this->assertInstanceOf(JsonResponse::class, $response); - $this->assertSame('Auth/Index', $page->component); + $this->assertSame('User/Edit', $page->component); $this->assertSame('Victor Gutt', $page->props->data->user->full_name); $this->assertSame('Transl.me', $page->props->data->user->organizations[0]->name); - $this->assertSame('/auth', $page->url); + $this->assertSame('/user/123', $page->url); $this->assertSame('123', $page->version); }