Media library remove button triggers field constraint validation

Created on 1 September 2021, almost 3 years ago
Updated 31 January 2023, over 1 year ago

Problem/Motivation

We have the following use case:

  • Node
    • Field "Media"
      • Constraint (that checks for a value in media entity)

The constraint gets the media entity and checks for a given field value. If this value is set validation runs through if not a violation is added.

Steps to reproduce

Config / Code

  • Create a node type X with an entity reference field to a media bundle.
  • Use media library as field widget.
  • Add a constraint on the field that dives into media entity. (Via hook_entity_bundle_field_info_alter())

Content

  • Create node of type X.
  • Add a media entity that violates your constraint.
  • Try saving the node. -> Constraint should not allow saving.
  • Try removing the media entity. -> Constraint falsely doesn't allow removal.
  • Deadlock.

Proposed resolution

In MediaLibraryWidget.php:413 do not limit validation errors to parent but instead set to empty array.

Remaining tasks

User interface changes

API changes

Data model changes

Release notes snippet

πŸ› Bug report
Status

Active

Version

9.5

Component
MediaΒ  β†’

Last updated about 14 hours ago

Created by

πŸ‡©πŸ‡ͺGermany lucastockmann

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

Comments & Activities

Not all content is available!

It's likely this issue predates Contrib.social: some issue and comment data are missing.

  • πŸ‡³πŸ‡±Netherlands Ruuds

    I also encountered this issue. Somehow the ConstraintValidator should be aware of which media items are removed. For now I implemented a dirty solution which checks if the remove button of a specific media item is clicked and skips the validation for that media item:

    public function validate($value, Constraint $constraint) {
        $field_name = $this->context->getPropertyName();
        $triggering_element_name = $this->requestStack->getCurrentRequest()
          ->get('_triggering_element_name');
    
        foreach ($value as $index => $item) {
          $media = $item->entity;
          if (!$media instanceof MediaInterface) {
            continue;
          }
    
          if ($triggering_element_name === $field_name . '-' . $index . '-media-library-remove-button') {
            // Remove button was clicked, so skip validation.
            continue;
          }
    
          if (!$this->canUse($media, $value->getEntity())) {
            $this->context->addViolation($this->t('This media item is already being used.'));
          }
        }
      }
    
  • πŸ‡³πŸ‡±Netherlands Ruuds

    Update: The _triggering_element_name contains extra text when the constraint is validated on a field which is added to a paragraph type. In that case,

    if ($triggering_element_name === $field_name . '-' . $index . '-media-library-remove-button') {
    

    can be replaced with

    if (stripos($triggering_element_name, $field_name . '-' . $index . '-media-library-remove-button') === 0) {
    

    which will possibly lead to other issues, but works in my case.

Production build 0.69.0 2024