Skip to content

Commit 27fb7e8

Browse files
[1.x] Persistent properties (#621)
* add persistent properties * persist properties in middleware * formatting --------- Co-authored-by: Taylor Otwell <[email protected]>
1 parent e05a8bd commit 27fb7e8

File tree

8 files changed

+135
-6
lines changed

8 files changed

+135
-6
lines changed

src/Inertia.php

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,9 @@
1818
* @method static void mixin(object $mixin, bool $replace = true)
1919
* @method static bool hasMacro(string $name)
2020
* @method static void flushMacros()
21+
* @method static void persist(string|array|\Illuminate\Contracts\Support\Arrayable $props)
22+
* @method static array getPersisted()
23+
* @method static void flushPersisted()
2124
*
2225
* @see \Inertia\ResponseFactory
2326
*/

src/Middleware.php

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,13 @@ class Middleware
1919
*/
2020
protected $rootView = 'app';
2121

22+
/**
23+
* The properties that should always be included on Inertia responses, regardless of "only" or "except" requests.
24+
*
25+
* @var array
26+
*/
27+
protected $persisted = [];
28+
2229
/**
2330
* Determines the current asset version.
2431
*
@@ -83,6 +90,7 @@ public function handle(Request $request, Closure $next)
8390
});
8491

8592
Inertia::share($this->share($request));
93+
Inertia::persist($this->persisted);
8694
Inertia::setRootView($this->rootView($request));
8795

8896
$response = $next($request);

src/Response.php

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,17 +23,19 @@ class Response implements Responsable
2323

2424
protected $component;
2525
protected $props;
26+
protected $persisted;
2627
protected $rootView;
2728
protected $version;
2829
protected $viewData = [];
2930

3031
/**
3132
* @param array|Arrayable $props
3233
*/
33-
public function __construct(string $component, $props, string $rootView = 'app', string $version = '')
34+
public function __construct(string $component, array $props, string $rootView = 'app', string $version = '', array $persisted = [])
3435
{
3536
$this->component = $component;
3637
$this->props = $props instanceof Arrayable ? $props->toArray() : $props;
38+
$this->persisted = $persisted;
3739
$this->rootView = $rootView;
3840
$this->version = $version;
3941
}
@@ -158,7 +160,10 @@ public function resolveArrayableProperties(array $props, Request $request, bool
158160
*/
159161
public function resolveOnly(Request $request, array $props): array
160162
{
161-
$only = array_filter(explode(',', $request->header(Header::PARTIAL_ONLY, '')));
163+
$only = array_merge(
164+
array_filter(explode(',', $request->header(Header::PARTIAL_ONLY, ''))),
165+
$this->persisted
166+
);
162167

163168
$value = [];
164169

src/ResponseFactory.php

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,9 @@ class ResponseFactory
2424
/** @var array */
2525
protected $sharedProps = [];
2626

27+
/** @var array */
28+
protected $persisted = [];
29+
2730
/** @var Closure|string|null */
2831
protected $version;
2932

@@ -66,6 +69,30 @@ public function flushShared(): void
6669
$this->sharedProps = [];
6770
}
6871

72+
/**
73+
* @param string|array|Arrayable $props
74+
*/
75+
public function persist($props): void
76+
{
77+
if (is_array($props)) {
78+
$this->persisted = array_merge($this->persisted, $props);
79+
} elseif ($props instanceof Arrayable) {
80+
$this->persisted = array_merge($this->persisted, $props->toArray());
81+
} else {
82+
$this->persisted[] = $props;
83+
}
84+
}
85+
86+
public function getPersisted(): array
87+
{
88+
return $this->persisted;
89+
}
90+
91+
public function flushPersisted(): void
92+
{
93+
$this->persisted = [];
94+
}
95+
6996
/**
7097
* @param Closure|string|null $version
7198
*/
@@ -101,7 +128,8 @@ public function render(string $component, $props = []): Response
101128
$component,
102129
array_merge($this->sharedProps, $props),
103130
$this->rootView,
104-
$this->getVersion()
131+
$this->getVersion(),
132+
$this->persisted
105133
);
106134
}
107135

tests/MiddlewareTest.php

Lines changed: 31 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -239,10 +239,39 @@ public function rootView(Request $request): string
239239
$response->assertViewIs('welcome');
240240
}
241241

