Entity.php 7.35 KB
Newer Older
1
2
3
4
5
6
7
8
9
<?php

/**
 * @file
 * Contains \Drupal\views\Plugin\views\argument_validator\Entity.
 */

namespace Drupal\views\Plugin\views\argument_validator;

10
use Drupal\Core\Config\Entity\ConfigEntityInterface;
11
use Drupal\Core\Entity\EntityInterface;
12
use Drupal\Core\Entity\EntityManagerInterface;
13
use Drupal\Core\Form\FormStateInterface;
14
15
16
17
18
19
20
21
use Drupal\views\Plugin\views\argument\ArgumentPluginBase;
use Symfony\Component\DependencyInjection\ContainerInterface;

/**
 * Defines a argument validator plugin for each entity type.
 *
 * @ViewsArgumentValidator(
 *   id = "entity",
22
 *   deriver = "Drupal\views\Plugin\Derivative\ViewsEntityArgumentValidator"
23
24
25
26
27
28
29
30
31
 * )
 *
 * @see \Drupal\views\Plugin\Derivative\ViewsEntityArgumentValidator
 */
class Entity extends ArgumentValidatorPluginBase {

  /**
   * The entity manager.
   *
32
   * @var \Drupal\Core\Entity\EntityManagerInterface
33
34
35
36
   */
  protected $entityManager;

  /**
37
38
39
   * If this validator can handle multiple arguments.
   *
   * @var bool
40
   */
41
  protected $multipleCapable = TRUE;
42
43
44
45
46
47
48
49

  /**
   * Constructs an \Drupal\views\Plugin\views\argument_validator\Entity object.
   *
   * @param array $configuration
   *   A configuration array containing information about the plugin instance.
   * @param string $plugin_id
   *   The plugin_id for the plugin instance.
50
   * @param mixed $plugin_definition
51
   *   The plugin implementation definition.
52
   * @param \Drupal\Core\Entity\EntityManagerInterface $entity_manager
53
54
   *   The entity manager.
   */
55
  public function __construct(array $configuration, $plugin_id, $plugin_definition, EntityManagerInterface $entity_manager) {
56
    parent::__construct($configuration, $plugin_id, $plugin_definition);
57

58
59
60
61
62
63
    $this->entityManager = $entity_manager;
  }

  /**
   * {@inheritdoc}
   */
64
  public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) {
65
66
67
68
    return new static(
      $configuration,
      $plugin_id,
      $plugin_definition,
69
      $container->get('entity.manager')
70
71
72
73
74
75
76
77
78
79
    );
  }

  /**
   * {@inheritdoc}
   */
  protected function defineOptions() {
    $options = parent::defineOptions();

    $options['bundles'] = array('default' => array());
80
    $options['access'] = array('default' => FALSE);
81
    $options['operation'] = array('default' => 'view');
82
    $options['multiple'] = array('default' => FALSE);
83
84
85
86
87
88
89

    return $options;
  }

  /**
   * {@inheritdoc}
   */
