Problem/Motivation
I'm using a bundle class to override the toUrl() method on a particular node type. If some condition is met (the specifics are not important) I don't want the node to be visible on its own page and I don't want teasers and cards to render any links to the node
public function toUrl($rel = 'canonical', array $options = []) {
if ($rel === 'canonical') {
if (//some condition) {
return Url::fromRoute('<nolink>');
}
}
return parent::toUrl($rel, $options);
}
Let's assume I have created a node that meets the condition to have <nolink> as its canonical url. If I delete that node, every single url alias gets deleted.
That's because AliasStorageHelperInterface::deleteBySourcePrefix() gets called with / as the prefiz, which of course matches all aliases.
Proposed resolution
Add some check somewhere to prevent accidentally deleting all url aliases if a canonical url is <nolink>. Not sure if that would be best in AliasStorageHelper or pathauto.module.
One way to prevent this mass deletion from happening is to override the hasLinkTemplate() method in the bundle class such that it returns false if the node has a canonical url.
/**
* {@inheritdoc}
*/
public function hasLinkTemplate($rel) {
if ($rel === 'canonical') {
if (//some condition) {
return FALSE;
}
}
return parent::hasLinkTemplate($rel);
}
Remaining tasks
User interface changes
API changes
Data model changes
Issue fork pathauto-3367067
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 #2
bvoynickThank you for the report & suggestion to override hasLinkTemplate, it's coming in handy for me today.
Comment #3
mably commentedHere is the
deleteBySourcePrefixcode fromAliasStorageHelper:May be we could simply check there that
$sourceis not equal to/.But the
hasLinkTemplate()solution is probably the least impactful for now.Comment #4
mably commentedComment #6
mably commentedProblem
When an entity with a
<nolink>canonical URL (e.g. certain menu link content entities) was deleted, all path aliases on the site were wiped out.In
AliasStorageHelper::deleteEntityPathAll(), callinggetInternalPath()on a<nolink>URL returned an empty string. This causeddeleteBySourcePrefix('/')to be called, which matched every alias in the database.Fix
Two guard conditions were added before any deletion occurs:
$url->isRouted()— skip unrouted URLs entirely$internal_path !== ''— never calldeleteBySourcePrefix('/')with a bare slashTest coverage
A kernel test was added (
testDeleteEntityPathAllWithNoLinkEntity) that:<nolink>canonical URLdeleteEntityPathAll()on itThe test was verified to fail without the fix and pass with it.
Comment #7
berdirA minor suggestion, then fine to merge.
Comment #9
mably commented