Completed
Push — 8.x-1.x ( a3faf0...bfc7fc )
by Janez
02:54
created

MultiStepDisplay::buildConfigurationForm()   B

Complexity

Conditions 5
Paths 12

Size

Total Lines 58
Code Lines 41

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 0
loc 58
rs 8.7274
cc 5
eloc 41
nc 12
nop 2

How to fix   Long Method   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
3
namespace Drupal\entity_browser\Plugin\EntityBrowser\SelectionDisplay;
4
5
use Drupal\Component\Utility\Html;
6
use Drupal\Core\Entity\EntityManagerInterface;
7
use Drupal\Core\Form\FormStateInterface;
8
use Drupal\entity_browser\FieldWidgetDisplayManager;
9
use Drupal\entity_browser\SelectionDisplayBase;
10
use Symfony\Component\DependencyInjection\ContainerInterface;
11
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
12
13
/**
14
 * Show current selection and delivers selected entities.
15
 *
16
 * @EntityBrowserSelectionDisplay(
17
 *   id = "multi_step_display",
18
 *   label = @Translation("Multi step selection display"),
19
 *   description = @Translation("Show current selection display and delivers selected entities.")
20
 * )
21
 */
22
class MultiStepDisplay extends SelectionDisplayBase {
23
24
  /**
25
   * Field widget display plugin manager.
26
   *
27
   * @var \Drupal\entity_browser\FieldWidgetDisplayManager
28
   */
29
  protected $fieldDisplayManager;
30
31
  /**
32
   * Constructs widget plugin.
33
   *
34
   * @param array $configuration
35
   *   A configuration array containing information about the plugin instance.
36
   * @param string $plugin_id
37
   *   The plugin_id for the plugin instance.
38
   * @param mixed $plugin_definition
39
   *   The plugin implementation definition.
40
   * @param \Symfony\Component\EventDispatcher\EventDispatcherInterface $event_dispatcher
41
   *   Event dispatcher service.
42
   * @param \Drupal\Core\Entity\EntityManagerInterface
43
   *   Entity manager service.
44
   * @param \Drupal\entity_browser\FieldWidgetDisplayManager $field_display_manager
45
   *   Field widget display plugin manager.
46
   */
47
  public function __construct(array $configuration, $plugin_id, $plugin_definition, EventDispatcherInterface $event_dispatcher, EntityManagerInterface $entity_manager, FieldWidgetDisplayManager $field_display_manager) {
48
    parent::__construct($configuration, $plugin_id, $plugin_definition, $event_dispatcher, $entity_manager);
49
    $this->fieldDisplayManager = $field_display_manager;
50
  }
51
52
  /**
53
   * {@inheritdoc}
54
   */
55 View Code Duplication
  public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) {
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in 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...
56
    return new static(
57
      $configuration,
58
      $plugin_id,
59
      $plugin_definition,
60
      $container->get('event_dispatcher'),
61
      $container->get('entity.manager'),
62
      $container->get('plugin.manager.entity_browser.field_widget_display')
63
    );
64
  }
65
  /**
66
   * {@inheritdoc}
67
   */
68
  public function defaultConfiguration() {
69
    return [
70
      'entity_type' => 'node',
71
      'display' => 'label',
72
      'display_settings' => [],
73
    ] + parent::defaultConfiguration();
74
  }
75
76
  /**
77
   * {@inheritdoc}
78
   */
79
  public function getForm(array &$original_form, FormStateInterface $form_state) {
80
    $selected_entities = $form_state->get(['entity_browser', 'selected_entities']);
81
82
    $form = [];
83
    $form['#attached']['library'][] = 'entity_browser/multi_step_display';
84
    $form['selected'] = [
85
      '#theme_wrappers' => ['container'],
86
      '#attributes' => ['class' => ['entities-list']],
87
      '#tree' => TRUE
88
    ];
89
    foreach ($selected_entities as $id => $entity) {
90
      $display_plugin = $this->fieldDisplayManager->createInstance(
91
        $this->configuration['display'],
92
        $this->configuration['display_settings'] + ['entity_type' => $this->configuration['entity_type']]
93
      );
94
      $display = $display_plugin->view($entity);
95
      if (is_string($display)) {
96
        $display = ['#markup' => $display];
97
      }
98
99
      $form['selected']['items_'. $entity->id()] = [
100
        '#theme_wrappers' => ['container'],
101
        '#attributes' => [
102
          'class' => ['item-container'],
103
          'data-entity-id' => $entity->id()
104
        ],
105
        'display' => $display,
106
        'remove_button' => [
107
          '#type' => 'submit',
108
          '#value' => $this->t('Remove'),
109
          '#submit' => [[get_class($this), 'removeItemSubmit']],
110
          '#name' => 'remove_' . $entity->id(),
111
          '#attributes' => [
112
            'data-row-id' => $id,
113
            'data-remove-entity' => 'items_' . $entity->id(),
114
          ]
115
        ],
116
        'weight' => [
117
          '#type' => 'hidden',
118
          '#default_value' => $id,
119
          '#attributes' => ['class' => ['weight']]
120
        ]
121
      ];
122
    }
123
    $form['use_selected'] = array(
124
      '#type' => 'submit',
125
      '#value' => t('Use selected'),
126
      '#name' => 'use_selected',
127
    );
128
129
    return $form;
130
  }
131
132
  /**
133
   * Submit callback for remove buttons.
134
   *
135
   * @param array $form
136
   * @param \Drupal\Core\Form\FormStateInterface $form_state
137
   */
