2

I'm attempting to follow this documentation to add a custom constraint to a field in a Paragraph but I'm having trouble in adding constraint to that field.

Currently I have book content type with paragraph type bibliographic_information. This paragraph type has a field named as field_book_edition. This field accepts a string value. I'd like to be able to add a constraint to the field so that it accepts a certain string pattern as input.

I've created constrain and tried using hook_entity_bundle_field_info_alter, when ever I try to save the node I am getting the following error.

The website encountered an unexpected error. Please try again later.

InvalidArgumentException: Field field_bibliographic_information is unknown. in Drupal\Core\Entity\ContentEntityBase->getTranslatedField() (line 587 of core/lib/Drupal/Core/Entity/ContentEntityBase.php).

My Code is as follows :

book_content.module

use Drupal\Core\Entity\EntityTypeInterface;

/**
 * Implements hook_entity_bundle_field_info_alter().
 */
function book_content_entity_bundle_field_info_alter(&$fields, EntityTypeInterface $entity_type, $bundle) {

  // Refer https://drupal.stackexchange.com/a/277438/

  if ($entity_type->id() === 'paragraph' && $bundle === 'bibliographic_information' && isset($fields['field_book_edition'])) {

    // Add our custom validation to the book edition field.
    $fields['field_book_edition']->addConstraint('BookContentEditionConstraint');
  }

}

BookContentEditionConstraintValidator.php

namespace Drupal\book_content\Plugin\Validation\Constraint;

use Symfony\Component\Validator\Constraint;
use Symfony\Component\Validator\ConstraintValidator;

/**
 * Validates the Book Content constraint.
 */
class BookContentEditionConstraintValidator extends ConstraintValidator {

  /**
   * {@inheritdoc}
   */
  public function validate($entity, Constraint $constraint) {

    $node = $entity->getEntity();

    // Get referenced paragraph entities.
    $referenceItem = $node->get('field_bibliographic_information')->referencedEntities();

    foreach ($referenceItem as $data) {

      $fields = [
        'field_book_author' => $data->field_book_price->value,
        'field_book_edition'  => $data->field_book_edition->value,
        'field_book_language'  => $data->field_book_language->value,
        'field_book_pages'  => $data->field_book_pages->value,
        'field_book_price'  => $data->field_book_price->value,
        'field_book_published_year'  => $data->field_book_published_year->value,
        'field_book_synopsis'  => $data->field_book_synopsis->value,
        'field_website'  => $data->field_website->getValue()[0]['uri'],
      ];
    }

    // Check if the book edition matches or not.
    if ($fields['field_book_edition'] != 'asdfg') {

      $this->context->addViolation($constraint->invalidEdition, ['@edition' => $fields['field_book_edition']]);
    }

  }

}

Attached the Node and Paragraph structures screenshot.

I have gone through similar questions and read their comments/answers but coundn't find what exactly is the error in the code.

Add Constraint to Paragraph Field answer by Carlos

Adding Constraint to Paragraph field comment by 4k4

I implemented the same what is mentioned in both the links.But still it is not working.

For debugging purpose I have added the above constraint to a node field and it worked as expected.

From what I read if you provide the correct $entity_type->id() all the fields for the particular entity id will be rendered in $fields variable in hook_entity_bundle_field_info_alter , is my understanding is correct ?

Should I be implementing hook_entity_bundle_field_info_alter or hook_form_alter for adding a custom constraint to a paragraph field ?

Paragraph Structure Node Structure

EDIT 1:

After further debugging if I add

if ($node->hasField('field_bibliographic_information')) {
   \Drupal::logger('book_content')->info('Hello');
 $referenceItem = $node->get('field_bibliographic_information')->referencedEntities();
 ....remaining code.....
 }

in validate method the code inside the loop doesn't get executed.

4
  • Your constraint is receiving an entity, then you need to add it to the entity type, see drupal.stackexchange.com/questions/224229/…
    – 4uk4
    Jun 22, 2020 at 12:57
  • Hi @4k4 thank you for your response. Are you referring to use hook_entity_type_alter ? If so isnt it is for whole entity type and not for a specific field in entity type ? Can you please elaborate what you re referring to ? Jun 22, 2020 at 14:16
  • A constraint with validate($entity) has to be attached to an entity, not a field. Besides from being an entity or field constraint you attach it to a paragraph and then expect that it has a node field.
    – 4uk4
    Jun 22, 2020 at 15:43
  • Hi @4k4 I am completely lost can you please share a code snippet or any reference contrib module so that I can have a look. I also added additional debug info to the question, can you please have a look ? Jun 22, 2020 at 16:06

1 Answer 1

2

I am able to achieve this finally.

Basically what I was doing wrong was I was assuming the $entity is a node object and but it actually is paragraph object.

<?php

namespace Drupal\book_content\Plugin\Validation\Constraint;

use Symfony\Component\Validator\Constraint;
use Symfony\Component\Validator\ConstraintValidator;


/**
 * Validates the Book Content constraint.
 */
class BookContentEditionConstraintValidator extends ConstraintValidator {


  /**
   * {@inheritdoc}
   */
  public function validate($items, Constraint $constraint) {

    if (!$item = $items->first()) {
      return;
    }

    $field_name = $items->getFieldDefinition()->getName();

    /** @var \Drupal\Core\Entity\EntityInterface $entity */
    $entity = $items->getEntity();

    if ($entity->hasField('field_book_edition')) {

      $edition = $entity->field_book_edition->value;


      // Check if the book edition matches or not.
      if ($edition != 'asdfg') {

        $this->context->addViolation($constraint->invalidEdition, ['@edition' => $edition]);
      }

    }

  }

}

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.