diff --git a/src/Plugin/DataType/DynamicEntityReference.php b/src/Plugin/DataType/DynamicEntityReference.php index 25b97d1..144bf26 100644 --- a/src/Plugin/DataType/DynamicEntityReference.php +++ b/src/Plugin/DataType/DynamicEntityReference.php @@ -56,30 +56,4 @@ class DynamicEntityReference extends EntityReference { return $this->target; } - /** - * {@inheritdoc} - * - * The field-item list and the field-item refer validation of bundles to the - * entity property, as depending on the selected target-type, the bundle may - * need validation. - */ - public function getConstraints() { - /* @var \Drupal\dynamic_entity_reference\Plugin\Field\FieldType\DynamicEntityReferenceFieldItemList $field */ - $field = $this->parent->parent; - $values = $this->parent->getValue(); - // We cannot validate the bundle until we know the target-type of this - // item. - if (isset($values['target_type'])) { - $target_type = $values['target_type']; - // Get the handler settings for the target type of this item. - $target_type_settings = $field->getSetting($target_type); - if (isset($target_type_settings['handler_settings']['target_bundles'])) { - // Add the constraint to limit the bundles of this item. - $this->definition->addConstraint('Bundle', ['bundle' => $target_type_settings['handler_settings']['target_bundles']]); - } - } - $constraints = parent::getConstraints(); - return $constraints; - } - } diff --git a/src/Plugin/Validation/Constraint/ValidDynamicReferenceConstraintValidator.php b/src/Plugin/Validation/Constraint/ValidDynamicReferenceConstraintValidator.php index c70386b..aa85080 100644 --- a/src/Plugin/Validation/Constraint/ValidDynamicReferenceConstraintValidator.php +++ b/src/Plugin/Validation/Constraint/ValidDynamicReferenceConstraintValidator.php @@ -2,14 +2,55 @@ namespace Drupal\dynamic_entity_reference\Plugin\Validation\Constraint; +use Drupal\Core\DependencyInjection\ContainerInjectionInterface; +use Drupal\Core\Entity\EntityReferenceSelection\SelectionPluginManagerInterface; +use Drupal\Core\Entity\EntityTypeManagerInterface; use Drupal\dynamic_entity_reference\Plugin\Field\FieldType\DynamicEntityReferenceItem; +use Symfony\Component\DependencyInjection\ContainerInterface; use Symfony\Component\Validator\Constraint; use Symfony\Component\Validator\ConstraintValidator; /** * Checks if referenced entities are valid. */ -class ValidDynamicReferenceConstraintValidator extends ConstraintValidator { +class ValidDynamicReferenceConstraintValidator extends ConstraintValidator implements ContainerInjectionInterface { + + /** + * The selection plugin manager. + * + * @var \Drupal\dynamic_entity_reference\SelectionPluginManager + */ + protected $selectionManager; + + /** + * The entity type manager. + * + * @var \Drupal\Core\Entity\EntityTypeManagerInterface + */ + protected $entityTypeManager; + + /** + * Constructs a ValidReferenceConstraintValidator object. + * + * @param \Drupal\Core\Entity\EntityReferenceSelection\SelectionPluginManagerInterface $selection_manager + * The selection plugin manager. + * @param \Drupal\Core\Entity\EntityTypeManagerInterface $entity_type_manager + * The entity type manager. + */ + public function __construct(SelectionPluginManagerInterface $selection_manager, EntityTypeManagerInterface $entity_type_manager) { + $this->selectionManager = $selection_manager; + $this->entityTypeManager = $entity_type_manager; + } + + /** + * {@inheritdoc} + */ + public static function create(ContainerInterface $container) { + return new static( + $container->get('plugin.manager.dynamic_entity_reference_selection'), + $container->get('entity_type.manager') + ); + } /** * {@inheritdoc} @@ -20,12 +61,9 @@ class ValidDynamicReferenceConstraintValidator extends ConstraintValidator { if (!isset($value)) { return; } - - // Collect new entities and IDs of existing entities across the field items. - $new_entities = []; - $target_ids = []; - $target_types = DynamicEntityReferenceItem::getTargetTypes($value->getFieldDefinition()->getSettings()); foreach ($value as $delta => $item) { + $valid_target_type = DynamicEntityReferenceItem::getTargetTypes($item->getFieldDefinition() + ->getSettings()); $target_id = $item->target_id; $target_type = $item->target_type; // We don't use a regular NotNull constraint for the target_id property as @@ -40,53 +78,23 @@ class ValidDynamicReferenceConstraintValidator extends ConstraintValidator { ->addViolation(); return; } - $new_entities[$delta] = $item->entity; - } - $valid_type = empty($target_type) || (!empty($target_type) && in_array($target_type, $target_types)); - // '0' or NULL are considered valid empty references. - if (!empty($target_id)) { - $target_ids[$delta] = $target_id; - } - } - - // Early opt-out if nothing to validate. - if (!$new_entities && !$target_ids) { - return; - } - - foreach ($value as $delta => $item) { - $id = $item->get('target_id')->getValue(); - $type = $item->get('target_type')->getValue(); - $types = DynamicEntityReferenceItem::getTargetTypes($item->getFieldDefinition() - ->getSettings()); - $valid_type = empty($type) || (!empty($type) && in_array($type, $types)); - // '0' or NULL are considered valid empty references. - if (empty($id) && $valid_type) { - return; + // It is a new entity. + else { + // @todo validate new entity. + } } + $valid_type = empty($target_type) || (!empty($target_type) && in_array($target_type, $valid_target_type)); if (!$valid_type) { - $this->context->addViolation($constraint->wrongTypeMessage, array('%type' => $type)); - return; - } - $referenced_entity = $item->get('entity')->getValue(); - if (!$referenced_entity) { - $this->context->addViolation($constraint->wrongIDMessage, array('%type' => $type, '%id' => $id)); - return; - } - // Get the handler settings for the target type of this item. - $target_type_settings = $item->getParent()->getSetting($type); - // No bundles selected = all bundles are valid. - if (!empty($target_type_settings['handler_settings']['target_bundles'])) { - if (!in_array($referenced_entity->bundle(), $target_type_settings['handler_settings']['target_bundles'], TRUE)) { - $this->context->buildViolation($constraint->wrongBundleMessage) - ->setParameter('%bundles', implode(', ', $target_type_settings['handler_settings']['target_bundles'])) - ->setParameter('%bundle', $referenced_entity->bundle()) - ->atPath((string) $delta . '.target_id') - ->setInvalidValue($referenced_entity->bundle()) - ->addViolation(); - return; - } + $this->context->buildViolation($constraint->wrongTypeMessage) + ->setParameter('%type', $target_type) + ->atPath((string) $delta . '.target_type') + ->setInvalidValue($target_type) + ->addViolation(); } + /** @var \Drupal\Core\Entity\EntityReferenceSelection\SelectionInterface $handler */ + $handler = $this->selectionManager->getSelectionHandler($value->getFieldDefinition(), NULL, $target_type); + // @todo validate target_id. + // @todo add bundle violations. } }