Problem/Motivation
IIRC entity_embed chose to use #post_render_cache to be able to support entity access checking correctly. At the time, this was the only solution possible to only show embedded entities if the current user could access them. It does come at the cost of significantly worse cacheability though!
Since then, #2429257: Bubble cache contexts has landed. This makes it possible to bubble cache contexts. Access results specify cache contexts. This is how we fixed #2099137: Entity/field access and node grants not taken into account with core cache contexts, which is basically the same problem.
Proposed resolution
Make entity_embed bubble the cacheability metadata associated with an entity's access result.
Basically:
$result = new FilterProcessResult($text);
// [Do the work of rendering the entity and its access checking.]
$access = …
$entity = …
// Make the FilterProcessResult have the cacheability metadata of the entity access result and the rendered entity itself.
$result = $result->merge($access)->merge($entity);
$result->setProcessedText(str_replace(…));
Remaining tasks
Discuss.
User interface changes
None.
API changes
The "context alter" hook would go away.
Comments
Comment #1
wim leersHappy to provide a patch if desired.
Comment #2
wim leersComment #3
dave reidExcellent Wim, I'll take a look at implementing this.
Comment #4
wim leersComment #5
wim leers#2478483: Introduce placeholders (#lazy_builder) to replace #post_render_cache landed,
#post_render_cacheis gone, so by now this is a bug; it'll prevent Entity Embed in its current state from working.Comment #6
dave reidWill be working on this this weekend.
Comment #7
dave reidRelevant change notice: https://www.drupal.org/node/2498803
Comment #8
wim leersCool, ping me if you have questions :)
Comment #9
slashrsm commentedComment #10
dave reid@Wim Leers: So with this new code, we don't actually need placeholders at all? We should just render directly in the filter itself?
Comment #11
wim leersCorrect.
Comment #12
dave reid@Wim Leers: I'm having problems implementing this part:
Neither using the entity object, nor the AccessResultInterface result from $entity->access() seems to be usable to provide to merge(). Any ideas on where we should look for that?
Comment #13
dave reidHrm, looks like I should be doing something like this?
Comment #14
dave reidBlargh, that doesn't work at all.
Comment #15
dave reidWhen I attempt to do $result = $result->merge(...) I always get:
Warning: Missing argument 1 for Drupal\filter\FilterProcessResult::__construct(), called in /home/davereid/Sync/projects/drupal8/core/lib/Drupal/Core/Cache/CacheableMetadata.php on line 142 and defined in Drupal\filter\FilterProcessResult->__construct() (line 86 of core/modules/filter/src/FilterProcessResult.php).
Notice: Undefined variable: processed_text in Drupal\filter\FilterProcessResult->__construct() (line 87 of core/modules/filter/src/FilterProcessResult.php).
Comment #16
wim leersSo,
FilterProcessResultextendsBubbleableMetadata.BubbleableMetadata::merge()typehints toCacheableMetadata, which is the base class ofBubbleableMetadata. So you can give it eitherCacheableMetadataorBubbleableMetadataobjects.This is therefore what you want:
Yes, this is painful. This is why for regular rendering code, we have
RendererInterface::addCacheableDependency(). We could consider adding that toBubbleableMetadata/CacheableMetadataas well. Then it'd become simply:Comment #17
wim leers(We cross-posted.)
Oh :(
That's a bug. This is because of:
Which means that upon merging, a new
FilterProcessResultobject is constructed, but it's not passed any parameters, even thoughBubbleableMetadataexpects that.IOW: You've found a core bug.
Comment #18
dave reidShouldn't it be using $result = clone $this instead?
Comment #19
dave reidComment #20
wim leersI think you did :D :D
Wanna file a core patch? :)
Comment #21
dave reidFiled #2516802: FilterProcessResult->merge() results in PHP warning: Missing argument 1 for FilterProcessResult::__construct() with patches.
Comment #22
wim leers#2516802: FilterProcessResult->merge() results in PHP warning: Missing argument 1 for FilterProcessResult::__construct() just landed!
Comment #23
dave reidComment #24
dave reidOk, calling this good for now.
Comment #25
wim leersCan you link to the commit(s) that fixed it?
Comment #26
dave reid@WimLeers: https://github.com/drupal-media/entity_embed/pull/146 was the fix.
Comment #27
dave reid