90
  public function buildOptionsForm(&$form, FormStateInterface $form_state) {
91
92
    parent::buildOptionsForm($form, $form_state);

93
    $entity_type_id = $this->definition['entity_type'];
94
95
96
    // Derivative IDs are all entity:entity_type. Sanitized for js.
    // The ID is converted back on submission.
    $sanitized_id = ArgumentPluginBase::encodeValidatorId($this->definition['id']);
97
    $entity_type = $this->entityManager->getDefinition($entity_type_id);
98
99

    // If the entity has bundles, allow option to restrict to bundle(s).
100
    if ($entity_type->hasKey('bundle')) {
101
      $bundle_options = array();
102
      foreach ($this->entityManager->getBundleInfo($entity_type_id) as $bundle_id => $bundle_info) {
103
104
        $bundle_options[$bundle_id] = $bundle_info['label'];
      }
105

106
      $form['bundles'] = array(
107
        '#title' => $entity_type->getBundleLabel() ?: $this->t('Bundles'),
108
109
110
        '#default_value' => $this->options['bundles'],
        '#type' => 'checkboxes',
        '#options' => $bundle_options,
111
        '#description' => $this->t('If none are selected, all are allowed.'),
112
113
114
115
116
117
      );
    }

    // Offer the option to filter by access to the entity in the argument.
    $form['access'] = array(
      '#type' => 'checkbox',
118
      '#title' => $this->t('Validate user has access to the %name', array('%name' => $entity_type->getLabel())),
119
120
121
122
      '#default_value' => $this->options['access'],
    );
    $form['operation'] = array(
      '#type' => 'radios',
123
124
125
126
127
128
      '#title' => $this->t('Access operation to check'),
      '#options' => array(
        'view' => $this->t('View'),
        'update' => $this->t('Edit'),
        'delete' => $this->t('Delete'),
      ),
129
130
131
132
133
134
135
136
137
138
139
140
      '#default_value' => $this->options['operation'],
      '#states' => array(
        'visible' => array(
          ':input[name="options[validate][options][' . $sanitized_id . '][access]"]' => array('checked' => TRUE),
        ),
      ),
    );

    // If class is multiple capable give the option to validate single/multiple.
    if ($this->multipleCapable) {
      $form['multiple'] = array(
        '#type' => 'radios',
141
        '#title' => $this->t('Multiple arguments'),
142
        '#options' => array(
143
144
          0 => $this->t('Single ID', array('%type' => $entity_type->getLabel())),
          1 => $this->t('One or more IDs separated by , or +', array('%type' => $entity_type->getLabel())),
145
146
147
148
149
150
151
152
153
        ),
        '#default_value' => (string) $this->options['multiple'],
      );
    }
  }

  /**
   * {@inheritdoc}
   */
154
  public function submitOptionsForm(&$form, FormStateInterface $form_state, &$options = array()) {
155
156
157
158
159
160
161
162
163
164
    // Filter out unused options so we don't store giant unnecessary arrays.
    $options['bundles'] = array_filter($options['bundles']);
  }

  /**
   * {@inheritdoc}
   */
  public function validateArgument($argument) {
    $entity_type = $this->definition['entity_type'];

165
    if ($this->multipleCapable && $this->options['multiple']) {
166
167
168
169
170
171
172
173
174
175
176
177
      // At this point only interested in individual IDs no matter what type,
      // just splitting by the allowed delimiters.
      $ids = array_filter(preg_split('/[,+ ]/', $argument));
    }
    elseif ($argument) {
      $ids = array($argument);
    }
    // No specified argument should be invalid.
    else {
      return FALSE;
    }

178
    $entities = $this->entityManager->getStorage($entity_type)->loadMultiple($ids);
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
    // Validate each id => entity. If any fails break out and return false.
    foreach ($ids as $id) {
      // There is no entity for this ID.
      if (!isset($entities[$id])) {
        return FALSE;
      }
      if (!$this->validateEntity($entities[$id])) {
        return FALSE;
      }
    }

    return TRUE;
  }

  /**
   * Validates an individual entity against class access settings.
   *
   * @param \Drupal\Core\Entity\EntityInterface $entity
   *
   * @return bool
   *   True if validated.
   */
  protected function validateEntity(EntityInterface $entity) {
    // If access restricted by entity operation.
203
    if ($this->options['access'] && !$entity->access($this->options['operation'])) {
204
205
206
207
208
209
210
211
212
213
214
      return FALSE;
    }
    // If restricted by bundle.
    $bundles = $this->options['bundles'];
    if (count($bundles) && empty($bundles[$entity->bundle()])) {
      return FALSE;
    }

    return TRUE;
  }

215
216
217
218
219
220
221
222
223
  /**
   * {@inheritdoc}
   */
  public function calculateDependencies() {
    $dependencies = parent::calculateDependencies();

    $entity_type_id = $this->definition['entity_type'];
    $bundle_entity_type = $this->entityManager->getDefinition($entity_type_id)->getBundleEntityType();

224
225
226
227
228
229
230
231
    // The bundle entity type might not exist. For example, users do not have
    // bundles.
    if ($this->entityManager->hasHandler($bundle_entity_type, 'storage')) {
      $bundle_entity_storage = $this->entityManager->getStorage($bundle_entity_type);

      foreach ($bundle_entity_storage->loadMultiple(array_keys($this->options['bundles'])) as $bundle_entity) {
        $dependencies[$bundle_entity->getConfigDependencyKey()][] = $bundle_entity->getConfigDependencyName();
      }
232
233
234
235
236
    }

    return $dependencies;
  }

237
}