There's no consistent way to find an entity when an object is passing through the theme system. I propose that all entity themes in the registry be annotated (overloaded) with the name of the entity's key in the render element array. Then this module's preprocess function should only be only added to specific entity themes where it can be supported.
Currently all entities (that I could find) are themed with a render element instead of variables. field_attach_view() adds entity type and bundle info to the render elements, so it appears to be a requirement that entities be themed with a render element.
This patch renames entity_view_mode_preprocess to entity_view_mode_template_suggest_view_mode so it is only called when it can actually do something useful and not for every single theme call. Then entity_view_mode_template_suggest_view_mode (the preprocess function) loads the theme registry (as a ThemeRegistry object) and grabs the name of the entity key and the name of the render element from the registry.
| Comment | File | Size | Author |
|---|---|---|---|
| #14 | 1795812-use-hook-entity-view-for-template-detection.patch | 10.65 KB | dave reid |
| #13 | 1795812-use-hook-entity-view-for-template-detection.patch | 9.13 KB | dave reid |
| #11 | 1795812-use-hook-entity-view-for-template-detection.patch | 7.9 KB | dave reid |
| #5 | 1795812-use-hook-entity-view-for-template-detection.patch | 2.1 KB | dave reid |
| #2 | improve_entity_type_check-1795812-2.patch | 3.36 KB | Anonymous (not verified) |
Comments
Comment #1
Anonymous (not verified) commentedHere's a patch.
Comment #1.0
Anonymous (not verified) commentedcorrecting my mistaken description of problem.
Comment #2
Anonymous (not verified) commentedThis patch changes indentation, which is really making it difficult for me to work with other patches in the queue. This is a patch that doesn't change indentation in the
entity_view_mode_preprocessfunction that is renamed toentity_view_mode_template_suggest_view_mode.Comment #3
dave reidI agree that the current approach is crap, but I am doubting that anything that requires a module to add something in it's theme registry and relying on magic keys to get the entity object is also not the optimal solution. I'm working on something that may work a bit more reliably.
Comment #4
dave reidSo if we were to try and get away from a theme registry / preprocess approach for detection, what else do we have?
Well we have the hook_field_attach_*() hooks, including hook_field_attach_preprocess_alter() which sounds like it could be useful, but those hooks are only available to entities that are fieldable, which may leave some entities that are viewable but not fieldable out.
Next up is hook_entity_view() and hook_entity_view_alter(). Using hook_entity_view_alter() is out since at that point we've lost the easy context/variable of the entity object and we're back to the same problem. But hook_entity_view() is very interesting. We're provided with specific variables for entity type, entity, view mode, and language code, all the things we need later. If we can store this information in the render API, and then detect this information later in the preprocess, this is pretty much a fool-proof method I think. As for reliability across all entity types, as far as I know, all entity types should to implement both of these hooks if they are viewable (and better yet in D8 it actually is enforced). The one entity type that violated this assumption was Fieldable Panels Panes, and I committed a fix to add the hook invocation: #1900528: PanelsPaneController::view() invokes hook_entity_view_alter() but doesn't invoke hook_entity_view().
Patch incoming.
Comment #5
dave reidPatch attached for review that implements #4. The only unexpected thing I found is that when rendering a user account via theme_user_profile, core also somehow puts the user render API array into a block, which then also runs preprocess and unwantingly detects our variables. I accounted for this by checking to make sure that the $hook variable actually matched the #theme function set in the entity's view callback.
Comment #6
dave reidThis really helps clean up the preprocess, and should really speed it up since we don't need to call entity_get_info() every time. What I didn't also express about the solution in #2 is that this also requires every entity module to add our preprocess function into their theme registry information as well. This alternate way, doesn't require anything of them at all, aside from implementing the required APIs that they normally would have to.
Comment #7
Anonymous (not verified) commentedThis looks really great, and it is a much better method than my patch!
Why is $langcode passed by reference?
I've tested this on my current projects, and the correct templates are still being used.
Comment #8
Anonymous (not verified) commentedI can't find any cases where entities do not use 'elements' as their render element in hook_theme. Is it safe to assume?
This is the code I was using to check for the render element key.
Maybe if 'elements' isn't set in the variables, it can dig into the theme registry?
Comment #9
dave reidI passed in langcode by reference, because I was thinking what if it changed somehow, but then I realized that is very silly and it should never happen, so it should be removed.
I wonder if checking for the render element would actually solve the weird issue I had with user entities and blocks.
Comment #10
dave reidJust checked, both $hook = 'user_profile' and $hook = 'block' use render element of 'element'. I think my concern with checking the actual render element on the preprocess means we have to do it first, which means that it has to happen for every single invocation of the preprocess function. I think we can just be ok with relying on that entity types always use the standard render element. If we encounter problems down the road we can deal with them then.
Comment #11
dave reidPatch includes tests now as well.
Comment #13
dave reidHelps to include the new testing module.
Comment #14
dave reidAdded test condition for #1831766: Theme hook suggestion for {$entity_type}__{$bundle}__{$view_mode} is added before {$entity_type}__{$bundle} .
Comment #15
dave reidPatch in #13 also prevents template suggestions with entity bundles from being added to entities that have no bundles.
Comment #16
dave reidConfirmed that #14 fails if 1831766 was reverted, so committed to 7.x-1.x! http://drupalcode.org/project/entity_view_mode.git/commit/6ec3774
Thanks for your help in getting this resolved bangpound!
Comment #17.0
(not verified) commentedadded a patch so i can rewrite description.