datafield-1.x-dev/src/Plugin/Field/FieldWidget/Base.php

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

namespace Drupal\datafield\Plugin\Field\FieldWidget;

use Drupal\Component\Render\FormattableMarkup;
use Drupal\Component\Utility\Html;
use Drupal\Component\Utility\NestedArray;
use Drupal\Core\Cache\CacheBackendInterface;
use Drupal\Core\Field\FieldDefinitionInterface;
use Drupal\Core\Field\FieldItemListInterface;
use Drupal\Core\Field\WidgetBase;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\KeyValueStore\KeyValueFactoryInterface;
use Drupal\datafield\Plugin\DataFieldTypePluginManager;
use Drupal\datafield\Plugin\DataFieldWidgetPluginManager;
use Drupal\datafield\Plugin\Field\FieldType\DataFieldItem as FieldItem;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\Validator\ConstraintViolationInterface;

/**
 * Base class for data field formatters.
 */
abstract class Base extends WidgetBase {

  /**
   * Constructs a WidgetBase object.
   *
   * @param string $plugin_id
   *   The plugin_id for the widget.
   * @param mixed $plugin_definition
   *   The plugin implementation definition.
   * @param \Drupal\Core\Field\FieldDefinitionInterface $field_definition
   *   The definition of the field to which the widget is associated.
   * @param array $settings
   *   The widget settings.
   * @param array $third_party_settings
   *   Any third party settings.
   * @param \Drupal\Core\KeyValueStore\KeyValueFactoryInterface $keyValue
   *   The key value service.
   * @param \Drupal\datafield\Plugin\DataFieldTypePluginManager $pluginType
   *   The plugin type manager.
   * @param \Drupal\datafield\Plugin\DataFieldWidgetPluginManager $pluginWidget
   *   The plugin widget service.
   * @param \Drupal\Core\Cache\CacheBackendInterface $cache
   *   The cache service.
   */
  public function __construct($plugin_id, $plugin_definition, FieldDefinitionInterface $field_definition, array $settings, array $third_party_settings, protected KeyValueFactoryInterface $keyValue, protected DataFieldTypePluginManager $pluginType, protected DataFieldWidgetPluginManager $pluginWidget, protected CacheBackendInterface $cache) {
    parent::__construct($plugin_id, $plugin_definition, $field_definition, $settings, $third_party_settings);
  }

