v2-hub
v2-hub copied to clipboard
Localizing a slug in the CP does not update URLs.
Describe the bug Changing a localized slug in the CP does not update all the appropriate URLs in the Stache.
To Reproduce Steps to reproduce the behavior:
- Set
stache_always_update: false
- Edit a page in the secondary locale
- Change the slug
- Using a
{{ dump }}
inside a nav tag, for example, notice thatslug
has been updated, but noturl
,uri
, etc
Expected behavior The URLs should be updated appropriately.
Environment details:
- Statamic Version [e.g. 2.8.12]: 2.10.3
Additional context Add any other context about the problem here.
Works fine with stache_always_update: true
cc @FrittenKeeZ
Hi @jasonvarga,
We are facing this bug on every project, as we have a lot of multi-locale projects in Switzerland. Changing a slug in a secondary language immediately results in a 404
, because the URI of such content cannot be found in the Stache. This is a serious problem for multi-locale setups and basically requires to use stache_always_update: true
or clearing the cache manually. Both are not a solution for projects with a lot of content.
I invested quite some time to figure out how to solve this issue. Attached is a diff with my changes. Applying the diff should result in the following changed behaviour:
- Uris of localized content (when changing slugs) are written into the Stache
- Changing a localized slug of a page will also update the localized uris of children
- The localized uris are deleted from the Stache when content gets deleted
Would it be possible to review, test and integrate these changes? I've run some basic tests and everything seems to work fine. However, I do not have enough knowledge about the Stache and thus I'm not sure if this implementation is the way to go or if it introduces other side-effects.
We really appreciate if you could find some time to solve this issue. ❤️If anyone wants to make some tests, here's the diff:
diff --git a/statamic/core/Stache/Listeners/UpdateItem.php b/statamic/core/Stache/Listeners/UpdateItem.php
index b170db59..f82067e8 100644
--- a/statamic/core/Stache/Listeners/UpdateItem.php
+++ b/statamic/core/Stache/Listeners/UpdateItem.php
@@ -2,6 +2,7 @@
namespace Statamic\Stache\Listeners;
+use Statamic\API\Config;
use Statamic\API\Str;
use Statamic\API\Path;
use Statamic\Stache\Stache;
@@ -113,8 +114,16 @@ class UpdateItem
->setPath($id, $path)
->setItem($id, $data);
- if ($this->stache->driver($this->driverKey($repo))->isRoutable()) {
+ $driver = $this->stache->driver($this->driverKey($repo));
+ if ($driver->isRoutable()) {
$this->stache->repo($repo)->setUri($id, $data->uri());
+
+ // Update localized uris in the Stache.
+ foreach (Config::getOtherLocales() as $locale) {
+ $localizedData = $this->getDataForLocale($data, $locale);
+ $localizedUri = $driver->getLocalizedUri($locale, $localizedData, $path);
+ $this->stache->repo($repo)->setUri($id, $localizedUri, $locale);
+ }
}
$this->stache->updated($this->repo());
@@ -122,6 +131,11 @@ class UpdateItem
if ($repo === 'pages') {
$this->updateSavedItem($data->structure());
$this->updateChildPages($data, $original);
+
+ // Recursively update localized uris of child pages.
+ foreach (Config::getOtherLocales() as $locale) {
+ $this->updateUriOfLocalizedChildPages($data, $locale);
+ }
}
}
@@ -317,4 +331,27 @@ class UpdateItem
{
return (Str::contains($key, '::')) ? explode('::', $key)[0] : $key;
}
+
+ protected function getDataForLocale(Data $data, $locale)
+ {
+ $localizedData = $data->dataForLocale($locale);
+ if (!isset($localizedData['id'])) {
+ $localizedData['id'] = $data->id();
+ }
+
+ return $localizedData;
+ }
+
+ protected function updateUriOfLocalizedChildPages(Data $data, $locale)
+ {
+ $driver = $this->stache->driver($this->driverKey('pages'));
+
+ foreach ($data->children(1) as $id => $child) {
+ $localizedData = $this->getDataForLocale($child, $locale);
+ $localizedUri = $driver->getLocalizedUri($locale, $localizedData, $child->path());
+ $this->stache->repo('pages')->setUri($id, $localizedUri, $locale);
+
+ $this->updateUriOfLocalizedChildPages($child, $locale);
+ }
+ }
}
diff --git a/statamic/core/Stache/Repository.php b/statamic/core/Stache/Repository.php
index 10c7b71e..7376fbaa 100644
--- a/statamic/core/Stache/Repository.php
+++ b/statamic/core/Stache/Repository.php
@@ -3,6 +3,7 @@
namespace Statamic\Stache;
use Illuminate\Support\Collection;
+use Statamic\API\Config;
use Statamic\Events\Stache\RepositoryItemInserted;
use Statamic\Events\Stache\RepositoryItemRemoved;
use Statamic\Events\StacheItemInserted;
@@ -273,6 +274,12 @@ class Repository
$uris->forget($id);
}
+ foreach (Config::getOtherLocales() as $locale) {
+ if ($uris = $this->uris->get($locale)) {
+ $uris->forget($id);
+ }
+ }
+
event(new RepositoryItemRemoved($this, $id, $item));
return $this;
Cheers
@jasonvarga I know v2 is not your first priority, but would it be possible to get this fixed?
Just had another client reporting a 404
of a page after changing the slug in the secondary language. Clearing the Stache manually solved it, but this cannot be the solution. This is a serious bug and IMHO I think this needs to be fixed. After all, Statamic 2 is still supported. Code for the fix is above. Thanks! 🙏