Problem/Motivation
Since Drupal 8.7 you can publish/unpublish block_content via the UI. I have enabled translation for my block_content.
Now I came into the situation, that I wanted to have different "Published" states for the english and second language. So I made the "Published" property translatable which seems to work fine UI backend-wise. But in the frontend the access check for the block_content entity fails. It checks for the published state of the source language, but does not respect if the default language is set to "Unpublished" and the second language is set to "Published".
The reason is the access check in core/modules/block_content/src/Plugin/Block/BlockContentBlock.php It checks the access for the entity which is retrieved by $this->getEntity(). In this method you can see that it's loading the block_content by id, which will not be language aware and explains, why the access check fails.
protected function getEntity() {
if (!isset($this->blockContent)) {
$uuid = $this->getDerivativeId();
if ($id = $this->uuidLookup->get($uuid)) {
$this->blockContent = $this->entityTypeManager->getStorage('block_content')->load($id);
}
}
return $this->blockContent;
}
I fixed the problem by using
\Drupal::service('entity.repository')->getTranslationFromContext($this->blockContent);
to load the correct translated entity and therefore check for the correct translated published state.
Steps to reproduce
1. Install Drupal with two languages
2. Create a translatable block_content type
3. Configure the "Published" property to be translatable
4. Create a block content with your default language and set it to unpublished
5. Translate this block content into your secondary language and set it to published
6. Place the block somewhere with block UI.
You will see, that the the block is not visible in both language frontends, although your secondary language translation have been set to "Published".
By adding getTranslationFromContext as described above, the access check will respect the languages and show the expected results.
Proposed resolution
Use getTranslationFromContext in getEntity to ensure blocks are always translation aware.
Remaining tasks
Review https://git.drupalcode.org/project/drupal/-/merge_requests/11297
User interface changes
None
API changes
None
Data model changes
None
Issue fork drupal-3175985
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:
- 3175985-published-access-check
changes, plain diff MR !11297
Comments
Comment #2
larowlanDoes the node module do the same thing?
Comment #3
szeidlerThe node module does the same thing via entity classes. E.g.
EntityViewBuilderhttps://api.drupal.org/api/drupal/core%21lib%21Drupal%21Core%21Entity%21... . But also for node-specific controllers likerevisionShow()in https://api.drupal.org/api/drupal/core%21modules%21node%21src%21Controll...When grepping the Drupal code base for
$this->entityRepository->getTranslationFromContextthere are a couple of examples.Comment #7
larowlanComment #13
acbramley commentedManually played around with this a bit and confirmed it's still an issue. Adding the getTranslationFromContext wrapper on getEntity does work and doesn't look to break anything! We just need tests now :)
Comment #14
acbramley commentedComment #15
smustgrave commentedTest-only job ran here https://git.drupalcode.org/issue/drupal-3175985/-/jobs/5698563 which outputted
Looking at the change
return $this->entityRepository->getTranslationFromContext($this->blockContent);seems like a good update!Comment #16
catchOne comment on the MR about constructor bc.
Comment #17
acbramley commentedDone
Comment #18
smustgrave commented1 small comment on the MR. Feedback appears to be addressed so probably good to self RTBC @acbramely
Comment #19
acbramley commentedThanks!
Comment #22
catchCommitted/pushed to 11.x, thanks!