
The EntityDisplay class introduced in #1852966: Rework entity display settings around EntityDisplay config entity includes hardcoded logic to handle "field" and "extra field" components.
Problem
- It currently only deals with "Field API field" & "extra field" (aka arbitrary render array snippet) components. There is hardcoded logic to determine which is which and how to handle each.
--> Contrib "component types" are currently not possible, and it's very much needed for Display Suite / Field groups.
The entity render flow is based on the fact that a single EntityDisplay object, loaded and altered once as a whole, contains the whole "display recipe" for an entity in a given view mode. Display suite / Field groups need to be able to participate in that flow.
- Now that widgets / formatters are theoretically usable on "base fields", EntityDisplay objects are the natural (and only) place to store widget / formatter configuration on base fields.
They thus need to be uncoupled from the notion of "configurable Field API field" (i.e field_info_*() API calls)
Proposed solution
If we want EntityDisplay objects to hold display options for every component in a entity view, including contrib stuff like field_groups, the EntityDisplay methods should be agnostic about what type of "thing" they contain (field, 'extra field', field_group, possibly blocksNG...), and the "component-type" specific logic needs to be split out into pluggable handler classes.
Thus, EntityDisplay objects become a collection of configured plugins, which is a well known pattern.
- Component types are plugins.
- Each component type ("field API field", "extra field", "field_group", ... possibly "block") has a handler class (one object of each is enough for the whole request).
- The EntityDisplay defers handling of setComponent() / getComponent() methods to the relevant component type handler, and just stores the result (i.e no more massaging code specific to fields or extra fields in EntityDisplay methods).
- Component types are responsible for determining which display elements they can handle, the EntityDisplay just interrogates them about an element and accepts the first component type to declare it should handle the element.
API Changes
A new plugin type.
Comment | File | Size | Author |
---|---|---|---|
#225 | interdiff_223-225.txt | 541 bytes | ravi.shankar |
#225 | 1875974-225.patch | 42.88 KB | ravi.shankar |
#223 | interdiff_222-223.txt | 6.36 KB | ravi.shankar |
#223 | 1875974-223.patch | 42.88 KB | ravi.shankar |
Comments
Comment #0.0
yched commentedfix method names
Comment #1
andypostSo set of components looks like PluginBag already used in core
Maybe we just convert all extra fields to TypedData plugings as #1732730: [meta] Implement the new entity field API for all field types done for fields
Seems it's time to resolve #1954188: Revaluate the concept of 'extra fields' or #1818680: Eliminate hook_field_extra_fields() / Redesign field UI architecture
Comment #2
swentel commentedtagging
Comment #2.0
swentel commentedformat
Comment #3
andypostThis would be very helpful to implement node and comment links on top of it!
Comment #4
andypostWhat's left here?
Comment #5
swentel commentedThe code in the sandbox works (and is also green on the test helper issue), but we need to check for interfaces, method names etc. That's at least the first step. Will merge head on the branch this weekend and reroll on the helper issue.
Comment #5.0
swentel commentedUpdated issue summary.
Comment #6
effulgentsia commentedTo determine if this is still eligible for D8, it would be very helpful to get an updated issue summary that explains exactly what API changes are entailed. I realize the helper issue isn't passing tests yet, but are we far enough along to know what the API changes are likely to be? I'm adding the "API change" tag based on the assumption that some API change will be needed here. Please remove the tag if I'm wrong about that.
Comment #6.0
effulgentsia commentedUpdated issue summary.
Comment #6.1
swentel commentedUpdated issue summary.
Comment #6.2
swentel commentedUpdated issue summary.
Comment #7
yched commented@swentel & I updated the summary with "reasons for the change" and "API impact"
Comment #7.0
yched commentedAdded reasons for the change.
Comment #8
yched commentedUnassigning, I'm not working on this right now :-/
Comment #9
effulgentsia commentedBased on the updated issue summary, I'm reclassifying this as an API addition rather than a change. Please correct me if I'm wrong on that.
Comment #10
yched commentedIf this works, then yes, it would keep 95% existing code working (code that accesses EntityDisplay->getComponent($name) for an 'extra field' would still break)
Comment #11
andypost..as I mentioned in #1848068-124: Helper issue for "EntityDisplay"
We need to change only
EntityDisplay->setComponent()
to allow set different types of pluginsEntityDisplay->getComponent($name)
could stay the same because component type (currently handler_type, needs better name) already stored in display entity objectAlso
EntityDisplay->getComponents($type = '')
seems better$type = 'field'
For field component type probably better to separate base and configurable fields
Comment #12
yched commentedHmm, I don't remember why my initial patch added a $type to getComponent(). You're right, probably best if we can avoid it.
Quite the contrary, the whole point of "unify base fields & config fields, make widgets / formatters work on both" is that most our code base should make no difference and just work with "fields". A field is a field, where it comes from (code or config) is irrelevant.
Comment #13
amateescu commentedI also agree that we should remove $type from getComponent(). It's not needed at all because we don't 'namespace' the components by type. And a default of 'field' for setComponent() sounds great.
Comment #13.0
amateescu commentedmore details about API changes
Comment #14
yched commentedBumping priority. This is needed to be able to generate proper config schemas for EntityDisplay config entities.
Anyone up for grabbing this ? ;-)
Comment #15
aspilicious commentedI'll try to reroll... Thats a start
Comment #16
aspilicious commentedI spend some hours rerolling and fixing bugs!
Testbots aren't back yet but I'm confident I fixed almost everything.
#1848068: Helper issue for "EntityDisplay"
There are some todo's and incomplete docs in the patch. As everything is build on the sandbox on branch "1875974-entity-components" everyone can fix stuff if they see issues.
Especially the extra field stuff needs serious review.
Comment #17
aspilicious commentedShould be green patch, makes 'type' optional if possible. Done by moving it to the second param everywhere and defaulting to 'field'.
It would be nice if there was an event after saving the fields in the UI that passes the display so "other modules" could use this for additional actions.
Comment #18
aspilicious commentedComment #19
yched commentedAwesome! Thanks a ton @aspilicious!
I'll try to look at the code soon - others are welcome to beat me to it ;-)
Can you expand on the use cases you have in mind ?
Not sure if that's related, but #2094499: Convert "Manage (form) display" forms to be the official entity edit forms for EntityView[Form]Display objects would make the "Manage display" forms be the "official entity forms" for the EntityDisplay / EntityFormDisplay config entities. Which might make it easier for 3rd party code to work on the $entity in $form_state before it's saved.
Comment #21
aspilicious commentedWhen an entity display contains components that are not available anymore. For example, *some* contrib module provides plugins to add fields in code and for a reason you decide to delete that file/plugin. After clearing the caches that field is gone but it's still in the entity display.
After re saving the field UI, a module maybe wants to inspect every component of it's display to make sure it still exists. If it doesn't exist, it should remove it...
That particular module could alter the form and add a second submit callback that does that, but it would nice if core provided such an event somehow.
Either way contrib will need the display in the form system.
Comment #22
yched commented@aspilicious: form submit should start with a fresh, empty EntityDisplay::$content, and then only populate it with stuff that are actually part of the submitted form ?
Would it solve the case you're talking about ?
Comment #23
yched commentedA couple remarks after an initial cursory look:
- EntityDisplay::$pluginManager shouldn't be needed anymore, the "plugin manager that is supposed to return rendered plugin objects" is a matter of each individual DisplayComponentHandler plugin
- The $type param has a default value of 'field' for all methods, except on getComponents() where it's just '' ?
- More generally, an EntityDisplay object does not accept two components of different "types" with the same name, so:
we do need a $type parameter for setComponent(),
a $type param could be useful for getComponents() (give me all the components of this type),
but the $type param looks useless for other methods (getComponent(), removeComponent(), getRenderer()) ?
Comment #24
aspilicious commentedI need more help on this one...
This different because leaving it to '' will return everything, which is the 80% use case.
The plugin manager is used to fetch the widget for getRenderer on the formdisplay. I think this is a side effect of a base class handling the form and the display side of things.
The third thing:
- I don't understand remove component and what it tries to do o_O, so I have no idea if it's possible to remove $type. For example why are we *settings* stuff in a function that should *remove* something. ANd that remove function calls massageIn, which sounds weird...
$this->content[$name] = array('handler_type' => $type) + $options;
- We can remove it from getComponent if "$this->content[$name]['handler_type']" always contains the correct $type. What should be the case I guess.
IF that is the case can we assume the same for.
In general I understand little of functions in the component handler, maybe because there is no documentation or no interface? ;) (massage in / out / prepare stuff) doesn't tell me much even after spending hours in it.
I fixed some bugs by trial and error and some well chosen guesses :p
Comment #25
yched commentedre #24:
- $type param in getComponents():
Ah, right, makes sense of course. But then NULL would be clearer than ''.
- EntityDisplayBase::$pluginManager
Well, EntityDisplay::getRenderer() gets deferred to DisplayComponentHandler::getRenderer(), so it's the DisplayComponentHandler, not the EntityDisplay that knows whether it needs a plugin manager, and which one.
I think what's currently preventing the removal of EntityDisplayBase::$pluginManager is the fact that the patch keeps the current Entity*Form*Display::getRendered(), which does the job itself and still uses $this->pluginManager, instead of deferring to DisplayComponentHandler::getRenderer()
(EntityFormDisplays were added after the initial versions of this patch)
The above means FieldDisplayComponentHandler needs to use either plugin.manager.field.formatter or plugin.manager.field.widget, depending on whether $this->context['display_context'] is 'display' or 'form'.
Then, we can remove the old EntityFormDisplay::getRendered().
- removeComponent() / $type:
yeah, sorry about the lack of interface for and the not super clear API, that's my bad :-/
That's the state the initial patch was in, and I was not too happy with it either (which is why I didn't freeze an interface yet...)
massageIn() is about "massage data that gets written into the EntityDisplay"
massageOut() is about "massage data that is read from the EntityDisplay"
And basically, yes, we only need to explicitly know the type of a component when we write it in (setComponent()).
When we remove a component (removeComponent()), we don't the caller to give us the type, just the component $name, then we already know the type in $this->content[$name]['handler_type']
And, at least for now, what happens on EntityDisplay::removeComponent() depends on the component type. So this currently goes through ComponentHandler::massageIn() (a "remove" is a "write"...)
Again, fully agreed that this can probably be made much cleaner...
I do intend to look into refining as soon as I can, but I really appreciate the help here :-)
-
Comment #26
andypostI've pushed 2 commits on top of @aspilicious refactoring, see interdiff #1848068-160: Helper issue for "EntityDisplay"
Commit b3c7d064ee6437d502ed80039bf2d276842b0f70 properly injects needed services into handler plugins.
Currently
DisplayComponentHandlerPluginManager
instantiates needed plugins only once and stores them in protected$plugins
array, this approach needs to usesetContext()
each time the handler used.Another approach could be to use factory pattern for handler plugins and store the instances directly in display entity, this will eat a bit more memory but could allow remove context switching when each component accessed.
There's still a question about validation of component existence #1848068-158: Helper issue for "EntityDisplay" shows thet when field or instance is deleted we still call
massageIn()
so I've added a check for field but probably we need to check for field instance.Comment #27
andypostThe magic with default values for
MassageIn()
&massageOut()
is really annoyingNo idea how to fit into interface
Comment #29
aspilicious commentedAndypost had the idea to loop through each display component to see if it exist on setComponent.
That way you don't need to pass the type.
It does make set component slower.
I sthta a good or terrible idea?
Comment #30
fagoI just did a short review.
Would component_type make more sense here? As afaik each of the entries is a display component?
Otherwise, I could see it even be just "type" and move the field's type to "field_type". The API is not primarily about fields anymore, so the keys should reflect that.
Do we need the handler term here as well? It's just a display component that I get.
Instead, imo it's more that the current getComponent() does return the component definition, but not the component object.
Comment #31
andypost@fago There's a new patch about (1) in testing issue #1848068-162: Helper issue for "EntityDisplay" and fixed broken tests in #165 also @yched already commented about approach #166
2) makes sense, probably '
component
' key is enough3) yes, we do special processing in
onComponentGet|Set|Remove
by the handler plugin mostly because of "extra fields" pitaThe idea about using
pluginBag
exposed by @yched in #1848068-166: Helper issue for "EntityDisplay" makes sense but I also cares about performance overhead by introducing additional wrapper.The context switching is very light function call comparing to instantiation of component handler plugins for each display and seems that plugin bag would do the same.
So having a lot of display objects on page will bring request time down.
PS: I'll roll new patch here after HEAD would be fixed in #2147581: Testbot has xdebug enabled with xdebug.max_nesting_level = 100
Comment #32
yched commentedre @fago:
AAMOF in my initial iterations of the patch I went with "type" for the component type, and moved the existing 'type' to 'widget/formatter'.
Later rerollers reverted that, and I can totally understand because it makes the patch size and conflict area explode, making rerolls quite painful. So, while I still think the above would be more intuitive in the end, it might be wiser to keep the current for now, and switch to the above either when the patch is otherwise "ready", or in a followup :-/
re @andypost:
True, but actually this exact same pattern of "check default settings defined in code if we have nothing configured in the EntityDisplay" is going to extend to regular fields as well when "base fields" kick in with #2144919: Allow widgets and formatters for base fields to be configured in Field UI. Base fields are going to behave the exact same way as extra fields do currently : defined in code, with default display / form settings.
This probably means we should switch the internal storage in EntityDisplays that way:
- content:
like currently, but only contains the *visible* components. Extra fields that are hidden are no longer listed here, and extra fields no longer have a 'visible: true/false' entry, just a weight.
Bonus points for sorting by weight before saving :-)
- hidden:
lists the names of the components (whichever, fields, extra fields...) that have been explicitly configured to be hidden.
That way we can easily differenciate between "hidden" and "no configured settings, switch back to the defaults for this component". This should also simplify the code quite a bit (probably no need for onComponentRemove anymore).
Comment #33
yched commentedBeen toying with that idea as well - on setComponent('foobar', $array), ask each handler "hey, which of you owns 'foobar' ?". Might be a good idea, especially since #1988612: Apply formatters and widgets to rendered entity base fields, starting with node.title puts us in a weird situation where some components can be seen either as a field or as an extra field (see the OP there - this is supposed to be temporary, but not sure how long this "temporary" will last). So this idea might let us account for that "flexibility" better.
Performance should not be too much of a concern if this only happens on setComponent(). Not sure if there would be other pitfalls, but might be worth a try.
Comment #34
andypostmakes sense but this makes ability to use pluginBag is hard from first view, otoh ds-module could split "content" part into region names by overriding base display, code reuse++
We can change storage until beta, so the issue needs to be approved as API change
and 'handler_type' could be easily grep'ed anytime
Related #1988612: Apply formatters and widgets to rendered entity base fields, starting with node.title is RTBC now, so here is a question - do we need a different component handlers for field and configurable field in the new world?
PS: will try to try to implement new setComponent() in next weekend, this should move us from API-change area to API-addition because
EntityDisplayBaseInterface
just extended without BC breaks, and yep, patch should be seriously much lessComment #35
yched commented@andypost : why do you think switching to 'content' / 'hidden' would make things harder ?
No, one single handler for "base field" & "configurable field", the content of content[field_name] will be the same in both cases, and widgets/formatters do not care.
This single handler might need to have a couple "if (base field) {...}" or "if (configurable field) {...}" code branches, but the entries in 'content' will be structured the same, and the overall logic should be vastly the same - that's the whole point of "unified Field API" :-)
Comment #36
andypostIssue #1988612: Apply formatters and widgets to rendered entity base fields, starting with node.title break a lot of things, so I think that better to postpone this one on
Comment #37
yched commented#2144919: Allow widgets and formatters for base fields to be configured in Field UI is in, this can now resume.
@andypost, @aspilicious : feel like going for it ? :-)
Food for thought: even though we need to have a 'type' for each component ('field', 'extra field', 'field_group'...) we could consider keeping the 'field' handling code hardcoded within EntityDisplay classes rather than in a separate handler plugin, to avoid the overhead on the most frequent case ?
Or we can also consider this is premature optimization for now, get to a working patch, and see then...
Comment #38
aspilicious commentedGoing to spend some time with it, I'll see how far I can get with it.
Comment #39
aspilicious commentedIt's not working yet, it doesn't save (or load) the correct items, everything is displayed hidden.
But I do think I'm going in the right direction.
At least this version is more of an api addition than the previous versions...
Can someone review the "general direction" of the patch?
I committed it to the 1875974-entity-components-aspilicious branch.
Unassigning, everyone can work on it :)
Comment #40
aspilicious commentedReviewing my own patch, ExtraFieldDisplayComponentHandler is missing the "hasElement" function
Comment #41
yched commentedThanks a lot @aspilicious ! This is looking nice.
One thing regarding getComponentHandlerByElementName() / "which handler handles which component" :
This should only be computed when a new component gets added in setComponent(), and then be kept as $options_form_the_component['handler'], so that it's known for the rest of the processing, saved in the yaml for each component, and then present again when the display is loaded.
-->
- No need to recompute it each time
- We need that info in the yml to be able to generate config schemas
Comment #42
aspilicious commentedI'm not going to work on it this weekend, so if anyone wants to finish it go ahead.
I'm still missing something.
At the moment there are two options
1) field is added to content
2) field is hidden
Can't we introduce the notion of regions here?
Makes it easy to introduce multiple regions AND makes the yml file easier to read, else I have to add some kind of funky mapping.
so in stead of going with:
$this->content['title']
We could have something like
$this->regions['content']['title']
EDITED EXAMPLE ABOVE
Comment #43
aspilicious commentedPushed some small changes, now a save of the display fatals but thats ok ;)
Ow! And one more thing I noticed, I saw that saving the default display also triggered a save of teaser. Is that by design?
Comment #44
yched commentedI don't think we should aim at regions atm. That's not anything formalized in core, and it would really complicated config schemas.
Some component types will want to add nesting but that's their business. They'll have a 'children' entry that lists their children, but I don't think we can have the structure of the display->content reflect that, would take us far far away ...
Comment #45
yched commentedHm - definitely not :-) Weird.
Comment #46
aspilicious commentedThis one at least work. Probably needs some doc updates.
Comment #47
aspilicious commentedMassageIn and massageOut are still confusing, certainly after my changes.
The massageIn is called AFTER pressing the save button for each element that is inside content.
So it's a function that fetches that manipulate the options. Before getting saved. So that function name is kinda ok, I'm open for suggestions as I think their could be some improvement in the naming.
The massageOut is a different story, originally it was located in the removeComponent function. We don't need any massaging anymore there so I moved it to the getExportOptions. But as this massageOut function has nothing todo with massageIn I think we should rename it to something like: "massageExportOptions()"
Anyway I noticed we are missing an interface with the needed documentation. Anyone want to take that task? ;) :p
Comment #49
aspilicious commentedThe order of parameters for "getInstance" apparantly changed, new patch!
Comment #51
aspilicious commentedLets see if this fixes some tests...
Comment #53
aspilicious commentedFixed most warnings
Comment #54
twistor commented$handler = NULL;
isn't doing anything.I think you mean break instead on continue.
$handler = $this->getComponentHandler($type);
should use a different variable or else reset it it after the check, otherwise the last one will win if none match.
Comment #56
aspilicious commentedSo this should be better. Not sure if it will fix some issues.
Comment #57
aspilicious commentedComment #59
andypostShould fix most of failures, also adds a @todo.
Plugins now serve view and form both so caching needs work
PS: comment pager bug introduced in #2155387: Multiple comment fields per entity are supported, but break horribly when they need pagers
Comment #60
andypostAdded interface for handler plugin and initial doc blocks, alter hook needs work
Comment #61
andypostre-roll
EDIT re-opened #2210177: Use getSetting() in comment formatter
Comment #63
swentel commented#2095195: Remove deprecated field_attach_form_*() got in, it would be great to get this one forward again!
Comment #64
yched commentedRight. This is (finally...) #1 in my list of things to review.
Comment #65
yched commented@andypost : did you push your latest reroll in a sandbox somewhere ?
Comment #66
andypostLast merge in
I'm thinking about how to render comment module components to properly test the issue, because history and comment statistics are seriously affected how this fromatter is configured to render a long comment list
Comment #67
swentel commentedComment #68
swentel commentedLet's see how hard this breaks
Comment #70
swentel commentedHmm, something really bad in the merge there .. needs fixing
Comment #71
aspilicious commentedComment #72
aspilicious commentedLet's see...
Comment #73
aspilicious commentedAnd I'll fix the funky phpunit file stuff tomorrow
Comment #75
swentel commentedComment #76
swentel commentedClean file now without the accidental php unit removals
Comment #78
aspilicious commentedIt's green lets review!
Comment #79
andypostthis needs work
seems we need to unify that
This makes to run this each time, probably array_key_exists() should be here
$handler should be defined before "foreach"
needs to be injected
Comment #80
aspilicious commentedWhile working on a POC for DS I noticed we are lacking something :D.
In the code that renders the field UI overview we are still hardcoding fields and extra fields.
So we still need dirty alter hooks.
Some sinippets from displayOverviewBase
This can easily be solved by abstracting the build form code into the display component but I have no idea if these kinda changes are allowed.
Comment #81
aspilicious commentedCleanup + reroll
Comment #82
andypostI'm sure that having of actual usage of component would be a way to core!
Comment #83
Stalski commentedPatch looks OK, Currently implementing a component handler for fieldgroup.
Comment #84
aspilicious commentedIt's not yet finished after a talk with Yched on drupalcon we need te rename some stuff and move the build/render logic to the component patch. But I don't think fieldgroup is affected by the build part.
Comment #85
yched commentedThis will also need to take #2271419: Allow field types, widgets, formatters to specify config dependencies (almost RTBC) into account - see item 2. in comment #37 over there)
In short, patch over there adds EntityWithPluginCollectionInterface to EntityDisplayBase for config dependency handling,
and currently implements the corresponding getPluginCollections() method in EVD / EFD by hardcoding the list of widgets / formatters.
Assembling that list will need to be delegated to the component handlers.
Also, well, since the generic tool for "config dependencies for config entities holding a list of plugins" (EntityWithPluginCollectionInterface) relies on the notion of PluginCollections (new name for PluginBags), it definitely raises the question of internally using PluginCollections to store our lists of widgets / formatters.
Comment #86
aspilicious commentedFound a way to move the build part onto the component handler.
Feels extremely dirty as I needed to pass $this->content to the buildMultiple function.
Curious how many things I broke with this...
Comment #88
aspilicious commentedI'm going to reroll 81
Comment #89
aspilicious commentedLets see...
ignore the first lines of the patch ;)
Comment #91
aspilicious commentedThe annotation was in the wrong place bu the plugin manager still doesn't work, debugging...
Comment #92
aspilicious commentedNew try
Comment #94
aspilicious commentedOk... apparantly something changed in the last hour
Comment #95
aspilicious commentedComment #97
aspilicious commentedSmall fix
Comment #101
aspilicious commentedComment #102
aspilicious commentedComment #103
andypostAwesome, so now we need a plan to bring that to core at this stage
Comment #104
Anonymous (not verified) commentedSo...any plans for this yet?
Comment #105
andypostI think merge should not be hard, but no idea how to write beta evaluation...
Comment #108
mlevasseur commentedRerolled.
No changes.
Comment #112
andypostI'm sure there's a way to make that in within minor releases
Comment #113
swentel commentedI guess we can try again for 8.1.x
Comment #114
andypostSuppose display should follow changes on #2296423: Implement layout plugin type in core
Comment #116
andypostComment #117
andypostComment #118
r.nabiullin commentedrerolled path from comment #81
Comment #120
r.nabiullin commentedComment #122
r.nabiullin commentedfix not clean merge
Comment #124
r.nabiullin commentedComment #126
r.nabiullin commentedfix not clean merge
Comment #128
benjy commentedHere's a re-roll with a fix in the plugin manager that was killing lots of tests.
Comment #130
benjy commentedFormatterPluginManager is throwing errors because it requires $configuration['label'], not sure where that is meant to be initialised, if at all? I've put it in
EntityDisplayBase
for now to try and work closer to a green patch.Comment #131
benjy commentedSchema updates required makes me think this is wrong but i'm not sure what FormatterPluginManager would do.
Comment #134
benjy commentedFixes a bug with the plugin not been unset causing stale settings in the formatter and reverts the label changes from the previous two patches in favour of initialising an empty label in
FormatterPluginManager
as needed.Comment #136
benjy commentedThe array_filter in
FieldDisplayComponentHandler::getFieldDefinitions()
was filtering out base fields, in this case theuuid
field which meant it could not be rendered with $field->view() because it had no display settings.Comment #137
andypost@benjy Thanx for taking that!
It's very interesting what plugin has no label and where it fails with empty label. Maybe use
assert()
no longer needed, please remove
out of scope
looks like remains to remove
I'd better test with
isset()
and trigger someassert()
hereDid you found what caused missing label?
Comment #139
andypostMaybe it makes sense to revert with different function name
getDisplayableFields() ???
We should filter out fields that has no configurable display
Comment #140
benjy commentedYeah the tests fail in funny ways, shame we don't have any explicit tests for this.
Interdiff against 134, i set some display options for uuid so that UuidFormatterTest passes but maybe that test is just wrong trying to render uuid when it doesn't have display options?
Will address 137 later tonight.
Comment #141
benjy commentedAddressed 137.
Comment #143
andypostI guess it expected because https://www.drupal.org/node/2208327
Probably that points weakness of abstraction in this area
Comment #144
andypostSuppose patch missing fallback logic support when field rendered directly with formatter options instead of usage of entity display settings, see
\Drupal\Core\Field\FieldItemListInterface::view()
Here should be a fallback to rendering field with passed in display options instead of entity display
Comment #145
benjy commentedSo, 140 is green, 141 would be if we removed the assertion. I can't do much more here without some direction from someone who knows the end goal better than I.
I don't much like the naming of massageIn/massageOut, they seem more like preSave() and postLoad() methods?
EDIT, crossposted with #144, will try implement that.
Comment #146
benjy commentedOne observation, prepareDisplayComponents() is never called right now but i'm not sure where that would happen? Maybe inside setComponent() after we have a handler, rather than calling massageIn()?
I don't see how the fallback is going to work, we need the handler but we don't get the handler because of the filter mentioned in #139.
Comment #147
jibranI think we need tests for new classes added here. Here are some review points.
Not needed anymore.
Method names don't seem right. Can we change these to something better? PreSave and PostLoad perhaps.
Seems unrelated change.
There is not no label key anymore.
Comment #148
benjy commented@jibran, not sure if you cross posted with about 5 previous comments, but everything you just said is either done, or mentioned above :)
Comment #149
jibranHeh! discard my comment then. :-)
Comment #150
benjy commentedTo do this we need to be aware that it is a "field" because it would need to use fieldTypeManager to get the field_type for rendering. We could call it FallbackFieldComponentHander? It would basically be FieldDisplayComponentHandler but using the passed in options rather than the display options?
Comment #151
andypostYep, exactly!
Comment #152
benjy commentedIf it is to be outside of the display, it needs to happen in EntityViewBuilder I think, see how the tests go with this patch.
Comment #153
andypostMinor clean-up and fix for assert
Comment #155
benjy commentedAre you sure label is always required? Because, when I did that previously for the views fields, we end up with it been saved into the display and the schema for that doesn't currently exist?
E.g. try this:
Comment #158
andypostComment #159
tameeshb commented@andypost which patch needs to be re-rolled? #153 ?
Comment #160
tameeshb commentedComment #161
tameeshb commentedReroll patch uploaded to patch on #153
Comment #162
tameeshb commentedComment #163
tameeshb commentedComment #165
Heervesh commentedheervesh@heervesh-VirtualBox:~/drupal$ wget https://www.drupal.org/files/issues/reroll-1875974-160_0.patch
--2016-12-14 14:53:07-- https://www.drupal.org/files/issues/reroll-1875974-160_0.patch
Resolving www.drupal.org (www.drupal.org)... 151.101.17.175
Connecting to www.drupal.org (www.drupal.org)|151.101.17.175|:443... connected.
HTTP request sent, awaiting response... 200 OK
Length: 26018 (25K) [text/plain]
Saving to: ‘reroll-1875974-160_0.patch’
reroll-1875974-160_0.patch 100%[=================================================================>] 25.41K 132KB/s in 0.2s
2016-12-14 14:53:08 (132 KB/s) - ‘reroll-1875974-160_0.patch’ saved [26018/26018]
heervesh@heervesh-VirtualBox:~/drupal$ git apply --check reroll-1875974-160_0.patch
Comment #166
MaskyS commentedPatch applied cleanly.
Comment #167
MaskyS commentedComment #168
tameeshb commented@Kifah Meeran Nope, not for me...
Comment #169
tameeshb commentedComment #170
MaskyS commentedThe patch applied cleanly on drupal 8.2.4, which is the current stable version of Drupal.
root@masky-VirtualBox:/home/masky/drupal# git pull
remote: Counting objects: 279, done.
remote: Compressing objects: 100% (139/139), done.
remote: Total 142 (delta 113), reused 0 (delta 0)
Receiving objects: 100% (142/142), 26.19 KiB | 29.00 KiB/s, done.
Resolving deltas: 100% (113/113), completed with 90 local objects.
From http://git.drupal.org/project/drupal
fa8939c..5d0814d 8.2.x -> origin/8.2.x
926f9dc..d2b4642 8.3.x -> origin/8.3.x
Updating fa8939c..5d0814d
Fast-forward
core/lib/Drupal/Core/Render/theme.api.php | 47 +++++++++++++++++++++++------------------------
core/modules/file/src/Plugin/Field/FieldWidget/FileWidget.php | 15 +++++++++++++++
core/modules/node/src/Form/NodePreviewForm.php | 2 +-
core/modules/node/src/NodeForm.php | 27 ++++++++++++---------------
core/modules/node/src/Tests/PagePreviewTest.php | 113 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++----
core/modules/node/tests/modules/node_test/node_test.module | 15 +++++++++++++++
6 files changed, 175 insertions(+), 44 deletions(-)
root@masky-VirtualBox:/home/masky/drupal# git apply --check reroll-1875974-160_0.patch
root@masky-VirtualBox:/home/masky/drupal# git apply reroll-1875974-160_0.patch
root@masky-VirtualBox:/home/masky/drupal#
Comment #171
tim.plunkettYes but it needs a reroll to apply to the development version, which is 8.3.x
Comment #172
tameeshb commented@Kifah Meeran the Version: in this issue is 8.3.x
Comment #173
jofitzRe-roll.
Comment #174
jofitzComment #177
rlmumfordRerolled on 8.4.x
Comment #179
rlmumfordLooks like the patch in #173 removed some of the new files. Adding those back in.
Comment #180
rlmumfordOne more missing file.
Comment #183
pk188 commentedComment #189
jonathanshawThe IS proposes a BC break:
Maybe D9 is the opportunity for this.
Comment #191
andypostComment #192
xjmThis is a minor-only addition. Since 8.9.x is now in beta, I'm moving this to 9.1.x. Thanks!
Comment #194
andrewsuth commentedThis improvement makes a lot of sense. Is there still interest in getting it into core?
Comment #196
suresh prabhu parkala commentedA re-rolled patch against 9.3.x. Please review.
Comment #197
longwaveSome coding standards issues in EntityDisplayBase.php: https://www.drupal.org/pift-ci-job/2184750
Also, the change to core.services.yml is incorrectly indented.
Comment #198
vsujeetkumar commentedAddressed #197.
Fixed the coding standard issues along with core.services.yml is incorrectly indented issue.
Comment #200
catchComment #201
quietone commentedCame here to bring this up to date.
The failures in the latest patch are 'Error: Class "Drupal\Core\Entity\DisplayComponentHandlerPluginManager" not found. And yes, that class is not in the patch. Then I noticed that the last three patches are significantly smaller than the one in #180. Since the patch in #180 has that class I rerolled from that.
Comment #203
quietone commentedAdding the suggestion in #155. Also make the settings of $handler consistent.
Let's see what breaks now.
edit: s/$handler/$handler consistent/
Comment #204
andypostThank you! it looks much better
I'm not sure FALSE is good replacement for NULL, since PHP 8.0 it could use https://www.php.net/manual/en/language.oop5.basic.php#language.oop5.basi...
I think instead of NULL/FALSE manager should provide "missing/broken" handler
Which in turn could hide massageIn() call
Comment #206
quietone commented@andypost, thank you.
#204. I have restored getComponentHandlerByElementName($name) to what it was before #203. I have not addressed the last two sentences of the comment. (I just wanted to work on the tests)
This patch adds fixes for the tests. One is to add a 'label' property to the configuration of the formatter plugin in FormatterPluginManager and the other is to the display_component_handler service to the container in EntityFormDisplayAccessControlHandlerTest. Also included is a start of a test for the new FieldDisplayComponentHandler. I am not sure where the test should live, I put it in the field module.
In my wanderings working on this I noticed that \Drupal\Core\TypedData\ListDataDefinition::setDataType does not call the parent to set the data type, which appears to be an error. I tracked it to #2047229-153: Make use of classes for entity field and data definitions but that is all I have done.
Comment #207
quietone commentedUploading the patch would really help.
Comment #209
quietone commentedFix namespace error
Comment #210
andypostI still not sure about massage (in/out) a good naming also it get some from related #2844302: Move Field Layout data model and API directly into \Drupal\Core\Entity\EntityDisplayBase
Comment #212
jonathanshawOne alternative might be prepareForStorage() and prepareForDisplay(). The meaning of in/out was actually opposite to what I expected.
Comment #213
quietone commentedCurrent options for the changing the name of massageIn() and massageOut() are:
#47: rename massageOut to massageExportOptions(). No suggestion there for massageOut.
#145: preSave() and postLoad()
#212: prepareForStorage() and prepareForDisplay().
Of those options I prefer the suggestions from #145 because they are names already in use in core. This patch is implementing that so we can all see what it looks like.
During my testing I found that prepareDisplayComponents() is never called. The same was pointed out by benjy in #146.
Comment #214
jonathanshaw#145 +1
Comment #215
jonathanshawI find it odd that the plugin is @DisplayComponent but everywhere called DisplayComponentHandler.
Comment #216
jonathanshawThe BC concern raised in the IS no longer seems relevant:
Also this no longer applies:
Comment #217
jonathanshawTodo:
1. Tests per #155
2. #146 prepareDisplayComponents() is never called
3. #204 provide "missing/broken" handler (although see #146 for contrary opinion)
4. Resolve the missing labels @todo in FormatterPluginManager
5. Create a follow-up for ListDataDefinition::setDataType does not call the parent to set the data type
Feels like this is getting close.
Comment #218
andypostI think instead of plugins (renderer of display component kind) we should use tagged services (collector) because there will be not a lot of them - field, extra_field, field_group, layout_builder
Comment #220
joachim commentedMostly nitpicks and docs :)
Interface, not base class.
'should process' / 'provides'. These don't mean the same thing, so the docs here are confusing.
I can see that maybe if the handler provides the component, THEN it should process it. But it's not clear that this isn't a typo. If it is the case that it's like this, the docs should be expanded a bit to say more on that.
As of D9 we should use parameter and return types on all these methods.
The values should be quoted. And are they examples, or an exhaustive list? The docs should say.
If it's an object or NULL, I think the right thing here is '\Class\Name|null'
NULL should be in caps.
Plural 'elements' and singular 'its' reads weirdly.
How about 'An array of handlers keyed by their display element names.'?
If this check is for subclasses that aren't calling the constructor, then shouldn't there be a deprecation warning somewhere?
'massage' reads a lot less clear and less formal than the comment line being removed.
Docblock is wrong.
Needs trailing comma.
Wrong class name.
Missing @return.
Missing @return.
Should be fully-qualified.
Comment #221
joachim commented> I think instead of plugins (renderer of display component kind) we should use tagged services (collector) because there will be not a lot of them
I'm not keen on there being two systems in Drupal for 'discovering things that do different flavours of a task'. It's not good DX.
AFAIK, tagged services are used for lower-level stuff, and things that we're extending from Symfony. My impression is that they're less widely known about than plugins.
I'd welcome a separate issue to discuss coding guidelines on when to use plugins vs when to use tagged services, but as the entity and field systems use plugins, I think we should stick to plugins here.
Comment #222
ravi.shankar commentedAdded reroll of patch #213 on Drupal 9.5.x., will work on #220 later.
Comment #223
ravi.shankar commentedAddressed these 1, 3, 4, 5, 6, 7, 10, 11, 12, 13, 14 and 15 points of comment #220.
Still needs works for these points 2, 8 and 9.
Comment #224
andypostshould be 'an interface'
Comment #225
ravi.shankar commentedAddressed comment #224, still needs work for #223 remaining points.