Problem/Motivation
The method DomainAccessManager::getAccessValues() uses a static cache keyed only by entity type ID, entity ID, and field name. It does not take the entity's language into account.
When called on translated nodes, the first translation cached is reused for all subsequent translations. This results in incorrect domain values being returned for translations. As a result, hook_node_access_records() writes incorrect entries into the node_access table, which leads to access being denied for otherwise published and properly domain-assigned translations.
Steps to reproduce
- Enable Domain and Domain Access submodule.
- Create a node in language A, assign it to Domain X.
- Add a translation in language B, assign it to Domain Y.
- Inspect the
node_accesstable or attempt to view the translation as an anonymous user. - The translation is either inaccessible (403) or the
node_accessrows show the wrong domain assignment (Domain X instead of Domain Y).
Proposed resolution
- Extend the static cache key in
getAccessValues()to include the entity language code. - Example change:
$langcode = $entity->language()->getId(); if (isset(self::$staticCache[$entity->getEntityTypeId()][$entity->id()][$field_name][$langcode])) { return self::$staticCache[$entity->getEntityTypeId()][$entity->id()][$field_name][$langcode]; } ... self::$staticCache[$entity->getEntityTypeId()][$entity->id()][$field_name][$langcode] = $list; - This ensures each translation stores and returns its own domain access values correctly.
Remaining tasks
- Provide patch and rerun test suite.
- Add test coverage for multilingual nodes with different domain assignments per translation.
User interface changes
None.
Introduced terminology
None.
API changes
DomainAccessManager::getAccessValues() static cache structure changes (adds a langcode key). Existing callers are unaffected.
Data model changes
None.
Release notes snippet
Fixed a bug where multilingual nodes could receive incorrect domain access grants because getAccessValues() ignored translation language when caching. Sites using multilingual content should run node_access_rebuild() after updating.
Issue fork domain-3547422
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 #5
mably commentedHi @xavier.masson, by default, the domain access field doesn't seem to be translatable from what I can read from the
domain_access_confirm_fieldsfunction.Are you using some custom domain access field that you made translatable?
EDIT: Looks like you can simply enabled it in the content translation configuration.
I'll merge your MR in the 3.x dev branch so people can start playing with it.
Comment #6
mably commentedComment #7
mably commentedWhile working on the related functional tests, I found that we were using the wrong hooks to clear the access values static cache.
We must use
presave/predeleteinstead ofupdate/delete.I have updated my 3.x MR accordingly.
Any feedback welcome.
@xavier.masson are there any other tests you think we should add?
Comment #10
mably commented