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 |
||
| 31 | class EntityEmbedDialog extends FormBase { |
||
| 32 | |||
| 33 | /** |
||
| 34 | * The entity embed display manager. |
||
| 35 | * |
||
| 36 | * @var \Drupal\entity_embed\EntityEmbedDisplay\EntityEmbedDisplayManager |
||
| 37 | */ |
||
| 38 | protected $entityEmbedDisplayManager; |
||
| 39 | |||
| 40 | /** |
||
| 41 | * The form builder. |
||
| 42 | * |
||
| 43 | * @var \Drupal\Core\Form\FormBuilderInterface |
||
| 44 | */ |
||
| 45 | protected $formBuilder; |
||
| 46 | |||
| 47 | /** |
||
| 48 | * The entity type manager service. |
||
| 49 | * |
||
| 50 | * @var \Drupal\Core\Entity\EntityTypeManagerInterface |
||
| 51 | */ |
||
| 52 | protected $entityTypeManager; |
||
| 53 | |||
| 54 | /** |
||
| 55 | * Event dispatcher service. |
||
| 56 | * |
||
| 57 | * @var \Symfony\Component\EventDispatcher\EventDispatcherInterface |
||
| 58 | */ |
||
| 59 | protected $eventDispatcher; |
||
| 60 | |||
| 61 | /** |
||
| 62 | * The entity browser. |
||
| 63 | * |
||
| 64 | * @var \Drupal\entity_browser\EntityBrowserInterface |
||
| 65 | */ |
||
| 66 | protected $entityBrowser; |
||
| 67 | |||
| 68 | /** |
||
| 69 | * The entity field manager. |
||
| 70 | * |
||
| 71 | * @var \Drupal\Core\Entity\EntityFieldManager |
||
| 72 | */ |
||
| 73 | protected $entityFieldManager; |
||
| 74 | |||
| 75 | /** |
||
| 76 | * The module handler service. |
||
| 77 | * |
||
| 78 | * @var \Drupal\Core\Extension\ModuleHandlerInterface |
||
| 79 | */ |
||
| 80 | protected $moduleHandler; |
||
| 81 | |||
| 82 | /** |
||
| 83 | * The entity browser settings from the entity embed button. |
||
| 84 | */ |
||
| 85 | protected $entityBrowserSettings = []; |
||
| 86 | |||
| 87 | /** |
||
| 88 | * Constructs a EntityEmbedDialog object. |
||
| 89 | * |
||
| 90 | * @param \Drupal\entity_embed\EntityEmbedDisplay\EntityEmbedDisplayManager $entity_embed_display_manager |
||
| 91 | * The Module Handler. |
||
| 92 | * @param \Drupal\Core\Form\FormBuilderInterface $form_builder |
||
| 93 | * The Form Builder. |
||
| 94 | * @param \Drupal\Core\Entity\EntityTypeManagerInterface $entity_type_manager |
||
| 95 | * The entity type manager service. |
||
| 96 | * @param \Symfony\Component\EventDispatcher\EventDispatcherInterface $event_dispatcher |
||
| 97 | * Event dispatcher service. |
||
| 98 | * @param \Drupal\Core\Entity\EntityFieldManagerInterface $entity_field_manager |
||
| 99 | * The entity field manager. |
||
| 100 | * @param \Drupal\Core\Extension\ModuleHandlerInterface $module_handler |
||
| 101 | * The module handler. |
||
| 102 | */ |
||
| 103 | public function __construct(EntityEmbedDisplayManager $entity_embed_display_manager, FormBuilderInterface $form_builder, EntityTypeManagerInterface $entity_type_manager, EventDispatcherInterface $event_dispatcher, EntityFieldManagerInterface $entity_field_manager, ModuleHandlerInterface $module_handler) { |
||
| 104 | $this->entityEmbedDisplayManager = $entity_embed_display_manager; |
||
| 105 | $this->formBuilder = $form_builder; |
||
| 106 | $this->entityTypeManager = $entity_type_manager; |
||
| 107 | $this->eventDispatcher = $event_dispatcher; |
||
| 108 | $this->entityFieldManager = $entity_field_manager; |
||
|
|
|||
| 109 | $this->moduleHandler = $module_handler; |
||
| 110 | } |
||
| 111 | |||
| 112 | /** |
||
| 113 | * {@inheritdoc} |
||
| 114 | */ |
||
| 115 | public static function create(ContainerInterface $container) { |
||
| 116 | return new static( |
||
| 117 | $container->get('plugin.manager.entity_embed.display'), |
||
| 118 | $container->get('form_builder'), |
||
| 119 | $container->get('entity_type.manager'), |
||
| 120 | $container->get('event_dispatcher'), |
||
| 121 | $container->get('entity_field.manager'), |
||
| 122 | $container->get('module_handler') |
||
| 123 | ); |
||
| 124 | } |
||
| 125 | |||
| 126 | /** |
||
| 127 | * {@inheritdoc} |
||
| 128 | */ |
||
| 129 | public function getFormId() { |
||
| 132 | |||
| 133 | /** |
||
| 134 | * {@inheritdoc} |
||
| 135 | * |
||
| 136 | * @param \Drupal\editor\EditorInterface $editor |
||
| 137 | * The editor to which this dialog corresponds. |
||
| 138 | * @param \Drupal\embed\EmbedButtonInterface $embed_button |
||
| 139 | * The URL button to which this dialog corresponds. |
||
| 140 | */ |
||
| 141 | public function buildForm(array $form, FormStateInterface $form_state, EditorInterface $editor = NULL, EmbedButtonInterface $embed_button = NULL) { |
||
| 142 | $values = $form_state->getValues(); |
||
| 143 | $input = $form_state->getUserInput(); |
||
| 144 | // Set embed button element in form state, so that it can be used later in |
||
| 145 | // validateForm() function. |
||
| 146 | $form_state->set('embed_button', $embed_button); |
||
| 147 | $form_state->set('editor', $editor); |
||
| 148 | // Initialize entity element with form attributes, if present. |
||
| 149 | $entity_element = empty($values['attributes']) ? array() : $values['attributes']; |
||
| 150 | $entity_element += empty($input['attributes']) ? array() : $input['attributes']; |
||
| 151 | // The default values are set directly from \Drupal::request()->request, |
||
| 152 | // provided by the editor plugin opening the dialog. |
||
| 153 | if (!$form_state->get('entity_element')) { |
||
| 154 | $form_state->set('entity_element', isset($input['editor_object']) ? $input['editor_object'] : array()); |
||
| 155 | } |
||
| 156 | $entity_element += $form_state->get('entity_element'); |
||
| 157 | $entity_element += [ |
||
| 158 | 'data-entity-type' => $embed_button->getTypeSetting('entity_type'), |
||
| 159 | 'data-entity-uuid' => '', |
||
| 160 | 'data-entity-embed-display' => 'entity_reference:entity_reference_entity_view', |
||
| 161 | 'data-entity-embed-display-settings' => isset($form_state->get('entity_element')['data-entity-embed-settings']) ? $form_state->get('entity_element')['data-entity-embed-settings'] : [], |
||
| 162 | ]; |
||
| 163 | $form_state->set('entity_element', $entity_element); |
||
| 164 | $entity = $this->entityTypeManager->getStorage($entity_element['data-entity-type']) |
||
| 165 | ->loadByProperties(['uuid' => $entity_element['data-entity-uuid']]); |
||
| 166 | $form_state->set('entity', current($entity) ?: NULL); |
||
| 167 | |||
| 168 | if (!$form_state->get('step')) { |
||
| 169 | // If an entity has been selected, then always skip to the embed options. |
||
| 170 | if ($form_state->get('entity')) { |
||
| 171 | $form_state->set('step', 'embed'); |
||
| 172 | } |
||
| 173 | else { |
||
| 174 | $form_state->set('step', 'select'); |
||
| 175 | } |
||
| 176 | } |
||
| 177 | |||
| 178 | $form['#tree'] = TRUE; |
||
| 179 | $form['#attached']['library'][] = 'editor/drupal.editor.dialog'; |
||
| 180 | $form['#attached']['library'][] = 'entity_embed/drupal.entity_embed.dialog'; |
||
| 181 | $form['#prefix'] = '<div id="entity-embed-dialog-form">'; |
||
| 182 | $form['#suffix'] = '</div>'; |
||
| 183 | $form['#attributes']['class'][] = 'entity-embed-dialog-step--' . $form_state->get('step'); |
||
| 184 | |||
| 185 | $this->loadEntityBrowser($form_state); |
||
| 186 | |||
| 187 | if ($form_state->get('step') == 'select') { |
||
| 188 | $form = $this->buildSelectStep($form, $form_state); |
||
| 189 | } |
||
| 190 | elseif ($form_state->get('step') == 'review') { |
||
| 191 | $form = $this->buildReviewStep($form, $form_state); |
||
| 192 | } |
||
| 193 | elseif ($form_state->get('step') == 'embed') { |
||
| 194 | $form = $this->buildEmbedStep($form, $form_state); |
||
| 195 | } |
||
| 196 | |||
| 197 | return $form; |
||
| 198 | } |
||
| 199 | |||
| 200 | /** |
||
| 201 | * Form constructor for the entity selection step. |
||
| 202 | * |
||
| 203 | * @param array $form |
||
| 204 | * An associative array containing the structure of the form. |
||
| 205 | * @param \Drupal\Core\Form\FormStateInterface $form_state |
||
| 206 | * The current state of the form. |
||
| 207 | * |
||
| 208 | * @return array |
||
| 209 | * The form structure. |
||
| 210 | */ |
||
| 211 | public function buildSelectStep(array &$form, FormStateInterface $form_state) { |
||
| 212 | // Entity element is calculated on every AJAX request/submit. See ::buildForm(). |
||
| 213 | $entity_element = $form_state->get('entity_element'); |
||
| 214 | /** @var \Drupal\embed\EmbedButtonInterface $embed_button */ |
||
| 215 | $embed_button = $form_state->get('embed_button'); |
||
| 216 | $entity = $form_state->get('entity'); |
||
| 217 | |||
| 218 | $form['attributes']['data-entity-type'] = array( |
||
| 219 | '#type' => 'value', |
||
| 220 | '#value' => $entity_element['data-entity-type'], |
||
| 221 | ); |
||
| 222 | |||
| 223 | $label = $this->t('Label'); |
||
| 224 | // Attempt to display a better label if we can by getting it from |
||
| 225 | // the label field definition. |
||
| 226 | $entity_type = $this->entityTypeManager->getDefinition($entity_element['data-entity-type']); |
||
| 227 | if ($entity_type->isSubclassOf('\Drupal\Core\Entity\FieldableEntityInterface') && $entity_type->hasKey('label')) { |
||
| 228 | $field_definitions = $this->entityFieldManager->getBaseFieldDefinitions($entity_type->id()); |
||
| 229 | if (isset($field_definitions[$entity_type->getKey('label')])) { |
||
| 230 | $label = $field_definitions[$entity_type->getKey('label')]->getLabel(); |
||
| 231 | } |
||
| 232 | } |
||
| 233 | |||
| 234 | $form['#title'] = $this->t('Select @type to embed', array('@type' => $entity_type->getLowercaseLabel())); |
||
| 235 | |||
| 236 | if ($this->entityBrowser) { |
||
| 237 | $this->eventDispatcher->addListener(Events::REGISTER_JS_CALLBACKS, [$this, 'registerJSCallback']); |
||
| 238 | $form['entity_browser'] = [ |
||
| 239 | '#type' => 'entity_browser', |
||
| 240 | '#entity_browser' => $this->entityBrowser->id(), |
||
| 241 | '#cardinality' => 1, |
||
| 242 | '#entity_browser_validators' => [ |
||
| 243 | 'entity_type' => ['type' => $entity_element['data-entity-type']], |
||
| 244 | ], |
||
| 245 | ]; |
||
| 246 | } |
||
| 247 | else { |
||
| 248 | $form['entity_id'] = array( |
||
| 249 | '#type' => 'entity_autocomplete', |
||
| 250 | '#target_type' => $entity_element['data-entity-type'], |
||
| 251 | '#title' => $label, |
||
| 252 | '#default_value' => $entity, |
||
| 253 | '#required' => TRUE, |
||
| 254 | '#description' => $this->t('Type label and pick the right one from suggestions. Note that the unique ID will be saved.'), |
||
| 255 | ); |
||
| 256 | if ($bundles = $embed_button->getTypeSetting('bundles')) { |
||
| 257 | $form['entity_id']['#selection_settings']['target_bundles'] = $bundles; |
||
| 258 | } |
||
| 259 | } |
||
| 260 | |||
| 261 | $form['attributes']['data-entity-uuid'] = array( |
||
| 262 | '#type' => 'value', |
||
| 263 | '#title' => $entity_element['data-entity-uuid'], |
||
| 264 | ); |
||
| 265 | $form['actions'] = array( |
||
| 266 | '#type' => 'actions', |
||
| 267 | ); |
||
| 268 | |||
| 269 | $form['actions']['save_modal'] = array( |
||
| 270 | '#type' => 'submit', |
||
| 271 | '#value' => $this->t('Next'), |
||
| 272 | '#button_type' => 'primary', |
||
| 273 | // No regular submit-handler. This form only works via JavaScript. |
||
| 274 | '#submit' => array(), |
||
| 275 | '#ajax' => array( |
||
| 276 | 'callback' => '::submitSelectStep', |
||
| 277 | 'event' => 'click', |
||
| 278 | ), |
||
| 279 | '#attributes' => [ |
||
| 280 | 'class' => [ |
||
| 281 | 'js-button-next', |
||
| 282 | ], |
||
| 283 | ], |
||
| 284 | ); |
||
| 285 | |||
| 286 | return $form; |
||
| 287 | } |
||
| 288 | |||
| 289 | /** |
||
| 290 | * Form constructor for the entity review step. |
||
| 291 | * |
||
| 292 | * @param array $form |
||
| 293 | * An associative array containing the structure of the form. |
||
| 294 | * @param \Drupal\Core\Form\FormStateInterface $form_state |
||
| 295 | * The current state of the form. |
||
| 296 | * |
||
| 297 | * @return array |
||
| 298 | * The form structure. |
||
| 299 | */ |
||
| 300 | public function buildReviewStep(array &$form, FormStateInterface $form_state) { |
||
| 301 | /** @var \Drupal\Core\Entity\EntityInterface $entity */ |
||
| 302 | $entity = $form_state->get('entity'); |
||
| 303 | |||
| 304 | $form['#title'] = $this->t('Review selected @type', array('@type' => $entity->getEntityType()->getLowercaseLabel())); |
||
| 305 | |||
| 306 | $form['selection'] = [ |
||
| 307 | '#markup' => $entity->label(), |
||
| 308 | ]; |
||
| 309 | |||
| 310 | $form['actions'] = array( |
||
| 311 | '#type' => 'actions', |
||
| 312 | ); |
||
| 313 | |||
| 314 | $form['actions']['back'] = array( |
||
| 315 | '#type' => 'submit', |
||
| 316 | '#value' => $this->t('Replace selection'), |
||
| 317 | // No regular submit-handler. This form only works via JavaScript. |
||
| 318 | '#submit' => array(), |
||
| 319 | '#ajax' => array( |
||
| 320 | 'callback' => '::submitAndShowSelect', |
||
| 321 | 'event' => 'click', |
||
| 322 | ), |
||
| 323 | ); |
||
| 324 | |||
| 325 | $form['actions']['save_modal'] = array( |
||
| 326 | '#type' => 'submit', |
||
| 327 | '#value' => $this->t('Next'), |
||
| 328 | '#button_type' => 'primary', |
||
| 329 | // No regular submit-handler. This form only works via JavaScript. |
||
| 330 | '#submit' => array(), |
||
| 331 | '#ajax' => array( |
||
| 332 | 'callback' => '::submitAndShowEmbed', |
||
| 333 | 'event' => 'click', |
||
| 334 | ), |
||
| 335 | '#attributes' => [ |
||
| 336 | 'class' => [ |
||
| 337 | 'js-button-next', |
||
| 338 | ], |
||
| 339 | ], |
||
| 340 | ); |
||
| 341 | |||
| 342 | return $form; |
||
| 343 | } |
||
| 344 | |||
| 345 | /** |
||
| 346 | * Form constructor for the entity embedding step. |
||
| 347 | * |
||
| 348 | * @param array $form |
||
| 349 | * An associative array containing the structure of the form. |
||
| 350 | * @param \Drupal\Core\Form\FormStateInterface $form_state |
||
| 351 | * The current state of the form. |
||
| 352 | * |
||
| 353 | * @return array |
||
| 354 | * The form structure. |
||
| 355 | */ |
||
| 356 | public function buildEmbedStep(array $form, FormStateInterface $form_state) { |
||
| 357 | // Entity element is calculated on every AJAX request/submit. See ::buildForm(). |
||
| 358 | $entity_element = $form_state->get('entity_element'); |
||
| 359 | /** @var \Drupal\embed\EmbedButtonInterface $embed_button */ |
||
| 360 | $embed_button = $form_state->get('embed_button'); |
||
| 361 | /** @var \Drupal\editor\EditorInterface $editor */ |
||
| 362 | $editor = $form_state->get('editor'); |
||
| 363 | /** @var \Drupal\Core\Entity\EntityInterface $entity */ |
||
| 364 | $entity = $form_state->get('entity'); |
||
| 365 | $values = $form_state->getValues(); |
||
| 366 | |||
| 367 | $form['#title'] = $this->t('Embed @type', array('@type' => $entity->getEntityType()->getLowercaseLabel())); |
||
| 368 | |||
| 369 | $entity_label = ''; |
||
| 370 | try { |
||
| 371 | $entity_label = $entity->link(); |
||
| 372 | } |
||
| 373 | catch (\Exception $e) { |
||
| 374 | // Construct markup of the link to the entity manually if link() fails. |
||
| 375 | // @see https://www.drupal.org/node/2402533 |
||
| 376 | $entity_label = '<a href="' . $entity->url() . '">' . $entity->label() . '</a>'; |
||
| 377 | } |
||
| 378 | |||
| 379 | $form['entity'] = array( |
||
| 380 | '#type' => 'item', |
||
| 381 | '#title' => $this->t('Selected entity'), |
||
| 382 | '#markup' => $entity_label, |
||
| 383 | ); |
||
| 384 | $form['attributes']['data-entity-type'] = array( |
||
| 385 | '#type' => 'hidden', |
||
| 386 | '#value' => $entity_element['data-entity-type'], |
||
| 387 | ); |
||
| 388 | $form['attributes']['data-entity-uuid'] = array( |
||
| 389 | '#type' => 'hidden', |
||
| 390 | '#value' => $entity_element['data-entity-uuid'], |
||
| 391 | ); |
||
| 392 | |||
| 393 | // Build the list of allowed Entity Embed Display plugins. |
||
| 394 | $display_plugin_options = $this->getDisplayPluginOptions($embed_button, $entity); |
||
| 395 | |||
| 396 | // If the currently selected display is not in the available options, |
||
| 397 | // use the first from the list instead. This can happen if an alter |
||
| 398 | // hook customizes the list based on the entity. |
||
| 399 | if (!isset($display_plugin_options[$entity_element['data-entity-embed-display']])) { |
||
| 400 | $entity_element['data-entity-embed-display'] = key($display_plugin_options); |
||
| 401 | } |
||
| 402 | |||
| 403 | // The default Entity Embed Display plugin has been deprecated by the |
||
| 404 | // rendered entity field formatter. |
||
| 405 | if ($entity_element['data-entity-embed-display'] === 'default') { |
||
| 406 | $entity_element['data-entity-embed-display'] = 'entity_reference:entity_reference_entity_view'; |
||
| 407 | } |
||
| 408 | |||
| 409 | $form['attributes']['data-entity-embed-display'] = array( |
||
| 410 | '#type' => 'select', |
||
| 411 | '#title' => $this->t('Display as'), |
||
| 412 | '#options' => $display_plugin_options, |
||
| 413 | '#default_value' => $entity_element['data-entity-embed-display'], |
||
| 414 | '#required' => TRUE, |
||
| 415 | '#ajax' => array( |
||
| 416 | 'callback' => '::updatePluginConfigurationForm', |
||
| 417 | 'wrapper' => 'data-entity-embed-display-settings-wrapper', |
||
| 418 | 'effect' => 'fade', |
||
| 419 | ), |
||
| 420 | // Hide the selection if only one option is available. |
||
| 421 | '#access' => count($display_plugin_options) > 1, |
||
| 422 | ); |
||
| 423 | $form['attributes']['data-entity-embed-display-settings'] = array( |
||
| 424 | '#type' => 'container', |
||
| 425 | '#prefix' => '<div id="data-entity-embed-display-settings-wrapper">', |
||
| 426 | '#suffix' => '</div>', |
||
| 427 | ); |
||
| 428 | $form['attributes']['data-embed-button'] = array( |
||
| 429 | '#type' => 'value', |
||
| 430 | '#value' => $embed_button->id(), |
||
| 431 | ); |
||
| 432 | $plugin_id = !empty($values['attributes']['data-entity-embed-display']) ? $values['attributes']['data-entity-embed-display'] : $entity_element['data-entity-embed-display']; |
||
| 433 | if (!empty($plugin_id)) { |
||
| 434 | if (is_string($entity_element['data-entity-embed-display-settings'])) { |
||
| 435 | $entity_element['data-entity-embed-display-settings'] = Json::decode($entity_element['data-entity-embed-display-settings']); |
||
| 436 | } |
||
| 437 | $display = $this->entityEmbedDisplayManager->createInstance($plugin_id, $entity_element['data-entity-embed-display-settings']); |
||
| 438 | $display->setContextValue('entity', $entity); |
||
| 439 | $display->setAttributes($entity_element); |
||
| 440 | $form['attributes']['data-entity-embed-display-settings'] += $display->buildConfigurationForm($form, $form_state); |
||
| 441 | } |
||
| 442 | |||
| 443 | // When Drupal core's filter_align is being used, the text editor may |
||
| 444 | // offer the ability to change the alignment. |
||
| 445 | if ($editor->getFilterFormat()->filters('filter_align')->status) { |
||
| 446 | $form['attributes']['data-align'] = array( |
||
| 447 | '#title' => $this->t('Align'), |
||
| 448 | '#type' => 'radios', |
||
| 449 | '#options' => array( |
||
| 450 | '' => $this->t('None'), |
||
| 451 | 'left' => $this->t('Left'), |
||
| 452 | 'center' => $this->t('Center'), |
||
| 453 | 'right' => $this->t('Right'), |
||
| 454 | ), |
||
| 455 | '#default_value' => isset($entity_element['data-align']) ? $entity_element['data-align'] : '', |
||
| 456 | '#wrapper_attributes' => array('class' => array('container-inline')), |
||
| 457 | '#attributes' => array('class' => array('container-inline')), |
||
| 458 | ); |
||
| 459 | } |
||
| 460 | |||
| 461 | // When Drupal core's filter_caption is being used, the text editor may |
||
| 462 | // offer the ability to add a caption. |
||
| 463 | if ($editor->getFilterFormat()->filters('filter_caption')->status) { |
||
| 464 | $form['attributes']['data-caption'] = array( |
||
| 465 | '#title' => $this->t('Caption'), |
||
| 466 | '#type' => 'textfield', |
||
| 467 | '#default_value' => isset($entity_element['data-caption']) ? Html::decodeEntities($entity_element['data-caption']) : '', |
||
| 468 | '#element_validate' => array('::escapeValue'), |
||
| 469 | ); |
||
| 470 | } |
||
| 471 | |||
| 472 | $form['actions'] = array( |
||
| 473 | '#type' => 'actions', |
||
| 474 | ); |
||
| 475 | $form['actions']['back'] = array( |
||
| 476 | '#type' => 'submit', |
||
| 477 | '#value' => $this->t('Back'), |
||
| 478 | // No regular submit-handler. This form only works via JavaScript. |
||
| 479 | '#submit' => array(), |
||
| 480 | '#ajax' => array( |
||
| 481 | 'callback' => !empty($this->entityBrowserSettings['display_review']) ? '::submitAndShowReview' : '::submitAndShowSelect', |
||
| 482 | 'event' => 'click', |
||
| 483 | ), |
||
| 484 | ); |
||
| 485 | $form['actions']['save_modal'] = array( |
||
| 486 | '#type' => 'submit', |
||
| 487 | '#value' => $this->t('Embed'), |
||
| 488 | '#button_type' => 'primary', |
||
| 489 | // No regular submit-handler. This form only works via JavaScript. |
||
| 490 | '#submit' => array(), |
||
| 491 | '#ajax' => array( |
||
| 492 | 'callback' => '::submitEmbedStep', |
||
| 493 | 'event' => 'click', |
||
| 494 | ), |
||
| 495 | ); |
||
| 496 | |||
| 497 | return $form; |
||
| 498 | } |
||
| 499 | |||
| 500 | /** |
||
| 501 | * {@inheritdoc} |
||
| 502 | */ |
||
| 503 | public function validateForm(array &$form, FormStateInterface $form_state) { |
||
| 504 | parent::validateForm($form, $form_state); |
||
| 505 | |||
| 506 | if ($form_state->get('step') == 'select') { |
||
| 507 | $this->validateSelectStep($form, $form_state); |
||
| 508 | } |
||
| 509 | elseif ($form_state->get('step') == 'embed') { |
||
| 510 | $this->validateEmbedStep($form, $form_state); |
||
| 511 | } |
||
| 512 | } |
||
| 513 | |||
| 514 | /** |
||
| 515 | * Form validation handler for the entity selection step. |
||
| 516 | * |
||
| 517 | * @param array $form |
||
| 518 | * An associative array containing the structure of the form. |
||
| 519 | * @param \Drupal\Core\Form\FormStateInterface $form_state |
||
| 520 | * The current state of the form. |
||
| 521 | */ |
||
| 522 | public function validateSelectStep(array $form, FormStateInterface $form_state) { |
||
| 523 | if ($form_state->hasValue(['entity_browser', 'entities'])) { |
||
| 524 | $id = $form_state->getValue(['entity_browser', 'entities', 0])->id(); |
||
| 525 | $element = $form['entity_browser']; |
||
| 526 | } |
||
| 527 | else { |
||
| 528 | $id = trim($form_state->getValue(['entity_id'])); |
||
| 529 | $element = $form['entity_id']; |
||
| 530 | } |
||
| 531 | |||
| 532 | $entity_type = $form_state->getValue(['attributes', 'data-entity-type']); |
||
| 533 | |||
| 534 | if ($entity = $this->entityTypeManager->getStorage($entity_type)->load($id)) { |
||
| 535 | if (!$entity->access('view')) { |
||
| 536 | $form_state->setError($element, $this->t('Unable to access @type entity @id.', array('@type' => $entity_type, '@id' => $id))); |
||
| 537 | } |
||
| 538 | else { |
||
| 539 | if ($uuid = $entity->uuid()) { |
||
| 540 | $form_state->setValueForElement($form['attributes']['data-entity-uuid'], $uuid); |
||
| 541 | } |
||
| 542 | else { |
||
| 543 | $form_state->setError($element, $this->t('Cannot embed @type entity @id because it does not have a UUID.', array('@type' => $entity_type, '@id' => $id))); |
||
| 544 | } |
||
| 545 | |||
| 546 | // Ensure that at least one Entity Embed Display plugin is present |
||
| 547 | // before proceeding to the next step. Raise an error otherwise. |
||
| 548 | $embed_button = $form_state->get('embed_button'); |
||
| 549 | $display_plugin_options = $this->getDisplayPluginOptions($embed_button, $entity); |
||
| 550 | // If no plugin is available after taking the intersection, raise error. |
||
| 551 | // Also log an exception. |
||
| 552 | if (empty($display_plugin_options)) { |
||
| 553 | $form_state->setError($element, $this->t('No display options available for the selected entity. Please select another entity.')); |
||
| 554 | $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())); |
||
| 555 | } |
||
| 556 | } |
||
| 557 | } |
||
| 558 | else { |
||
| 559 | $form_state->setError($element, $this->t('Unable to load @type entity @id.', array('@type' => $entity_type, '@id' => $id))); |
||
| 560 | } |
||
| 561 | } |
||
| 562 | |||
| 563 | /** |
||
| 564 | * Form validation handler for the entity embedding step. |
||
| 565 | * |
||
| 566 | * @param array $form |
||
| 567 | * An associative array containing the structure of the form. |
||
| 568 | * @param \Drupal\Core\Form\FormStateInterface $form_state |
||
| 569 | * The current state of the form. |
||
| 570 | */ |
||
| 571 | public function validateEmbedStep(array $form, FormStateInterface $form_state) { |
||
| 572 | // Validate configuration forms for the Entity Embed Display plugin used. |
||
| 573 | $entity_element = $form_state->getValue('attributes'); |
||
| 574 | $entity = $this->entityTypeManager->getStorage($entity_element['data-entity-type']) |
||
| 575 | ->loadByProperties(['uuid' => $entity_element['data-entity-uuid']]); |
||
| 576 | $entity = current($entity) ?: NULL; |
||
| 577 | $plugin_id = $entity_element['data-entity-embed-display']; |
||
| 578 | $plugin_settings = !empty($entity_element['data-entity-embed-display-settings']) ? $entity_element['data-entity-embed-display-settings'] : array(); |
||
| 579 | $display = $this->entityEmbedDisplayManager->createInstance($plugin_id, $plugin_settings); |
||
| 580 | $display->setContextValue('entity', $entity); |
||
| 581 | $display->setAttributes($entity_element); |
||
| 582 | $display->validateConfigurationForm($form, $form_state); |
||
| 583 | } |
||
| 584 | |||
| 585 | /** |
||
| 586 | * {@inheritdoc} |
||
| 587 | */ |
||
| 588 | public function submitForm(array &$form, FormStateInterface $form_state) {} |
||
| 589 | |||
| 590 | /** |
||
| 591 | * Form submission handler to update the plugin configuration form. |
||
| 592 | * |
||
| 593 | * @param array $form |
||
| 594 | * The form array. |
||
| 595 | * @param \Drupal\Core\Form\FormStateInterface $form_state |
||
| 596 | * The form state. |
||
| 597 | */ |
||
| 598 | public function updatePluginConfigurationForm(array &$form, FormStateInterface $form_state) { |
||
| 601 | |||
| 602 | /** |
||
| 603 | * Form submission handler to to another step of the form. |
||
| 604 | * |
||
| 605 | * @param array $form |
||
| 606 | * The form array. |
||
| 607 | * @param \Drupal\Core\Form\FormStateInterface $form_state |
||
| 608 | * The form state. |
||
| 609 | * |
||
| 610 | * @return \Drupal\Core\Ajax\AjaxResponse |
||
| 611 | * The ajax response. |
||
| 612 | */ |
||
| 613 | public function submitStep(array &$form, FormStateInterface $form_state, $step) { |
||
| 625 | |||
| 626 | /** |
||
| 627 | * Form submission handler for the entity selection step. |
||
| 628 | * |
||
| 629 | * On success will send the user to the next step of the form to select the |
||
| 630 | * embed display settings. On form errors, this will rebuild the form and |
||
| 631 | * display the error messages. |
||
| 632 | * |
||
| 633 | * @param array $form |
||
| 634 | * The form array. |
||
| 635 | * @param \Drupal\Core\Form\FormStateInterface $form_state |
||
| 636 | * The form state. |
||
| 637 | * |
||
| 638 | * @return \Drupal\Core\Ajax\AjaxResponse |
||
| 639 | * The ajax response. |
||
| 640 | */ |
||
| 641 | public function submitSelectStep(array &$form, FormStateInterface $form_state) { |
||
| 664 | |||
| 665 | /** |
||
| 666 | * Submit and show select step after submit. |
||
| 667 | * |
||
| 668 | * @param array $form |
||
| 669 | * The form array. |
||
| 670 | * @param \Drupal\Core\Form\FormStateInterface $form_state |
||
| 671 | * The form state. |
||
| 672 | * |
||
| 673 | * @return \Drupal\Core\Ajax\AjaxResponse |
||
| 674 | * The ajax response. |
||
| 675 | */ |
||
| 676 | public function submitAndShowSelect(array &$form, FormStateInterface $form_state) { |
||
| 679 | |||
| 680 | /** |
||
| 681 | * Submit and show review step after submit. |
||
| 682 | * |
||
| 683 | * @param array $form |
||
| 684 | * The form array. |
||
| 685 | * @param \Drupal\Core\Form\FormStateInterface $form_state |
||
| 686 | * The form state. |
||
| 687 | * |
||
| 688 | * @return \Drupal\Core\Ajax\AjaxResponse |
||
| 689 | * The ajax response. |
||
| 690 | */ |
||
| 691 | public function submitAndShowReview(array &$form, FormStateInterface $form_state) { |
||
| 694 | |||
| 695 | /** |
||
| 696 | * Submit and show embed step after submit. |
||
| 697 | * |
||
| 698 | * @param array $form |
||
| 699 | * The form array. |
||
| 700 | * @param \Drupal\Core\Form\FormStateInterface $form_state |
||
| 701 | * The form state. |
||
| 702 | * |
||
| 703 | * @return \Drupal\Core\Ajax\AjaxResponse |
||
| 704 | * The ajax response. |
||
| 705 | */ |
||
| 706 | public function submitAndShowEmbed(array $form, FormStateInterface $form_state) { |
||
| 709 | |||
| 710 | /** |
||
| 711 | * Form submission handler for the entity embedding step. |
||
| 712 | * |
||
| 713 | * On success this will submit the command to save the embedded entity with |
||
| 714 | * the configured display settings to the WYSIWYG element, and then close the |
||
| 715 | * modal dialog. On form errors, this will rebuild the form and display the |
||
| 716 | * error messages. |
||
| 717 | * |
||
| 718 | * @param array $form |
||
| 719 | * An associative array containing the structure of the form. |
||
| 720 | * @param FormStateInterface $form_state |
||
| 721 | * An associative array containing the current state of the form. |
||
| 722 | * |
||
| 723 | * @return \Drupal\Core\Ajax\AjaxResponse |
||
| 724 | * The ajax response. |
||
| 725 | */ |
||
| 726 | public function submitEmbedStep(array &$form, FormStateInterface $form_state) { |
||
| 771 | |||
| 772 | /** |
||
| 773 | * Form element validation handler; Escapes the value an element. |
||
| 774 | * |
||
| 775 | * This should be used for any element in the embed form which may contain |
||
| 776 | * HTML that should be serialized as an attribute element on the embed. |
||
| 777 | */ |
||
| 778 | public static function escapeValue($element, FormStateInterface $form_state) { |
||
| 783 | |||
| 784 | /** |
||
| 785 | * Returns the allowed Entity Embed Display plugins given an embed button and |
||
| 786 | * an entity. |
||
| 787 | * |
||
| 788 | * @param \Drupal\embed\EmbedButtonInterface $embed_button |
||
| 789 | * The embed button. |
||
| 790 | * @param \Drupal\Core\Entity\EntityInterface $entity |
||
| 791 | * The entity. |
||
| 792 | * |
||
| 793 | * @return array |
||
| 794 | * List of allowed Entity Embed Display plugins. |
||
| 795 | */ |
||
| 796 | public function getDisplayPluginOptions(EmbedButtonInterface $embed_button, EntityInterface $entity) { |
||
| 806 | |||
| 807 | /** |
||
| 808 | * Registers JS callback that gets entities from entity browser and updates |
||
| 809 | * form values accordingly. |
||
| 810 | */ |
||
| 811 | public function registerJSCallback(RegisterJSCallbacks $event) { |
||
| 816 | |||
| 817 | /** |
||
| 818 | * Load the current entity browser and its settings from the form state. |
||
| 819 | * |
||
| 820 | * @param \Drupal\Core\Form\FormStateInterface $form_state |
||
| 821 | */ |
||
| 822 | protected function loadEntityBrowser(FormStateInterface $form_state) { |
||
| 834 | |||
| 835 | } |
||
| 836 |
Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.
Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..