From e65e7ed1a51b0de088f03468275a4540b65dd025 Mon Sep 17 00:00:00 2001 From: lazerg Date: Thu, 17 Sep 2026 22:21:09 +0500 Subject: [PATCH 1/3] [6.x] Build the control panel nav only when an Inertia page is rendered --- .../CP/HandleAuthenticatedInertiaRequests.php | 6 +- src/Statamic.php | 15 +++- ...HandleAuthenticatedInertiaRequestsTest.php | 78 +++++++++++++++++++ 3 files changed, 93 insertions(+), 6 deletions(-) create mode 100644 tests/Http/Middleware/HandleAuthenticatedInertiaRequestsTest.php diff --git a/src/Http/Middleware/CP/HandleAuthenticatedInertiaRequests.php b/src/Http/Middleware/CP/HandleAuthenticatedInertiaRequests.php index 1fc91378565..55cee2ec441 100644 --- a/src/Http/Middleware/CP/HandleAuthenticatedInertiaRequests.php +++ b/src/Http/Middleware/CP/HandleAuthenticatedInertiaRequests.php @@ -49,7 +49,7 @@ private function alwaysProps() return [ 'version' => Statamic::version(), 'isPro' => Statamic::pro(), - 'nav' => $this->nav(), + 'nav' => fn () => $this->nav(), 'cmsName' => __(Statamic::pro() ? config('statamic.cp.custom_cms_name', 'Statamic') : 'Statamic'), ]; } @@ -63,8 +63,8 @@ private function protectedProps() return [ 'supportUrl' => config('statamic.cp.support_url'), 'selectedSiteUrl' => Site::selected()->url(), - 'licensing' => $this->licensing(), - 'sessionExpiry' => $this->sessionExpiry(), + 'licensing' => fn () => $this->licensing(), + 'sessionExpiry' => fn () => $this->sessionExpiry(), ]; } diff --git a/src/Statamic.php b/src/Statamic.php index bd5d7149a32..432758c103e 100644 --- a/src/Statamic.php +++ b/src/Statamic.php @@ -512,13 +512,22 @@ public static function cpPerPage($perPage) public static function nonInertiaPageData() { - $props = Inertia::getShared(); - return [ 'url' => '/'.request()->path(), 'component' => 'NonInertiaPage', 'version' => inertia()->getVersion(), - 'props' => $props, + 'props' => static::resolveProps(Inertia::getShared()), ]; } + + private static function resolveProps(array $props) + { + return collect($props)->map(function ($value) { + if ($value instanceof Closure) { + $value = $value(); + } + + return is_array($value) ? static::resolveProps($value) : $value; + })->all(); + } } diff --git a/tests/Http/Middleware/HandleAuthenticatedInertiaRequestsTest.php b/tests/Http/Middleware/HandleAuthenticatedInertiaRequestsTest.php new file mode 100644 index 00000000000..83c63c2287d --- /dev/null +++ b/tests/Http/Middleware/HandleAuthenticatedInertiaRequestsTest.php @@ -0,0 +1,78 @@ + ['foo' => 'bar']); + + Route::get('blade-page-test', fn () => view('statamic::layout')); + }); + } + + #[Test] + public function it_doesnt_build_the_nav_for_responses_that_arent_inertia_pages() + { + $built = false; + + Nav::extend(function () use (&$built) { + $built = true; + }); + + $this + ->actingAs(User::make()->makeSuper()) + ->get('/cp/json-response-test') + ->assertOk(); + + $this->assertFalse($built); + } + + #[Test] + public function it_builds_the_nav_for_inertia_pages() + { + $built = false; + + Nav::extend(function () use (&$built) { + $built = true; + }); + + $this + ->actingAs(User::make()->makeSuper()->save()) + ->get('/cp/dashboard') + ->assertOk(); + + $this->assertTrue($built); + } + + #[Test] + public function it_builds_the_nav_for_blade_based_pages() + { + $response = $this + ->actingAs(User::make()->makeSuper()->save()) + ->get('/cp/blade-page-test') + ->assertOk(); + + preg_match('/data-page="([^"]*)"/', $response->getContent(), $matches); + + $page = json_decode(htmlspecialchars_decode($matches[1], ENT_QUOTES), true); + + $this->assertNotEmpty($page['props']['_statamic']['nav']); + } +} From f7ab774ab67b136119d1c490e9a5a0007fd607a6 Mon Sep 17 00:00:00 2001 From: lazerg Date: Thu, 17 Sep 2026 22:46:13 +0500 Subject: [PATCH 2/3] [6.x] Assert the resolved page data instead of parsing it out of the layout --- ...HandleAuthenticatedInertiaRequestsTest.php | 19 ++++++++----------- 1 file changed, 8 insertions(+), 11 deletions(-) diff --git a/tests/Http/Middleware/HandleAuthenticatedInertiaRequestsTest.php b/tests/Http/Middleware/HandleAuthenticatedInertiaRequestsTest.php index 83c63c2287d..5cd37d48ce6 100644 --- a/tests/Http/Middleware/HandleAuthenticatedInertiaRequestsTest.php +++ b/tests/Http/Middleware/HandleAuthenticatedInertiaRequestsTest.php @@ -23,7 +23,7 @@ protected function resolveApplicationConfiguration($app) Statamic::pushCpRoutes(function () { Route::get('json-response-test', fn () => ['foo' => 'bar']); - Route::get('blade-page-test', fn () => view('statamic::layout')); + Route::get('non-inertia-page-data-test', fn () => Statamic::nonInertiaPageData()); }); } @@ -37,7 +37,7 @@ public function it_doesnt_build_the_nav_for_responses_that_arent_inertia_pages() }); $this - ->actingAs(User::make()->makeSuper()) + ->actingAs(User::make()->makeSuper()->save()) ->get('/cp/json-response-test') ->assertOk(); @@ -62,17 +62,14 @@ public function it_builds_the_nav_for_inertia_pages() } #[Test] - public function it_builds_the_nav_for_blade_based_pages() + public function it_resolves_the_nav_for_pages_rendered_outside_of_inertia() { - $response = $this + $data = $this ->actingAs(User::make()->makeSuper()->save()) - ->get('/cp/blade-page-test') - ->assertOk(); - - preg_match('/data-page="([^"]*)"/', $response->getContent(), $matches); - - $page = json_decode(htmlspecialchars_decode($matches[1], ENT_QUOTES), true); + ->get('/cp/non-inertia-page-data-test') + ->assertOk() + ->json(); - $this->assertNotEmpty($page['props']['_statamic']['nav']); + $this->assertNotEmpty($data['props']['_statamic']['nav']); } } From ea4546a05c8b118497af59f242a1be424e81cab9 Mon Sep 17 00:00:00 2001 From: lazerg Date: Sat, 19 Sep 2026 01:38:39 +0500 Subject: [PATCH 3/3] [6.x] Resolve shared props the same way Inertia does --- src/Statamic.php | 4 +-- ...HandleAuthenticatedInertiaRequestsTest.php | 28 +++++++++++++++++++ 2 files changed, 30 insertions(+), 2 deletions(-) diff --git a/src/Statamic.php b/src/Statamic.php index 432758c103e..619b95e10e8 100644 --- a/src/Statamic.php +++ b/src/Statamic.php @@ -523,8 +523,8 @@ public static function nonInertiaPageData() private static function resolveProps(array $props) { return collect($props)->map(function ($value) { - if ($value instanceof Closure) { - $value = $value(); + if (is_object($value) && is_callable($value)) { + $value = App::call($value); } return is_array($value) ? static::resolveProps($value) : $value; diff --git a/tests/Http/Middleware/HandleAuthenticatedInertiaRequestsTest.php b/tests/Http/Middleware/HandleAuthenticatedInertiaRequestsTest.php index 5cd37d48ce6..332ea190c2b 100644 --- a/tests/Http/Middleware/HandleAuthenticatedInertiaRequestsTest.php +++ b/tests/Http/Middleware/HandleAuthenticatedInertiaRequestsTest.php @@ -2,7 +2,9 @@ namespace Tests\Http\Middleware; +use Illuminate\Http\Request; use Illuminate\Support\Facades\Route; +use Inertia\Inertia; use PHPUnit\Framework\Attributes\Test; use Statamic\Facades\CP\Nav; use Statamic\Facades\User; @@ -72,4 +74,30 @@ public function it_resolves_the_nav_for_pages_rendered_outside_of_inertia() $this->assertNotEmpty($data['props']['_statamic']['nav']); } + + #[Test] + public function it_resolves_shared_callables_the_same_way_inertia_does() + { + Inertia::share([ + 'closure_with_dependency' => fn (Request $request) => $request->path(), + 'invokable' => new SharedInvokable, + ]); + + $data = $this + ->actingAs(User::make()->makeSuper()->save()) + ->get('/cp/non-inertia-page-data-test') + ->assertOk() + ->json(); + + $this->assertEquals('cp/non-inertia-page-data-test', $data['props']['closure_with_dependency']); + $this->assertEquals('invoked', $data['props']['invokable']); + } +} + +class SharedInvokable +{ + public function __invoke() + { + return 'invoked'; + } }