diff --git a/config/rapidez/frontend.php b/config/rapidez/frontend.php index 6c1421fa4..e8c41801d 100644 --- a/config/rapidez/frontend.php +++ b/config/rapidez/frontend.php @@ -95,4 +95,10 @@ // The path to redirect to after a failed checkout 'checkout_success_fail_redirect_path' => 'cart', + + // This array should contain any turbo frames with their respective views. + // These should then be used by using @turboframe('frame-name') + 'turbo-frames' => [ + // 'frame-name' => 'view-path', + ], ]; diff --git a/resources/views/layouts/app.blade.php b/resources/views/layouts/app.blade.php index 8d22cec1d..79227dc9e 100644 --- a/resources/views/layouts/app.blade.php +++ b/resources/views/layouts/app.blade.php @@ -21,7 +21,7 @@ - @php($configPath = route('config') . '?v=' . Cache::rememberForever('cachekey', fn () => md5(Str::random())) . '&s=' . config('rapidez.store')) + @php($configPath = route('config') . '?v=' . Rapidez::getCacheKey() . '&s=' . config('rapidez.store')) diff --git a/resources/views/turbo-frame.blade.php b/resources/views/turbo-frame.blade.php new file mode 100644 index 000000000..a143f83fb --- /dev/null +++ b/resources/views/turbo-frame.blade.php @@ -0,0 +1,5 @@ +@props(['frame', 'viewPath', 'isRoute' => false) + + + @includeCached($viewPath, ['deferred' => $isRoute]) + diff --git a/routes/web.php b/routes/web.php index 9a6c53f50..d0fbd13c0 100644 --- a/routes/web.php +++ b/routes/web.php @@ -32,4 +32,18 @@ Route::fallback(config('rapidez.routing.controllers.fallback')); Route::get('heartbeat', fn () => response()->json(['alive' => true])); + + // Register all turbo frame routes + if (count(config('rapidez.frontend.turbo-frames', []))) { + Route::middleware('cache.headers:public;max_age=3600;stale_while_revalidate=3600;etag')->group(function () { + Route::get('turbo/{frame}/{cachekey}', function (string $frame) { + $viewPath = config('rapidez.frontend.turbo-frames')[$frame] ?? null; + if (! $viewPath) { + abort(404); + } + + return view('rapidez::turbo-frame', ['frame' => $frame, 'viewPath' => $viewPath, 'isRoute' => true]); + }); + }); + } }); diff --git a/src/Facades/Rapidez.php b/src/Facades/Rapidez.php index a605ff5e9..3fb750a9e 100644 --- a/src/Facades/Rapidez.php +++ b/src/Facades/Rapidez.php @@ -11,6 +11,7 @@ * @method static ?string config(string $path, $default = null, bool $sensitive = false) * @method static ?string content($content) * @method static object fancyMagentoSyntaxDecoder(string $encodedString) + * @method static string getCacheKey() * @method static array getStores($storeId = null) * @method static array getStore($storeId) * @method static void setStore($store) diff --git a/src/Http/Controllers/ConfigController.php b/src/Http/Controllers/ConfigController.php index a2eeffb09..d67a33ccd 100644 --- a/src/Http/Controllers/ConfigController.php +++ b/src/Http/Controllers/ConfigController.php @@ -4,7 +4,6 @@ use Illuminate\Support\Arr; use Illuminate\Support\Facades\Cache; -use Illuminate\Support\Str; use Rapidez\Core\Facades\Rapidez; use Rapidez\Core\Models\Attribute; use Rapidez\Core\Models\Category; @@ -44,7 +43,7 @@ public function getExposedConfigValues(): array public function getConfig(): array { return [ - 'cachekey' => Cache::rememberForever('cachekey', fn () => md5(Str::random())), + 'cachekey' => Rapidez::getCacheKey(), 'translations' => __('rapidez::frontend'), 'index' => $this->getIndexNames(), diff --git a/src/Rapidez.php b/src/Rapidez.php index d37304409..801f66e05 100644 --- a/src/Rapidez.php +++ b/src/Rapidez.php @@ -7,9 +7,11 @@ use Illuminate\Support\Arr; use Illuminate\Support\Collection; use Illuminate\Support\Facades\App; +use Illuminate\Support\Facades\Cache; use Illuminate\Support\Facades\DB; use Illuminate\Support\Facades\Event; use Illuminate\Support\Facades\URL; +use Illuminate\Support\Str; use Rapidez\Core\Exceptions\StoreNotFoundException; use Rapidez\Core\Models\Config; use Rapidez\Core\Models\ConfigScopes; @@ -86,6 +88,11 @@ public function fancyMagentoSyntaxDecoder(string $encodedString): object return json_decode(str_replace(array_values($mapping), array_keys($mapping), $encodedString)); } + public function getCacheKey(): string + { + return Cache::rememberForever('cachekey', fn () => md5(Str::random())); + } + public function getStores(callable|array|int|string|null $store = null): array { $storeModel = config('rapidez.models.store'); diff --git a/src/RapidezServiceProvider.php b/src/RapidezServiceProvider.php index bee1c8b30..162d71541 100644 --- a/src/RapidezServiceProvider.php +++ b/src/RapidezServiceProvider.php @@ -3,6 +3,7 @@ namespace Rapidez\Core; use BladeUI\Icons\Factory; +use Exception; use Illuminate\Cache\RateLimiting\Limit; use Illuminate\Contracts\Debug\ExceptionHandler; use Illuminate\Contracts\Http\Kernel; @@ -133,7 +134,7 @@ protected function bootPublishables(): self // We're so explicit here as otherwise the json translations will also be published. // That will publish to /lang/vendor/rapidez/nl.json where it will not be loaded - // by default and; you should keep everyting in one place: /lang/nl.json + // by default and; you should keep everything in one place: /lang/nl.json foreach (['en', 'nl'] as $lang) { $this->publishes([ __DIR__ . '/../lang/' . $lang . '/frontend.php' => lang_path('vendor/rapidez/' . $lang . '/frontend.php'), @@ -238,6 +239,15 @@ protected function registerBladeDirectives(): self return ""; }); + Blade::directive('turboframe', function (string $frame) { + $viewPath = config('rapidez.frontend.turbo-frames')[$frame] ?? null; + if (! $viewPath) { + throw new Exception('Turbo frame ' . $frame . ' not found.'); + } + + return "make('rapidez::turbo-frame', [...\Illuminate\Support\Arr::except(get_defined_vars(), ['__data', '__path']), 'frame' => '{$frame}', 'viewPath' => '{$viewPath}', 'isRoute' => false])->render(); ?>"; + }); + Blade::if('storecode', function ($value) { $value = is_array($value) ? $value : func_get_args(); @@ -412,7 +422,7 @@ function ($url) { $this->setAppends( Arr::reject( - $this->getAppends(), fn ($curentAppends) => in_array($curentAppends, $appendsToRemove) + $this->getAppends(), fn ($currentAppends) => in_array($currentAppends, $appendsToRemove) ) );