Disclaimer : this bug has not been filled against D8 because it seems that it has been fixed by moving the drupal_alter('entity_view_mode') call to Drupal\Core\Entity\EntityRenderController::viewMultiple()
It took me a lot of time to fill this issue because I was not sure it was not caused by a contrib module so I dug into the core then found the cause.
To illustrate the case, I made a tiny module (using Features for quickness)
Problem
The problem is that when you implements hook_entity_view_mode_alter to change the default view mode of a node to "custom_vm", this one's fields are prepared for view (hook_field_formatter_prepare_view) using the "full" view mode then show (hook_field_formatter_view) using the chosen view mode (custom_vm). Most of the time this will not be a problem but, with taxonomies for example this can lead to an error screen.
Steps to reproduce (very quick way)
- Launch a sandbox
- Go to node/1
Steps to reproduce (quick way) :
- Install drupal
- Download and enable my module
- Go to node/1
Steps to reproduce (long way) :
- Install drupal
- Create a vocabulary, add it a term
- Create a content type, add it a taxonomy reference field to your vocabulary
- In the content type display management, hide the taxonomy field from "full" view mode and show it on "teaser" one
- Create a node using your term
- Create a tiny module which implements hook_entity_view_mode_alter to change the view mode to "teaser" (see below)
- Go to node/1
Tiny example module which implements hook_entity_view_mode_alter
/**
* Implements hook_entity_view_mode_alter().
*/
function MODULE_entity_view_mode_alter(&$view_mode, $context) {
$view_mode = 'teaser';
}
Comments
Comment #1
DuaelFrProposed solution
Call
drupal_alter('entity_view_mode')
in thenode_show()
function before the node is prepared byfield_attach_prepare_view()
.Unit testing
I am not confident with Drupal's unit testing for the moment so please excuse me to not provide tests to highlight this bug and to show it is fixed by my patch.
Manual testing
Click here to launch a patched sandbox
This patch is part of the #1day1patch initiative.
Comment #2
BerdirThe original issue that added this is still open, see #1154382: View mode no longer can be changed because of a problem with it. Is this the same problem? If so then we should close either of those (I'd suggest to keep this open and mark the other as fixed). The tests that were added will have to be updated, not sure if the patch in the other issue is already doing this.
Comment #3
DuaelFrYes #1154382-103: View mode no longer can be changed seems to describe exactly the same issue as mine, thank you to point it out.
I read the following patches and while they are not proposing tests they are far more advanced than mine.
Maybe it would be better to close the main issue and to use this one for cleaner reading. I let you decide.
Comment #4
BerdirYes, let's mark that one as fixed and point to this issue, taking the patches over. That issue has been sitting there for way too long, something that happens quite often when issues are kept open for follow-up fixes.
Comment #5
BerdirAdding tag.
Comment #6
DuaelFrUse the patch #1154382-113: View mode no longer can be changed as basis for the tests writing.
Test this patch against my demonstration module
Comment #7
znerol CreditAttribution: znerol commentedWorking on a patch with tests.
Comment #8
znerol CreditAttribution: znerol commentedOk, first patch ist tests-only, that one is expected to fail. The second one contains the test plus the unchanged fix from #1154382-113: View mode no longer can be changed.
Comment #9
znerol CreditAttribution: znerol commentedGood, the test fails with the exact same message given in the original report.
@Berdir: Is there anything left to do here?
Comment #10
BerdirShouldn't use t() or maybe even randomName(), we have a custom assertion message anyway.
Comment #11
znerol CreditAttribution: znerol commentedCall to
t()
removed, also in the preceding test which served as the copy-paste source.Comment #12
peximo CreditAttribution: peximo commentedThis fixes the issue here.
The patch looks good, there were just a couple of comments not wrapping correctly.
Comment #13
plachI can confirm #12 fixes the issue. I can't spot anyhting bad with it and in #8 we can see test coverage is ok. I had a quick look to the D8 code and agree it should not be affected by this, we may want to forward-port tests.
Comment #14
David_Rothstein CreditAttribution: David_Rothstein commentedUgh, horrible issue - thanks for a great bug report and patch, though. Makes me wish we never added this new hook to Drupal 7, but it's too late :( I can't think of another way to fix it except something like this patch so I guess that's what we have to do.
I do see one major problem, though. To use nodes as an example (but it also applies to others too):
So the code at the top takes into account the possibility of a different returned $view_mode for each node (which it definitely has to) but then further down node_view() is called with the final $view_mode only. Since hook_entity_view_mode_alter() won't be invoked again during the node_view() call, this could actually break people's existing (and previously working) code. So I think we have to arrange to make sure the correct view mode for each particular node is always passed in during each node_view() call.
Other than that, everything looked great to me except a few minor nits:
Pretty sure that should be field_info_instance() instead?
That's a pretty unwieldy class name and description (and the docs go way over 80 characters also) :)
I'd suggest just ditching it as a separate class altogether and moving it into the existing NodeEntityViewModeAlterTest class as a new test method. So basically:
And then basically the same test code that the patch added after that.
Comment #15
David_Rothstein CreditAttribution: David_Rothstein commentedWe also definitely should forward-port the tests to Drupal 8, but I think that can wait until after commit given that it seems pretty clear this bug doesn't exist in Drupal 8 (plus it's a relatively serious bug so better to fix in Drupal 7 sooner than later).
After Drupal 7 commit, I suppose we'll also have to update this change notification for the new pattern: https://drupal.org/node/1833086
Comment #16
znerol CreditAttribution: znerol commentedWorking on the patch...
Comment #17
znerol CreditAttribution: znerol commentedComment #18
znerol CreditAttribution: znerol commentedUgh, I need to think about how to handle the weights. Attempt from #17 obviously does not work.
Comment #19
znerol CreditAttribution: znerol commentedI consider #17 as invalid, therefore interdiff is against #12.
Comment #20
nadavoid CreditAttribution: nadavoid commentedI've tested this out and it works great for me. I'm using this with custom entity types extending the Entity API module. I've posted a patch for Entity API over here #2139639: Support updated hook_entity_view_mode_alter() to support this implementation. Sure would be nice to see this in the next point release of D7.
Comment #21
David_Rothstein CreditAttribution: David_Rothstein commentedHate to do this because I'd really like to see this patch go in now, but I don't think it's a good idea to remove the sorting behavior of functions like node_view_multiple(). Although drupal_render() will sort the entities correctly anyway (such that it shouldn't make a difference in the end), these are heavily-called functions and people could be relying on a consistent order of the returned array.
So here's a fix for that (and I also made the node module's internal variables consistent with the rest, i.e. $entities rather than $entitys).
Hopefully we can still get this patch in soon though.
Comment #23
znerol CreditAttribution: znerol commentedI'm fine with #21. I cannot RTBC it though, another review is still necessary.
Comment #24
davidwbarratt CreditAttribution: davidwbarratt commented#21 works perfectly for me! :)
Thank you so much for your work!
Comment #26
David_Rothstein CreditAttribution: David_Rothstein commentedLikely testbot glitch - moving back to RTBC.
Comment #27
agileadam#21 solved this issue for me: #2322031: Fields don't display when altering view mode
Comment #32
David_Rothstein CreditAttribution: David_Rothstein commentedCommitted to 7.x - thanks!
So we need a couple things here, based on my comment above:
The first could be filed as a separate followup issue, I think.
Comment #33
David_Rothstein CreditAttribution: David_Rothstein commentedDraft change record here: https://www.drupal.org/node/2369141
I decided it made more sense to create a new one rather than put everything in the old one.
But I also modified the old one from https://www.drupal.org/node/1833086 to point to it:
https://www.drupal.org/node/1833086/revisions/view/6918819/7799713