diff --git a/src/Response.php b/src/Response.php index 8966d4b0..86ea9f44 100644 --- a/src/Response.php +++ b/src/Response.php @@ -445,14 +445,24 @@ public function resolveCacheDirections(Request $request): array ]; } + /** + * Get the props that should be reset based on the request headers. + * + * @return array + */ + public function getResetProps(Request $request): array + { + return array_filter(explode(',', $request->header(Header::RESET, ''))); + } + /** * Get the props that should be considered for merging based on the request headers. * * @return \Illuminate\Support\Collection */ - protected function getMergePropsForRequest(Request $request): Collection + protected function getMergePropsForRequest(Request $request, bool $rejectResetProps = true): Collection { - $resetProps = array_filter(explode(',', $request->header(Header::RESET, ''))); + $resetProps = $rejectResetProps ? $this->getResetProps($request) : []; $onlyProps = array_filter(explode(',', $request->header(Header::PARTIAL_ONLY, ''))); $exceptProps = array_filter(explode(',', $request->header(Header::PARTIAL_EXCEPT, ''))); @@ -589,9 +599,14 @@ public function resolveDeferredProps(Request $request): array */ public function resolveScrollProps(Request $request): array { - $scrollProps = $this->getMergePropsForRequest($request) + $resetProps = $this->getResetProps($request); + + $scrollProps = $this->getMergePropsForRequest($request, false) ->filter(fn (Mergeable $prop) => $prop instanceof ScrollProp) - ->mapWithKeys(fn (ScrollProp $prop, string $key) => [$key => $prop->metadata()]); + ->mapWithKeys(fn (ScrollProp $prop, string $key) => [$key => [ + ...$prop->metadata(), + 'reset' => in_array($key, $resetProps), + ]]); return $scrollProps->isNotEmpty() ? ['scrollProps' => $scrollProps->toArray()] : []; } diff --git a/tests/ResponseTest.php b/tests/ResponseTest.php index 717eac44..425d87d0 100644 --- a/tests/ResponseTest.php +++ b/tests/ResponseTest.php @@ -17,11 +17,14 @@ use Inertia\LazyProp; use Inertia\MergeProp; use Inertia\ProvidesInertiaProperties; +use Inertia\ProvidesScrollMetadata; use Inertia\RenderContext; use Inertia\Response; +use Inertia\ScrollProp; use Inertia\Tests\Stubs\FakeResource; use Inertia\Tests\Stubs\MergeWithSharedProp; use Mockery; +use PHPUnit\Framework\Attributes\DataProvider; class ResponseTest extends TestCase { @@ -138,6 +141,78 @@ public function test_server_response_with_deferred_prop_and_multiple_groups(): v $this->assertSame('
', $view->render()); } + /** + * @return array + */ + public static function resetUsersProp(): array + { + return [ + 'no reset' => [false], + 'with reset' => [true], + ]; + } + + #[DataProvider('resetUsersProp')] + public function test_server_response_with_scroll_props(bool $resetUsersProp): void + { + $request = Request::create('/user/123', 'GET'); + + if ($resetUsersProp) { + $request->headers->add(['X-Inertia-Reset' => 'users']); + } + + $response = new Response( + 'User/Index', + [ + 'users' => new ScrollProp(['data' => [['id' => 1]]], 'data', new class implements ProvidesScrollMetadata + { + public function getPageName(): string + { + return 'page'; + } + + public function getPreviousPage(): ?int + { + return null; + } + + public function getNextPage(): int + { + return 2; + } + + public function getCurrentPage(): int + { + return 1; + } + }), + ], + 'app', + '123' + ); + $response = $response->toResponse($request); + /** @var BaseResponse $response */ + $view = $response->getOriginalContent(); + $page = $view->getData()['page']; + + $this->assertInstanceOf(BaseResponse::class, $response); + $this->assertInstanceOf(View::class, $view); + + $this->assertSame('User/Index', $page['component']); + $this->assertSame(['data' => [['id' => 1]]], $page['props']['users']); + $this->assertSame('/user/123', $page['url']); + $this->assertSame('123', $page['version']); + $this->assertSame([ + 'users' => [ + 'pageName' => 'page', + 'previousPage' => null, + 'nextPage' => 2, + 'currentPage' => 1, + 'reset' => $resetUsersProp, + ], + ], $page['scrollProps']); + } + public function test_server_response_with_merge_props(): void { $request = Request::create('/user/123', 'GET'); @@ -501,6 +576,38 @@ public function test_exclude_merge_props_from_partial_except_response(): void $this->assertSame(['bar'], $page->mergeProps); } + public function test_exclude_merge_props_when_passed_in_reset_header(): 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' => 'foo']); + $request->headers->add(['X-Inertia-Reset' => 'foo']); + + $user = ['name' => 'Jonathan']; + $response = new Response( + 'User/Edit', + [ + 'user' => $user, + 'foo' => new MergeProp('foo value'), + 'bar' => new MergeProp('bar value'), + ], + 'app', + '123' + ); + + /** @var JsonResponse $response */ + $response = $response->toResponse($request); + $page = $response->getData(); + + $props = get_object_vars($page->props); + + $this->assertInstanceOf(JsonResponse::class, $response); + $this->assertSame($props['foo'], 'foo value'); + $this->assertArrayNotHasKey('bar', $props); + $this->assertFalse(isset($page->mergeProps)); + } + public function test_xhr_response(): void { $request = Request::create('/user/123', 'GET');