You are here

function paragraphs_ee_field_widget_multivalue_form_alter in Paragraphs Editor Enhancements 8

Implements hook_field_widget_multivalue_form_alter().

File

./paragraphs_ee.module, line 76
Main functions for "Paragraphs Editor Enhancements" module.

Code

function paragraphs_ee_field_widget_multivalue_form_alter(array &$elements, FormStateInterface $form_state, array $context) {

  /** @var \Drupal\paragraphs\Plugin\Field\FieldWidget\ParagraphsWidget $widget */
  $widget = $context['widget'];
  if (!$widget instanceof ParagraphsWidget) {
    return;
  }

  // Check if modifications to widget are allowed.
  $hook_arguments = [
    $elements,
    $form_state,
    $context,
  ];
  $access_results = \Drupal::moduleHandler()
    ->invokeAll('paragraphs_ee_widget_access', $hook_arguments);

  /** @var \Drupal\Core\Access\AccessResultInterface $result */
  $result = AccessResult::neutral();
  if (!empty($access_results)) {
    $result = array_shift($access_results);
    foreach ($access_results as $access_result) {
      $result = $result
        ->orIf($access_result);
    }
  }
  if (!$result
    ->isAllowed()) {
    return;
  }
  if (!isset($elements['add_more'])) {
    return;
  }

  /** @var \Drupal\entity_reference_revisions\EntityReferenceRevisionsFieldItemList $items */
  $items = $context['items'];

  // Add custom library.
  $elements['#attached']['library'][] = 'paragraphs_ee/paragraphs_ee.paragraphs';
  $field_definition_settings = $items
    ->getFieldDefinition()
    ->getSetting('handler_settings');

  // Load all available paragraph types.
  $types_available = ParagraphsType::loadMultiple(array_column($elements['add_more'], '#bundle_machine_name'));
  $buttons_ref = [];

  /** @var \Drupal\paragraphs\Entity\ParagraphsType $type */
  foreach ($types_available as $id => $type) {
    $button_id = "add_more_button_{$id}";
    $button = $elements['add_more'][$button_id];

    // Use custom button layout (and rewrite <input> to <button>).
    $button['#theme_wrappers'] = [
      'input__submit__paragraphs_action__image',
    ];
    $button['#attributes']['class'][] = 'paragraphs-button--add-more';
    $button['#description'] = $type
      ->getDescription();
    $button['#icon_attributes'] = new Attribute();
    $button['#icon_attributes']['aria-hidden'] = 'true';
    $button['#icon_attributes']['class'] = [
      'paragraphs-button--icon',
    ];
    if ($icon_url = $type
      ->getIconUrl()) {

      // Extract icon from button.
      $elements['add_more'][$button_id]['#attributes']['class'][] = 'icon';
      unset($button['#attributes']['style']);
      $button['#icon'] = $icon_url;
    }
    else {
      $button['#icon_attributes']['class'][] = 'image-default';
    }
    $button['#weight'] = 0;
    if (isset($field_definition_settings['target_bundles_drag_drop'][$id]['weight'])) {
      $button['#weight'] = $field_definition_settings['target_bundles_drag_drop'][$id]['weight'];
    }
    $elements['add_more'][$button_id] = $button;
    $settings = array_filter($type
      ->getThirdPartySetting('paragraphs_ee', 'paragraphs_categories', []));
    if (empty($settings)) {

      // Store category for later use.
      $elements['add_more'][$button_id]['#paragraphs_category'] = '_none';

      // Paragraph type is uncategorized so we do not need to process it here.
      continue;
    }

    // We need to call this first because the value is changed on second run
    // only.
    Html::getUniqueId($button_id);
    foreach ($settings as $paragraphs_category) {
      $buttons_ref[$button_id] = empty($buttons_ref[$button_id]) ? 1 : $buttons_ref[$button_id] + 1;
      if (empty($elements['add_more'][$button_id]['#paragraphs_category'])) {

        // Store category for later use.
        $elements['add_more'][$button_id]['#paragraphs_category'] = $paragraphs_category;
        continue;
      }

      // Clone button and change some attributes so AJAX is working.
      $button['#id'] = Html::getUniqueId($button['#id']);
      $button_new_id = strtr(Html::getUniqueId($button_id), [
        '-' => '_',
      ]);
      $button['#name'] .= '__' . $buttons_ref[$button_id];

      // Add clone of button to add_more-element.
      $elements['add_more'][$button_new_id] = $button;

      // Store category for later use.
      $elements['add_more'][$button_new_id]['#paragraphs_category'] = $paragraphs_category;
    }
  }
  uasort($elements['add_more'], 'Drupal\\Component\\Utility\\SortArray::sortByWeightProperty');
  $widget_third_party_settings = $widget
    ->getThirdPartySetting('paragraphs_ee', 'paragraphs_ee');
  $easy_access_buttons = [];
  $easy_access_buttons_max = isset($widget_third_party_settings['easy_access_count']) ? $widget_third_party_settings['easy_access_count'] : 2;

  // Mark the first unique buttons for easy access.
  foreach (Element::children($elements['add_more']) as $child_key) {
    if (empty($elements['add_more'][$child_key]['#bundle_machine_name'])) {
      continue;
    }
    if (count($easy_access_buttons) >= $easy_access_buttons_max) {

      // No need to process more elements as we reached the limit already.
      break;
    }
    if (isset($easy_access_buttons[$elements['add_more'][$child_key]['#bundle_machine_name']])) {

      // Button is already in list and is not added again.
      continue;
    }
    $easy_access_buttons[$elements['add_more'][$child_key]['#bundle_machine_name']] = $elements['add_more'][$child_key]['#weight'];
    $elements['add_more'][$child_key]['#easy_access'] = TRUE;
  }

  // Remove type attribute from "add_more" to prevent a duplicate dialog.
  // @see https://www.drupal.org/i/3153820 for background information.
  unset($elements['add_more']['#type']);

  // Use different theme for modal dialog.
  $elements['add_more']['#theme'] = 'paragraphs_add_dialog__categorized';
  $elements['add_more']['#attributes'] = isset($elements['add_more']['#attributes']) ? $elements['add_more']['#attributes'] : new Attribute();
  $elements['add_more']['#attributes']['class'] = [
    'paragraphs-add-dialog',
    'paragraphs-add-dialog--categorized',
    'js-hide',
  ];
  if (!empty($widget_third_party_settings['dialog_style']) && 'tiles' !== $widget_third_party_settings['dialog_style']) {
    $elements['add_more']['#attributes']['class'][] = 'paragraphs-style-' . $widget_third_party_settings['dialog_style'];
  }
  $elements['add_more']['#attributes']['role'] = 'dialog';
  $elements['add_more']['#attributes']['aria-modal'] = 'true';
  $elements['add_more']['#attributes']['aria-label'] = t('Add @widget_title', [
    '@widget_title' => $widget
      ->getSetting('title'),
  ], [
    'context' => 'Paragraphs Editor Enhancements',
  ]);
  $elements['add_more']['#attributes']['data-widget-title'] = $widget
    ->getSetting('title');
  $elements['add_more']['#attributes']['data-widget-title-plural'] = $widget
    ->getSetting('title_plural');
  $elements['add_more']['#attributes']['data-paragraphs-ee-dialog-wrapper'] = '';
  $elements['add_more']['#attached']['library'][] = 'paragraphs_ee/paragraphs_ee.categories';
  if (!empty($widget_third_party_settings['dialog_off_canvas'])) {

    /** @var \Drupal\Core\Entity\Display\EntityFormDisplayInterface $form_display */
    $form_display = $form_state
      ->get('form_display');
    $elements['add_more']['#attributes']['data-dialog-off-canvas'] = 'true';
    $elements['add_more']['#attributes']['data-dialog-field-name'] = $items
      ->getFieldDefinition()
      ->getName();
    $browser_params = [
      'entity_type' => $form_display
        ->getTargetEntityTypeId(),
      'bundle' => $form_display
        ->getTargetBundle(),
      'form_mode' => $form_display
        ->getMode(),
      'field_name' => $items
        ->getFieldDefinition()
        ->getName(),
    ];
    $elements['add_more']['#attributes']['data-dialog-browser-url'] = Url::fromRoute('paragraphs_ee.paragraphs_browser', $browser_params)
      ->toString();
  }
  $elements['#attributes']['data-paragraphs-ee'] = '';
  $elements['#attributes']['data-paragraphs-ee-easy-access-max'] = $easy_access_buttons_max;
}