Drupal 8: A custom validator for checking Start time field depending on the value of End Time

8 Nov.2018
A custom validator for checking Start time field depending on the value of End Time

In one project I use two independent time fields provided by Time Field module and called "Start Time" field_work_start_time and "End Time"field_work_end_time. Both fields are optional, indecencies and don't know about each other. However, if "End Time" is selected, I need to check "Start Time" and display a message, so the first field shouldn't be empty and "End Time" should be greater or equal.

This code shows how I implemented the solution, which checks a few fields at the same time.

Look also my previous article there we have the similar code for Datetime and works with Start/End Date field.

File
[MODULE_NAME]/[MODULE_NAME].module
<?php
 
use Drupal\Core\Entity\EntityTypeInterface;
 
/**
 * Implements hook_entity_bundle_field_info_alter().
 */
function [MODULE_NAME]_entity_bundle_field_info_alter(&$fields, EntityTypeInterface $entity_type, $bundle) {
  if (!empty($fields['field_work_end_time'])) {
    $fields['field_work_end_time']->addConstraint('StartEndTimeChecking');
  }
}
File
[MODULE_NAME]/src/Plugin/Validation/Constraint/StartEndTimeCheckingConstraint.php
<?php
 
namespace Drupal\[MODULE_NAME]\Plugin\Validation\Constraint;
 
use Symfony\Component\Validator\Constraint;
 
/**
 * Checks if "End Time" not empty.
 *
 * "Start Time" must be not empty
 * and "End Time" must be greater then "Start Time".
 *
 * @Constraint(
 *   id = "StartEndTimeChecking",
 *   label = @Translation("Start/End Time checking", context = "Validation")
 * )
 */
class StartEndTimeCheckingConstraint extends Constraint {
 
  public $message = '"End Time" may not be less than "Start Time".';
 
}
File
[MODULE_NAME]/src/Plugin/Validation/Constraint/StartEndTimeCheckingConstraintValidator.php
<?php
 
namespace Drupal\[MODULE_NAME]\Plugin\Validation\Constraint;
 
use Symfony\Component\Validator\Constraint;
use Symfony\Component\Validator\ConstraintValidator;
use Drupal\Core\Datetime\DrupalDateTime;
 
/**
 * Validates start/end time.
 */
class StartEndTimeCheckingConstraintValidator extends ConstraintValidator {
 
  /**
   * {@inheritdoc}
   */
  public function validate($entity, Constraint $constraint) {
 
    $entity = $entity->getEntity();
    $start_time = $entity->get('field_work_start_time')->getString();
    $end_time = $entity->get('field_work_end_time')->getString();
 
    // Nothing to do if $end_time is empty.
    if ($end_time == '') {
      return;
    }
 
    // If the $start_time is empty,
    // set zero to avoid a fatal error during creating from format.
    if ($start_time == '') {
      $start_time = 0;
    }
 
    $tz = drupal_get_user_timezone();
    $start_datetime = DrupalDateTime::createFromFormat('U', $start_time, $tz);
    $end_datetime = DrupalDateTime::createFromFormat('U', $end_time, $tz);
 
    if ($start_datetime > $end_datetime || $start_time == '') {
      $this->context->addViolation($constraint->message);
    }
  }
 
}