Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
0.00% covered (danger)
0.00%
0 / 27
0.00% covered (danger)
0.00%
0 / 4
CRAP
0.00% covered (danger)
0.00%
0 / 1
ExternalIdConstraintValidator
0.00% covered (danger)
0.00%
0 / 27
0.00% covered (danger)
0.00%
0 / 4
110
0.00% covered (danger)
0.00%
0 / 1
 __construct
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 create
0.00% covered (danger)
0.00%
0 / 3
0.00% covered (danger)
0.00%
0 / 1
2
 validate
0.00% covered (danger)
0.00%
0 / 7
0.00% covered (danger)
0.00%
0 / 1
20
 isUnique
0.00% covered (danger)
0.00%
0 / 16
0.00% covered (danger)
0.00%
0 / 1
20
1<?php
2
3namespace Drupal\crm_case_external_id\Plugin\Validation\Constraint;
4
5use Drupal\Core\DependencyInjection\ContainerInjectionInterface;
6use Drupal\Core\Entity\EntityTypeManagerInterface;
7use Symfony\Component\DependencyInjection\ContainerInterface;
8use Symfony\Component\Validator\Constraint;
9use Symfony\Component\Validator\ConstraintValidator;
10
11/**
12 * Validates the UniqueInteger constraint.
13 */
14class ExternalIdConstraintValidator extends ConstraintValidator implements ContainerInjectionInterface {
15
16  /**
17   * The entity type manager.
18   *
19   * @var \Drupal\Core\Entity\EntityTypeManagerInterface
20   */
21  private $entityTypeManager;
22
23  /**
24   * Creates a new TaxonomyTermHierarchyConstraintValidator instance.
25   *
26   * @param \Drupal\Core\Entity\EntityTypeManagerInterface $entity_type_manager
27   *   The entity type manager.
28   */
29  public function __construct(EntityTypeManagerInterface $entity_type_manager) {
30    $this->entityTypeManager = $entity_type_manager;
31  }
32
33  /**
34   * {@inheritdoc}
35   */
36  public static function create(ContainerInterface $container) {
37    return new static(
38      $container->get('entity_type.manager')
39    );
40  }
41
42  /**
43   * {@inheritdoc}
44   */
45  public function validate($value, Constraint $constraint) {
46    $entity = $value->getEntity();
47    $field_definition = $value->getFieldDefinition();
48
49    foreach ($value as $item) {
50      // First check if the value is an integer.
51      if (!is_int((int) $item->value)) {
52        // The value is not an integer, so a violation, aka error, is applied.
53        // The type of violation applied comes from the constraint description
54        // in step 1.
55        $this->context->addViolation($constraint->notInteger, ['%value' => $item->value]);
56      }
57
58      // Next check if the value is unique.
59      if (!$this->isUnique($item->value, $entity, $field_definition)) {
60        $this->context->addViolation($constraint->notUnique, ['%value' => $item->value]);
61      }
62    }
63  }
64
65  /**
66   * Is unique?
67   *
68   * @param string $value
69   *   The value to check.
70   * @param \Drupal\Core\Entity\EntityInterface $entity
71   *   The entity.
72   * @param \Drupal\Core\Field\FieldDefinitionInterface $field_definition
73   *   The field definition.
74   */
75  private function isUnique($value, $entity, $field_definition) {
76
77    $entity_type = $field_definition->get('entity_type');
78    $field_name = $field_definition->get('field_name');
79    $bundle = $field_definition->get('bundle');
80    $bundles = $field_definition->getThirdPartySetting('external_id', 'bundles', []);
81    $bundles = array_filter($bundles);
82    $negate = $field_definition->getThirdPartySetting('external_id', 'negate', FALSE);
83    // Here is where the check for a unique value would happen.
84    $query = $this->entityTypeManager->getStorage($entity_type)->getQuery();
85    $query->condition($field_name, $value);
86    if (!$entity->isNew()) {
87      $entity_id = $entity->id();
88      $query->condition('id', $entity_id, '<>');
89    }
90    if (!empty($bundles)) {
91      $operator = $negate ? 'NOT IN' : 'IN';
92      $query->condition('bundle', $bundles, $operator);
93    }
94
95    $results = $query->accessCheck(FALSE)->count()->execute();
96
97    return $results === 0;
98  }
99
100}