3 namespace Drupal\views\Plugin\views\argument_validator;
5 use Drupal\Core\Entity\EntityInterface;
6 use Drupal\Core\Entity\EntityManagerInterface;
7 use Drupal\Core\Form\FormStateInterface;
8 use Drupal\Core\Plugin\Context\ContextDefinition;
9 use Drupal\views\Plugin\views\argument\ArgumentPluginBase;
10 use Symfony\Component\DependencyInjection\ContainerInterface;
13 * Defines a argument validator plugin for each entity type.
15 * @ViewsArgumentValidator(
17 * deriver = "Drupal\views\Plugin\Derivative\ViewsEntityArgumentValidator"
20 * @see \Drupal\views\Plugin\Derivative\ViewsEntityArgumentValidator
22 class Entity extends ArgumentValidatorPluginBase {
27 * @var \Drupal\Core\Entity\EntityManagerInterface
29 protected $entityManager;
32 * If this validator can handle multiple arguments.
36 protected $multipleCapable = TRUE;
39 * Constructs an \Drupal\views\Plugin\views\argument_validator\Entity object.
41 * @param array $configuration
42 * A configuration array containing information about the plugin instance.
43 * @param string $plugin_id
44 * The plugin_id for the plugin instance.
45 * @param mixed $plugin_definition
46 * The plugin implementation definition.
47 * @param \Drupal\Core\Entity\EntityManagerInterface $entity_manager
50 public function __construct(array $configuration, $plugin_id, $plugin_definition, EntityManagerInterface $entity_manager) {
51 parent::__construct($configuration, $plugin_id, $plugin_definition);
53 $this->entityManager = $entity_manager;
59 public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) {
64 $container->get('entity.manager')
71 protected function defineOptions() {
72 $options = parent::defineOptions();
74 $options['bundles'] = ['default' => []];
75 $options['access'] = ['default' => FALSE];
76 $options['operation'] = ['default' => 'view'];
77 $options['multiple'] = ['default' => FALSE];
85 public function buildOptionsForm(&$form, FormStateInterface $form_state) {
86 parent::buildOptionsForm($form, $form_state);
88 $entity_type_id = $this->definition['entity_type'];
89 // Derivative IDs are all entity:entity_type. Sanitized for js.
90 // The ID is converted back on submission.
91 $sanitized_id = ArgumentPluginBase::encodeValidatorId($this->definition['id']);
92 $entity_type = $this->entityManager->getDefinition($entity_type_id);
94 // If the entity has bundles, allow option to restrict to bundle(s).
95 if ($entity_type->hasKey('bundle')) {
97 foreach ($this->entityManager->getBundleInfo($entity_type_id) as $bundle_id => $bundle_info) {
98 $bundle_options[$bundle_id] = $bundle_info['label'];
102 '#title' => $entity_type->getBundleLabel() ?: $this->t('Bundles'),
103 '#default_value' => $this->options['bundles'],
104 '#type' => 'checkboxes',
105 '#options' => $bundle_options,
106 '#description' => $this->t('If none are selected, all are allowed.'),
110 // Offer the option to filter by access to the entity in the argument.
112 '#type' => 'checkbox',
113 '#title' => $this->t('Validate user has access to the %name', ['%name' => $entity_type->getLabel()]),
114 '#default_value' => $this->options['access'],
116 $form['operation'] = [
118 '#title' => $this->t('Access operation to check'),
120 'view' => $this->t('View'),
121 'update' => $this->t('Edit'),
122 'delete' => $this->t('Delete'),
124 '#default_value' => $this->options['operation'],
127 ':input[name="options[validate][options][' . $sanitized_id . '][access]"]' => ['checked' => TRUE],
132 // If class is multiple capable give the option to validate single/multiple.
133 if ($this->multipleCapable) {
134 $form['multiple'] = [
136 '#title' => $this->t('Multiple arguments'),
138 0 => $this->t('Single ID', ['%type' => $entity_type->getLabel()]),
139 1 => $this->t('One or more IDs separated by , or +', ['%type' => $entity_type->getLabel()]),
141 '#default_value' => (string) $this->options['multiple'],
149 public function submitOptionsForm(&$form, FormStateInterface $form_state, &$options = []) {
150 // Filter out unused options so we don't store giant unnecessary arrays.
151 $options['bundles'] = array_filter($options['bundles']);
157 public function validateArgument($argument) {
158 $entity_type = $this->definition['entity_type'];
160 if ($this->multipleCapable && $this->options['multiple']) {
161 // At this point only interested in individual IDs no matter what type,
162 // just splitting by the allowed delimiters.
163 $ids = array_filter(preg_split('/[,+ ]/', $argument));
168 // No specified argument should be invalid.
173 $entities = $this->entityManager->getStorage($entity_type)->loadMultiple($ids);
174 // Validate each id => entity. If any fails break out and return false.
175 foreach ($ids as $id) {
176 // There is no entity for this ID.
177 if (!isset($entities[$id])) {
180 if (!$this->validateEntity($entities[$id])) {
189 * Validates an individual entity against class access settings.
191 * @param \Drupal\Core\Entity\EntityInterface $entity
196 protected function validateEntity(EntityInterface $entity) {
197 // If access restricted by entity operation.
198 if ($this->options['access'] && !$entity->access($this->options['operation'])) {
201 // If restricted by bundle.
202 $bundles = $this->options['bundles'];
203 if (count($bundles) && empty($bundles[$entity->bundle()])) {
213 public function calculateDependencies() {
214 $dependencies = parent::calculateDependencies();
216 $entity_type_id = $this->definition['entity_type'];
217 $bundle_entity_type = $this->entityManager->getDefinition($entity_type_id)->getBundleEntityType();
219 // The bundle entity type might not exist. For example, users do not have
221 if ($this->entityManager->hasHandler($bundle_entity_type, 'storage')) {
222 $bundle_entity_storage = $this->entityManager->getStorage($bundle_entity_type);
224 foreach ($bundle_entity_storage->loadMultiple(array_keys($this->options['bundles'])) as $bundle_entity) {
225 $dependencies[$bundle_entity->getConfigDependencyKey()][] = $bundle_entity->getConfigDependencyName();
229 return $dependencies;
235 public function getContextDefinition() {
236 return new ContextDefinition('entity:' . $this->definition['entity_type'], $this->argument->adminLabel(), FALSE);