Skip to content

Commit 8e4d31e

Browse files
committed
Implement redirecting
Fix PHPstan errors
1 parent 71edb66 commit 8e4d31e

10 files changed

+134
-36
lines changed

README.md

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -247,6 +247,34 @@ The style can also be configured in the database model, then you can skip the `s
247247

248248
See the [menu seeding documentation](documentation/seeders.md) for programmatic menu creation.
249249

250+
## Redirects
251+
252+
The package includes automatic redirect management: when the slug of a page changes, a redirect from the old page
253+
to the new page is added. These redirects are stored in the database and are managable with the Filament resource,
254+
so you can add your own redirects.
255+
256+
Additionally, we integrated [spatie/laravel-missing-page-redirector](https://github.com/spatie/laravel-missing-page-redirector),
257+
so you can easily configure other redirects in the spatie packages config.
258+
259+
### Configuration
260+
261+
1. Prepend/append the [RedirectsMissingPages.php](src/Http/Middleware/RedirectsMissingPages.php) middleware to your global middleware stack:
262+
263+
```php
264+
// bootstrap/app.php
265+
->withMiddleware(function (Middleware $middleware) {
266+
$middleware->append([
267+
\Statikbe\FilamentFlexibleContentBlockPages\Http\Middleware\RedirectsMissingPages::class,
268+
]);
269+
})
270+
```
271+
272+
2. **Optional:** If you want to hardcode a set of redirects, you can [do this in the config file of the spatie package](https://github.com/spatie/laravel-missing-page-redirector?tab=readme-ov-file#usage). Publish this package:
273+
274+
```php
275+
php artisan vendor:publish --provider="Spatie\MissingPageRedirector\MissingPageRedirectorServiceProvider"
276+
```
277+
250278
## Sitemap Generator
251279

252280
The package includes an automatic sitemap generator that creates XML sitemaps for your website with support for multilingual sites and various content types.

config/filament-flexible-content-block-pages.php

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -136,6 +136,17 @@
136136

137137
'redirects' => [
138138
'navigation_sort' => 10,
139+
140+
/*
141+
|--------------------------------------------------------------------------
142+
| Redirector
143+
|--------------------------------------------------------------------------
144+
|
145+
| This package implements its own redirector for spatie/laravel-missing-page-redirector.
146+
| To avoid manual configuration of this custom redirector in the spatie-package's config, we set the default here.
147+
| In case you would like to customise this, please change the redirector here and not in the spatie package.
148+
*/
149+
'redirector' => \Statikbe\FilamentFlexibleContentBlockPages\Services\DatabaseAndConfigRedirector::class,
139150
],
140151

141152
'settings' => [

src/Actions/LinkedToMenuItemBulkDeleteAction.php

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ public function setUp(): void
2828
/** @var Model&HasMenuLabel $record */
2929
// Prevent deletion if the page is referenced by a menu item
3030
/** @var ?MenuItem $menuItem */
31+
/** @phpstan-ignore-next-line */
3132
$menuItem = $record->menuItem;
3233

3334
if ($menuItem) {
@@ -39,11 +40,14 @@ public function setUp(): void
3940

4041
if (! empty($referencedPages)) {
4142
$pageNames = collect($referencedPages)->map(function (Model&HasMenuLabel $page) {
43+
/** @var ?MenuItem $menuItem */
44+
/** @phpstan-ignore-next-line */
45+
$menuItem = $page->menuItem;
4246
return '<li>'.
4347
flexiblePagesTrans('pages.notifications.page_referenced_by_menu_item', [
4448
'page' => $page->getMenuLabel(),
45-
'menu' => $page->menuItem->menu->name,
46-
'menu_item' => $page->menuItem->getDisplayLabel(),
49+
'menu' => $menuItem?->menu->name,
50+
'menu_item' => $menuItem?->getDisplayLabel(),
4751
])
4852
.'</li>';
4953
})->join('');

src/Actions/LinkedToMenuItemDeleteAction.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ protected function setUp(): void
2020
$this->action(function (Model&HasMenuLabel $record, $action) {
2121
// Prevent deletion if the page is referenced by a menu item
2222
/** @var ?MenuItem $menuItem */
23+
/** @phpstan-ignore-next-line */
2324
$menuItem = $record->menuItem;
2425

2526
if ($menuItem) {

src/FilamentFlexibleContentBlockPagesServiceProvider.php

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
use Mcamara\LaravelLocalization\Facades\LaravelLocalization;
77
use Spatie\LaravelPackageTools\Package;
88
use Spatie\LaravelPackageTools\PackageServiceProvider;
9+
use Spatie\MissingPageRedirector\Redirector\Redirector;
910
use Statikbe\FilamentFlexibleContentBlockPages\Commands\GenerateSitemapCommand;
1011
use Statikbe\FilamentFlexibleContentBlockPages\Commands\SeedDefaultsCommand;
1112
use Statikbe\FilamentFlexibleContentBlockPages\Components\BaseLayout;
@@ -69,5 +70,8 @@ function ($app) {
6970
return $app->make($serviceClass);
7071
}
7172
);
73+
74+
// set our custom redirector for spatie/laravel-missing-page-redirector
75+
$this->app->bind(Redirector::class, config('filament-flexible-content-block-pages.redirects.redirector'));
7276
}
7377
}
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
<?php
2+
3+
namespace Statikbe\FilamentFlexibleContentBlockPages\Http\Middleware;
4+
5+
use Closure;
6+
use Illuminate\Http\RedirectResponse;
7+
use Illuminate\Http\Request;
8+
use Illuminate\Http\Response;
9+
use Illuminate\Support\Str;
10+
use Spatie\MissingPageRedirector\RedirectsMissingPages as SpatieRedirectsMissingPages;
11+
12+
/**
13+
* Extended to keep query strings in redirects working.
14+
*/
15+
class RedirectsMissingPages extends SpatieRedirectsMissingPages
16+
{
17+
public function handle(Request $request, Closure $next)
18+
{
19+
/** @var Response $response */
20+
$response = parent::handle($request, $next);
21+
22+
if ($request->query->count() > 0 && $response->$this->shouldRedirect($response)) {
23+
// make sure we do not lose the query string:
24+
/** @var RedirectResponse $response */
25+
if (! Str::contains($response->getTargetUrl(), '?')) {
26+
$response->setTargetUrl($response->getTargetUrl().'?'.$request->getQueryString());
27+
}
28+
}
29+
30+
return $response;
31+
}
32+
}

src/Models/MenuItem.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
* @property int $parent_id
3030
* @property \Illuminate\Database\Eloquent\Collection<int, MenuItem> $children
3131
* @property \Illuminate\Database\Eloquent\Model|null $linkable
32+
* @property Menu $menu
3233
*/
3334
class MenuItem extends Model
3435
{

src/Models/Redirect.php

Lines changed: 0 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -21,42 +21,13 @@ class Redirect extends Model
2121
{
2222
use HasFactory;
2323

24-
const CACHE_REDIRECTS_KEY = 'filament-flexible-content-block-pages:redirects';
25-
2624
protected $guarded = ['id'];
2725

2826
public function getTable()
2927
{
3028
return FilamentFlexibleContentBlockPages::config()->getRedirectsTable();
3129
}
3230

33-
/**
34-
* Returns a list of old and new urls with the status code if set compatible with spatie/laravel-missing-page-redirector,
35-
* that merges the redirects set in the database over the redirects set in the config.
36-
*/
37-
public static function getDirectionMap(): array
38-
{
39-
// Get from the database and remember forever
40-
// we clear this on new model or updated model
41-
$dbRedirects = Cache::rememberForever(static::CACHE_REDIRECTS_KEY, function () {
42-
return Redirect::all()->flatMap(function (Redirect $redirect) {
43-
if ($redirect->status_code) {
44-
return [
45-
$redirect->old_url => [$redirect->new_url, $redirect->status_code],
46-
];
47-
} else {
48-
return [$redirect->old_url => $redirect->new_url];
49-
}
50-
})->toArray();
51-
});
52-
53-
// Get the redirects from the config
54-
$configRedirects = config('missing-page-redirector.redirects');
55-
56-
// Merge both values
57-
return array_merge($configRedirects, $dbRedirects);
58-
}
59-
6031
public function getMorphClass()
6132
{
6233
return 'filament-flexible-content-block-pages::redirect';

src/Observers/RedirectObserver.php

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
use Illuminate\Support\Facades\Cache;
66
use Statikbe\FilamentFlexibleContentBlockPages\Models\Redirect;
7+
use Statikbe\FilamentFlexibleContentBlockPages\Services\DatabaseAndConfigRedirector;
78

89
/**
910
* Clear redirect cache if a redirect changes
@@ -15,38 +16,43 @@ class RedirectObserver
1516
*/
1617
public function created(Redirect $redirect): void
1718
{
18-
Cache::forget(Redirect::CACHE_REDIRECTS_KEY);
19+
$this->clearRedirectCache();
1920
}
2021

2122
/**
2223
* Handle the Redirect "updated" event.
2324
*/
2425
public function updated(Redirect $redirect): void
2526
{
26-
Cache::forget(Redirect::CACHE_REDIRECTS_KEY);
27+
$this->clearRedirectCache();
2728
}
2829

2930
/**
3031
* Handle the Redirect "deleted" event.
3132
*/
3233
public function deleted(Redirect $redirect): void
3334
{
34-
Cache::forget(Redirect::CACHE_REDIRECTS_KEY);
35+
$this->clearRedirectCache();
3536
}
3637

3738
/**
3839
* Handle the Redirect "restored" event.
3940
*/
4041
public function restored(Redirect $redirect): void
4142
{
42-
Cache::forget(Redirect::CACHE_REDIRECTS_KEY);
43+
$this->clearRedirectCache();
4344
}
4445

4546
/**
4647
* Handle the Redirect "force deleted" event.
4748
*/
4849
public function forceDeleted(Redirect $redirect): void
4950
{
50-
Cache::forget(Redirect::CACHE_REDIRECTS_KEY);
51+
$this->clearRedirectCache();
52+
}
53+
54+
private function clearRedirectCache(): void
55+
{
56+
Cache::forget(DatabaseAndConfigRedirector::CACHE_REDIRECTS_KEY);
5157
}
5258
}
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
<?php
2+
3+
namespace Statikbe\FilamentFlexibleContentBlockPages\Services;
4+
5+
use Illuminate\Support\Facades\Cache;
6+
use Spatie\MissingPageRedirector\Redirector\Redirector;
7+
use Statikbe\FilamentFlexibleContentBlockPages\Models\Redirect;
8+
use Symfony\Component\HttpFoundation\Request;
9+
10+
class DatabaseAndConfigRedirector implements Redirector
11+
{
12+
const CACHE_REDIRECTS_KEY = 'filament-flexible-content-block-pages:redirects';
13+
14+
/**
15+
* Returns a list of old and new urls with the status code if set compatible with spatie/laravel-missing-page-redirector,
16+
* that merges the redirects set in the database over the redirects set in the config.
17+
*/
18+
public function getRedirectsFor(Request $request): array
19+
{
20+
// Get from the database and remember forever
21+
// we clear this on new model or updated model
22+
$dbRedirects = Cache::rememberForever(static::CACHE_REDIRECTS_KEY, function () {
23+
return Redirect::all()->flatMap(function (Redirect $redirect) {
24+
if ($redirect->status_code) {
25+
return [
26+
$redirect->old_url => [$redirect->new_url, $redirect->status_code],
27+
];
28+
} else {
29+
return [$redirect->old_url => $redirect->new_url];
30+
}
31+
})->toArray();
32+
});
33+
34+
// Get the redirects from the config
35+
$configRedirects = config('missing-page-redirector.redirects', []);
36+
37+
// Merge both values
38+
return array_merge($configRedirects, $dbRedirects);
39+
}
40+
}

0 commit comments

Comments
 (0)