Updated all the contrib modules to their latest versions.
[yaffs-website] / web / modules / contrib / entity_browser / src / Plugin / EntityBrowser / Widget / View.php
1 <?php
2
3 namespace Drupal\entity_browser\Plugin\EntityBrowser\Widget;
4
5 use Drupal\Component\Plugin\Exception\PluginNotFoundException;
6 use Drupal\Core\Access\AccessResult;
7 use Drupal\Core\Form\FormStateInterface;
8 use Drupal\Core\Render\Element;
9 use Drupal\entity_browser\WidgetBase;
10 use Drupal\Core\Url;
11 use Drupal\entity_browser\WidgetValidationManager;
12 use Drupal\views\Entity\View as ViewEntity;
13 use Drupal\views\Views;
14 use Symfony\Component\DependencyInjection\ContainerInterface;
15 use Drupal\Core\Session\AccountInterface;
16 use Drupal\Core\Plugin\ContainerFactoryPluginInterface;
17 use Symfony\Component\EventDispatcher\EventDispatcherInterface;
18 use Drupal\Core\Entity\EntityTypeManagerInterface;
19
20 /**
21  * Uses a view to provide entity listing in a browser's widget.
22  *
23  * @EntityBrowserWidget(
24  *   id = "view",
25  *   label = @Translation("View"),
26  *   provider = "views",
27  *   description = @Translation("Uses a view to provide entity listing in a browser's widget."),
28  *   auto_select = TRUE
29  * )
30  */
31 class View extends WidgetBase implements ContainerFactoryPluginInterface {
32
33   /**
34    * The current user.
35    *
36    * @var \Drupal\Core\Session\AccountInterface
37    */
38   protected $currentUser;
39
40   /**
41    * {@inheritdoc}
42    */
43   public function defaultConfiguration() {
44     return [
45       'view' => NULL,
46       'view_display' => NULL,
47     ] + parent::defaultConfiguration();
48   }
49
50   /**
51    * {@inheritdoc}
52    */
53   public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) {
54     return new static(
55       $configuration,
56       $plugin_id,
57       $plugin_definition,
58       $container->get('event_dispatcher'),
59       $container->get('entity_type.manager'),
60       $container->get('plugin.manager.entity_browser.widget_validation'),
61       $container->get('current_user')
62     );
63   }
64
65   /**
66    * Constructs a new View object.
67    *
68    * @param array $configuration
69    *   A configuration array containing information about the plugin instance.
70    * @param string $plugin_id
71    *   The plugin_id for the plugin instance.
72    * @param mixed $plugin_definition
73    *   The plugin implementation definition.
74    * @param \Symfony\Component\EventDispatcher\EventDispatcherInterface $event_dispatcher
75    *   Event dispatcher service.
76    * @param \Drupal\Core\Entity\EntityTypeManagerInterface $entity_type_manager
77    *   The entity type manager.
78    * @param \Drupal\entity_browser\WidgetValidationManager $validation_manager
79    *   The Widget Validation Manager service.
80    * @param \Drupal\Core\Session\AccountInterface $current_user
81    *   The current user.
82    */
83   public function __construct(array $configuration, $plugin_id, $plugin_definition, EventDispatcherInterface $event_dispatcher, EntityTypeManagerInterface $entity_type_manager, WidgetValidationManager $validation_manager, AccountInterface $current_user) {
84     parent::__construct($configuration, $plugin_id, $plugin_definition, $event_dispatcher, $entity_type_manager, $validation_manager);
85     $this->currentUser = $current_user;
86   }
87
88   /**
89    * {@inheritdoc}
90    */
91   public function getForm(array &$original_form, FormStateInterface $form_state, array $additional_widget_parameters) {
92     $form = parent::getForm($original_form, $form_state, $additional_widget_parameters);
93     // TODO - do we need better error handling for view and view_display (in case
94     // either of those is nonexistent or display not of correct type)?
95     $form['#attached']['library'] = ['entity_browser/view'];
96
97     /** @var \Drupal\views\ViewExecutable $view */
98     $view = $this->entityTypeManager
99       ->getStorage('view')
100       ->load($this->configuration['view'])
101       ->getExecutable();
102
103     // Check if the current user has access to this view.
104     if (!$view->access($this->configuration['view_display'])) {
105       return [
106         '#markup' => $this->t('You do not have access to this View.'),
107       ];
108     }
109
110     if (!empty($this->configuration['arguments'])) {
111       if (!empty($additional_widget_parameters['path_parts'])) {
112         $arguments = [];
113         // Map configuration arguments with original path parts.
114         foreach ($this->configuration['arguments'] as $argument) {
115           $arguments[] = isset($additional_widget_parameters['path_parts'][$argument]) ? $additional_widget_parameters['path_parts'][$argument] : '';
116         }
117         $view->setArguments(array_values($arguments));
118       }
119     }
120
121     $form['view'] = $view->executeDisplay($this->configuration['view_display']);
122
123     if (empty($view->field['entity_browser_select'])) {
124       $url = Url::fromRoute('entity.view.edit_form', ['view' => $this->configuration['view']])->toString();
125       if ($this->currentUser->hasPermission('administer views')) {
126         return [
127           '#markup' => $this->t('Entity browser select form field not found on a view. <a href=":link">Go fix it</a>!', [':link' => $url]),
128         ];
129       }
130       else {
131         return [
132           '#markup' => $this->t('Entity browser select form field not found on a view. Go fix it!'),
133         ];
134       }
135     }
136
137     // When rebuilding makes no sense to keep checkboxes that were previously
138     // selected.
139     if (!empty($form['view']['entity_browser_select'])) {
140       foreach (Element::children($form['view']['entity_browser_select']) as $child) {
141         $form['view']['entity_browser_select'][$child]['#process'][] = ['\Drupal\entity_browser\Plugin\EntityBrowser\Widget\View', 'processCheckbox'];
142         $form['view']['entity_browser_select'][$child]['#process'][] = ['\Drupal\Core\Render\Element\Checkbox', 'processAjaxForm'];
143         $form['view']['entity_browser_select'][$child]['#process'][] = ['\Drupal\Core\Render\Element\Checkbox', 'processGroup'];
144       }
145     }
146
147     $form['view']['view'] = [
148       '#markup' => \Drupal::service('renderer')->render($form['view']['view']),
149     ];
150
151     return $form;
152   }
153
154   /**
155    * Sets the #checked property when rebuilding form.
156    *
157    * Every time when we rebuild we want all checkboxes to be unchecked.
158    *
159    * @see \Drupal\Core\Render\Element\Checkbox::processCheckbox()
160    */
161   public static function processCheckbox(&$element, FormStateInterface $form_state, &$complete_form) {
162     if ($form_state->isRebuilding()) {
163       $element['#checked'] = FALSE;
164     }
165
166     return $element;
167   }
168
169   /**
170    * {@inheritdoc}
171    */
172   public function validate(array &$form, FormStateInterface $form_state) {
173     $user_input = $form_state->getUserInput();
174     if (isset($user_input['entity_browser_select'])) {
175       $selected_rows = array_values(array_filter($user_input['entity_browser_select']));
176       foreach ($selected_rows as $row) {
177         // Verify that the user input is a string and split it.
178         // Each $row is in the format entity_type:id.
179         if (is_string($row) && $parts = explode(':', $row, 2)) {
180           // Make sure we have a type and id present.
181           if (count($parts) == 2) {
182             try {
183               $storage = $this->entityTypeManager->getStorage($parts[0]);
184               if (!$storage->load($parts[1])) {
185                 $message = $this->t('The @type Entity @id does not exist.', [
186                   '@type' => $parts[0],
187                   '@id' => $parts[1],
188                 ]);
189                 $form_state->setError($form['widget']['view']['entity_browser_select'], $message);
190               }
191             }
192             catch (PluginNotFoundException $e) {
193               $message = $this->t('The Entity Type @type does not exist.', [
194                 '@type' => $parts[0],
195               ]);
196               $form_state->setError($form['widget']['view']['entity_browser_select'], $message);
197             }
198           }
199         }
200       }
201
202       // If there weren't any errors set, run the normal validators.
203       if (empty($form_state->getErrors())) {
204         parent::validate($form, $form_state);
205       }
206     }
207   }
208
209   /**
210    * {@inheritdoc}
211    */
212   protected function prepareEntities(array $form, FormStateInterface $form_state) {
213     $selected_rows = array_values(array_filter($form_state->getUserInput()['entity_browser_select']));
214     $entities = [];
215     foreach ($selected_rows as $row) {
216       list($type, $id) = explode(':', $row);
217       $storage = $this->entityTypeManager->getStorage($type);
218       if ($entity = $storage->load($id)) {
219         $entities[] = $entity;
220       }
221     }
222     return $entities;
223   }
224
225   /**
226    * {@inheritdoc}
227    */
228   public function submit(array &$element, array &$form, FormStateInterface $form_state) {
229     $entities = $this->prepareEntities($form, $form_state);
230     $this->selectEntities($entities, $form_state);
231   }
232
233   /**
234    * {@inheritdoc}
235    */
236   public function buildConfigurationForm(array $form, FormStateInterface $form_state) {
237     $form = parent::buildConfigurationForm($form, $form_state);
238
239     $options = [];
240     // Get only those enabled Views that have entity_browser displays.
241     $displays = Views::getApplicableViews('entity_browser_display');
242     foreach ($displays as $display) {
243       list($view_id, $display_id) = $display;
244       $view = $this->entityTypeManager->getStorage('view')->load($view_id);
245       $options[$view_id . '.' . $display_id] = $this->t('@view : @display', ['@view' => $view->label(), '@display' => $view->get('display')[$display_id]['display_title']]);
246     }
247
248     $form['view'] = [
249       '#type' => 'select',
250       '#title' => $this->t('View : View display'),
251       '#default_value' => $this->configuration['view'] . '.' . $this->configuration['view_display'],
252       '#options' => $options,
253       '#empty_option' => $this->t('- Select a view -'),
254       '#required' => TRUE,
255     ];
256
257     return $form;
258   }
259
260   /**
261    * {@inheritdoc}
262    */
263   public function submitConfigurationForm(array &$form, FormStateInterface $form_state) {
264     $values = $form_state->getValues()['table'][$this->uuid()]['form'];
265     $this->configuration['submit_text'] = $values['submit_text'];
266     $this->configuration['auto_select'] = $values['auto_select'];
267     if (!empty($values['view'])) {
268       list($view_id, $display_id) = explode('.', $values['view']);
269       $this->configuration['view'] = $view_id;
270       $this->configuration['view_display'] = $display_id;
271     }
272   }
273
274   /**
275    * {@inheritdoc}
276    */
277   public function calculateDependencies() {
278     $dependencies = [];
279     if ($this->configuration['view']) {
280       $view = ViewEntity::load($this->configuration['view']);
281       $dependencies[$view->getConfigDependencyKey()] = [$view->getConfigDependencyName()];
282     }
283     return $dependencies;
284   }
285
286   /**
287    * {@inheritdoc}
288    */
289   public function access() {
290     // Mark the widget as not visible if the user has no access to the view.
291     /** @var \Drupal\views\ViewExecutable $view */
292     $view = $this->entityTypeManager
293       ->getStorage('view')
294       ->load($this->configuration['view'])
295       ->getExecutable();
296
297
298     // Check if the current user has access to this view.
299     return AccessResult::allowedIf($view->access($this->configuration['view_display']));
300   }
301
302 }