When modules add news fields through hook_field_extra_fields() to an entity with existing display suite layouts, these new fields get placed in the "disabled" region first and are thus not displayed.
The problem is that field_extra_fields_get_display() still reports "visible" = TRUE on these fields. The solution currently is to move the field to a different region, save, move it back to disabled, save again. After that the visibility status is correct.
This behavior is highly critical in combination with modules like Entity Views Attachment, or any other modules that provide computation intensive entity fields. What happens in the case of EVA is that the attached view is still executed whenever the entity is displayed (even for teasers!), even though nothing gets displayed.
Before I figured this out I was struggling with very slow page loads and even a few infinite loops or memory exhaustion errors.
| Comment | File | Size | Author |
|---|---|---|---|
| #11 | ds-1296596-10.patch | 839 bytes | tim.plunkett |
| #4 | default-ds-layout-fields-visibility-to-false.txt | 1.42 KB | tdway |
Comments
Comment #1
swentel commentedIn my testing, saving the manage display screen once (without even moving the extra fields) sets the status to unvisible, so that should be really ok. (the _ds_field_valid() function in ds.field_ui.inc resets the field visibility and field_ui itself picks that up). Note, haven't tested it with eva, but I'm using the same technique in a custom local module with another extra field, so should be fine. I can't think of another way right now to alter that behavior, so maybe a better patch might be for eva to disable the extra field by default - if possible at all.
Comment #2
ralf.strobel commentedI have posted an issue for EVA, but not sure they can come up with something.
#1296610: Prevent disabled fields from being rendered (performance)
Wouldn't it be an option to add new fields to a displayed region by default? That way users would be forced to manually disable them. Since new fields seem to be visible by default outside of DS, this would be a more consistent handling.
Comment #3
swentel commentedSo, after some digging it's _field_info_prepare_extra_fields() which sets extra fields to be displayed by default. Even when not using DS, you'd be forced to disable them as well.
So it's either up to core to change this behavior or eva can also implement the alter hook to disable the extra field by default, that's not up to me.
Comment #4
tdway commentedI've had success using the attached patch to fix this issue. It's basically just an implementation of hook_field_extra_fields_display_alter() so it can be used as a patch to the ds module or added as a hook in any custom module. It defaults fields visibility to FALSE only if the current view mode is using a display suite layout and no visibility setting is already configured.
Comment #5
swentel commentedWhat bothers me here is that this is potentially called a lot on the display level which I'd rather not do. For the same reason I already implemented 'ds_module_implements_alter' so that 'field_display_node_alter' isn't called a hundred of times on a page.
So I'm still not sure about this one to be honest.
Comment #6
tdway commentedThis should be a pretty light weight hook. The two variables that get checked (ds layout and field bundle settings) are statically cached and already loaded elsewhere in the request so it doesn't add any additional queries. The only real expense here is a for loop I think. Without this there can be a significant impact to performance if you don't go back and resave the manage display page for every view mode when new extra fields get added to a content type.
If there's still a concern, maybe this can be an configurable option in DS or even a separate module. I've got a few other "extensions" to DS that I've been using on projects. I might be able to provide this in a separate contrib module along with some related functionality if that would work?
Comment #7
swentel commentedI agree the saving can be annoying :)
A better way to solve this imo, is to use hook_modules_enabled() where we investigate whether a module exposes extra fields or not and then manipulate the variables. with hook_modules_disabled() we can even investigate again and cleanup the variables (unless field module already does that, but don't think so iirc).
Note: I don't mind an extra module in contrib for DS, just trying to make sure DS core is clean and mean :)
But I'd accept a hook_modules_enabled patch though.
Comment #8
ralf.strobel commentedI don't think hook_modules_enabled is the right place to detect this. The original use case I reported was that I created a new field without adding or removing any modules. I bet there are other situations as well, where a new field can appear without a module being en/disabled. A module update for example.
Comment #9
swentel commentedHmm, you're right, still, it's something I'd rather see being changed in core - there's a patch for that over #1256368: Add 'visible' key to hook_field_extra_fields() (which ironically does it wrong first to make a backport work, but there's going to be a new one once that patch lands).
Comment #10
tim.plunkettI just hit this, and wrote almost an identical patch.
I'm going to sleep on this and see if I come up with a more temporary solution.
Comment #11
tim.plunkettMine was a little less complex than #4, not sure if I'm missing some edge cases. But just posting this in case I decide to use it in drush make :)
Comment #12
gaëlgI used #4 for a while, but it broke the display in some cases (many fields disappeared). I switched to #11 and my fields reappeared.