stacks-8.x-1.x-dev/src/Plugin/Field/FieldWidget/FormWidgetType.php

src/Plugin/Field/FieldWidget/FormWidgetType.php
<?php

namespace Drupal\stacks\Plugin\Field\FieldWidget;

use Drupal\Component\Utility\NestedArray;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Field\FieldItemListInterface;
use Drupal\Core\Field\WidgetBase;
use Drupal\Core\Url;
use Drupal\stacks\Entity\WidgetEntityType;
use Drupal\stacks\Entity\WidgetInstanceEntity;
use Drupal\stacks\Widget\WidgetData;

/**
 * Plugin implementation of the 'form_widget_type' widget.
 *
 * @FieldWidget(
 *   id = "form_widget_type",
 *   label = @Translation("Form Stacks"),
 *   field_types = {
 *     "stacks_type"
 *   }
 * )
 */
class FormWidgetType extends WidgetBase {

  /**
   * {@inheritdoc}
   */
  public static function defaultSettings() {
    return [
      'bundles' => [],
      'bundles_required_pos_locked' => [],
      'bundles_required_pos_optional' => [],
    ] + parent::defaultSettings();
  }

  /**
   * {@inheritdoc}
   */
  public function settingsForm(array $form, FormStateInterface $form_state) {
    $elements = [];

    $widget_type_manager = \Drupal::service('plugin.manager.stacks_widget_type');
    $widget_entity_types = WidgetEntityType::loadMultiple();
    $bundles = [];
    foreach ($widget_entity_types as $widget_entity_type) {
      if ($widget_type_manager->hasDefinition($widget_entity_type->getPlugin())) {
        $bundles[$widget_entity_type->id()] = $widget_entity_type->label();
      }
    }

    $elements['bundles'] = [
      '#type' => 'checkboxes',
      '#title' => t('Enabled Widget Types'),
      '#options' => $bundles,
      '#default_value' => $this->getSetting('bundles'),
      '#required' => TRUE,
      '#description' => t('The widgets that are available for this field. Note that all widget bundles are automatically added to all widget fields.'),
    ];

    $elements['bundles_required_pos_locked'] = [
      '#type' => 'checkboxes',
      '#title' => t('Required Widget Bundles: Position Locked'),
      '#options' => $bundles,
      '#default_value' => $this->getSetting('bundles_required_pos_locked'),
      '#required' => FALSE,
      '#description' => t('The widgets that are auto added to this field, where the position cannot be changed per node (displayed at the top).'),
    ];

    $elements['bundles_required_pos_optional'] = [
      '#type' => 'checkboxes',
      '#title' => t('Required Widget Bundles: Position Optional'),
      '#options' => $bundles,
      '#default_value' => $this->getSetting('bundles_required_pos_optional'),
      '#required' => FALSE,
      '#description' => t('The widgets that are auto added to this field, where the position can be changed per node.'),
    ];

    return $elements;
  }

  /**
   * {@inheritdoc}
   */
  public function settingsSummary() {
    $summary = [];

    $enable_stacks = $this->displayBundlesAsList($this->getSetting('bundles'), t('Enabled Stacks'));
    if (!empty($enable_stacks)) {
      $summary[] = $enable_stacks;
    }

    $required_stacks = $this->displayBundlesAsList($this->getSetting('bundles_required_pos_locked'), t('Required Stacks - Position Locked'));
    if (!empty($required_stacks)) {
      $summary[] = $required_stacks;
    }

    $required_stacks_pos_optional = $this->displayBundlesAsList($this->getSetting('bundles_required_pos_optional'), t('Required Stacks - Position Optional'));
    if (!empty($required_stacks_pos_optional)) {
      $summary[] = $required_stacks_pos_optional;
    }

    return $summary;
  }

  /**
   * Takes an array of bundles and returns then in a string, separate by a comma.
   *
   * @param array $bundles
   * @param string $label Label for what to label this list as.
   *
   * @return string
   */
  public function displayBundlesAsList($bundles, $label) {
    if (empty($bundles)) {
      return '';
    }

    $bundles_array = [];
    foreach ($bundles as $value) {
      if (!empty($value)) {
        $bundles_array[] = $value;
      }
    }

    $bundles_html = implode(', ', $bundles_array);
    $return = '';
    if (!empty($bundles_html)) {
      $return = t('@label: @bundles', [
        '@label' => $label,
        '@bundles' => $bundles_html,
      ]);
    }

    return $return;
  }

