Project View: Realizing the Power of Drupal's Constraint Validation

  • 5 minute read

I have been working with Drupal for quite some time (from the days of Drupal-7 πŸ™‚). I was always up to-date with the new changes in Drupal APIs (at least in theory πŸ˜… ). Whenever a new change was introduced in APIs, I checked them and tried them out.

I did the same thing for the new ValidationAPI. I checked the documentation, tried one basic Hello World type of scenario with some example code and thought it was all good.

Recently, I got a chance to work on an application where I encountered some use cases of Constraint Validation API and I realized the importance and power of this API which I never thought when I tried it with my initial Hello World sample.

In this blog, I will share those use cases which we handled using the Validation API.

For documentation and detail about the Validation API, you can refer to the drupal.org documentation which can be found here:  https://www.drupal.org/docs/drupal-apis/entity-api/entity-validation-api/entity-validation-api-overview

Use Cases

Publish content only when content is added in all languages

This application is multilingual where content needs to be added for multiple languages. One of the requirements was that content can only be published if available and added for all of the languages. If content is not added for any specific language, then content editors are not allowed to publish the content. However, content can be saved and created, but in draft mode only (not published).

Number of field values should be same in all languages for a given field

There were some fields for the content which were having cardinality unlimited, meaning they can be added any number of times. But as I mentioned earlier, it was a multilingual application, and the requirement was that the number of values added for that field should be the same in all languages.

To explain further, here is an example: There is a field called "Bullet Points" of type text. Content editors added seven bullet points for this field in the English language. Then, if a content admin adds other than seven bullet points in other languages, it’s not allowed.

A given field needs to have content in all languages if added in any one language

This was different from the first use case. In the first use case, its for the full content level validation. But in this case, requirement was content added in a given field in one language, then that field needs to have the content or value in all the languages or not allowed to be published.

Only one field can be marked to be used for default value

In this use case we are using Paragraphs to add content. Here the Paragraph has two fields: a "Default Value" field as a checkbox and a "Translation" field as textfield.

Multiple content Paragraphs of this type can be added and rendered. A requirement in this case is that if there isn't a matching translation available, then render the Paragraph that contains the "Default Value" checkbox selected as a fallback. So while adding the content, content editors are required to check one of the "Default Value" checkbox fields in a Paragraph that will act as the fallback if needed. If multiple Paragraphs are added and multiple Default Values are checked, this is not allowed.

The following code shows the logic written to check for multilingual content.

// To add validation at entity field level
function hook_entity_bundle_field_info_alter() {
  foreach ($fields as $field_name) {
    if (isset($fields[$field_name])) {
      $fields[$field_name]->addConstraint(ConstraintClassNameHere::class);
    }
  }
}
// To add validation at full entity level
function hook_entity_type_alter() {
  $entity_types['node']->addConstraint(ContraintClassNameHere::class);
}
class TranslationVerifyConstraintValidator extends ConstraintValidator {
  /**
   * {@inheritdoc}
   */
  public function validate($entity, Constraint $constraint) {
    if (!$entity instanceof NodeInterface || !$entity->setPublished()) {
      return;
    }
    // Logic written here to check for multilingual content
  }
}