Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.
Common duplication problems, and corresponding solutions are:
Complex classes like EntityEmbedDialog often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes. You can also have a look at the cohesion graph to spot any un-connected, or weakly-connected components.
Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.
While breaking up the class, it is a good idea to analyze how other classes use EntityEmbedDialog, and based on these observations, apply Extract Interface, too.
1 | <?php |
||
34 | class EntityEmbedDialog extends FormBase { |
||
35 | use EntityHelperTrait; |
||
36 | |||
37 | /** |
||
38 | * The form builder. |
||
39 | * |
||
40 | * @var \Drupal\Core\Form\FormBuilderInterface |
||
41 | */ |
||
42 | protected $formBuilder; |
||
43 | |||
44 | /** |
||
45 | * The entity type manager service. |
||
46 | * |
||
47 | * @var \Drupal\Core\Entity\EntityTypeManagerInterface |
||
48 | */ |
||
49 | protected $entityTypeManager; |
||
50 | |||
51 | /** |
||
52 | * Event dispatcher service. |
||
53 | * |
||
54 | * @var \Symfony\Component\EventDispatcher\EventDispatcherInterface |
||
55 | */ |
||
56 | protected $eventDispatcher; |
||
57 | |||
58 | /** |
||
59 | * The entity browser. |
||
60 | * |
||
61 | * @var \Drupal\entity_browser\EntityBrowserInterface |
||
62 | */ |
||
63 | protected $entityBrowser; |
||
64 | |||
65 | /** |
||
66 | * The entity browser settings from the entity embed button. |
||
67 | */ |
||
68 | protected $entityBrowserSettings = []; |
||
69 | |||
70 | /** |
||
71 | * Constructs a EntityEmbedDialog object. |
||
72 | * |
||
73 | * @param \Drupal\entity_embed\EntityEmbedDisplay\EntityEmbedDisplayManager $plugin_manager |
||
74 | * The Module Handler. |
||
75 | * @param \Drupal\Core\Form\FormBuilderInterface $form_builder |
||
76 | * The Form Builder. |
||
77 | * @param \Drupal\Core\Entity\EntityTypeManagerInterface $entity_type_manager |
||
78 | * The entity type manager service. |
||
79 | * @param \Symfony\Component\EventDispatcher\EventDispatcherInterface $event_dispatcher |
||
80 | * Event dispatcher service. |
||
81 | */ |
||
82 | public function __construct(EntityEmbedDisplayManager $plugin_manager, FormBuilderInterface $form_builder, EntityTypeManagerInterface $entity_type_manager, EventDispatcherInterface $event_dispatcher) { |
||
83 | $this->setDisplayPluginManager($plugin_manager); |
||
84 | $this->formBuilder = $form_builder; |
||
85 | $this->entityTypeManager = $entity_type_manager; |
||
86 | $this->eventDispatcher = $event_dispatcher; |
||
87 | } |
||
88 | |||
89 | /** |
||
90 | * {@inheritdoc} |
||
91 | */ |
||
92 | public static function create(ContainerInterface $container) { |
||
93 | return new static( |
||
94 | $container->get('plugin.manager.entity_embed.display'), |
||
95 | $container->get('form_builder'), |
||
96 | $container->get('entity_type.manager'), |
||
97 | $container->get('event_dispatcher') |
||
98 | ); |
||
99 | } |
||
100 | |||
101 | /** |
||
102 | * {@inheritdoc} |
||
103 | */ |
||
104 | public function getFormId() { |
||
105 | return 'entity_embed_dialog'; |
||
106 | } |
||
107 | |||
108 | /** |
||
109 | * {@inheritdoc} |
||
110 | * |
||
111 | * @param \Drupal\editor\EditorInterface $editor |
||
112 | * The editor to which this dialog corresponds. |
||
113 | * @param \Drupal\embed\EmbedButtonInterface $embed_button |
||
114 | * The URL button to which this dialog corresponds. |
||
115 | */ |
||
116 | public function buildForm(array $form, FormStateInterface $form_state, EditorInterface $editor = NULL, EmbedButtonInterface $embed_button = NULL) { |
||
117 | $values = $form_state->getValues(); |
||
118 | $input = $form_state->getUserInput(); |
||
119 | // Set embed button element in form state, so that it can be used later in |
||
120 | // validateForm() function. |
||
121 | $form_state->set('embed_button', $embed_button); |
||
122 | $form_state->set('editor', $editor); |
||
123 | // Initialize entity element with form attributes, if present. |
||
124 | $entity_element = empty($values['attributes']) ? array() : $values['attributes']; |
||
125 | $entity_element += empty($input['attributes']) ? array() : $input['attributes']; |
||
126 | // The default values are set directly from \Drupal::request()->request, |
||
127 | // provided by the editor plugin opening the dialog. |
||
128 | if (!$form_state->get('entity_element')) { |
||
129 | $form_state->set('entity_element', isset($input['editor_object']) ? $input['editor_object'] : array()); |
||
130 | } |
||
131 | $entity_element += $form_state->get('entity_element'); |
||
132 | $entity_element += array( |
||
133 | 'data-entity-type' => $embed_button->getTypeSetting('entity_type'), |
||
134 | 'data-entity-uuid' => '', |
||
135 | 'data-entity-embed-display' => 'entity_reference:entity_reference_entity_view', |
||
136 | 'data-entity-embed-settings' => array(), |
||
137 | 'data-align' => '', |
||
138 | 'data-caption' => '', |
||
139 | ); |
||
140 | $form_state->set('entity_element', $entity_element); |
||
141 | $form_state->set('entity', $this->loadEntity($entity_element['data-entity-type'], $entity_element['data-entity-uuid'])); |
||
142 | |||
143 | if (!$form_state->get('step')) { |
||
144 | // If an entity has been selected, then always skip to the embed options. |
||
145 | if ($form_state->get('entity')) { |
||
146 | $form_state->set('step', 'embed'); |
||
147 | } |
||
148 | else { |
||
149 | $form_state->set('step', 'select'); |
||
150 | } |
||
151 | } |
||
152 | |||
153 | $form['#tree'] = TRUE; |
||
154 | $form['#attached']['library'][] = 'editor/drupal.editor.dialog'; |
||
155 | $form['#attached']['library'][] = 'entity_embed/drupal.entity_embed.dialog'; |
||
156 | $form['#prefix'] = '<div id="entity-embed-dialog-form">'; |
||
157 | $form['#suffix'] = '</div>'; |
||
158 | $form['#attributes']['class'][] = 'entity-embed-dialog-step--' . $form_state->get('step'); |
||
159 | |||
160 | $this->loadEntityBrowser($form_state); |
||
161 | |||
162 | if ($form_state->get('step') == 'select') { |
||
163 | $form = $this->buildSelectStep($form, $form_state); |
||
164 | } |
||
165 | elseif ($form_state->get('step') == 'review') { |
||
166 | $form = $this->buildReviewStep($form, $form_state); |
||
167 | } |
||
168 | elseif ($form_state->get('step') == 'embed') { |
||
169 | $form = $this->buildEmbedStep($form, $form_state); |
||
170 | } |
||
171 | |||
172 | return $form; |
||
173 | } |
||
174 | |||
175 | /** |
||
176 | * Form constructor for the entity selection step. |
||
177 | * |
||
178 | * @param array $form |
||
179 | * An associative array containing the structure of the form. |
||
180 | * @param \Drupal\Core\Form\FormStateInterface $form_state |
||
181 | * The current state of the form. |
||
182 | * |
||
183 | * @return array |
||
184 | * The form structure. |
||
185 | */ |
||
186 | public function buildSelectStep(array &$form, FormStateInterface $form_state) { |
||
187 | $entity_element = $form_state->get('entity_element'); |
||
188 | /** @var \Drupal\embed\EmbedButtonInterface $embed_button */ |
||
189 | $embed_button = $form_state->get('embed_button'); |
||
190 | $entity = $form_state->get('entity'); |
||
191 | |||
192 | $form['attributes']['data-entity-type'] = array( |
||
193 | '#type' => 'value', |
||
194 | '#value' => $entity_element['data-entity-type'], |
||
195 | ); |
||
196 | |||
197 | $label = $this->t('Label'); |
||
198 | // Attempt to display a better label if we can by getting it from |
||
199 | // the label field definition. |
||
200 | $entity_type = $this->entityTypeManager->getDefinition($entity_element['data-entity-type']); |
||
201 | if ($entity_type->isSubclassOf('\Drupal\Core\Entity\FieldableEntityInterface') && $entity_type->hasKey('label')) { |
||
202 | $field_definitions = $this->entityManager()->getBaseFieldDefinitions($entity_type->id()); |
||
203 | if (isset($field_definitions[$entity_type->getKey('label')])) { |
||
204 | $label = $field_definitions[$entity_type->getKey('label')]->getLabel(); |
||
205 | } |
||
206 | } |
||
207 | |||
208 | $form['#title'] = $this->t('Select @type to embed', array('@type' => $entity_type->getLowercaseLabel())); |
||
209 | |||
210 | if ($this->entityBrowser) { |
||
211 | $this->eventDispatcher->addListener(Events::REGISTER_JS_CALLBACKS, [$this, 'registerJSCallback']); |
||
212 | |||
213 | $form['attributes']['entity_browser']['#theme_wrappers'] = ['container']; |
||
214 | $form['attributes']['entity_browser']['browser'] = $this->entityBrowser->getDisplay()->displayEntityBrowser($form_state); |
||
215 | $form['attributes']['entity_browser']['entity-id'] = [ |
||
216 | '#type' => 'hidden', |
||
217 | '#default_value' => $entity ? $entity->id() : '', |
||
218 | '#attributes' => ['class' => ['eb-target']] |
||
219 | ]; |
||
220 | $form['#attached']['library'][] = 'entity_browser/common'; |
||
221 | $form['#attached']['drupalSettings']['entity_browser'] = [ |
||
222 | $this->entityBrowser->getDisplay()->getUuid() => [ |
||
223 | 'cardinality' => 1 |
||
224 | ] |
||
225 | ]; |
||
226 | $form['attributes']['data-entity-id'] = array( |
||
227 | '#type' => 'value', |
||
228 | '#title' => $entity_element['data-entity-id'], |
||
229 | ); |
||
230 | } |
||
231 | else { |
||
232 | $form['attributes']['data-entity-id'] = array( |
||
233 | '#type' => 'entity_autocomplete', |
||
234 | '#target_type' => $entity_element['data-entity-type'], |
||
235 | '#title' => $label, |
||
236 | '#default_value' => $entity, |
||
237 | '#required' => TRUE, |
||
238 | '#description' => $this->t('Type label and pick the right one from suggestions. Note that the unique ID will be saved.'), |
||
239 | ); |
||
240 | if ($bundles = $embed_button->getTypeSetting('bundles')) { |
||
241 | $form['attributes']['data-entity-id']['#selection_settings']['target_bundles'] = $bundles; |
||
242 | } |
||
243 | } |
||
244 | |||
245 | $form['attributes']['data-entity-uuid'] = array( |
||
246 | '#type' => 'value', |
||
247 | '#title' => $entity_element['data-entity-uuid'], |
||
248 | ); |
||
249 | $form['actions'] = array( |
||
250 | '#type' => 'actions', |
||
251 | ); |
||
252 | |||
253 | $form['actions']['save_modal'] = array( |
||
254 | '#type' => 'submit', |
||
255 | '#value' => $this->t('Next'), |
||
256 | '#button_type' => 'primary', |
||
257 | // No regular submit-handler. This form only works via JavaScript. |
||
258 | '#submit' => array(), |
||
259 | '#ajax' => array( |
||
260 | 'callback' => '::submitSelectStep', |
||
261 | 'event' => 'click', |
||
262 | ), |
||
263 | '#attributes' => [ |
||
264 | 'class' => [ |
||
265 | 'js-button-next', |
||
266 | ], |
||
267 | ], |
||
268 | ); |
||
269 | |||
270 | return $form; |
||
271 | } |
||
272 | |||
273 | /** |
||
274 | * Form constructor for the entity review step. |
||
275 | * |
||
276 | * @param array $form |
||
277 | * An associative array containing the structure of the form. |
||
278 | * @param \Drupal\Core\Form\FormStateInterface $form_state |
||
279 | * The current state of the form. |
||
280 | * |
||
281 | * @return array |
||
282 | * The form structure. |
||
283 | */ |
||
284 | public function buildReviewStep(array &$form, FormStateInterface $form_state) { |
||
285 | /** @var \Drupal\Core\Entity\EntityInterface $entity */ |
||
286 | $entity = $form_state->get('entity'); |
||
287 | |||
288 | $form['#title'] = $this->t('Review selected @type', array('@type' => $entity->getEntityType()->getLowercaseLabel())); |
||
289 | |||
290 | $form['selection'] = [ |
||
291 | '#markup' => $entity->label() |
||
292 | ]; |
||
293 | |||
294 | $form['actions'] = array( |
||
295 | '#type' => 'actions', |
||
296 | ); |
||
297 | |||
298 | $form['actions']['back'] = array( |
||
299 | '#type' => 'submit', |
||
300 | '#value' => $this->t('Replace selection'), |
||
301 | // No regular submit-handler. This form only works via JavaScript. |
||
302 | '#submit' => array(), |
||
303 | '#ajax' => array( |
||
304 | 'callback' => '::submitAndShowSelect', |
||
305 | 'event' => 'click', |
||
306 | ), |
||
307 | ); |
||
308 | |||
309 | $form['actions']['save_modal'] = array( |
||
310 | '#type' => 'submit', |
||
311 | '#value' => $this->t('Next'), |
||
312 | '#button_type' => 'primary', |
||
313 | // No regular submit-handler. This form only works via JavaScript. |
||
314 | '#submit' => array(), |
||
315 | '#ajax' => array( |
||
316 | 'callback' => '::submitAndShowEmbed', |
||
317 | 'event' => 'click', |
||
318 | ), |
||
319 | '#attributes' => [ |
||
320 | 'class' => [ |
||
321 | 'js-button-next', |
||
322 | ], |
||
323 | ], |
||
324 | ); |
||
325 | |||
326 | return $form; |
||
327 | } |
||
328 | |||
329 | /** |
||
330 | * Form constructor for the entity embedding step. |
||
331 | * |
||
332 | * @param array $form |
||
333 | * An associative array containing the structure of the form. |
||
334 | * @param \Drupal\Core\Form\FormStateInterface $form_state |
||
335 | * The current state of the form. |
||
336 | * |
||
337 | * @return array |
||
338 | * The form structure. |
||
339 | */ |
||
340 | public function buildEmbedStep(array $form, FormStateInterface $form_state) { |
||
341 | $entity_element = $form_state->get('entity_element'); |
||
342 | /** @var \Drupal\embed\EmbedButtonInterface $embed_button */ |
||
343 | $embed_button = $form_state->get('embed_button'); |
||
344 | /** @var \Drupal\editor\EditorInterface $editor */ |
||
345 | $editor = $form_state->get('editor'); |
||
346 | /** @var \Drupal\Core\Entity\EntityInterface $entity */ |
||
347 | $entity = $form_state->get('entity'); |
||
348 | $values = $form_state->getValues(); |
||
349 | |||
350 | $form['#title'] = $this->t('Embed @type', array('@type' => $entity->getEntityType()->getLowercaseLabel())); |
||
351 | |||
352 | $entity_label = ''; |
||
353 | try { |
||
354 | $entity_label = $entity->link(); |
||
355 | } |
||
356 | catch (\Exception $e) { |
||
357 | // Construct markup of the link to the entity manually if link() fails. |
||
358 | // @see https://www.drupal.org/node/2402533 |
||
359 | $entity_label = '<a href="' . $entity->url() . '">' . $entity->label() . '</a>'; |
||
360 | } |
||
361 | |||
362 | $form['entity'] = array( |
||
363 | '#type' => 'item', |
||
364 | '#title' => $this->t('Selected entity'), |
||
365 | '#markup' => $entity_label, |
||
366 | ); |
||
367 | $form['attributes']['data-entity-type'] = array( |
||
368 | '#type' => 'hidden', |
||
369 | '#value' => $entity_element['data-entity-type'], |
||
370 | ); |
||
371 | $form['attributes']['data-entity-uuid'] = array( |
||
372 | '#type' => 'hidden', |
||
373 | '#value' => $entity_element['data-entity-uuid'], |
||
374 | ); |
||
375 | |||
376 | // Build the list of allowed Entity Embed Display plugins. |
||
377 | $display_plugin_options = $this->getDisplayPluginOptions($embed_button, $entity); |
||
378 | |||
379 | // If the currently selected display is not in the available options, |
||
380 | // use the first from the list instead. This can happen if an alter |
||
381 | // hook customizes the list based on the entity. |
||
382 | if (!isset($display_plugin_options[$entity_element['data-entity-embed-display']])) { |
||
383 | $entity_element['data-entity-embed-display'] = key($display_plugin_options); |
||
384 | } |
||
385 | |||
386 | // The default Entity Embed Display plugin has been deprecated by the |
||
387 | // rendered entity field formatter. |
||
388 | if ($entity_element['data-entity-embed-display'] === 'default') { |
||
389 | $entity_element['data-entity-embed-display'] = 'entity_reference:entity_reference_entity_view'; |
||
390 | } |
||
391 | |||
392 | $form['attributes']['data-entity-embed-display'] = array( |
||
393 | '#type' => 'select', |
||
394 | '#title' => $this->t('Display as'), |
||
395 | '#options' => $display_plugin_options, |
||
396 | '#default_value' => $entity_element['data-entity-embed-display'], |
||
397 | '#required' => TRUE, |
||
398 | '#ajax' => array( |
||
399 | 'callback' => '::updatePluginConfigurationForm', |
||
400 | 'wrapper' => 'data-entity-embed-settings-wrapper', |
||
401 | 'effect' => 'fade', |
||
402 | ), |
||
403 | // Hide the selection if only one option is available. |
||
404 | '#access' => count($display_plugin_options) > 1, |
||
405 | ); |
||
406 | $form['attributes']['data-entity-embed-settings'] = array( |
||
407 | '#type' => 'container', |
||
408 | '#prefix' => '<div id="data-entity-embed-settings-wrapper">', |
||
409 | '#suffix' => '</div>', |
||
410 | ); |
||
411 | $form['attributes']['data-embed-button'] = array( |
||
412 | '#type' => 'value', |
||
413 | '#value' => $embed_button->id(), |
||
414 | ); |
||
415 | $plugin_id = !empty($values['attributes']['data-entity-embed-display']) ? $values['attributes']['data-entity-embed-display'] : $entity_element['data-entity-embed-display']; |
||
416 | if (!empty($plugin_id)) { |
||
417 | if (is_string($entity_element['data-entity-embed-settings'])) { |
||
418 | $entity_element['data-entity-embed-settings'] = Json::decode($entity_element['data-entity-embed-settings']); |
||
419 | } |
||
420 | $display = $this->displayPluginManager()->createInstance($plugin_id, $entity_element['data-entity-embed-settings']); |
||
421 | $display->setContextValue('entity', $entity); |
||
422 | $display->setAttributes($entity_element); |
||
423 | $form['attributes']['data-entity-embed-settings'] += $display->buildConfigurationForm($form, $form_state); |
||
424 | } |
||
425 | |||
426 | // When Drupal core's filter_align is being used, the text editor may |
||
427 | // offer the ability to change the alignment. |
||
428 | if (isset($entity_element['data-align']) && $editor->getFilterFormat()->filters('filter_align')->status) { |
||
429 | $form['attributes']['data-align'] = array( |
||
430 | '#title' => $this->t('Align'), |
||
431 | '#type' => 'radios', |
||
432 | '#options' => array( |
||
433 | 'none' => $this->t('None'), |
||
434 | 'left' => $this->t('Left'), |
||
435 | 'center' => $this->t('Center'), |
||
436 | 'right' => $this->t('Right'), |
||
437 | ), |
||
438 | '#default_value' => $entity_element['data-align'] === '' ? 'none' : $entity_element['data-align'], |
||
439 | '#wrapper_attributes' => array('class' => array('container-inline')), |
||
440 | '#attributes' => array('class' => array('container-inline')), |
||
441 | ); |
||
442 | } |
||
443 | |||
444 | // When Drupal core's filter_caption is being used, the text editor may |
||
445 | // offer the ability to add a caption. |
||
446 | if (isset($entity_element['data-caption']) && $editor->getFilterFormat()->filters('filter_caption')->status) { |
||
447 | $form['attributes']['data-caption'] = array( |
||
448 | '#title' => $this->t('Caption'), |
||
449 | '#type' => 'textfield', |
||
450 | '#default_value' => Html::decodeEntities($entity_element['data-caption']), |
||
451 | '#element_validate' => array('::escapeValue'), |
||
452 | ); |
||
453 | } |
||
454 | |||
455 | $form['actions'] = array( |
||
456 | '#type' => 'actions', |
||
457 | ); |
||
458 | $form['actions']['back'] = array( |
||
459 | '#type' => 'submit', |
||
460 | '#value' => $this->t('Back'), |
||
461 | // No regular submit-handler. This form only works via JavaScript. |
||
462 | '#submit' => array(), |
||
463 | '#ajax' => array( |
||
464 | 'callback' => !empty($this->entityBrowserSettings['display_review']) ? '::submitAndShowReview' : '::submitAndShowSelect', |
||
465 | 'event' => 'click', |
||
466 | ), |
||
467 | ); |
||
468 | $form['actions']['save_modal'] = array( |
||
469 | '#type' => 'submit', |
||
470 | '#value' => $this->t('Embed'), |
||
471 | '#button_type' => 'primary', |
||
472 | // No regular submit-handler. This form only works via JavaScript. |
||
473 | '#submit' => array(), |
||
474 | '#ajax' => array( |
||
475 | 'callback' => '::submitEmbedStep', |
||
476 | 'event' => 'click', |
||
477 | ), |
||
478 | ); |
||
479 | |||
480 | return $form; |
||
481 | } |
||
482 | |||
483 | /** |
||
484 | * {@inheritdoc} |
||
485 | */ |
||
486 | public function validateForm(array &$form, FormStateInterface $form_state) { |
||
487 | parent::validateForm($form, $form_state); |
||
488 | |||
489 | if ($form_state->get('step') == 'select') { |
||
490 | $this->validateSelectStep($form, $form_state); |
||
491 | } |
||
492 | elseif ($form_state->get('step') == 'embed') { |
||
493 | $this->validateEmbedStep($form, $form_state); |
||
494 | } |
||
495 | } |
||
496 | |||
497 | /** |
||
498 | * Form validation handler for the entity selection step. |
||
499 | * |
||
500 | * @param array $form |
||
501 | * An associative array containing the structure of the form. |
||
502 | * @param \Drupal\Core\Form\FormStateInterface $form_state |
||
503 | * The current state of the form. |
||
504 | */ |
||
505 | public function validateSelectStep(array $form, FormStateInterface $form_state) { |
||
506 | if ($eb_id = $form_state->getValue(['attributes', 'entity_browser', 'entity-id'])) { |
||
507 | $form_state->setValue(['attributes', 'data-entity-id'], $eb_id); |
||
508 | } |
||
509 | |||
510 | $values = $form_state->getValues(); |
||
511 | |||
512 | $entity_type = $values['attributes']['data-entity-type']; |
||
513 | $id = trim($values['attributes']['data-entity-id']); |
||
514 | if ($entity = $this->loadEntity($entity_type, $id)) { |
||
515 | if (!$entity->access('view')) { |
||
516 | $form_state->setError($form['attributes']['data-entity-id'], $this->t('Unable to access @type entity @id.', array('@type' => $entity_type, '@id' => $id))); |
||
517 | } |
||
518 | else { |
||
519 | if ($uuid = $entity->uuid()) { |
||
520 | $form_state->setValueForElement($form['attributes']['data-entity-uuid'], $uuid); |
||
521 | } |
||
522 | View Code Duplication | else { |
|
|
|||
523 | $form_state->setError($form['attributes']['data-entity-id'], $this->t('Cannot embed @type entity @id because it does not have a UUID.', array('@type' => $entity_type, '@id' => $id))); |
||
524 | } |
||
525 | |||
526 | // Ensure that at least one Entity Embed Display plugin is present |
||
527 | // before proceeding to the next step. Rasie an error otherwise. |
||
528 | $embed_button = $form_state->get('embed_button'); |
||
529 | $display_plugin_options = $this->getDisplayPluginOptions($embed_button, $entity); |
||
530 | // If no plugin is available after taking the intersection, |
||
531 | // raise error. Also log an exception. |
||
532 | if (empty($display_plugin_options)) { |
||
533 | $form_state->setError($form['attributes']['data-entity-id'], $this->t('No display options available for the selected entity. Please select another entity.')); |
||
534 | $this->logger('entity_embed')->warning('No display options available for "@type:" entity "@id" while embedding using button "@button". Please ensure that at least one Entity Embed Display plugin is allowed for this embed button which is available for this entity.', array('@type' => $entity_type, '@id' => $entity->id(), '@button' => $embed_button->id())); |
||
535 | } |
||
536 | } |
||
537 | } |
||
538 | View Code Duplication | else { |
|
539 | $form_state->setError($form['attributes']['data-entity-id'], $this->t('Unable to load @type entity @id.', array('@type' => $entity_type, '@id' => $id))); |
||
540 | } |
||
541 | } |
||
542 | |||
543 | /** |
||
544 | * Form validation handler for the entity embedding step. |
||
545 | * |
||
546 | * @param array $form |
||
547 | * An associative array containing the structure of the form. |
||
548 | * @param \Drupal\Core\Form\FormStateInterface $form_state |
||
549 | * The current state of the form. |
||
550 | */ |
||
551 | public function validateEmbedStep(array $form, FormStateInterface $form_state) { |
||
552 | // Validate configuration forms for the Entity Embed Display plugin used. |
||
553 | $entity_element = $form_state->getValue('attributes'); |
||
554 | $entity = $this->loadEntity($entity_element['data-entity-type'], $entity_element['data-entity-uuid']); |
||
555 | $plugin_id = $entity_element['data-entity-embed-display']; |
||
556 | $plugin_settings = $entity_element['data-entity-embed-settings'] ?: array(); |
||
557 | $display = $this->displayPluginManager()->createInstance($plugin_id, $plugin_settings); |
||
558 | $display->setContextValue('entity', $entity); |
||
559 | $display->setAttributes($entity_element); |
||
560 | $display->validateConfigurationForm($form, $form_state); |
||
561 | } |
||
562 | |||
563 | /** |
||
564 | * {@inheritdoc} |
||
565 | */ |
||
566 | public function submitForm(array &$form, FormStateInterface $form_state) {} |
||
567 | |||
568 | /** |
||
569 | * Form submission handler to update the plugin configuration form. |
||
570 | * |
||
571 | * @param array $form |
||
572 | * The form array. |
||
573 | * @param \Drupal\Core\Form\FormStateInterface $form_state |
||
574 | * The form state. |
||
575 | */ |
||
576 | public function updatePluginConfigurationForm(array &$form, FormStateInterface $form_state) { |
||
577 | return $form['attributes']['data-entity-embed-settings']; |
||
578 | } |
||
579 | |||
580 | /** |
||
581 | * Form submission handler to to another step of the form. |
||
582 | * |
||
583 | * @param array $form |
||
584 | * The form array. |
||
585 | * @param \Drupal\Core\Form\FormStateInterface $form_state |
||
586 | * The form state. |
||
587 | * |
||
588 | * @return \Drupal\Core\Ajax\AjaxResponse |
||
589 | * The ajax response. |
||
590 | */ |
||
591 | public function submitStep(array &$form, FormStateInterface $form_state, $step) { |
||
592 | $response = new AjaxResponse(); |
||
593 | |||
594 | $form_state->set('step', $step); |
||
595 | $form_state->setRebuild(TRUE); |
||
596 | $rebuild_form = $this->formBuilder->rebuildForm('entity_embed_dialog', $form_state, $form); |
||
597 | unset($rebuild_form['#prefix'], $rebuild_form['#suffix']); |
||
598 | $response->addCommand(new HtmlCommand('#entity-embed-dialog-form', $rebuild_form)); |
||
599 | $response->addCommand(new SetDialogTitleCommand('', $rebuild_form['#title'])); |
||
600 | |||
601 | return $response; |
||
602 | } |
||
603 | |||
604 | /** |
||
605 | * Form submission handler for the entity selection step. |
||
606 | * |
||
607 | * On success will send the user to the next step of the form to select the |
||
608 | * embed display settings. On form errors, this will rebuild the form and |
||
609 | * display the error messages. |
||
610 | * |
||
611 | * @param array $form |
||
612 | * The form array. |
||
613 | * @param \Drupal\Core\Form\FormStateInterface $form_state |
||
614 | * The form state. |
||
615 | * |
||
616 | * @return \Drupal\Core\Ajax\AjaxResponse |
||
617 | * The ajax response. |
||
618 | */ |
||
619 | public function submitSelectStep(array &$form, FormStateInterface $form_state) { |
||
620 | $response = new AjaxResponse(); |
||
621 | |||
622 | // Display errors in form, if any. |
||
623 | if ($form_state->hasAnyErrors()) { |
||
624 | unset($form['#prefix'], $form['#suffix']); |
||
625 | $form['status_messages'] = array( |
||
626 | '#type' => 'status_messages', |
||
627 | '#weight' => -10, |
||
628 | ); |
||
629 | $response->addCommand(new HtmlCommand('#entity-embed-dialog-form', $form)); |
||
630 | } |
||
631 | else { |
||
632 | $form_state->set('step', !empty($this->entityBrowserSettings['display_review']) ? 'review' : 'embed'); |
||
633 | $form_state->setRebuild(TRUE); |
||
634 | $rebuild_form = $this->formBuilder->rebuildForm('entity_embed_dialog', $form_state, $form); |
||
635 | unset($rebuild_form['#prefix'], $rebuild_form['#suffix']); |
||
636 | $response->addCommand(new HtmlCommand('#entity-embed-dialog-form', $rebuild_form)); |
||
637 | $response->addCommand(new SetDialogTitleCommand('', $rebuild_form['#title'])); |
||
638 | } |
||
639 | |||
640 | return $response; |
||
641 | } |
||
642 | |||
643 | /** |
||
644 | * Submit and show select step after submit. |
||
645 | * |
||
646 | * @param array $form |
||
647 | * The form array. |
||
648 | * @param \Drupal\Core\Form\FormStateInterface $form_state |
||
649 | * The form state. |
||
650 | * |
||
651 | * @return \Drupal\Core\Ajax\AjaxResponse |
||
652 | * The ajax response. |
||
653 | */ |
||
654 | public function submitAndShowSelect(array &$form, FormStateInterface $form_state) { |
||
655 | return $this->submitStep($form, $form_state, 'select'); |
||
656 | } |
||
657 | |||
658 | /** |
||
659 | * Submit and show review step after submit. |
||
660 | * |
||
661 | * @param array $form |
||
662 | * The form array. |
||
663 | * @param \Drupal\Core\Form\FormStateInterface $form_state |
||
664 | * The form state. |
||
665 | * |
||
666 | * @return \Drupal\Core\Ajax\AjaxResponse |
||
667 | * The ajax response. |
||
668 | */ |
||
669 | public function submitAndShowReview(array &$form, FormStateInterface $form_state) { |
||
670 | return $this->submitStep($form, $form_state, 'review'); |
||
671 | } |
||
672 | |||
673 | /** |
||
674 | * Submit and show embed step after submit. |
||
675 | * |
||
676 | * @param array $form |
||
677 | * The form array. |
||
678 | * @param \Drupal\Core\Form\FormStateInterface $form_state |
||
679 | * The form state. |
||
680 | * |
||
681 | * @return \Drupal\Core\Ajax\AjaxResponse |
||
682 | * The ajax response. |
||
683 | */ |
||
684 | public function submitAndShowEmbed(array $form, FormStateInterface $form_state) { |
||
687 | |||
688 | /** |
||
689 | * Form submission handler for the entity embedding step. |
||
690 | * |
||
691 | * On success this will submit the command to save the embedded entity with |
||
692 | * the configured display settings to the WYSIWYG element, and then close the |
||
693 | * modal dialog. On form errors, this will rebuild the form and display the |
||
694 | * error messages. |
||
695 | * |
||
696 | * @param array $form |
||
697 | * An associative array containing the structure of the form. |
||
698 | * @param FormStateInterface $form_state |
||
699 | * An associative array containing the current state of the form. |
||
700 | * |
||
701 | * @return \Drupal\Core\Ajax\AjaxResponse |
||
702 | * The ajax response. |
||
703 | */ |
||
704 | public function submitEmbedStep(array &$form, FormStateInterface $form_state) { |
||
742 | |||
743 | /** |
||
744 | * Form element validation handler; Escapes the value an element. |
||
745 | * |
||
746 | * This should be used for any element in the embed form which may contain |
||
747 | * HTML that should be serialized as an attribute element on the embed. |
||
748 | */ |
||
749 | public static function escapeValue($element, FormStateInterface $form_state) { |
||
754 | |||
755 | /** |
||
756 | * Returns the allowed Entity Embed Display plugins given an embed button and |
||
757 | * an entity. |
||
758 | * |
||
759 | * @param \Drupal\embed\EmbedButtonInterface $embed_button |
||
760 | * The embed button. |
||
761 | * @param \Drupal\Core\Entity\EntityInterface $entity |
||
762 | * The entity. |
||
763 | * |
||
764 | * @return array |
||
765 | * List of allowed Entity Embed Display plugins. |
||
766 | */ |
||
767 | public function getDisplayPluginOptions(EmbedButtonInterface $embed_button, EntityInterface $entity) { |
||
777 | |||
778 | /** |
||
779 | * Registers JS callback that gets entities from entity browser and updates |
||
780 | * form values accordingly. |
||
781 | */ |
||
782 | public function registerJSCallback(RegisterJSCallbacks $event) { |
||
787 | |||
788 | /** |
||
789 | * Load the current entity browser and its settings from the form state. |
||
790 | * |
||
791 | * @param \Drupal\Core\Form\FormStateInterface $form_state |
||
792 | */ |
||
793 | protected function loadEntityBrowser(FormStateInterface $form_state) { |
||
805 | |||
806 | } |
||
807 |
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.