From 5675663d9619528544cc2dca60e0f8b9603980ae Mon Sep 17 00:00:00 2001 From: Boris Lepikhin Date: Fri, 17 May 2024 15:12:22 -0700 Subject: [PATCH] exclude properties from partial responses (#622) --- src/Response.php | 18 ++++++++++++- src/Support/Header.php | 1 + tests/ResponseTest.php | 59 ++++++++++++++++++++++++++++++++++++++++-- 3 files changed, 75 insertions(+), 3 deletions(-) diff --git a/src/Response.php b/src/Response.php index 17772ed5..7e1373a9 100644 --- a/src/Response.php +++ b/src/Response.php @@ -113,7 +113,7 @@ public function resolveProperties(Request $request, array $props): array { $isPartial = $request->header(Header::PARTIAL_COMPONENT) === $this->component; - if(!$isPartial) { + if(! $isPartial) { $props = array_filter($this->props, static function ($prop) { return ! ($prop instanceof LazyProp); }); @@ -125,6 +125,10 @@ public function resolveProperties(Request $request, array $props): array $props = $this->resolveOnly($request, $props); } + if($isPartial && $request->hasHeader(Header::PARTIAL_EXCEPT)) { + $props = $this->resolveExcept($request, $props); + } + $props = $this->resolvePropertyInstances($props, $request); return $props; @@ -174,6 +178,18 @@ public function resolveOnly(Request $request, array $props): array return $value; } + /** + * Resolve the `except` partial request props. + */ + public function resolveExcept(Request $request, array $props): array + { + $except = array_filter(explode(',', $request->header(Header::PARTIAL_EXCEPT, ''))); + + Arr::forget($props, $except); + + return $props; + } + /** * Resolve all necessary class instances in the given props. */ diff --git a/src/Support/Header.php b/src/Support/Header.php index 87563896..2b902d8a 100644 --- a/src/Support/Header.php +++ b/src/Support/Header.php @@ -10,4 +10,5 @@ class Header public const VERSION = 'X-Inertia-Version'; public const PARTIAL_COMPONENT = 'X-Inertia-Partial-Component'; public const PARTIAL_ONLY = 'X-Inertia-Partial-Data'; + public const PARTIAL_EXCEPT = 'X-Inertia-Partial-Except'; } diff --git a/tests/ResponseTest.php b/tests/ResponseTest.php index 2d8cf286..eb925cbc 100644 --- a/tests/ResponseTest.php +++ b/tests/ResponseTest.php @@ -256,6 +256,29 @@ public function test_xhr_partial_response(): void $this->assertSame('123', $page->version); } + public function test_exclude_props_from_partial_response(): void + { + $request = Request::create('/user/123', 'GET'); + $request->headers->add(['X-Inertia' => 'true']); + $request->headers->add(['X-Inertia-Partial-Component' => 'User/Edit']); + $request->headers->add(['X-Inertia-Partial-Except' => 'user']); + + $user = (object) ['name' => 'Jonathan']; + $response = new Response('User/Edit', ['user' => $user, 'partial' => 'partial-data'], 'app', '123'); + $response = $response->toResponse($request); + $page = $response->getData(); + + $props = get_object_vars($page->props); + + $this->assertInstanceOf(JsonResponse::class, $response); + $this->assertSame('User/Edit', $page->component); + $this->assertFalse(isset($props['user'])); + $this->assertCount(1, $props); + $this->assertSame('partial-data', $page->props->partial); + $this->assertSame('/user/123', $page->url); + $this->assertSame('123', $page->version); + } + public function test_nested_partial_props(): void { $request = Request::create('/user/123', 'GET'); @@ -275,8 +298,8 @@ public function test_nested_partial_props(): void 'token' => 'value', ], 'shared' => [ - 'flash' => 'Value', - ] + 'flash' => 'value', + ], ]; $response = new Response('User/Edit', $props); @@ -290,6 +313,38 @@ public function test_nested_partial_props(): void $this->assertSame('value', $page->props->auth->refresh_token); } + public function test_exclude_nested_props_from_partial_response(): void + { + $request = Request::create('/user/123', 'GET'); + $request->headers->add(['X-Inertia' => 'true']); + $request->headers->add(['X-Inertia-Partial-Component' => 'User/Edit']); + $request->headers->add(['X-Inertia-Partial-Data' => 'auth']); + $request->headers->add(['X-Inertia-Partial-Except' => 'auth.user']); + + $props = [ + 'auth' => [ + 'user' => new LazyProp(function () { + return [ + 'name' => 'Jonathan Reinink', + 'email' => 'jonathan@example.com', + ]; + }), + 'refresh_token' => 'value', + ], + 'shared' => [ + 'flash' => 'value', + ], + ]; + + $response = new Response('User/Edit', $props); + $response = $response->toResponse($request); + $page = $response->getData(); + + $this->assertFalse(isset($page->props->auth->user)); + $this->assertFalse(isset($page->props->shared)); + $this->assertSame('value', $page->props->auth->refresh_token); + } + public function test_lazy_props_are_not_included_by_default(): void { $request = Request::create('/users', 'GET');