The field entity should be passed to the plugin

Created on 9 July 2024, 5 months ago
Updated 10 July 2024, 5 months ago

Problem/Motivation

Currently, the only information passed to the plugin that's supposed to determine whether or not the field is required is the field definition and the active user. In a lot of real world scenario's, the entity the field is attached to will also be needed to determine this, for example if we want the required state to depend on other field values.

Proposed resolution

Pass the entity as argument to Drupal\required_api\Plugin\RequiredPluginInterface::isRequired().

Feature request
Status

Needs review

Version

2.0

Component

Code

Created by

🇧🇪Belgium dieterholvoet Brussels

Live updates comments and jobs are added and updated live.
Sign in to follow issues

Merge Requests

Comments & Activities

  • Issue created by @dieterholvoet
  • 🇧🇪Belgium dieterholvoet Brussels

    Adding this argument will result in backwards-incompatible changes, but since a new 2.x branch was started we can do that there, right? I feel like it would also be a good idea to get rid of the $account argument. Plugins that need this can inject the current_user service instead.

  • Merge request !6Resolve #3460341 "Pass field entity" → (Open) created by dieterholvoet
  • 🇧🇪Belgium dieterholvoet Brussels

    I pushed a pretty big refactor of the module:

    • I replaced the original approach with an approach where I override the EntityFormDisplay entity class in order to have access to the field entity
    • I added an extra approach where I override the TypedDataManager & RecursiveValidator classes in order to add support for validating entities in non-form contexts, e.g. when executing Drupal\Core\Entity\FieldableEntityInterface::validate().
    • I removed the $account argument of the Drupal\required_api\Plugin\RequiredPluginInterface::isRequired() method, because it can be replaced with an injected current_user service
    • I added the $entity argument to the Drupal\required_api\Plugin\RequiredPluginInterface::isRequired() method, in order to have access to e.g. other fields to determine whether or not a field should be required.

    Let me know what you think!

  • Status changed to Needs review 5 months ago
  • 🇧🇪Belgium dieterholvoet Brussels

    The reason for this refactor is my intention of releasing a required_by_content_moderation_state module, allowing fields to only be required when their associated entity reaches a certain Content Moderation state. Before, this would only be necessary by reading parameters of the global request, and even then it wouldn't work when programatically validating entities. After the changes in this MR, all these things work.

  • Status changed to Needs work 5 months ago
  • 🇧🇪Belgium dieterholvoet Brussels

    Okay, this isn't it yet. Drupal\required_api\Entity\RequiredApiEntityFormDisplay::buildForm() isn't executed when submitting the form, so any new values aren't being considered in the required logic.

  • 🇧🇪Belgium dieterholvoet Brussels

    Seems like the first chance to get an entity object which is updated with the last form changes is in ContentEntityForm::validateForm(), after $this->buildEntity() is called. It seems like at that point, the required validation errors are already present in the form state though. This means that it's impossible to determine the required status based on the entity object, if we want to change the required status before the form is built/validated. The alternative is to do it after the form is built/validated and to remove any unnecessary required validation errors from the form state. I'll try out this approach in the MR.

  • Status changed to Needs review 5 months ago
  • 🇧🇪Belgium dieterholvoet Brussels

    I replaced the overridden EntityFormDisplay with an overridden FormErrorHandler, that seems to do the trick.

  • 🇧🇪Belgium dieterholvoet Brussels

    There is a visual difference: this approach makes it so the delayed required fields still show the required asterisk, but they don't trigger a form error. Personally, I like this even better.

Production build 0.71.5 2024