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.

Support from Acquia helps fund testing for Drupal Acquia logo

Comments

stevector’s picture

stevector’s picture

Title: Allow form modes to use default operation if an operation is not explicitly set » Allow form modes to use default operation if a form operation is not explicitly set
Assigned: stevector » Unassigned
Status: Postponed (maintainer needs more info) » Needs review

Status: Needs review » Needs work

The last submitted patch, 1: fall-back-to-default-2511720-1.patch, failed testing.

stevector’s picture

Closing brackets are helpful.

stevector’s picture

Status: Needs work » Needs review
stevector’s picture

Adding a related issue.

Status: Needs review » Needs work

The last submitted patch, 4: fall-back-to-default-2511720-4.patch, failed testing.

andypost’s picture

the 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 regression

Version: 8.0.x-dev » 8.1.x-dev

Drupal 8.0.6 was released on April 6 and is the final bugfix release for the Drupal 8.0.x series. Drupal 8.0.x will not receive any further development aside from security fixes. Drupal 8.1.0-rc1 is now available and sites should prepare to update to 8.1.0.

Bug reports should be targeted against the 8.1.x-dev branch from now on, and new development or disruptive changes should be targeted against the 8.2.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

Version: 8.1.x-dev » 8.2.x-dev

Drupal 8.1.9 was released on September 7 and is the final bugfix release for the Drupal 8.1.x series. Drupal 8.1.x will not receive any further development aside from security fixes. Drupal 8.2.0-rc1 is now available and sites should prepare to upgrade to 8.2.0.

Bug reports should be targeted against the 8.2.x-dev branch from now on, and new development or disruptive changes should be targeted against the 8.3.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

Version: 8.2.x-dev » 8.3.x-dev

Drupal 8.2.6 was released on February 1, 2017 and is the final full bugfix release for the Drupal 8.2.x series. Drupal 8.2.x will not receive any further development aside from critical and security fixes. Sites should prepare to update to 8.3.0 on April 5, 2017. (Drupal 8.3.0-alpha1 is available for testing.)

Bug reports should be targeted against the 8.3.x-dev branch from now on, and new development or disruptive changes should be targeted against the 8.4.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

woprrr’s picture

This feature are assumed in form_mode_manager module. I guess we can reproduce similar mecanism onto this issue ?

Version: 8.3.x-dev » 8.4.x-dev

Drupal 8.3.6 was released on August 2, 2017 and is the final full bugfix release for the Drupal 8.3.x series. Drupal 8.3.x will not receive any further development aside from critical and security fixes. Sites should prepare to update to 8.4.0 on October 4, 2017. (Drupal 8.4.0-alpha1 is available for testing.)

Bug reports should be targeted against the 8.4.x-dev branch from now on, and new development or disruptive changes should be targeted against the 8.5.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

joachim’s picture

I 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?

bastnic’s picture

Update patch to current version. Work great on my side (with a Group entity). Thanks stevector

Version: 8.4.x-dev » 8.5.x-dev

Drupal 8.4.4 was released on January 3, 2018 and is the final full bugfix release for the Drupal 8.4.x series. Drupal 8.4.x will not receive any further development aside from critical and security fixes. Sites should prepare to update to 8.5.0 on March 7, 2018. (Drupal 8.5.0-alpha1 is available for testing.)

Bug reports should be targeted against the 8.5.x-dev branch from now on, and new development or disruptive changes should be targeted against the 8.6.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

Version: 8.5.x-dev » 8.6.x-dev

Drupal 8.5.6 was released on August 1, 2018 and is the final bugfix release for the Drupal 8.5.x series. Drupal 8.5.x will not receive any further development aside from security fixes. Sites should prepare to update to 8.6.0 on September 5, 2018. (Drupal 8.6.0-rc1 is available for testing.)

Bug reports should be targeted against the 8.6.x-dev branch from now on, and new development or disruptive changes should be targeted against the 8.7.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

ikouoh’s picture

Update patch to core 8.7

shubhangi1995’s picture

bradjones1’s picture

Version: 8.6.x-dev » 8.7.x-dev

Status: Needs review » Needs work

The last submitted patch, 21: 2511720-21.patch, failed testing. View results

aleevas’s picture

Status: Needs work » Needs review
FileSize
2.09 KB
2.83 KB

Sorry, was attached a wrong patch.
This patch should be better

aleevas’s picture

FileSize
2.09 KB

I don't understand why it failed.
Trying this one

andypost’s picture

