Skip to content

Commit

Permalink
Fixed Issue with Sharing
Browse files Browse the repository at this point in the history
Added Middleware
Proper Serialization / Unserialization
  • Loading branch information
jon committed Apr 27, 2022
1 parent 76754df commit 0e7fe8a
Show file tree
Hide file tree
Showing 5 changed files with 160 additions and 39 deletions.
16 changes: 16 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,17 @@ return [
'persistent-keys' => [
// foo, bar, baz
],

/*
|--------------------------------------------------------------------------
| Middleware
|--------------------------------------------------------------------------
|
| Middleware to register the inertia share request
| Default: 'web'
|
*/
'middleware' => 'web',
];
```

Expand All @@ -71,6 +82,11 @@ $flash->share('foo', 'bar');
// Or using the helper
inertia_flash()->share('foo', 'bar');

// With a closure that will be serialized
inertia_flash()->share('foo', fn() => 'bar');

// With a nested closure
inertia_flash()->share('foo', ['bar' => 'foo', 'baz' => fn() => 'bar']);

// On Controllers return back()
return back()->inertia('foo', 'bar');
Expand Down
14 changes: 13 additions & 1 deletion config/inertia-flash.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
return [
/*
|--------------------------------------------------------------------------
| Session Key
| Session Configuration
|--------------------------------------------------------------------------
|
| Key to be used on session, when we flash the items. This should be a
Expand All @@ -11,6 +11,7 @@
*/

'session-key' => 'inertia-container',
'flush' => true,

/*
|--------------------------------------------------------------------------
Expand All @@ -25,4 +26,15 @@
'persistent-keys' => [
// foo, bar, baz
],

/*
|--------------------------------------------------------------------------
| Middleware
|--------------------------------------------------------------------------
|
| Middleware to register the inertia share request
| Default: 'web'
|
*/
'middleware' => 'web',
];
23 changes: 23 additions & 0 deletions src/Http/Middleware/InertiaFlashMiddleware.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
<?php

namespace Igerslike\InertiaFlash\Http\Middleware;

use Illuminate\Http\Request;
use Illuminate\Http\Response;

class InertiaFlashMiddleware
{
/**
* Handle the incoming request.
*
* @param Request $request
* @param callable $next
*
* @return Response
*/
public function handle($request, $next)
{
inertia_flash()->shareToInertia();
return $next($request);
}
}
137 changes: 99 additions & 38 deletions src/InertiaFlash.php
Original file line number Diff line number Diff line change
Expand Up @@ -24,15 +24,10 @@ public function __construct()
{
// On build, we will pull from session.
$this->container = collect(session()->get(config('inertia-flash.session-key','inertia-container'), []));
// Unpack the variables in case if its serialized.
$this->resolveContainerValues();
// then for each item that is still on the container if any, we will inertia share them :)
$this->syncToInertia();
// We need to Flush also
session()->forget(config('inertia-flash.session-key','inertia-container'));
$this->flushSession();
}


/**
*
* Shares the Value with Inertia & Also stores it in the session.
Expand All @@ -45,10 +40,8 @@ public function __construct()
*/
public function share(string $key, $value, bool $append = false): static
{

if($value instanceof Closure) {
$value = new SerializableClosure($value);
}
// Ensure we serialize the value for sharing
$value = $this->serializeValue($value);

if($append) {
$current = array_merge_recursive($this->container->get($key, []), [$value]);
Expand All @@ -57,7 +50,7 @@ public function share(string $key, $value, bool $append = false): static
$this->container->put($key, $value);
}

$this->syncWithSessionAndInertia();
$this->shareToSession();

return $this;
}
Expand Down Expand Up @@ -112,85 +105,153 @@ public function shareUnless(bool $condition, string $key, $value, bool $append =
* Forget the value from the container & session
*
* @param ...$keys
* @return $this
* @return static
*/
public function forget(...$keys): static
{
$this->container->forget(...$keys);
inertia()->forget(...$keys);
$this->syncWithSessionAndInertia();
$this->shareToSession();
return $this;
}

/**
* Flush the items from the session
* And also from inertia
*
* @return $this
* @return static
*/
public function flush(): static
{
$keys = $this->container->keys();
$this->container = collect([]);
inertia()->forget($keys->toArray());
$this->flushSession();
return $this;
}

/**
* Flush the session only
*
* @return $this
*/
public function flushSession(): static
{
session()->forget(config('inertia-flash.session-key','inertia-container'));
return $this;
}

/**
* Attempts to resolve the value recursively.
* Syncs to Inertia Share
*
* @param $value
* @return mixed
* @param bool $flushSession
* @return InertiaFlash
*/
public function shareToInertia(bool $flushSession = true): static
{
// Unserialize/Unpack any pending Serialized Closures
$this->unserializeContainerValues();

// Persist the keys for emptiness
$persistentKeys = config('inertia-flash.persistent-keys', []);
if(!empty($persistentKeys)) {
collect($persistentKeys)->each(fn($value, $key) => inertia()->share($key, $value));
}

// Share with Inertia
$this->container->each(fn($value, $key) => inertia()->share($key, $value));

// Flush on sharing
if($flushSession && config('inertia-flash.flush', true)) {
$this->flushSession();
}
return $this;
}

/**
* Syncs to Inertia Share & Also for the Session
*
* @return $this
*/
protected function shareToSession(): static
{
// Need to pack/serialize to session, because session does not support closures
// But it does take Laravel Serializable Closure
$this->serializeContainerValues();

// Then we are ready to put it in the session
session()->put(config('inertia-flash.session-key','inertia-container'), $this->container->toArray());

return $this;
}

/**
* Attempt to Serialize closures
* @throws PhpVersionNotSupportedException
*/
protected function resolveValue($value): mixed
protected function serializeValue($value)
{
if($value instanceof SerializableClosure) {
return $value->getClosure();
if($value instanceof Closure) {
return new SerializableClosure($value);
}

if(is_array($value)) {
foreach($value as $key => $item) {
$value[$key] = $this->resolveValue($item);

// Other edge cases can be added here
if(!$item instanceof Closure) {
continue;
}

$value[$key] = $this->serializeValue($item);

}
}

return $value;
}

/**
* Transforms the values, and attempts to resolve pending Serialized Closures
* Attempts to resolve the value recursively.
*
* @return void
* @param $value
* @return mixed
* @throws PhpVersionNotSupportedException
*/
protected function resolveContainerValues(): void
protected function unserializeValue($value): mixed
{
$this->container->transform(fn($value) => $this->resolveValue($value));
if($value instanceof SerializableClosure) {
return $value->getClosure();
}

if(is_array($value)) {
foreach($value as $key => $item) {
$value[$key] = $this->unserializeValue($item);
}
}

return $value;
}

/**
* Syncs to Inertia Share
* Transforms the values, and attempts to resolve pending Serialized Closures
*
* @return void
* @return static
*/
protected function syncToInertia(): void
protected function unserializeContainerValues(): static
{
$persistentKeys = config('inertia-flash.persistent-keys', []);
if(!empty($persistentKeys)) {
collect($persistentKeys)->each(fn($value, $key) => inertia()->share($key, $value));
}
$this->container->each(fn($value, $key) => inertia()->share($key, $value));
$this->container->transform(fn($value) => $this->unserializeValue($value));
return $this;
}

/**
* Syncs to Inertia Share & Also for the Session
* Transforms the values, and attempts to resolve pending Serialized Closures
*
* @return $this
* @return static
*/
protected function syncWithSessionAndInertia(): static
protected function serializeContainerValues(): static
{
$this->syncToInertia();
session()->put(config('inertia-flash.session-key','inertia-container'), $this->container->toArray());
$this->container->transform(fn($value) => $this->serializeValue($value));
return $this;
}
}
9 changes: 9 additions & 0 deletions src/InertiaFlashServiceProvider.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

namespace Igerslike\InertiaFlash;

use Igerslike\InertiaFlash\Http\Middleware\InertiaFlashMiddleware;
use Illuminate\Contracts\Http\Kernel;
use Illuminate\Http\RedirectResponse;
use Illuminate\Support\Arr;
use Inertia\Inertia;
Expand All @@ -17,6 +19,13 @@ public function configurePackage(Package $package): void
->hasConfigFile();
}

public function bootingPackage()
{
$kernel = $this->app->make(Kernel::class);
$kernel->appendMiddlewareToGroup(config('inertia-flash.middleware','web'), InertiaFlashMiddleware::class);
$kernel->appendToMiddlewarePriority(InertiaFlashMiddleware::class);
}

public function registeringPackage()
{
// Register Singleton
Expand Down

0 comments on commit 0e7fe8a

Please sign in to comment.