Follow-up to #3424962: Allow redirects to be 'disabled'.
Problem/Motivation
When a path alias changes, redirect_path_alias_update() uses findMatchingRedirect() to check for an existing redirect from the old alias. Since #3424962: Allow redirects to be 'disabled' that lookup skips disabled redirects, but the unique key on redirect.hash doesn't. If a disabled redirect holds the old alias, a second one is created and the entity save fails:
SQLSTATE[23000]: Integrity constraint violation: 1062 Duplicate entry '...' for key 'redirect.hash'
With Workspaces support (#3313540: Convert the Redirect entity type to revisionable) this is common: a redirect created in a workspace is disabled in Live but holds its hash, so changing the same alias in Live or in another workspace fails.
Steps to reproduce
- Create a node with the alias
/x. - Add a disabled redirect from
xto any path. - Change the node's alias to
/y.
Proposed resolution
Leave a disabled redirect from the old alias alone, as the hook already does for an enabled one:
- Add
RedirectRepository::findBySourceHash(), which finds redirects holding a source's hash, enabled or not. - Only create the redirect when neither
findMatchingRedirect()norfindBySourceHash()finds one. - Use
findBySourceHash()inUniqueHashValidatortoo, so the form and the hook run the same check.
API changes
New RedirectRepository::findBySourceHash(). UniqueHashValidator takes the redirect repository instead of the entity type manager.
Issue fork redirect-3629356
Show commands
Start within a Git clone of the project using the version control instructions.
Or, if you do not have SSH keys set up on git.drupalcode.org:
Comments
Comment #3
amateescu commentedComment #4
plachComment #5
amateescu commentedPushed a follow-up commit:
findBySourceHash()now reads the base table directly, since that's where the unique key onhashis. On 8.x-1.x this gives the same result as the entity query. It matters once redirects are revisionable (#3313540: Convert the Redirect entity type to revisionable): inside a workspace an entity query matches the workspace revisions, so a redirect whose source was changed in the workspace wasn't found, and a new redirect from its old source failed on the unique key. Thanks to @plach for spotting this.A redirect trashed in a workspace has the same problem, because Trash hides it from the check. That part is fixed in Trash: #3630354: A new redirect fails to save when a redirect trashed in the same workspace has the same source.
Comment #6
plachLooks good and works well, thanks!