Completed
Push — 8.x-1.x ( 563420...b8d656 )
by Janez
02:43
created

View::prepareEntities()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 12
Code Lines 9

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 3
eloc 9
c 1
b 0
f 0
nc 3
nop 1
dl 0
loc 12
rs 9.4285
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\KeyValueStore\KeyValueStoreExpirableInterface;
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\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
use Symfony\Component\HttpFoundation\Request;
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
 * )
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 array(
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 = [];
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' => t('You do not have access to this View.'),
106
      ];
107
    }
108
109
    if (!empty($this->configuration['arguments'])) {
110
      if (!empty($aditional_widget_parameters['path_parts'])) {
0 ignored issues
show
Bug introduced by
The variable $aditional_widget_parameters does not exist. Did you mean $additional_widget_parameters?

This check looks for variables that are accessed but have not been defined. It raises an issue if it finds another variable that has a similar name.

The variable may have been renamed without also renaming all references.

Loading history...
111
        $arguments = [];
112
        // Map configuration arguments with original path parts.
113
        foreach ($this->configuration['arguments'] as $argument) {
114
          $arguments[] = isset($aditional_widget_parameters['path_parts'][$argument]) ? $aditional_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' => 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' => 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 = 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) {
0 ignored issues
show
Bug introduced by
The class Drupal\Component\Plugin\...PluginNotFoundException does not exist. Did you forget a USE statement, or did you not list all dependencies?

Scrutinizer analyzes your composer.json/composer.lock file if available to determine the classes, and functions that are defined by your dependencies.

It seems like the listed class was neither found in your dependencies, nor was it found in the analyzed files in your repository. If you are using some other form of dependency management, you might want to disable this analysis.

Loading history...
189
              $message = 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(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_state);
226
    $this->selectEntities($entities, $form_state);
227
  }
228
229
  /**
230
   * {@inheritdoc}
231
   */
232
  public function buildConfigurationForm(array $form, FormStateInterface $form_state) {
233
    $options = [];
234
    // Get only those enabled Views that have entity_browser displays.
235
    $displays = Views::getApplicableViews('entity_browser_display');
236
    foreach ($displays as $display) {
237
      list($view_id, $display_id) = $display;
238
      $view = $this->entityTypeManager->getStorage('view')->load($view_id);
239
      $options[$view_id . '.' . $display_id] = $this->t('@view : @display', array('@view' => $view->label(), '@display' => $view->get('display')[$display_id]['display_title']));
240
    }
241
242
    $form['view'] = [
243
      '#type' => 'select',
244
      '#title' => $this->t('View : View display'),
245
      '#default_value' => $this->configuration['view'] . '.' . $this->configuration['view_display'],
246
      '#options' => $options,
247
      '#empty_option' => $this->t('- Select a view -'),
248
      '#required' => TRUE,
249
    ];
250
251
    return $form;
252
  }
253
254
  /**
255
   * {@inheritdoc}
256
   */
257
  public function submitConfigurationForm(array &$form, FormStateInterface $form_state) {
258
    $values = $form_state->getValues()['table'][$this->uuid()]['form'];
259
260 View Code Duplication
    if (!empty($values['view'])) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
261
      list($view_id, $display_id) = explode('.', $values['view']);
262
      $this->configuration['view'] = $view_id;
263
      $this->configuration['view_display'] = $display_id;
264
    }
265
  }
266
267
}
268