Add support for compound fields like Name and Address fields

Created on 12 June 2024, 5 months ago
Updated 18 June 2024, 5 months ago

Problem/Motivation

Partially filled compound fields are not validated by Require on Publish (ROP).

When partially filled, the subfields are not considered during ROP validation unless they pass their individual require validation.

Keep in mind that these contrib-module fields have their own required/optional setting for the subfields. Those can be set as either optional or required.

Example with Name

Here are examples of the Name field issue.

Example with Address

Address field takes it a step further by issuing the required="required" attribute, which kicks in the client-side form validation.

Steps to reproduce

  1. Install Address β†’ and/or Name β†’
  2. On the Basic Page content type, create a field of type Address and/or Name.
  3. Leave the default require settings (Overrides for Address or Minimum components for Name).
  4. Ensure Require on Publish is selected on each field.
  5. Create a Basic Page node; fill out only one of the required subfields, leaving the others empty.
  6. Attempt to submit Draft. Fails require validation.
  7. Attempt to submit Published. Fails require validation.

Proposed resolution

When a field is marked Required on Publish, we must Ensure that the required="required" attribute is removed from subfields, and either...

  1. Provide module-specific field settings to mark subfields as required on publish.
  2. Consider any required subfields to be required on publish.

The latter is the simpler of the two, but still may require module-specific handling because modules have different methods of creating and marking subfields as required.

Remaining tasks

Add support for compound fields.

User interface changes

Add indicators (blue carat) to subfields.

✨ Feature request
Status

Needs work

Version

1.0

Component

Code

Created by

πŸ‡ΊπŸ‡ΈUnited States jumoke

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

Comments & Activities

  • Issue created by @jumoke
  • πŸ‡ΊπŸ‡ΈUnited States jcandan

    Updated the description to take into account how the https://www.drupal.org/project/address and https://www.drupal.org/project/name modules let site-builders manage which sub-fields are required.

  • πŸ‡ΊπŸ‡ΈUnited States jcandan
  • πŸ‡ΊπŸ‡ΈUnited States jcandan
  • πŸ‡ΊπŸ‡ΈUnited States jcandan

    Updated title to clarify that this isn't about cardinality, but fields types that include multiple fields--compound fields.

  • πŸ‡ΊπŸ‡ΈUnited States jcandan

    Original report

    The original report proposed that all subfields should be marked optional when reproducing this issue. It then suggested that the field could be subsequently submitted as Published without the desired required fields. This makes sense because there was no field marked as required. ROP validation kicks in if the field is left completely empty.

    For the Address field, this means that to not have selected a Country, it would not pass Require on Publish validation. And it correctly does not.

    For the Name field, it does not even allow you to set all subfields as optional, at least Given or Family must be required:

    If I were to fill in the Given and Family fields, and Select a Country, this is able to be saved as Published.

  • πŸ‡ΊπŸ‡ΈUnited States jcandan

    Gave this a shot.

    /**
     * Implements hook_field_widget_complete_form_alter().
     */
    function require_on_publish_field_widget_complete_form_alter(&$field_widget_complete_form, FormStateInterface $form_state, $context) {
      $field_config = $context['items']->getFieldDefinition();
      $field_name = $field_widget_complete_form['widget']['#field_name'];
      /** @var \Drupal\Core\Entity\EntityFormInterface $form_object */
      $form_object = $form_state->getFormObject();
      if ($form_object instanceof EntityFormInterface) {
        /** @var \Drupal\Core\Entity\ContentEntityInterface $entity */
        $entity = $form_object->getEntity();
        if (_require_on_publish_entity_is_publishable(get_class($entity))) {
          // $field = $entity->getFields()[$field_name];
          // $field_config = $field->getFieldDefinition();
          if (($field_config instanceof FieldConfigInterface)) {
            if ($field_config->getThirdPartySetting('require_on_publish', 'require_on_publish', FALSE)) {
              $place_breakpoint_here = 'Analyze the available Widget';
              // Loop the widget sub-fields and determine if they're required. Then,
              // treat each required subfield as if it were required on publish.
            }
          }
        }
      }
    }
    

    Tried similar attempts from preprocess hooks, like require_on_publish_preprocess_form_element(). The problem is that I cannot get a combination of render array and the entity context necessary to alter the render array to:

    1. Determine the subfield's parent is required on publish.
    2. Remove the required attribute.
    3. Somehow implement the require_on_publish logic.

    I am open to suggestions and willing to accept DMs in #slack.

  • πŸ‡ΊπŸ‡ΈUnited States jcandan
  • πŸ‡ΊπŸ‡ΈUnited States jcandan

    Just had an idea, noting it here so I don't forget.

    What if I tackle this from a new Constraint?

  • πŸ‡ΊπŸ‡ΈUnited States jcandan

    I was able to Disable HTML5 validation β†’ to get around the Address module's required attribute. So, similar to Name, I am getting the required subfield validation.

  • πŸ‡ΊπŸ‡ΈUnited States jcandan

    Using the existing constraint, if I could just get it to run the AddressFormatConstraintValidator before RequireOnPublishValidator, I think I would then be able to alter the $this->context->getViolations.

    Tried increasing the module weight with module_set_weight() to no avail.

  • Status changed to Needs work 5 months ago
  • πŸ‡ΊπŸ‡ΈUnited States jcandan

    A patch supporting the Name field.

Production build 0.71.5 2024