  /**
   * {@inheritdoc}
   */
  public function formElement(FieldItemListInterface $items, $delta, array $element, array &$form, FormStateInterface $form_state) {
    $element = [];

    // Attach the js/css.
    $element['#attached']['library'][] = 'stacks/admin';

    // Send to a custom method to add the correct buttons, display title, etc...
    $this->widgetRow($items, $delta, $element, $form, $form_state);

    return $element;
  }

  /**
   * Outputs the html for a widget row.
   *
   * @param \Drupal\Core\Field\FieldItemListInterface $items
   * @param $delta
   * @param array $element
   * @param array $form
   * @param \Drupal\Core\Form\FormStateInterface $form_state
   * @param array $required_options
   */
  public function widgetRow(FieldItemListInterface $items, $delta, array &$element, array &$form, FormStateInterface $form_state, $required_options = []) {
    // Default options for the query parameters for the buttons.
    $field_name = $items->getFieldDefinition()->getName();
    $link_options = [
      'query' => [
        'entity-type' => $items->getEntity()->getEntityTypeId(),
        'entity-id' => $items->getEntity()->id(),
        'content-type' => $items->getEntity()->bundle(),
        'field' => $field_name,
        'delta' => $delta,
      ]
    ];

    $wrapper_id = "widget-form-{$delta}";
    $element['form_wrapper_start'] = ['#markup' => '<div id="' . $wrapper_id . '" class="widget-form">'];
    $element['data'] = [];


    // We first try to load the widget_instance_id property. If that is not set
    // we then try to grab it from the form, which happens when the add new row
    // is called. If both of those are false, we know we need to display the add
    // new row button.
    $widget_instance_id = isset($items[$delta]->widget_instance_id) ? $items[$delta]->widget_instance_id : FALSE;
    if (!$widget_instance_id) {
      $form_values = $form_state->getValue($field_name);
      $widget_instance_id = isset($form_values[$delta]['widget_instance_id']) ? $form_values[$delta]['widget_instance_id'] : FALSE;
    }

    // Is this an edit row?
    if ($widget_instance_id) {
      // Update: calling static function to build widget fields with existing data.
      $element = array_merge($element, $this->getWidgetInstanceField($wrapper_id, $widget_instance_id, $link_options));
    }
    else {
      $element['form_wrapper_start'] = ['#markup' => '<div id="' . $wrapper_id . '" class="add-widget-row widget-form">'];
      // Add new row.
      $element['data']['link'] = [
        '#type' => 'link',
        '#title' => t('Add a New Widget'),
        '#url' => Url::fromRoute('stacks.admin.ajax', [], $link_options),
        '#attributes' => [
          'class' => ['use-ajax', 'button', 'add-widget', 'button--primary'],
        ],
        '#prefix' => '<div class="add-widget-wrapper">',
        '#suffix' => '</div>',
      ];
    }

    $element['form_wrapper_end'] = ['#markup' => '</div>'];

    $element['widget_instance_id'] = $element + [
        '#type' => 'hidden',
        '#default_value' => isset($items[$delta]->widget_instance_id) ? $items[$delta]->widget_instance_id : '',
        '#placeholder' => t('Widget Instance ID'),
        '#prefix' => '<div id="widget-instance-' . $delta . '" class="widget_instance">',
        '#suffix' => '</div>',
      ];
  }

