Skip to content

Commit 1258894

Browse files
committed
Avoid circular redirect references when slug changes
1 parent 06556b8 commit 1258894

File tree

1 file changed

+35
-9
lines changed

1 file changed

+35
-9
lines changed

src/Listeners/SlugChangedListener.php

Lines changed: 35 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
namespace Statikbe\FilamentFlexibleContentBlockPages\Listeners;
44

55
use Illuminate\Http\Response;
6+
use Illuminate\Support\Facades\DB;
67
use Statikbe\FilamentFlexibleContentBlockPages\Models\Page;
78
use Statikbe\FilamentFlexibleContentBlockPages\Models\Redirect;
89
use Statikbe\FilamentFlexibleContentBlocks\Events\SlugChanged;
@@ -33,16 +34,41 @@ public function handle(SlugChanged $event): void
3334
$oldUrlPath = parse_url($oldUrl, PHP_URL_PATH);
3435
$newUrlPath = parse_url($newUrl, PHP_URL_PATH);
3536

36-
$redirectExists = Redirect::where('old_url', $oldUrlPath)
37-
->where('new_url', $newUrlPath)
38-
->exists();
37+
try {
38+
DB::beginTransaction();
3939

40-
if (! $redirectExists) {
41-
$redirect = new Redirect;
42-
$redirect->old_url = $oldUrlPath;
43-
$redirect->new_url = $newUrlPath;
44-
$redirect->status_code = Response::HTTP_MOVED_PERMANENTLY;
45-
$redirect->save();
40+
// clean up old redirects & avoid circular references:
41+
// Rule 1: Delete records where $newUrlPath matches existing old_url.
42+
// This means that the starting point of the redirect, has been recreated.
43+
Redirect::where('old_url', $newUrlPath)->delete();
44+
45+
// Rule 2: Update records where $oldUrlPath matches existing new_url.
46+
// This means that old slug, was already the destination of an existing redirect, so to avoid
47+
// hopping multiple redirects, we update the existing redirect to the new slug.
48+
Redirect::where('new_url', $oldUrlPath)->update(['new_url' => $newUrlPath]);
49+
50+
// Rule 3: Delete self-redirects
51+
// Maybe we have created cases were the source and destination is the same.
52+
Redirect::whereColumn('old_url', 'new_url')->delete();
53+
54+
// Rule 4: Add a new redirect if it doesn't exist yet
55+
$redirectExists = Redirect::where('old_url', $oldUrlPath)
56+
->where('new_url', $newUrlPath)
57+
->exists();
58+
59+
if (!$redirectExists) {
60+
$redirect = new Redirect;
61+
$redirect->old_url = $oldUrlPath;
62+
$redirect->new_url = $newUrlPath;
63+
$redirect->status_code = Response::HTTP_MOVED_PERMANENTLY;
64+
$redirect->save();
65+
}
66+
67+
DB::commit();
68+
}
69+
catch (\Exception $e) {
70+
report($e);
71+
DB::rollBack();
4672
}
4773
}
4874
}

0 commit comments

Comments
 (0)