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