  /**
   * Static function to build existing widget field.
   */
  public static function getWidgetInstanceField($wrapper_id, $widget_instance_id, $link_options) {
    // Setting some general placeholder messages first for the rare case
    // in which a widget instance is not found
    $element['data']['stacks_begin'] = ['#markup' => '<div class="stacks">'];
    $element['data']['title'] = [
      [
        '#type' => 'html_tag',
        '#tag' => 'div',
        '#attributes' => [
          'class' => [
            'widget_type_list',
          ],
        ],
        '#value' => 'Widget instance ' . $widget_instance_id . ' missing',
      ],
      [
        '#type' => 'html_tag',
        '#tag' => 'h2',
        '#attributes' => [
          'class' => [
            'widget-title',
          ],
        ],
        '#value' => 'Widget missing',
      ],
    ];

    // Load the widget instance.
    $widget_instance = WidgetInstanceEntity::load($widget_instance_id);
    if (!$widget_instance) {
      return $element;
    }

    // Set the widget type div.
    $element['data']['title'][0]['#value'] = WidgetData::getWidgetType($widget_instance);

    // Set the widget title. If the node hasn't been saved with new widgets yet,
    // the title will not be set.
    $widget_title = $widget_instance->getTitle();
    if (empty($widget_title)) {
      $widget_title = WidgetData::getWidgetType($widget_instance) . ' (' . $widget_instance_id . ')';
    }

    $element['data']['title'][1]['#value'] = $widget_title;

    $edit_button_label = 'Edit';
    $link_options['query']['widget_instance_id'] = $widget_instance->id();

    // Is this is a required widget?
    $is_required = $widget_instance->getIsRequired();
    if ($is_required) {
      $required_type = $widget_instance->getRequiredType();
      $required_bundle = $widget_instance->getRequiredBundle();
      $bundles_get = \Drupal::service('entity_type.bundle.info')->getBundleInfo('widget_entity');

      $edit_button_label = $bundles_get[$required_bundle]['label'];
      unset($element['data']['title']);

      // Add special classes to the wrapper.
      $element['form_wrapper_start'] = ['#markup' => '<div id="' . $wrapper_id . '" class="required required_' . $required_type . ' widget-form">'];
    }

    if (!$is_required) {
      // Handle Delete Button.
      $element['data']['delete'] = [
        '#type' => 'link',
        '#title' => t('Delete'),
        '#url' => Url::fromRoute('stacks.admin.ajax_delete', [], $link_options),
        '#attributes' => [
          'class' => ['use-ajax', 'link--gray', 'remove-widget'],
          'data-dialog-type' => 'modal',
        ],
        '#prefix' => '<div class="widget-collapsed__buttons">'
      ];
    }

    // Handle Edit Button.
    $element['data']['link'] = [
      '#type' => 'link',
      '#title' => t($edit_button_label),
      '#url' => Url::fromRoute('stacks.admin.ajax', [], $link_options),
      '#attributes' => [
        'class' => ['use-ajax', 'button', 'edit-widget', 'button--primary'],
        'data-dialog-type' => 'modal',
      ],
      '#suffix' => '</div>',
    ];

    $element['data']['stacks_end'] = ['#markup' => '</div>'];

    return $element;
  }

  /**
   * {@inheritdoc}
   */
  public function form(FieldItemListInterface $items, array &$form, FormStateInterface $form_state, $get_delta = NULL) {
    $array = parent::form($items, $form, $form_state, $get_delta);
    return $array;
  }

  /**
   * {@inheritdoc}
   */
  protected function formMultipleElements(FieldItemListInterface $items, array &$form, FormStateInterface $form_state) {
    $element = parent::formMultipleElements($items, $form, $form_state);
    return $element;
  }

  /**
   * {@inheritdoc}
   */
  public static function addMoreAjax(array $form, FormStateInterface $form_state) {
    $element = parent::addMoreAjax($form, $form_state);
    return $element;
  }

  /**
   * {@inheritdoc}
   */
  public static function addMoreSubmit(array $form, FormStateInterface $form_state) {
    $button = $form_state->getTriggeringElement();

    // Go one level up in the form, to the stacks container.
    $element = NestedArray::getValue($form, array_slice($button['#array_parents'], 0, -1));
    $field_name = $element['#field_name'];
    $parents = $element['#field_parents'];

    // Increment the items count. Only if the last value is not empty.
    $field_state = static::getWidgetState($parents, $field_name, $form_state);
    $prev_delta = $field_state['items_count'];
    if (!empty($element[$prev_delta]['widget_instance_id']['#value'])) {
      $field_state['items_count']++;
    }

    static::setWidgetState($parents, $field_name, $form_state, $field_state);

    $form_state->setRebuild();
  }

}

Главная | Обратная связь

drupal hosting | друпал хостинг | it patrol .inc