  /**
   * {@inheritdoc}
   */
  public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) {
    return new static($plugin_id, $plugin_definition,
      $configuration['field_definition'], $configuration['settings'],
      $configuration['third_party_settings'],
      $container->get('keyvalue'),
      $container->get('plugin.manager.data_field.type'),
      $container->get('plugin.manager.data_field.widget'),
      $container->get('cache.default'),
    );
  }

  /**
   * {@inheritdoc}
   */
  public static function defaultSettings(): array {
    $settings = [
      'inline' => FALSE,
      'widget_settings' => [],
    ];

    return $settings + parent::defaultSettings();
  }

  /**
   * {@inheritdoc}
   */
  public function settingsForm(array $form, FormStateInterface $form_state): array {
    $field_settings = $this->getFieldSetting('field_settings');
    $settings = $this->getSettings();
    $widget_settings = $settings['widget_settings'];
    $subfields = array_keys($columns = $this->getFieldSetting("columns"));
    if (!empty($setting = $settings['widget_settings'])) {
      uasort($setting, [
        'Drupal\Component\Utility\SortArray',
        'sortByWeightElement',
      ]);
      $subfields = array_keys($setting);
    }
    $types = FieldItem::subfieldTypes();

    $field_name = $this->fieldDefinition->getName();

    $element['inline'] = [
      '#type' => 'checkbox',
      '#title' => $this->t('Display as inline element'),
      '#default_value' => $settings['inline'] ?? FALSE,
    ];
    $widgetTypes = $this->pluginType->getDefinitions();
    $option_widget = $default_widget = [];
    foreach ($widgetTypes as $widget_type) {
      $default_widget[$widget_type['id']] = $widget_type['default_widget'];
    }
    $pluginWidget = $this->pluginWidget;
    $widget_types = $pluginWidget->getDefinitions();
    foreach ($widget_types as $widget_type) {
      foreach ($widget_type['field_types'] as $type) {
        $option_widget[$type][$widget_type['id']] = $widget_type['label'];
      }
    }
    foreach ($subfields as $subfield) {
      if (empty($columns[$subfield])) {
        continue;
      }
      $item = $columns[$subfield];
      $type = $item['type'];
      $optWidget = $option_widget[$type] ?? [];
      if (in_array($type, ['date', 'datetime_iso8601']) && count($widget_settings[$subfield]) == 1) {
        $dateType = $item['datetime_type'];
        $widget_settings[$subfield]["type"] = $dateType;
        if (in_array($dateType, ['time', 'week', 'month', 'year'])) {
          $optWidget = [$dateType => $option_widget[$type][$dateType]];
        }
      }
      $element['widget_settings'][$subfield] = [
        '#type' => 'details',
        '#title' => ($field_settings[$subfield]['label'] ?? $subfield) . ' - ' . $types[$type],
        '#open' => FALSE,
      ];
      $form['#storage_settings'] = $item;
      $form['#field_settings'] = $field_settings[$subfield] ?? [];
      $form['#settings'] = $widget_settings[$subfield] ?? [];
      $form['#machine_name'] = $subfield;
      $form['#field_name'] = $field_name;
      $widget_type = $widget_settings[$subfield]["type"] ?? $default_widget[$type];
      $plugin = $pluginWidget->createInstance($widget_type);
      $widgetSettings = [];
      if (method_exists($plugin, 'settingsForm')) {
        $widgetSettings = $plugin->settingsForm($form, $form_state);
      }
      if (empty($widget_settings)) {
        $widget_settings = [];
      }
      $options = [
        'block' => $this->t('Above'),
        'hidden' => $this->t('Hidden'),
      ];
      if ($settings['widget_settings'][$subfield]['type'] != 'datetime') {
        $options['inline'] = $this->t('Inline');
        $options['invisible'] = $this->t('Invisible');
      }
      $title = $item['name'] . ' - ' . $types[$type];
      $element['widget_settings'][$subfield] = [
        '#title' => $title,
        '#type' => 'details',
        'type' => [
          '#type' => 'select',
          '#title' => $this->t('Widget type'),
          '#default_value' => $widget_type,
          '#required' => TRUE,
          '#empty_option' => $this->t('- Select -'),
          '#options' => $optWidget,
          '#description' => $this->t('Save and back again to get options.'),
        ],
        'label_display' => [
          '#type' => 'select',
          '#title' => $this->t('Label'),
          '#default_value' => $widget_settings[$subfield]['label_display'] ?? '',
          '#options' => $options,
          '#empty_option' => $this->t('- Select -'),
          '#access' => static::isLabelSupported($item['type']),
        ],
        'field_display' => [
          '#type' => 'checkbox',
          '#title' => $this->t('Show field'),
          '#default_value' => $widget_settings[$subfield]['field_display'] ?? TRUE,
        ],
        'weight' => [
          '#type' => 'weight',
          '#title' => $this->t('Weight for fields'),
          // '#title_display' => 'invisible',
          '#default_value' => $widget_settings[$subfield]['weight'] ?? 0,
          '#weight' => 20,
        ],
      ] + $widgetSettings;
    }

    return $element;
  }

  /**
   * {@inheritdoc}
   */
  public function settingsSummary(): array {
    $settings = $this->getSettings();
    $field_settings = $this->getFieldSettings();
    $widgetTypes = $this->pluginType->getDefinitions();
    $widget_settings = $settings['widget_settings'];
    $default_widget = [];
    foreach ($widgetTypes as $widget_type) {
      $default_widget[$widget_type['id']] = $widget_type['default_widget'];
    }
    $pluginWidget = $this->pluginWidget;
    $summary = [];
    if (!empty($settings['inline'])) {
      $summary[] = $this->t('Display as inline element');
    }
    if (!empty($settings['field_reference'])) {
      $summary[] = $this->t('Field reference search: %field', ['%field' => $settings['field_reference']]);
    }

    foreach ($field_settings["columns"] as $subfield => $item) {
      $subfield_type = $item['type'];

      $summary[] = new FormattableMarkup(
        '<b>@subfield - @subfield_type</b>',
        [
          '@subfield' => $field_settings["field_settings"][$subfield]['label'] ?? $subfield,
          '@subfield_type' => strtolower($subfield_type),
        ]
      );
      if (!empty($settings['widget_settings'][$subfield]['type'])) {
        $summary[] = $this->t('Widget: @type', ['@type' => $settings['widget_settings'][$subfield]['type']]);
      }
      if (!empty($settings['widget_settings'][$subfield]['label_display']) && static::isLabelSupported($settings['widget_settings'][$subfield]['type'])) {
        $summary[] = $this->t('Label display: @label', ['@label' => $settings['widget_settings'][$subfield]['label_display']]);
      }
      $type = $item['type'];
      $widget_type = $widget_settings[$subfield]["type"] ?? $default_widget[$type];
      $plugin = $pluginWidget->createInstance($widget_type);
      if (method_exists($plugin, 'settingsSummary')) {
        $settingsSummary = $widget_settings[$subfield];
        if (!empty($field_settings["field_settings"][$subfield])) {
          $settingsSummary += $field_settings["field_settings"][$subfield] ?? [];
        }
        $summary = [...$summary, ...$plugin->settingsSummary($settingsSummary)];
      }

    }

    return $summary;
  }

  /**
   * Transfer value foreach widget.
   *
   * {@inheritdoc}
   */
  public function massageFormValues(array $values, array $form, FormStateInterface $form_state): array {
    $storage_settings = $this->getFieldSettings();
    $settings = $this->getSetting('widget_settings');
    $fieldName = $this->fieldDefinition->getName();
    $path = array_merge($form['#parents'], [$fieldName]);
    $key_exists = NULL;
    $userInputs = NestedArray::getValue($form_state->getUserInput(), $path, $key_exists);
    if (!empty($userInputs) && !empty($values) && is_array($userInputs) && count($userInputs) != count($values)) {
      $values = $userInputs;
    }
    $typeDefinitions = $this->pluginType->getDefinitions();
    foreach ($values as $delta => &$value) {
      $checkEmpty = [];
      if (!empty($value[0])) {
        $value = $value[0];
      }
      foreach ($storage_settings['columns'] as $subfield => $item) {
        $checkEmpty[$subfield] = $value[$subfield] ?? NULL;
        if (!empty($value[$subfield]) && is_array($value[$subfield]) && !empty($value[$subfield]['value'])) {
          $value[$subfield] = $value[$subfield]['value'];
        }
        if (isset($values[$delta][$subfield]) && !is_numeric($values[$delta][$subfield]) && empty($value[$subfield])) {
          $values[$delta][$subfield] = NULL;
        }
        if (!empty($value[$delta][$subfield])) {
          if ($item["type"] != 'datetime_iso8601') {
            $value[$subfield] = $value[$delta][$subfield];
          }
          unset($value[$delta]);
        }
        $widget_type = $settings[$subfield]['type'] ?? $typeDefinitions[$item["type"]]["default_widget"];
        if ($widget_type) {
          $plugin = $this->pluginWidget->createInstance($widget_type);
          if (method_exists($plugin, 'massageFormValues') && isset($value[$subfield])) {
            $widget_settings = [];
            if (method_exists($plugin, 'defaultSettings')) {
              $widget_settings = $plugin->defaultSettings();
            }
            $form['#machine_name'] = $subfield;
            $form['#storage_settings'] = $item;
            $form['#field_settings'] = $storage_settings["field_settings"][$subfield];
            $form['#widget_settings'] = $settings[$subfield] ?? $widget_settings;
            $form['#value_origin'] = $userInputs;
            $form['#field_name'] = $fieldName;
            $form['#delta'] = $delta;
            $value[$subfield] = $plugin->massageFormValues($value[$subfield], $form, $form_state);
          }
        }
      }
      if (count(array_filter($checkEmpty, function ($value) {
        return $value !== NULL && $value !== FALSE && $value !== "";
      })) === 0) {
        unset($values[$delta]);
      }
    }
    NestedArray::setValue($form_state->getValues(), $path, $values);
    return array_values($values);
  }

  /**
   * {@inheritDoc}
   */
  public static function addMoreSubmit(array $form, FormStateInterface $form_state) {
    $button = $form_state->getTriggeringElement();
    $element = NestedArray::getValue($form, array_slice($button['#array_parents'], 0, -1));
    $field_name = $element['#field_name'];
    $parents = $element['#field_parents'];
    // Increment the items count.
    $field_state = static::getWidgetState($parents, $field_name, $form_state);
    $userInput = $form_state->getUserInput()[$field_name] ?? [];
    if (is_array($userInput) && count($userInput) > 2 && $field_state['items_count'] < count($userInput) - 1) {
      $field_state = static::getWidgetState($form['#parents'], $field_name, $form_state);
      $field_state['items_count'] = count($userInput) - 2;
      static::setWidgetState($form['#parents'], $field_name, $form_state, $field_state);
    }
    parent::addMoreSubmit($form, $form_state);
  }

  /**
   * Determines whether widget can render subfield label.
   */
  public static function isLabelSupported(?string $widget_type = NULL): bool {
    return $widget_type != 'checkbox';
  }

  /**
   * {@inheritdoc}
   */
  public function errorElement(array $element, ConstraintViolationInterface $violation, array $form, FormStateInterface $form_state) {
    [$delta, $subfield] = explode('.', $violation->getPropertyPath());
    $element['#subfield'] = $subfield;
    $element['#delta'] = $delta;
    if (isset($element[$subfield]["#field_storage"]["datetime_type"]) && $element[$subfield]["#field_storage"]["datetime_type"] == 'year') {
      return FALSE;
    }
    if ($element[$subfield]["#field_storage"]["type"] == 'datetime_iso8601' && $element[$subfield]["#field_storage"]["datetime_type"] == 'timestamp') {
      return FALSE;
    }
    if (!empty($element[$delta][$subfield])) {
      $settings = $element[$delta][$subfield]['#widget_settings'];
      $widget_type = $settings["type"];
      $plugin = $this->pluginWidget->createInstance($widget_type);
      if (method_exists($plugin, 'errorElement')) {
        return $plugin->errorElement($element, $violation, $form, $form_state);
      }
    }
    if (!empty($element[$subfield])) {
      $settings = $element[$subfield]['#widget_settings'];
      $widget_type = $settings["type"];
      $plugin = $this->pluginWidget->createInstance($widget_type);
      if (method_exists($plugin, 'errorElement')) {
        return $plugin->errorElement($element, $violation, $form, $form_state);
      }
    }
    return isset($violation->arrayPropertyPath[$delta]) ? $element[$violation->arrayPropertyPath[$delta]] : $element;
  }

  /**
   * {@inheritdoc}
   */
  protected function getFieldSettings(): array {
    $field_settings = parent::getFieldSettings();
    foreach ($field_settings["columns"] as $subfield => $item) {
      if (!empty($field_settings["field_settings"][$subfield]['list']) && !FieldItem::isListAllowed($item['type'])) {
        $field_settings["field_settings"][$subfield]['list'] = FALSE;
      }
    }

    return $field_settings;
  }

  /**
   * {@inheritdoc}
   */
  public function getSettings(): array {
    // Unique cache ID for these settings.
    $cid = 'datafieldsettingsdefault';
    $default_widget = [];
    // Attempt to get cached settings.
    $cache = $this->cache->get($cid);
    if ($cache) {
      $default_widget = $cache->data;
    }
    else {
      $widget_types = $this->pluginType->getDefinitions();
      foreach ($widget_types as $widget_type) {
        $default_widget[$widget_type['id']] = $widget_type['default_widget'];
      }
      // Save the newly computed settings to cache.
      $this->cache->set($cid, $default_widget);
    }

    $settings = parent::getSettings();
    $field_settings = $this->getFieldSettings();
    foreach ($field_settings['columns'] as $subfield => $item) {
      if (empty($settings['widget_settings'][$subfield]['type']) && !empty($default_widget[$item["type"]])) {
        $settings['widget_settings'][$subfield]['type'] = $default_widget[$item["type"]];
      }
      if ($default_widget[$item["type"]] == 'datetime' && !empty($field_settings['columns'][$subfield]['datetime_type'])) {
        $settings['widget_settings'][$subfield]['type'] = $field_settings['columns'][$subfield]['datetime_type'];
      }
    }

    return $settings;
  }

  /**
   * {@inheritdoc}
   */
  public function getFormElement(FieldItemListInterface $items, $delta, array $element, array &$form, FormStateInterface $form_state): array {
    $field_settings = $this->getFieldSetting('field_settings');
    $settings = $this->getSettings();
    $subfields = array_keys($storage = $this->getFieldSetting("columns"));
    $fieldDef = $items->getFieldDefinition();
    $field = $items[0]->getFieldDefinition();
    $field_widget_default = $field->getDefaultValueLiteral();

    if (!empty($setting = $settings['widget_settings'])) {
      uasort($setting, [
        'Drupal\Component\Utility\SortArray',
        'sortByWeightElement',
      ]);
      $subfields = array_keys($setting);
    }
    $widget = [];
    $entityDefault = [
      'entity_reference_type' => $fieldDef->getTargetEntityTypeId() ?? 'node',
      'target_bundles' => $fieldDef->getTargetBundle() ?? 'page',
      'label' => $fieldDef->label(),
    ];
    $fieldName = $this->fieldDefinition->getName();
    $userInput = $form_state->getUserInput();
    foreach ($subfields as $subfield) {
      if (empty($storage[$subfield])) {
        continue;
      }
      $widget_settings = $settings["widget_settings"][$subfield];
      $title = $field_settings[$subfield]['label'] ?? ucfirst($subfield);
      $field_default = !empty($field_widget_default[$delta]) ? $field_widget_default[$delta][$subfield] : '';
      $default_value = $items[$delta]->{$subfield} ?? $field_default;
      if (is_array($default_value) && array_key_exists('url', $default_value)) {
        $default_value = $default_value['url'];
      }
      if (empty($default_value) && !empty($userInput[$fieldName][$delta][$subfield])) {
        $default_value = $userInput[$fieldName][$delta][$subfield][$subfield] ?? $userInput[$fieldName][$delta][$subfield];
      }
      $storage_type = $storage[$subfield]['type'];
      $widget_type = $widget_settings["type"] ?? $storage_type;
      $checkFormDefaultValue = !empty($form["#parents"][0]) && $form["#parents"][0] == 'default_value_input';
      if ($storage_type == 'file' && $checkFormDefaultValue) {
        $widget_type = 'number';
      }
      $widget[$delta][$subfield] = [
        '#id' => Html::getUniqueId($items->getName() . '-' . $delta),
        '#title' => $title,
        '#title_display' => 'invisible',
        '#type' => $widget_type,
        '#machine_name' => $subfield,
        '#default_value' => $default_value,
        '#field_name' => $fieldName,
        '#field_storage' => $storage[$subfield],
        '#field_settings' => $field_settings[$subfield] ?? [],
        '#field_parents' => $element['#field_parents'] ?? [],
        '#widget_settings' => $widget_settings,
        '#entity_type' => $entityDefault['entity_reference_type'],
        '#bundle' => $entityDefault['target_bundles'],
        '#delta' => $delta,
        '#wrapper_attributes' => ['class' => [Html::getId('data_field-subfield-form-item')]],
      ];
      if (!$checkFormDefaultValue) {
        $widget[$delta][$subfield]['#required'] = $field_settings[$subfield]['required'] ?? 0;
        $widget[$delta][$subfield]['#default_value_input'] = TRUE;
      }
      if ($storage_type == 'entity_reference') {
        $plugin = $this->pluginType->createInstance($storage_type);
        if (!isset($field_settings[$subfield])) {
          $field_settings[$subfield] = $entityDefault;
        }
        $plugin->setWidgetForm($widget[$delta][$subfield], $field_settings[$subfield], $items->getEntity());
      }
      $plugin = $this->pluginWidget->createInstance($widget_type);
      if ($plugin) {
        $settingsWidget = $storage[$subfield] + $widget_settings;
        $plugin->getFormElement($widget[$delta][$subfield], $items[$delta], $settingsWidget);
      }
    }
    return $widget;
  }

  /**
   * {@inheritDoc}
   */
  public static function itemAjax(array $form, FormStateInterface $form_state) {
    $button = $form_state->getTriggeringElement();
    // Go one level up in the form, to the widgets' container.
    $element = NestedArray::getValue($form, array_slice($button['#array_parents'], 0, -4));
    $element['#prefix'] = '<div class="ajax-new-content">' . $element['#prefix'] ?? '';
    if (isset($element['#suffix'])) {
      $element['#suffix'] .= '</div>';
    }
    return $element;
  }

}

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

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