Problem/Motivation
Form modes added through the UI are not usable until a form class is registered for the form mode using hook_entity_type_build. The form modes can be configured per bundle (setting which fields and field widgets are to be used by the form mode). Calling the form mode (which overlaps with a form operation) results in this error.
Drupal\Component\Plugin\Exception\InvalidPluginDefinitionException: The "node" entity type did not specify a "ief" form class. in Drupal\Core\Entity\EntityManager->getFormObject() (line 294 of /var/www/workbench.local/web/core/lib/Drupal/Core/Entity/EntityManager.php).
Proposed resolution
Add run time, use the "default" operation class for any view mode that does not correspond to an already registered operation class.
Remaining tasks
- Agree that falling back to the "default" form class is the appropriate resolution.
- Decide whether to check for an "edit" class for entity types that have no "default" class.
- Review patch.
- Write tests.
User interface changes
None. This change should make the existing UI more usable. With this change (or something similar) there will need to be a UI change saying something like "Your form mode will not be usable until you register a form class with hook_entity_type_build"
API changes
I don't think this change qualifies as an API change.
Data model changes
None
Original report by [username]
I'm making this issue as a placeholder to follow up on #2510274: Add ability to select form Display Mode
I will add more detail shortly.
Comment | File | Size | Author |
---|---|---|---|
#45 | 2511720-45.patch | 1.92 KB | ravi.shankar |
| |||
#45 | interdiff_37-45.txt | 850 bytes | ravi.shankar |
#45 | 2511720-45.patch | 1.92 KB | ravi.shankar |
| |||
#37 | 2511720-37.patch | 2.1 KB | ravi.shankar |
#34 | 2511720-34.patch | 2.1 KB | jantoine |
Comments
Comment #1
stevectorComment #2
stevectorComment #4
stevectorClosing brackets are helpful.
Comment #5
stevectorComment #6
stevectorAdding a related issue.
Comment #8
andypostthe problem here that contrib module developers will require to check each form-alter for class to make sure that edit/delete or other form is used that makes
hook_form_FORM_ID_alter()
a regressionComment #12
woprrr CreditAttribution: woprrr as a volunteer and at NeoLynk commentedThis feature are assumed in form_mode_manager module. I guess we can reproduce similar mecanism onto this issue ?
Comment #14
joachim CreditAttribution: joachim as a volunteer commentedI don't quite understand the problem in #8.
What would hook_form_FORM_ID_alter() do at the moment that this patch would prevent?
Given the forms in question can't be output at the moment anyway, who would be altering them?
Comment #15
bastnic CreditAttribution: bastnic commentedUpdate patch to current version. Work great on my side (with a Group entity). Thanks stevector
Comment #18
ikouoh CreditAttribution: ikouoh commentedUpdate patch to core 8.7
Comment #19
shubhangi1995fall_back patch for 8.6.15
Comment #20
bradjones1Comment #21
aleevasHere is my fix for #18
Comment #23
aleevasSorry, was attached a wrong patch.
This patch should be better
Comment #24
aleevasI don't understand why it failed.
Trying this one
Comment #25
andypostI recall there was reason to have no fallback to default
Comment #26
golddragon007 CreditAttribution: golddragon007 at European Commission and European Union Institutions, Agencies and Bodies, Petend commentedThe condition was added in this issue: https://www.drupal.org/project/drupal/issues/2168333
But I can't see any mentioning anywhere in this issue or any other issue why there's no fallback. However for custom entities maybe there are some cases when the fallback won't work properly if the default/add/edit all different or just the first and last two.
Anyway, for me, this #24 patch works in my scenarios.
Comment #27
hchonovInstead of falling back to default I would prefer that we can choose the form handler during the form mode creation process.
Making this more explicit will be more understandable for developers and for site builders.
We can let the user select either a form class to be used or a form operation from which to dynamically retrieve the form class. I think that we need both options to make it more flexible.
Comment #28
golddragon007 CreditAttribution: golddragon007 at European Commission and European Union Institutions, Agencies and Bodies, Petend commentedI disagree with it, if we let the 'user' choose, then there's no guarantee the chosen class can handle the entity properly (except if you filtering really well). You need to make sure somehow that class can handle the entity properly. These are by default the default, add, edit and delete forms, which the entity annotates (from here the first three is the same most cases, except if you have a custom entity but in that case any way you need to define in code your form handler). Besides that, if we allow the user to choose which form builder he wants to use then we need to allow which display render want to use, I mean currently in the system there are fallbacks (i.e. manage display I'm pretty sure that also falls back to default), if the fallback is not good to you, then you can define your own way, in this case, i.e. hook_entity_type_build(). And personally I don't want to use a system that looks like a dog and behaves like a cat, it just increases the complexity.
In short, I don't see any reason to do it in 99.99% of the cases.
Comment #29
hchonovBut that is valid for the default form class as well. There is no promise for it being an universal one. Following this logic this issue would be "won't fix" simply because there is no guarantee that any of the form handlers can manage the form display.
Comment #31
c7bamford CreditAttribution: c7bamford commentedI feel like developers needing more custom form behavior should be able to write or specify the form class they want to use in code. Adding a form class discovery system seems like unnecessary complication to this issue.
It should be assumed that the entity's default form should be able to correctly display the form. If it can't, that should be considered a problem with the entity's default form, not with using the 'default' form mode as a default.
I could see an argument being made to allow the site builder to select an operation from those defined on the entity type to create a new form mode for, but that seems like it should go in a follow up to this issue.
Comment #32
c7bamford CreditAttribution: c7bamford commentedComment #34
jantoine CreditAttribution: jantoine as a volunteer commentedRerolled against 8.9.x.
Comment #36
ravi.shankar CreditAttribution: ravi.shankar at OpenSense Labs commentedComment #37
ravi.shankar CreditAttribution: ravi.shankar at OpenSense Labs commentedThis patch might fix the failed tests of patch #34.
Comment #44
nod_code is fairly old, doesn't pass commit checks anymore for 10.1.x
Comment #45
ravi.shankar CreditAttribution: ravi.shankar at OpenSense Labs commentedAddress Drupal CS issue of patch #37.
Comment #46
ravi.shankar CreditAttribution: ravi.shankar at OpenSense Labs commentedBy mistake added a patch twice.
Comment #47
smustgrave CreditAttribution: smustgrave at Mobomo commentedNot sure #8 was answered
Reading the comments doesn't seem like there is an agreement on the solution forward.
Comment #49
Ghost of Drupal PastI just separated and expanded on the form operations documentation at https://www.drupal.org/docs/drupal-apis/entity-api/display-modes-view-mo... it might be useful when considering this patch.
Comment #50
Ghost of Drupal PastIn light of the clarity brought by reading all the code relating to that handbook page I would like to offer a few observations. I have no opinion whether this patch should or should not be added, a few things are worth noting:
array_keys($entity_type->getHandlerClass('form'))
retrieves all possible values that can be passed to the second argument togetFormObject($entity_type->id(), $operation)
and after the patch this will not be case. However, I am not sure this is an API, it's certainly not documented: the only slight hint in the doxygen is the fact @return can be an array on getHandlerClass(). But that's just a slight hint. Neither getFromClass() nor getFormObject() mentions this. It is also not clear to me why would anyone need to enumerate all possible form operations. So it's possible this is still not an API change but IMO it's worth considering this briefly.Comment #51
joachim CreditAttribution: joachim as a volunteer commented> Currently array_keys($entity_type->getHandlerClass('form')) retrieves all possible values that can be passed to the second argument to getFormObject($entity_type->id(), $operation) and after the patch this will not be case.
I don't understand this at all -- the patch doesn't touch getHandlerClass() at all.
> However, I am not sure this is an API, it's certainly not documented
The @return also says 'handlers' plural, so I'd consider this to be documented.
(BTW see also #3295307: EntityTypeManager::getHandler() doesn't allow for nesting.)
Comment #52
Ghost of Drupal Past> I don't understand this at all -- the patch doesn't touch getHandlerClass() at all.
Currently, if you want to know what $operation can you pass to getFormObject, the answer is: whatever getHandlerClass() return. After the patch it is, I believe, "anything". That's the difference I was pointing to.
Comment #53
joachim CreditAttribution: joachim as a volunteer commentedAh ok I think I understand.
Currently, the valid values for the $operation parameter of EntityTypeManager::getFormObject($entity_type_id, $operation) are specifically the array keys in the returned array from $entity_type->getHandlerClass('form').
After the patch, you could call EntityTypeManager::getFormObject($entity_type_id, 'any old rubbish I made up') and get back the default form operation.
So it's a DX question - is it the right behaviour to fallback silently, or should it complain that the $operation is invalid.
It's clearly not the intention that you can invent a form operation on the fly -- the docs for getHandlerClasses() say:
Comment #54
lazzyvn CreditAttribution: lazzyvn commentedFor someone looking for a temporary solution before fixing this issue, you can do like this to get a custom form
It will add to handlers['form']['custom_mode'] = handlers['form']['default']