138
  public static function removeItemSubmit(array &$form, FormStateInterface $form_state) {
139
    $triggering_element = $form_state->getTriggeringElement();
140
141
    // Remove weight of entity being removed.
142
    $form_state->unsetValue(['selected', $triggering_element['#attributes']['data-remove-entity']]);
143
144
    // Remove entity itself.
145
    $selected_entities = &$form_state->get(['entity_browser', 'selected_entities']);
146
    unset($selected_entities[$triggering_element['#attributes']['data-row-id']]);
147
148
    static::saveNewOrder($form_state);
149
    $form_state->setRebuild();
150
  }
151
152
  /**
153
   * {@inheritdoc}
154
   */
155
  public function submit(array &$form, FormStateInterface $form_state) {
156
    $this->saveNewOrder($form_state);
157
    if ($form_state->getTriggeringElement()['#name'] == 'use_selected') {
158
      $this->selectionDone($form_state);
159
    }
160
  }
161
162
  /**
163
   * Saves new ordering of entities based on weight.
164
   *
165
   * @param FormStateInterface $form_state
166
   *   Form state.
167
   */
168
  public static function saveNewOrder(FormStateInterface $form_state) {
169
    $selected = $form_state->getValue('selected');
170
    if (!empty($selected)) {
171
      $weights = array_column($selected, 'weight');
172
      $selected_entities = $form_state->get(['entity_browser', 'selected_entities']);
173
174
      // If we added new entities to the selection at this step we won't have
175
      // weights for them so we have to fake them.
176
      if (sizeof($weights) < sizeof($selected_entities)) {
177
        for ($new_weigth = (max($weights) + 1); $new_weigth < sizeof($selected_entities); $new_weigth++) {
0 ignored issues
show
Performance Best Practice introduced by
It seems like you are calling the size function sizeof() as part of the test condition. You might want to compute the size beforehand, and not on each iteration.

If the size of the collection does not change during the iteration, it is generally a good practice to compute it beforehand, and not on each iteration:

for ($i=0; $i<count($array); $i++) { // calls count() on each iteration
}

// Better
for ($i=0, $c=count($array); $i<$c; $i++) { // calls count() just once
}
Loading history...
178
          $weights[] = $new_weigth;
179
        }
180
      }
181
182
      $ordered = array_combine($weights, $selected_entities);
183
      ksort($ordered);
184
      $form_state->set(['entity_browser', 'selected_entities'], $ordered);
185
    }
186
  }
187
188
  /**
189
   * {@inheritdoc}
190
   */
191
  public function buildConfigurationForm(array $form, FormStateInterface $form_state) {
192
    $default_entity_type = $form_state->getValue('entity_type', $this->configuration['entity_type']);
193
    $default_display = $form_state->getValue('display', $this->configuration['display']);
194
    $default_display_settings = $form_state->getValue('display_settings', $this->configuration['display_settings']);
195
    $default_display_settings += ['entity_type' => $default_entity_type];
196
197
    $form['#prefix'] = '<div id="multi-step-form-wrapper">';
198
    $form['#suffix'] = '</div>';
199
200
    $entity_types = [];
201
    foreach ($this->entityManager->getDefinitions() as $entity_type_id => $entity_type) {
202
      /** @var \Drupal\Core\Entity\EntityTypeInterface $entity_type */
203
      $entity_types[$entity_type_id] = $entity_type->getLabel();
204
    }
205
    $form['entity_type'] = [
206
      '#type' => 'select',
207
      '#title' => $this->t('Entity type'),
208
      '#description' => $this->t("Entity browser itself does not need information about entity type being selected. It can actually select entities of different type. However, some of the display plugins need to know which entity type they are operating with. Display plugins that do not need this info will ignore this configuration value."),
209
      '#default_value' => $default_entity_type,
210
      '#options' => $entity_types,
211
      '#ajax' => [
212
        'callback' => [$this, 'updateSettingsAjax'],
213
        'wrapper' => 'multi-step-form-wrapper',
214
      ],
215
    ];
216
217
    $displays = [];
218
    foreach ($this->fieldDisplayManager->getDefinitions() as $display_plugin_id => $definition) {
219
      $entity_type = $this->entityManager->getDefinition($default_entity_type);
220
      if ($this->fieldDisplayManager->createInstance($display_plugin_id)->isApplicable($entity_type)) {
221
        $displays[$display_plugin_id] = $definition['label'];
222
      }
223
    }
224
    $form['display'] = [
225
      '#title' => t('Entity display plugin'),
226
      '#type' => 'select',
227
      '#default_value' => $default_display,
228
      '#options' => $displays,
229
      '#ajax' => [
230
        'callback' => [$this, 'updateSettingsAjax'],
231
        'wrapper' => 'multi-step-form-wrapper',
232
      ],
233
    ];
234
235
    $form['display_settings'] = [
236
      '#type' => 'container',
237
      '#title' => t('Entity display plugin configuration'),
238
      '#tree' => TRUE,
239
    ];
240
    if ($default_display_settings) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $default_display_settings of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using ! empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
241
      $display_plugin = $this->fieldDisplayManager
242
        ->createInstance($default_display, $default_display_settings);
243
244
      $form['display_settings'] += $display_plugin->settingsForm($form, $form_state);
245
    }
246
247
    return $form;
248
  }
249
250
  /**
251
   * Ajax callback that updates multi-step plugin configuration form on AJAX updates.
252
   */
253
  public function updateSettingsAjax(array $form, FormStateInterface $form_state) {
254
    return $form;
255
  }
256
257
}
258