242-
private function prepareMockEndpoint($version = null, $shared = [], $middleware = null): \Illuminate\Routing\Route
242+
public function test_middleware_can_set_persisted_properties(): void
243+
{
244+
$shared = [
245+
'shared' => [
246+
'flash' => 'The user has been updated.'
247+
]
248+
];
249+
250+
$this->prepareMockEndpoint(null, $shared, null, ['shared']);
251+
252+
$response = $this->get('/', [
253+
'X-Inertia' => 'true',
254+
'X-Inertia-Partial-Component' => 'User/Edit',
255+
'X-Inertia-Partial-Data' => 'user'
256+
]);
257+
258+
$response->assertOk();
259+
$response->assertJson([
260+
'props' => [
261+
'shared' => [
262+
'flash' => 'The user has been updated.'
263+
],
264+
'user' => [
265+
'name' => 'Jonathan',
266+
]
267+
]
268+
]);
269+
}
270+
271+
private function prepareMockEndpoint($version = null, $shared = [], $middleware = null, $persisted = []): \Illuminate\Routing\Route
243272
{
244273
if (is_null($middleware)) {
245-
$middleware = new ExampleMiddleware($version, $shared);
274+
$middleware = new ExampleMiddleware($version, $shared, $persisted);
246275
}
247276

248277
return Route::middleware(StartSession::class)->get('/', function (Request $request) use ($middleware) {

tests/ResponseFactoryTest.php

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -150,6 +150,22 @@ public function test_can_flush_shared_data(): void
150150
$this->assertSame([], Inertia::getShared());
151151
}
152152

153+
public function test_can_persist_properties(): void
154+
{
155+
Inertia::persist('auth.user');
156+
$this->assertSame(['auth.user'], Inertia::getPersisted());
157+
Inertia::persist(['posts']);
158+
$this->assertSame(['auth.user', 'posts'], Inertia::getPersisted());
159+
}
160+
161+
public function test_can_flush_persisted_data(): void
162+
{
163+
Inertia::persist('auth.user');
164+
$this->assertSame(['auth.user'], Inertia::getPersisted());
165+
Inertia::flushPersisted();
166+
$this->assertSame([], Inertia::getPersisted());
167+
}
168+
153169
public function test_can_create_lazy_prop(): void
154170
{
155171
$factory = new ResponseFactory();

tests/ResponseTest.php

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -326,6 +326,40 @@ public function test_lazy_props_are_included_in_partial_reload(): void
326326
$this->assertSame('A lazy value', $page->props->lazy);
327327
}
328328

329+
public function test_persist_props_on_partial_reload(): void
330+
{
331+
$request = Request::create('/user/123', 'GET');
332+
$request->headers->add(['X-Inertia' => 'true']);
333+
$request->headers->add(['X-Inertia-Partial-Component' => 'User/Edit']);
334+
$request->headers->add(['X-Inertia-Partial-Data' => 'data']);
335+
336+
$props = [
337+
'auth' => [
338+
'user' => new LazyProp(function () {
339+
return [
340+
'name' => 'Jonathan Reinink',
341+
'email' => '[email protected]',
342+
];
343+
}),
344+
'token' => 'value',
345+
],
346+
'data' => [
347+
'name' => 'Taylor Otwell',
348+
'email' => '[email protected]',
349+
]
350+
];
351+
352+
$response = new Response('User/Edit', $props, 'app', '123', ['auth.user']);
353+
$response = $response->toResponse($request);
354+
$page = $response->getData();
355+
356+
$this->assertFalse(isset($page->props->auth->token));
357+
$this->assertSame('Jonathan Reinink', $page->props->auth->user->name);
358+
$this->assertSame('[email protected]', $page->props->auth->user->email);
359+
$this->assertSame('Taylor Otwell', $page->props->data->name);
360+
$this->assertSame('[email protected]', $page->props->data->email);
361+
}
362+
329363
public function test_top_level_dot_props_get_unpacked(): void
330364
{
331365
$props = [

tests/Stubs/ExampleMiddleware.php

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,10 +19,16 @@ class ExampleMiddleware extends Middleware
1919
*/
2020
protected $shared = [];
2121

22-
public function __construct($version = null, $shared = [])
22+
/**
23+
* @var array
24+
*/
25+
protected $persisted = [];
26+
27+
public function __construct($version = null, $shared = [], $persisted = [])
2328
{
2429
$this->version = $version;
2530
$this->shared = $shared;
31+
$this->persisted = $persisted;
2632
}
2733

2834
/**

0 commit comments

Comments
 (0)