contacts_events-8.x-1.x-dev/src/Plugin/Validation/Constraint/UniqueFieldValueForGivenReferenceFieldValidator.php
src/Plugin/Validation/Constraint/UniqueFieldValueForGivenReferenceFieldValidator.php
<?php
namespace Drupal\contacts_events\Plugin\Validation\Constraint;
use Drupal\Core\Entity\EntityInterface;
use Drupal\Core\Entity\Query\QueryInterface;
use Drupal\Core\Field\Plugin\Field\FieldType\EntityReferenceItem;
use Symfony\Component\Validator\Constraint;
use Symfony\Component\Validator\ConstraintValidator;
/**
* Validates that a reference field is unique for a given entity type and field.
*/
class UniqueFieldValueForGivenReferenceFieldValidator extends ConstraintValidator {
/**
* {@inheritdoc}
*/
public function validate($items, Constraint $constraint) {
/** @var \Drupal\Core\Field\FieldItemInterface $item */
if (!$item = $items->first()) {
return;
}
$field_name = $items->getFieldDefinition()->getName();
/** @var \Drupal\Core\Entity\ContentEntityInterface $entity */
$entity = $items->getEntity();
/** @var \Drupal\contacts_events\Plugin\Validation\Constraint\UniqueFieldValueForGivenReferenceField $constraint */
$grouping_field = $constraint->getGroupingFieldOption();
$grouping_entity = $entity->get($grouping_field)->target_id;
$entity_type_id = $entity->getEntityTypeId();
$id_key = $entity->getEntityType()->getKey('id');
// Field main property is not always 'value', eg entity reference.
$field_value_property = $item->mainPropertyName();
$field_value = $item->{$field_value_property};
if ($field_value) {
$query = \Drupal::entityQuery($entity_type_id)
// The id could be NULL, so we cast it to 0 in that case.
->accessCheck(TRUE)
->condition($id_key, (int) $items->getEntity()->id(), '<>')
->condition($field_name, $field_value)
->condition($grouping_field, $grouping_entity)
->range(0, 1)
->count();
$this->alterQuery($query);
$value_taken = (bool) $query->execute();
if ($value_taken) {
$params = [
'%value' => $field_value,
'@entity_type' => $entity->getEntityType()->getSingularLabel(),
'@field_name' => mb_strtolower($items->getFieldDefinition()->getLabel()),
];
// Get entity label if grouping field is an entity reference.
if ($item instanceof EntityReferenceItem) {
$reference_entity = $item->entity;
if ($reference_entity && $reference_entity instanceof EntityInterface) {
$params['%value_label'] = $reference_entity->label();
}
}
$this->context->addViolation($constraint->getMessage(), $params);
}
}
}
/**
* Alter the query checking for existing values.
*
* @param \Drupal\Core\Entity\Query\QueryInterface $query
* The query.
*/
protected function alterQuery(QueryInterface $query) {
// Allows extending validators to add custom conditions and alter the query.
}
}