+++ b/core/lib/Drupal/Core/Entity/EntityTypeManager.php
@@ -220,7 +220,12 @@ public function getListBuilder($entity_type_id) {
     if (!$class = $this->getDefinition($entity_type_id, TRUE)->getFormClass($operation)) {
-      throw new InvalidPluginDefinitionException($entity_type_id, sprintf('The "%s" entity type did not specify a "%s" form class.', $entity_type_id, $operation));
+      // If there is not a class specified for this operation, try the default
+      // class. This condition is likely used by form modes added through
+      // the form modes user interface.
+      if (!$class = $this->getDefinition($entity_type_id, TRUE)->getFormClass('default')) {

I recall there was reason to have no fallback to default

golddragon007’s picture

Status: Needs review » Reviewed & tested by the community

The 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.

hchonov’s picture

Status: Reviewed & tested by the community » Needs work
Issue tags: +DX (Developer Experience)

Instead 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.

golddragon007’s picture

I 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.

hchonov’s picture

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)

But 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.

Version: 8.7.x-dev » 8.8.x-dev

Drupal 8.7.9 was released on November 6 and is the final full bugfix release for the Drupal 8.7.x series. Drupal 8.7.x will not receive any further development aside from security fixes. Sites should prepare to update to 8.8.0 on December 4, 2019. (Drupal 8.8.0-beta1 is available for testing.)

Bug reports should be targeted against the 8.8.x-dev branch from now on, and new development or disruptive changes should be targeted against the 8.9.x-dev branch. For more information see the Drupal 8 and 9 minor version schedule and the Allowed changes during the Drupal 8 and 9 release cycles.

c7bamford’s picture

I 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.

c7bamford’s picture

Status: Needs work » Reviewed & tested by the community
Issue tags: -DX (Developer Experience)

Status: Reviewed & tested by the community » Needs work

The last submitted patch, 24: 2511720-24.patch, failed testing. View results

jantoine’s picture

Version: 8.8.x-dev » 8.9.x-dev
Status: Needs work » Needs review
FileSize
2.1 KB

Rerolled against 8.9.x.

Status: Needs review » Needs work

The last submitted patch, 34: 2511720-34.patch, failed testing. View results

ravi.shankar’s picture

Assigned: Unassigned » ravi.shankar
ravi.shankar’s picture

Assigned: ravi.shankar » Unassigned
Status: Needs work » Needs review
FileSize
2.1 KB

This patch might fix the failed tests of patch #34.

Version: 8.9.x-dev » 9.1.x-dev

Drupal 8.9.0-beta1 was released on March 20, 2020. 8.9.x is the final, long-term support (LTS) minor release of Drupal 8, which means new developments and disruptive changes should now be targeted against the 9.1.x-dev branch. For more information see the Drupal 8 and 9 minor version schedule and the Allowed changes during the Drupal 8 and 9 release cycles.

Version: 9.1.x-dev » 9.2.x-dev

Drupal 9.1.0-alpha1 will be released the week of October 19, 2020, which means new developments and disruptive changes should now be targeted for the 9.2.x-dev branch. For more information see the Drupal 9 minor version schedule and the Allowed changes during the Drupal 9 release cycle.

Version: 9.2.x-dev » 9.3.x-dev

Drupal 9.2.0-alpha1 will be released the week of May 3, 2021, which means new developments and disruptive changes should now be targeted for the 9.3.x-dev branch. For more information see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.

Version: 9.3.x-dev » 9.4.x-dev

Drupal 9.3.0-rc1 was released on November 26, 2021, which means new developments and disruptive changes should now be targeted for the 9.4.x-dev branch. For more information see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.

Version: 9.4.x-dev » 9.5.x-dev

Drupal 9.4.0-alpha1 was released on May 6, 2022, which means new developments and disruptive changes should now be targeted for the 9.5.x-dev branch. For more information see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.

Version: 9.5.x-dev » 10.1.x-dev

Drupal 9.5.0-beta2 and Drupal 10.0.0-beta2 were released on September 29, 2022, which means new developments and disruptive changes should now be targeted for the 10.1.x-dev branch. For more information see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.

nod_’s picture

Status: Needs review » Needs work

code is fairly old, doesn't pass commit checks anymore for 10.1.x

ravi.shankar’s picture

Status: Needs work » Needs review
FileSize
1.92 KB
850 bytes
1.92 KB

Address Drupal CS issue of patch #37.

ravi.shankar’s picture

By mistake added a patch twice.

smustgrave’s picture

Status: Needs review » Needs work
Issue tags: +Needs Review Queue Initiative

Not sure #8 was answered
Reading the comments doesn't seem like there is an agreement on the solution forward.

Version: 10.1.x-dev » 11.x-dev

Drupal core is moving towards using a “main” branch. As an interim step, a new 11.x branch has been opened, as Drupal.org infrastructure cannot currently fully support a branch named main. New developments and disruptive changes should now be targeted for the 11.x branch, which currently accepts only minor-version allowed changes. For more information, see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.

Ghost of Drupal Past’s picture

I 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.

Ghost of Drupal Past’s picture

In 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:

  1. 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. 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.
  2. Currently, there is some operation fallback in DefaultHtmlRouteProvider for add-form and edit-form. This is why HtmlEntityFormController / EntityTypeManager work without a problem even if add/edit is not defined as a form operation. For example, User defines the edit-form link template but not an edit form operation.
  3. Even with this patch, any UI defined form modes would still not provide anything to the user. No pages, no local tabs, no modals, no nothing. Cstom code is still necssary for any of that to happen. In light of that and what DefaultHtmlRouteProvider does, is this the place to do the fallback? Or perhaps the custom code should do the fallback?
  4. If the patch is accepted, the fallback from DefaultHtmlRouteProvider could be removed. The routes and the entity form display objects and alter hooks would all get "add" / "edit" as form mode versus just "default". Core currently works around this in, for example, media where the add and edit operations are separately defined (but are handled by the same form class). Perhaps this could be removed as well. Perhaps in a followup. But if such cleanups are deemed worthy to be doing that's an argument in favor of the patch.
  5. Perhaps the fallback should be optional. collectRenderDisplay has such an argument, for example.
joachim’s picture

> 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.)

Ghost of Drupal Past’s picture

> 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.

joachim’s picture

Ah 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:

* - form: An associative array where the keys are the names of the
* different form operations (such as 'create', 'edit', or 'delete') and
* the values are the names of the handler classes for those
* operations. The name of the operation is passed also to the form

lazzyvn’s picture

For 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']

 $handler_type = $this->entityTypeManager()->getDefinition($entity_type, TRUE);
    $default_handler_class = $handler_type->getFormClass('default'); 
// or $default_handler_class = $handler_type->getHandlerClasses()['form']['default']; 
      $mode = 'custom_mode';
      $handler_type->setFormClass($mode, $default_handler_class);
    $form = $this->entityTypeManager()->getFormObject($entity_type, $mode)->setEntity($entity);