pluginreference-2.0.0/src/Plugin/Validation/Constraint/ValidPluginReferenceConstraintValidator.php
src/Plugin/Validation/Constraint/ValidPluginReferenceConstraintValidator.php
<?php
namespace Drupal\pluginreference\Plugin\Validation\Constraint;
use Drupal\Component\Plugin\PluginManagerInterface;
use Drupal\Core\DependencyInjection\ContainerInjectionInterface;
use Drupal\Core\Entity\EntityInterface;
use Drupal\Core\Entity\EntityTypeManagerInterface;
use Drupal\Core\Session\AccountProxyInterface;
use Drupal\pluginreference\PluginReferenceSelectionInterface;
use Drupal\pluginreference\PluginReferenceSelectionManagerInterface;
use Drupal\pluginreference\PluginTypeHelperInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\Validator\Constraint;
use Symfony\Component\Validator\ConstraintValidator;
/**
* Checks if referenced plugins are valid.
*/
class ValidPluginReferenceConstraintValidator extends ConstraintValidator implements ContainerInjectionInterface {
/**
* The plugin reference selection manager.
*
* @var \Drupal\pluginreference\PluginReferenceSelectionManagerInterface
*/
protected $pluginReferenceSelectionManager;
/**
* The plugin type helper.
*
* @var \Drupal\pluginreference\PluginTypeHelperInterface
*/
protected $pluginTypeHelper;
/**
* The entity type manager.
*
* @var \Drupal\Core\Entity\EntityTypeManagerInterface
*/
protected $entityTypeManager;
/**
* The current user.
*
* @var \Drupal\Core\Session\AccountProxyInterface
*/
protected $currentUser;
/**
* Constructs a ValidPluginReferenceConstraintValidator object.
*
* @param \Drupal\pluginreference\PluginReferenceSelectionManagerInterface $plugin_reference_selection_manager
* The plugin reference selection manager.
* @param \Drupal\pluginreference\PluginTypeHelperInterface $plugin_type_helper
* The plugin type helper.
* @param \Drupal\Core\Entity\EntityTypeManagerInterface $entity_type_manager
* The entity type manager.
* @param \Drupal\Core\Session\AccountProxyInterface $current_user
* The current user.
*/
public function __construct(PluginReferenceSelectionManagerInterface $plugin_reference_selection_manager, PluginTypeHelperInterface $plugin_type_helper, EntityTypeManagerInterface $entity_type_manager, AccountProxyInterface $current_user) {
$this->pluginReferenceSelectionManager = $plugin_reference_selection_manager;
$this->pluginTypeHelper = $plugin_type_helper;
$this->entityTypeManager = $entity_type_manager;
$this->currentUser = $current_user;
}
/**
* {@inheritdoc}
*/
public static function create(ContainerInterface $container) {
return new static(
$container->get('plugin.manager.plugin_reference_selection'),
$container->get('plugin_reference.plugin_type_helper'),
$container->get('entity_type.manager'),
$container->get('current_user')
);
}
/**
* {@inheritdoc}
*/
public function validate($value, Constraint $constraint): void {
if (!$constraint instanceof ValidPluginReferenceConstraint) {
return;
}
if ($value === NULL) {
return;
}
$plugin_ids = [];
foreach ($value as $delta => $item) {
if (!empty($item->plugin_id)) {
$plugin_ids[$delta] = $item->plugin_id;
}
}
// Early opt-out if nothing to validate.
if (!$plugin_ids) {
return;
}
$entity = $value->getParent() !== NULL ? $value->getEntity() : NULL;
$handler = $this->pluginReferenceSelectionManager->getSelectionHandler($value->getFieldDefinition(), $entity);
if (!$handler instanceof PluginReferenceSelectionInterface) {
return;
}
$target_type_id = $value->getFieldDefinition()->getSetting('target_type');
// Get a list of pre-existing references.
$previously_referenced_ids = [];
$entity = $value->getParent() !== NULL ? $value->getEntity() : NULL;
if ($entity instanceof EntityInterface && !$entity->isNew()) {
$existing_entity = $this->entityTypeManager->getStorage($entity->getEntityTypeId())->loadUnchanged($entity->id());
foreach ($existing_entity->{$value->getFieldDefinition()->getName()}->getValue() as $item) {
$previously_referenced_ids[$item['plugin_id']] = $item['plugin_id'];
}
}
$valid_target_ids = $handler->validateReferenceablePlugins($plugin_ids);
if ($invalid_target_ids = array_diff($plugin_ids, $valid_target_ids)) {
$plugin_manager = $this->pluginTypeHelper->getPluginManager($target_type_id);
if (!$plugin_manager instanceof PluginManagerInterface) {
return;
}
// For accuracy of the error message, differentiate non-referenceable
// and non-existent plugins.
foreach ($invalid_target_ids as $delta => $target_id) {
// Check if any of the invalid existing references are simply not
// accessible by the user, in which case they need to be excluded from
// validation.
$existing_plugin = NULL;
if ($plugin_manager->hasDefinition($target_id)) {
$existing_plugin = $plugin_manager->createInstance($target_id);
}
if (isset($previously_referenced_ids[$target_id]) && $existing_plugin && method_exists($existing_plugin, 'access') && !$existing_plugin->access($this->currentUser)) {
continue;
}
$message = $existing_plugin ? $constraint->message : $constraint->nonExistingMessage;
$this->context->buildViolation($message)
->setParameter('%type', $target_type_id)
->setParameter('%id', $target_id)
->atPath($delta . '.plugin_id')
->setInvalidValue($target_id)
->addViolation();
}
}
}
}
