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\Plugin\PluginManagerBase;
use Drupal\Component\Render\FormattableMarkup;
use Drupal\Component\Utility\Html;
use Drupal\Core\Datetime\DrupalDateTime;
use Drupal\Core\Entity\EntityTypeManagerInterface;
use Drupal\Core\Extension\ModuleHandlerInterface;
use Drupal\Core\Field\FieldDefinitionInterface;
use Drupal\Core\Field\FieldItemListInterface;
use Drupal\Core\Field\WidgetBase;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Render\Element\Email;
use Drupal\datafield\Plugin\Field\FieldType\DataField as FieldItem;
use Symfony\Component\Validator\ConstraintViolationInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;

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

  /**
   * The help topic plugin manager.
   *
   * @var \Drupal\help_topics\HelpTopicPluginManagerInterface
   */
  protected $pluginManager;

  /**
   * The entity type manager.
   *
   * @var \Drupal\Core\Entity\EntityTypeManagerInterface
   */
  protected $entityTypeManager;

  /**
   * The module handler.
   *
   * @var \Drupal\Core\Extension\ModuleHandlerInterface
   */
  protected $moduleHandler;

  /**
   * 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\Component\Plugin\PluginManagerBase $plugin_manager
   *   The widget plugin manager.
   * @param \Drupal\Core\Entity\EntityTypeManagerInterface $entity_type_manager
   *   The entity type manager.
   * @param \Drupal\Core\Extension\ModuleHandlerInterface $module_handler
   *   Module handler service.
   */
  public function __construct($plugin_id, $plugin_definition, FieldDefinitionInterface $field_definition, array $settings, array $third_party_settings, PluginManagerBase $plugin_manager, EntityTypeManagerInterface $entity_type_manager, ModuleHandlerInterface $module_handler) {
    parent::__construct($plugin_id, $plugin_definition, $field_definition, $settings, $third_party_settings);
    $this->pluginManager = $plugin_manager;
    $this->entityTypeManager = $entity_type_manager;
    $this->moduleHandler = $module_handler;
  }

  /**
   * {@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('plugin.manager.field.widget'),
      $container->get('entity_type.manager'),
      $container->get('module_handler')
    );
  }

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

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

  /**
   * {@inheritdoc}
   */
  public static function widgetDefault() {
    return [
      'type' => NULL,
      'label_display' => 'block',
      'field_display' => TRUE,
      'size' => 30,
      'placeholder' => '',
      'label' => t('Ok'),
      'cols' => 10,
      'rows' => 5,
      'plugin' => '',
      'file_extensions' => 'jpg jpeg gif png txt doc xls pdf ppt pps odt ods odp docx xlsx pptx',
      'preview_image_style' => 'thumbnail',
    ];
  }

  /**
   * {@inheritdoc}
   */
  public function settingsForm(array $form, FormStateInterface $form_state): array {
    $widget_settings_default = self::widgetDefault();
    $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'] ?? '',
    ];

    foreach ($subfields as $subfield) {
      if (empty($columns[$subfield])) {
        continue;
      }
      $item = $columns[$subfield];
      $type = $item['type'];
      $element['widget_settings'][$subfield] = [
        '#type' => 'details',
        '#title' => ($field_settings[$subfield]['label'] ?? $subfield) . ' - ' . $types[$type],
        '#open' => FALSE,
      ];
      $typeWidget = $item['datetime_type'] ?? FALSE;
      if ($item['type'] == 'entity_reference') {
        $typeWidget = $field_settings[$subfield]["entity_reference_type"];
      }
      $element['widget_settings'][$subfield]['type'] = [
        '#type' => 'select',
        '#title' => $this->t('Widget'),
        '#default_value' => $widget_settings[$subfield]["type"] ?? $widget_settings_default['type'],
        '#required' => TRUE,
        '#empty_option' => $this->t('- Select -'),
        '#options' => $this->getSubwidgets($type, $field_settings[$subfield]['list'] ?? FALSE, $typeWidget),
      ];

      $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');
      }
      $element['widget_settings'][$subfield]['label_display'] = [
        '#type' => 'select',
        '#title' => $this->t('Label'),
        '#default_value' => $widget_settings[$subfield]['label_display'] ?? $widget_settings_default['label_display'],
        '#options' => $options,
        '#empty_option' => $this->t('- Select -'),
        '#access' => static::isLabelSupported($item['type']),
      ];
      $element['widget_settings'][$subfield]['field_display'] = [
        '#type' => 'checkbox',
        '#title' => $this->t('Show field'),
        '#default_value' => $widget_settings[$subfield]['field_display'] ?? $widget_settings_default['field_display'],
      ];
      $type_selector = "select[name='fields[$field_name][settings_edit_form][settings][widget_settings][$subfield][type]'";
      $element['widget_settings'][$subfield]['size'] = [
        '#type' => 'number',
        '#title' => $this->t('Size'),
        '#default_value' => $widget_settings[$subfield]['size'] ?? $widget_settings_default['size'],
        '#min' => 1,
        '#states' => [
          'visible' => [
            [$type_selector => ['value' => 'textfield']],
            [$type_selector => ['value' => 'email']],
            [$type_selector => ['value' => 'tel']],
            [$type_selector => ['value' => 'url']],
          ],
        ],
      ];
      if (!in_array($item["type"], [
        'datetime_iso8601',
        'date',
        'boolean',
      ])) {
        $element['widget_settings'][$subfield]['placeholder'] = [
          '#type' => 'textfield',
          '#title' => $this->t('Placeholder'),
          '#default_value' => $widget_settings[$subfield]['placeholder'] ?? $widget_settings_default['placeholder'],
          '#states' => [
            'visible' => [
              [$type_selector => ['value' => 'textfield']],
              [$type_selector => ['value' => 'textarea']],
              [$type_selector => ['value' => 'email']],
              [$type_selector => ['value' => 'tel']],
              [$type_selector => ['value' => 'url']],
              [$type_selector => ['value' => 'number']],
              [$type_selector => ['value' => 'password']],
              [$type_selector => ['value' => 'text_format']],
              [$type_selector => ['value' => 'date']],
              [$type_selector => ['value' => 'json']],
            ],
          ],
        ];
      }

      $element['widget_settings'][$subfield]['label'] = [
        '#type' => 'textfield',
        '#title' => $this->t('Label'),
        '#default_value' => $widget_settings[$subfield]['label'] ?? $widget_settings_default['label'],
        '#states' => [
          'visible' => [$type_selector => ['value' => 'checkbox']],
        ],
      ];

      if (in_array($item["type"], ['text', 'json', 'blob'])) {
        $element['widget_settings'][$subfield]['cols'] = [
          '#type' => 'number',
          '#title' => $this->t('Columns'),
          '#default_value' => $widget_settings[$subfield]['cols'] ?? $widget_settings_default['cols'],
          '#min' => 1,
          '#description' => $this->t('How many columns wide the textarea should be'),
          '#states' => [
            'visible' => [
              $type_selector => [
                ['value' => 'textarea'],
                ['value' => 'json'],
              ],
            ],
          ],
        ];

        $element['widget_settings'][$subfield]['rows'] = [
          '#type' => 'number',
          '#title' => $this->t('Rows'),
          '#default_value' => $widget_settings[$subfield]['rows'] ?? $widget_settings_default['rows'],
          '#min' => 1,
          '#description' => $this->t('How many rows high the textarea should be.'),
          '#states' => [
            'visible' => [
              $type_selector => [
                ['value' => 'textarea'],
                ['value' => 'json'],
              ],
            ],
          ],
        ];
      }

      if (in_array($item["type"], ['file'])) {
        $element['widget_settings'][$subfield]['preview_image_style'] = [
          '#title' => $this->t('Preview image style'),
          '#type' => 'select',
          '#options' => image_style_options(FALSE),
          '#empty_option' => '<' . $this->t('no preview') . '>',
          '#default_value' => $widget_settings[$subfield]['preview_image_style'] ?? $widget_settings_default['preview_image_style'],
          '#description' => $this->t('The preview image will be shown while editing the content.'),
          '#states' => [
            'visible' => [
              $type_selector => [
                ['value' => 'image_image'],
              ],
            ],
          ],
        ];
      }

      $element['widget_settings'][$subfield]['weight'] = [
        '#type' => 'weight',
        '#title' => $this->t('Weight for fields'),
        // '#title_display' => 'invisible',
        '#default_value' => $widget_settings[$subfield]['weight'] ?? 0,
        '#weight' => 20,
      ];
    }

    return $element;
  }

  /**
   * {@inheritdoc}
   */
  public function settingsSummary(): array {
    $settings = $this->getSettings();
    $field_settings = $this->getFieldSettings();

    $summary = [];
    if (!empty($settings['inline'])) {
      $summary[] = $this->t('Display as inline element');
    }

    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']]);
      }
      switch ($settings['widget_settings'][$subfield]['type']) {
        case 'textfield':
        case 'email':
        case 'tel':
        case 'url':
          if (!empty($settings['widget_settings'][$subfield]['size'])) {
            $summary[] = $this->t('Size: @size', ['@size' => $settings['widget_settings'][$subfield]['size']]);
          }
          if (!empty($settings['widget_settings'][$subfield]['placeholder'])) {
            $summary[] = $this->t('Placeholder: @placeholder', ['@placeholder' => $settings['widget_settings'][$subfield]['placeholder']]);
          }
          break;

        case 'checkbox':
          if (!empty($settings['widget_settings'][$subfield]['label'])) {
            $summary[] = $this->t('Label: @label', ['@label' => $settings['widget_settings'][$subfield]['label']]);
          }
          break;

        case 'select':
          break;

        case 'textarea':
          if (!empty($settings['widget_settings'][$subfield]['cols'])) {
            $summary[] = $this->t('Columns: @cols', ['@cols' => $settings['widget_settings'][$subfield]['cols']]);
          }
          if (!empty($settings['widget_settings'][$subfield]['rows'])) {
            $summary[] = $this->t('Rows: @rows', ['@rows' => $settings['widget_settings'][$subfield]['rows']]);
          }
          if (!empty($settings[$subfield]['placeholder'])) {
            $summary[] = $this->t('Placeholder: @placeholder', ['@placeholder' => $settings['widget_settings'][$subfield]['placeholder']]);
          }
          break;
      }

    }

    return $summary;
  }

  /**
   * {@inheritdoc}
   */
  public function massageFormValues(array $values, array $form, FormStateInterface $form_state): array {
    $storage_settings = $this->getFieldSettings();
    foreach ($values as $delta => &$value) {
      $checkEmpty = [];
      foreach ($storage_settings['columns'] as $subfield => $item) {
        $checkEmpty[$subfield] = $value[$subfield];
        if (!empty($value[$subfield]) && is_array($value[$subfield])) {
          if (isset($value[$subfield]['value'])) {
            $value[$subfield] = $value[$subfield]['value'];
          }
          $isFile = $item['type'] == 'file';
          $entityType = $storage_settings["field_settings"][$subfield]["entity_reference_type"];
          $checkEntityFile = in_array($entityType, ['file', 'image']);
          if ($item['type'] == 'entity_reference' && $checkEntityFile) {
            $isFile = TRUE;
          }
          if ($isFile && is_array($value[$subfield])) {
            $value[$subfield] = current($value[$subfield]);
          }
        }
        if (!is_numeric($values[$delta][$subfield]) && empty($value[$subfield])) {
          $values[$delta][$subfield] = NULL;
        }
        elseif ($value[$subfield] instanceof DrupalDateTime) {
          $date = $value[$subfield];
          $storage_timezone = new \DateTimezone(FieldItem::DATETIME_STORAGE_TIMEZONE);
          $storage_format = $item['datetime_type'] == 'datetime'
            ? FieldItem::DATETIME_DATETIME_STORAGE_FORMAT
            : FieldItem::DATETIME_DATE_STORAGE_FORMAT;

          if ($item['datetime_type'] == 'year') {
            $storage_format = 'Y';
          }
          if ($item['datetime_type'] == 'time') {
            $storage_format = 'H:i:s';
          }
          if ($item['datetime_type'] == 'timestamp') {
            if ($item['type'] == 'date') {
              $storage_format = 'Y-m-d H:i:s';
              $values[$delta][$subfield] = $date->format($storage_format);
            }
            elseif ($item['type'] == 'datetime_iso8601') {
              $values[$delta][$subfield] = $date->setTimezone($storage_timezone)
                ->getTimestamp();
            }
            continue;
          }
          // Before it can be saved, the time entered by the user must be
          // converted to the storage time zone.
          $values[$delta][$subfield] = $date->setTimezone($storage_timezone)
            ->format($storage_format);
        }
      }
      if (count(array_filter($checkEmpty)) == 0) {
        unset($values[$delta]);
      }
    }
    $values = array_values($values);
    return $values;
  }

  /**
   * {@inheritDoc}
   */
  public static function convertWidgetType($storage_setting) {
    $type = 'textfield';

    switch ($storage_setting['type']) {
      case 'boolean':
        $type = 'checkbox';
        break;

      case 'json':
      case 'text':
        $type = 'textarea';
        break;

      case 'float':
      case 'integer':
      case 'numeric':
        $type = 'number';
        break;

      case 'datetime_iso8601':
        $type = 'date';
        if (!empty($storage_setting["datetime_type"])) {
          $type = $storage_setting["datetime_type"];
          if ($type == 'timespan') {
            $type = 'datetime_default';
          }
          if ($type == 'time') {
            $type = 'time';
          }
        }
        break;

      case 'date':
        if ($storage_setting["datetime_type"] == 'datetime') {
          $type = 'datetime';
        }
        if ($storage_setting["datetime_type"] == 'date') {
          $type = 'date';
        }
        break;

      case 'email':
        $type = 'email';
        break;

      case 'telephone':
        $type = 'tel';
        break;

      case 'uri':
        $type = 'url';
        break;

      case 'hidden':
        $type = 'hidden';
        break;

      case 'entity_reference':
        $type = 'entity_reference_autocomplete';
        break;

      case 'file':
      case 'blob':
        $type = 'file';
        break;
    }

    return $type;
  }

  /**
   * Returns available subwidgets.
   */
  public function getSubwidgets($subfield_type, bool $list = FALSE, $type = FALSE): array {
    $subwidgets = [];

    if (!empty($list)) {
      $subwidgets['select'] = $this->t('Select list');
      $subwidgets['radios'] = $this->t('Radio buttons');
    }

    switch ($subfield_type) {

      case 'boolean':
        $subwidgets['checkbox'] = $this->t('Checkbox');
        break;

      case 'string':
        $subwidgets['textfield'] = $this->t('Textfield');
        $subwidgets['email'] = $this->t('Email');
        $subwidgets['tel'] = $this->t('Telephone');
        $subwidgets['url'] = $this->t('Url');
        $subwidgets['color'] = $this->t('Color');
        $subwidgets['search'] = $this->t('Search');
        $subwidgets['hidden'] = $this->t('Hidden');
        $subwidgets['password'] = $this->t('Password');
        break;

      case 'email':
        $subwidgets['email'] = $this->t('Email');
        $subwidgets['textfield'] = $this->t('Textfield');
        break;

      case 'telephone':
        $subwidgets['tel'] = $this->t('Telephone');
        $subwidgets['textfield'] = $this->t('Textfield');
        break;

      case 'uri':
        $subwidgets['url'] = $this->t('Url');
        $subwidgets['textfield'] = $this->t('Textfield');
        $subwidgets['path'] = $this->t('Path');
        break;

      case 'text':
        $subwidgets['textarea'] = $this->t('Text area');
        $subwidgets['text_format'] = $this->t("Text (formatted, long)");
        break;

      case 'integer':
      case 'float':
      case 'numeric':
        $subwidgets['number'] = $this->t('Number');
        $subwidgets['textfield'] = $this->t('Textfield');
        $subwidgets['range'] = $this->t('Range');
        break;

      case 'json':
        $subwidgets['textarea'] = $this->t('Text area');
        $subwidgets['json'] = $this->t('Json editor');
        break;

      case 'date':
      case 'datetime_iso8601':
        $subwidgets['datetime'] = $this->t('Date time');
        if ($type == 'date') {
          $subwidgets['date'] = $this->t('Date only');
        }
        if ($type == 'time') {
          $subwidgets['time'] = $this->t('Time');
        }
        if ($type == 'week') {
          $subwidgets['week'] = $this->t('Week');
        }
        if ($type == 'month') {
          $subwidgets['month_year'] = $this->t('Month year');
        }
        if ($type == 'year') {
          $subwidgets['year'] = $this->t('Year');
        }
        if ($type == 'timestamp') {
          $subwidgets['timestamp'] = $this->t('Timestamp');
        }
        break;

      case 'entity_reference':
        if ($type == 'file') {
          $subwidgets['managed_file'] = $this->t('Uploading and saving file');
          break;
        }
        if ($type == 'image') {
          $subwidgets['image_image'] = $this->t('Image');
          break;
        }
        $pluginsWidget = $this->pluginManager->getOptions('entity_reference');
        foreach ($pluginsWidget as $option => $label) {
          // $plugin_class = DefaultFactory::getPluginClass($option,
          // $pluginManager->getDefinition($option));
          // it must be checked is applicable for entity reference.
          $subwidgets[$option] = $label;
        }
        break;

      case 'file':
        $subwidgets['managed_file'] = $this->t('Uploading and saving file');
        $subwidgets['image_image'] = $this->t('Image');
        if ($this->moduleHandler->moduleExists('media_library')) {
          $subwidgets['media_library'] = $this->t('Media library');
        }
        break;

      case 'blob':
        $subwidgets['file'] = $this->t('File');
        $subwidgets['textarea'] = $this->t('Text area');
        $subwidgets['hidden'] = $this->t('Hidden');
        break;

      case 'uuid':
        $subwidgets['uuid'] = $this->t('Universally unique identifiers');
        break;

    }
    if ($subfield_type == 'date' && $type) {
      switch ($type) {
        case 'timestamp':
          $subwidgets = [
            'timestamp' => $this->t('Timestamp'),
          ];
          break;
      }
    }

    return $subwidgets;
  }

  /**
   * 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) {
    /* @noinspection PhpUndefinedFieldInspection */
    // @see https://www.drupal.org/project/drupal/issues/2600790
    return isset($violation->arrayPropertyPath[0]) ? $element[$violation->arrayPropertyPath[0]] : $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 {
    $settings = parent::getSettings();
    $field_settings = $this->getFieldSettings();
    foreach ($field_settings['columns'] as $subfield => $item) {
      if ($item['type'] == 'entity_reference') {
        $item["datetime_type"] = $field_settings["field_settings"][$subfield]["entity_reference_type"];
      }
      $widget_types = (array) $this->getSubwidgets($item['type'], $field_settings["field_settings"][$subfield]['list'] ?? FALSE, $item["datetime_type"] ?? FALSE);
      // Use the first eligible widget type unless it is set explicitly.
      if (empty($settings['widget_settings'][$subfield]['type'])) {
        $settings['widget_settings'][$subfield]['type'] = array_key_first($widget_types);
      }
    }

    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"));
    $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 = [];
    $widget_settings_default = self::widgetDefault();
    foreach ($subfields as $subfield) {
      if (empty($storage[$subfield])) {
        continue;
      }
      if (empty($settings["widget_settings"][$subfield])) {
        $settings["widget_settings"][$subfield] = $widget_settings_default;
      }
      // $item = $storage[$subfield];
      $field_default = !empty($field_widget_default[$delta]) ? $field_widget_default[$delta][$subfield] : '';
      $default_value = $items[$delta]->{$subfield} ?? $field_default;
      $settings["widget_settings"][$subfield] += $widget_settings_default;
      $widget_type = $settings["widget_settings"][$subfield]["type"];
      $widget[$delta][$subfield] = [
        '#type' => $widget_type ?? $this->convertWidgetType($storage[$subfield]),
        '#default_value' => $default_value,
        '#subfield_settings' => $settings["widget_settings"][$subfield],
        '#wrapper_attributes' => ['class' => [Html::getId('data_field-subfield-form-item')]],
      ];
      if ($storage[$subfield]['type'] == 'datetime_iso8601') {
        if (!empty($field_settings[$subfield]["min"])) {
          $widget[$delta][$subfield]["#min"] = $field_settings[$subfield]["min"];
          if ($settings["widget_settings"][$subfield]["type"] == 'week') {
            $widget[$delta][$subfield]["#min"] = date('Y-\WW', strtotime($field_settings[$subfield]["min"]));
          }
          if ($settings["widget_settings"][$subfield]["type"] == 'month_year') {
            $widget[$delta][$subfield]["#min"] = date('Y-m', strtotime($field_settings[$subfield]["min"]));
          }
          if ($settings["widget_settings"][$subfield]["type"] == 'time') {
            $widget[$delta][$subfield]["#min"] = $field_settings[$subfield]["min"];
          }
        }
        if (!empty($field_settings[$subfield]["max"])) {
          $widget[$delta][$subfield]["#max"] = $field_settings[$subfield]["max"];
          if ($settings["widget_settings"][$subfield]["type"] == 'week') {
            $widget[$delta][$subfield]["#max"] = date('Y-\WW', strtotime($field_settings[$subfield]["max"]));
          }
          if ($settings["widget_settings"][$subfield]["type"] == 'month_year') {
            $widget[$delta][$subfield]["#max"] = date('Y-m', strtotime($field_settings[$subfield]["max"]));
          }
          if ($settings["widget_settings"][$subfield]["type"] == 'time') {
            $widget[$delta][$subfield]["#max"] = $field_settings[$subfield]["max"];
          }
        }
      }
      if ($storage[$subfield]['type'] == 'entity_reference' && !empty($field_settings[$subfield]["entity_reference_type"])) {
        $explode = explode(':', $field_settings[$subfield]["entity_reference_type"]);
        $reference_type = end($explode);
        $widget[$delta][$subfield]['#target_type'] = $reference_type;
        $widget[$delta][$subfield] = [
          '#type' => $widget_type ?? $this->convertWidgetType($storage[$subfield]),
          '#default_value' => $default_value,
        ];
        switch ($widget_type) {
          case 'options_buttons':
          case 'options_select':
            $entity_storage = $this->entityTypeManager->getStorage($reference_type);
            if ($reference_type == 'taxonomy_term' && !empty($field_settings[$subfield]["target_bundles"])) {
              $entities = $entity_storage->loadByProperties([
                'vid' => $field_settings[$subfield]["target_bundles"],
              ]);
            }
            elseif ($reference_type == 'user') {
              $entities = $entity_storage->loadByProperties([
                'status' => 1,
              ]);
            }
            elseif (!empty($field_settings[$subfield]["target_bundles"]) &&
              !in_array($field_settings[$subfield]["entity_reference_type"], [
                'file',
                'image',
              ])) {
              $entities = $entity_storage->loadByProperties(['type' => $field_settings[$subfield]["target_bundles"]]);
            }
            $options = [];
            if (!empty($entities)) {
              foreach ($entities as $id => $entity) {
                switch ($reference_type) {
                  case 'user':
                    $options[$id] = $entity->getDisplayName();
                    break;

                  case 'taxonomy_term':
                    $options[$id] = $entity->getName();
                    break;

                  case 'node':
                    $options[$id] = $entity->getTitle();
                    break;

                  default:
                    $options[$id] = $entity->label();
                    break;

                }
              }
            }
            $widget[$delta][$subfield]['#type'] = $widget_type == 'options_select' ? 'select' : 'radios';
            $widget[$delta][$subfield]['#options'] = $options;
            $widget[$delta][$subfield]['#empty_option'] = $this->t('- Select -');
            break;

          case 'entity_reference_autocomplete':
          case 'entity_reference_autocomplete_tags':
            if (is_numeric($default_value)) {
              $default_value = $this->entityTypeManager->getStorage($reference_type)
                ->load($default_value);
            }
            $widget[$delta][$subfield]['#default_value'] = $default_value;
            $widget[$delta][$subfield]['#type'] = 'entity_autocomplete';
            $widget[$delta][$subfield]['#maxlength'] = 1024;
            $widget[$delta][$subfield]['#tag'] = $widget_type == 'entity_reference_autocomplete_tags';
            $widget[$delta][$subfield]['#placeholder'] = implode(' ', [
              $this->t('Typing'),
              $field_settings[$subfield]["label"],
            ]);
            $widget[$delta][$subfield]['#target_type'] = $reference_type;
            $widget[$delta][$subfield]['#selection_handler'] = 'default';
            if ($reference_type == 'user') {
              $widget[$delta][$subfield]['#selection_settings'] = [
                'include_anonymous' => FALSE,
              ];
            }
            else {
              $bundle = $field_settings[$subfield]["target_bundles"];
              if (!empty($bundle)) {
                $widget[$delta][$subfield]['#autocreate'] = [
                  'bundle' => $bundle,
                ];
              }
              $widget[$delta][$subfield]['#selection_settings'] = [
                'target_bundles' => [$bundle],
              ];
            }
            break;

          default:
            if ($reference_type == 'taxonomy_term' && !empty($field_settings[$subfield]["target_bundles"])) {
              $widget[$delta][$subfield]['#type'] = 'select';
              $widget[$delta][$subfield]['#options'] = $this->loadVoc($field_settings[$subfield]["target_bundles"]);
              $widget[$delta][$subfield]['#empty_option'] = $this->t('- Select -');
            }
            break;
        }
      }

      switch ($widget_type) {

        case 'textfield':
        case 'email':
        case 'tel':
        case 'url':
          // Find out appropriate max length fot the element.
          $max_length_map = [
            'string' => $storage[$subfield]['max_length'],
            'telephone' => $storage[$subfield]['max_length'],
            'email' => Email::EMAIL_MAX_LENGTH,
            'uri' => 2048,
          ];
          if (isset($max_length_map[$widget_type])) {
            $widget[$delta][$subfield]['#maxlength'] = $max_length_map[$widget_type];
          }
          if (!empty($settings["widget_settings"][$subfield]['size'])) {
            $widget[$delta][$subfield]['#size'] = $settings["widget_settings"][$subfield]['size'];
          }
          if (!empty($settings["widget_settings"][$subfield]['placeholder'])) {
            $widget[$delta][$subfield]['#placeholder'] = $settings["widget_settings"][$subfield]['placeholder'];
          }
          break;

        case 'checkbox':
          $widget[$delta][$subfield]['#title'] = $settings["widget_settings"][$subfield]['label'];
          break;

        case 'select':
          $label = $field_settings[$subfield]['required'] ? $this->t('- Select a value -') : $this->t('- None -');
          $widget[$delta][$subfield]['#options'] = ['' => $label];
          if ($field_settings[$subfield]['list']) {
            $widget[$delta][$subfield]['#options'] += $field_settings[$subfield]['allowed_values'];
          }
          break;

        case 'radios':
          $label = $field_settings[$subfield]['required'] ? $this->t('N/A') : $this->t('- None -');
          $widget[$delta][$subfield]['#options'] = ['' => $label];
          if ($field_settings[$subfield]['list']) {
            $widget[$delta][$subfield]['#options'] += $field_settings[$subfield]['allowed_values'];
          }
          break;

        case 'textarea':
          if ($settings["widget_settings"][$subfield]['rows']) {
            $widget[$delta][$subfield]['#rows'] = $settings["widget_settings"][$subfield]['rows'];
          }
          if ($settings["widget_settings"][$subfield]['placeholder']) {
            $widget[$delta][$subfield]['#placeholder'] = $settings["widget_settings"][$subfield]['placeholder'];
          }
          break;

        case 'number':
        case 'range':
          if (in_array($storage[$subfield]["type"], [
            'integer',
            'float',
            'numeric',
          ])) {
            $widget[$delta][$subfield]['#step'] = 1;
            if (!empty($field_settings[$subfield]['min'])) {
              $widget[$delta][$subfield]['#min'] = $field_settings[$subfield]['min'];
            }
            if (!empty($field_settings[$subfield]['max'])) {
              $widget[$delta][$subfield]['#max'] = $field_settings[$subfield]['max'];
            }
            if ($storage[$subfield]["type"] == 'numeric') {
              $widget[$delta][$subfield]['#step'] = 0.1;
              if (!empty($storage[$subfield]['scale'])) {
                $widget[$delta][$subfield]['#step'] = pow(0.1, $storage[$subfield]['scale']);
              }
            }
            elseif ($storage[$subfield]["type"] == 'float') {
              $widget[$delta][$subfield]['#step'] = 'any';
            }
          }
          break;

        case 'date':
        case 'datetime':
          $widget[$delta][$subfield]['#default_value'] = $items[$delta]->createDate($subfield);
          if ($storage[$subfield]['datetime_type'] == 'date') {
            $widget[$delta][$subfield]['#date_time_element'] = 'none';
            $widget[$delta][$subfield]['#date_time_format'] = '';
            if ($storage[$subfield]["type"] != 'date') {
              $widget[$delta][$subfield]['#default_value'] = $items[$delta]->{$subfield};
            }
          }
          elseif ($storage[$subfield]['datetime_type'] == 'timestamp') {
            $widget[$delta][$subfield]['#date_timezone'] = date_default_timezone_get();
          }
          else {
            if (!empty($widget[$subfield]['#default_value'])) {
              $widget[$delta][$subfield]['#default_value']->setTimezone(new \DateTimezone(date_default_timezone_get()));
            }
            // Ensure that the datetime field processing doesn't set its own
            // time zone here.
            $widget[$delta][$subfield]['#date_timezone'] = date_default_timezone_get();
          }
          break;

        case 'time':
          if ($storage[$subfield]['type'] == 'datetime_iso8601') {
            $widget[$delta][$subfield]['#type'] = 'date';
            $widget[$delta][$subfield]['#date_timezone'] = date_default_timezone_get();
            $widget[$delta][$subfield]['#attributes']['type'] = 'time';
          }
          else {
            $widget[$delta][$subfield]['#default_value'] = $items[$delta]->createDate($subfield);
            $widget[$delta][$subfield]['#type'] = 'datetime';
            $widget[$delta][$subfield]['#date_timezone'] = date_default_timezone_get();
            $widget[$delta][$subfield]['#date_date_element'] = 'none';
            $widget[$delta][$subfield]['#date_time_element'] = 'time';
            $widget[$delta][$subfield]['#date_time_format'] = 'H:i';
          }
          break;

        case 'timestamp':
          $widget[$delta][$subfield]['#default_value'] = $items[$delta]->createDate($subfield);
          $widget[$delta][$subfield]['#type'] = 'datetime';
          $widget[$delta][$subfield]['#date_time_format'] = 'Y-m-d H:i:s';
          break;

        case 'week':
          $widget[$delta][$subfield]['#type'] = 'date';
          $widget[$delta][$subfield]['#date_timezone'] = date_default_timezone_get();
          $widget[$delta][$subfield]['#attributes']['type'] = 'week';
          break;

        case 'month_year':
          $widget[$delta][$subfield]['#type'] = 'date';
          $widget[$delta][$subfield]['#date_timezone'] = date_default_timezone_get();
          $widget[$delta][$subfield]['#date_date_format'] = 'm/Y';
          $widget[$delta][$subfield]['#date_date_element'] = 'month';
          $widget[$delta][$subfield]['#date_time_element'] = 'none';
          $widget[$delta][$subfield]['#attributes']['type'] = 'month';
          break;

        case 'year':
          $widget[$delta][$subfield]['#type'] = 'datelist';
          $widget[$delta][$subfield]['#date_timezone'] = date_default_timezone_get();
          $widget[$delta][$subfield]['#date_part_order'] = ['year'];
          $widget[$delta][$subfield]['#date_date_format'] = 'Y';
          $widget[$delta][$subfield]['#date_date_element'] = 'year';
          $widget[$delta][$subfield]['#date_time_element'] = 'none';
          $widget[$delta][$subfield]['#date_year_range'] = date('Y') - 20 . ':' . (date('Y') + 10);
          if (!empty($field_settings[$subfield]["min"]) && !empty($field_settings[$subfield]["max"])) {
            $widget[$delta][$subfield]['#date_year_range'] = date('Y', strtotime($field_settings[$subfield]["min"])) . ':' . date('Y', strtotime($field_settings[$subfield]["max"]));
          }
          if ($storage[$subfield]['type'] == 'date') {
            if (!is_object($widget[$delta][$subfield]["#default_value"])) {
              $widget[$delta][$subfield]['#default_value'] = $items[$delta]->createDate($subfield);
            }
          }
          elseif (!empty($items[$delta]->{$subfield})) {
            $widget[$delta][$subfield]['#default_value'] = DrupalDateTime::createFromFormat('Y', $items[$delta]->{$subfield});
          }
          break;

        case 'managed_file':
        case 'image_image':
        case 'media_library':
          $fieldName = str_replace('field_', '', $this->fieldDefinition->getName());
          $widget[$delta][$subfield]['#upload_location'] = 'public://' . $fieldName . '/';
          if (!empty($items[$delta]->{$subfield})) {
            $widget[$delta][$subfield]["#default_value"] = [$items[$delta]->{$subfield}];
          }
          if (!empty($field_settings[$subfield]["file_directory"])) {
            $widget[$delta][$subfield]['#upload_location'] = 'public://' . $field_settings[$subfield]["file_directory"] . '/';
          }
          if (!empty($field_settings[$subfield]["file_extensions"])) {
            $field_settings[$subfield]["file_extensions"] = str_replace(
              [',', '  '], ' ',
              $field_settings[$subfield]["file_extensions"]
            );
            $widget[$delta][$subfield]['#upload_validators'] = [
              'file_validate_extensions' => [$field_settings[$subfield]["file_extensions"]],
            ];
          }
          if ($widget_type == 'image_image') {
            $widget[$delta][$subfield]["#type"] = 'managed_file';
            $widget[$delta][$subfield]["#upload_validators"] = [
              'file_validate_extensions' => ['gif png jpg jpeg'],
            ];
            $preview = $settings["widget_settings"][$subfield]["preview_image_style"];
            $widget[$delta][$subfield]['#theme'] = 'image_widget';
            $widget[$delta][$subfield]['#preview_image_style'] = $preview ?? 'medium';
          }
          if ($widget_type == 'media_library') {
            $widget[$delta][$subfield] = [
              '#type' => 'entity_autocomplete',
              '#target_type' => 'media',
              "#default_value" => [$items[$delta]->{$subfield}],
              '#allowed_bundles' => [
                'audio', 'document', 'image',
                'video', 'remote_video',
              ],
            ];
            if ($this->moduleHandler->moduleExists('media_library_form_element')) {
              $widget[$delta][$subfield]['#type'] = 'media_library';
            }
          }
          break;

        case 'json':
          $id = Html::getUniqueId($items->getName() . '-' . $delta);
          $widget[$delta][$subfield]["#type"] = 'textarea';
          $widget[$delta][$subfield]['#attached']['library'] = ['datafield/json_editor'];
          $widget[$delta][$subfield]['#description'] = '<div id="' . $id . '"></div>';
          $widget[$delta][$subfield]['#attributes'] = [
            'data-json-editor' => $this->getSetting('mode'),
            'data-id' => $id,
            'class' => ['json-editor', 'js-hide', $this->getSetting('mode')],
          ];
          break;
      }
    }
    return $widget;
  }

  /**
   * Loads the tree of a vocabulary.
   *
   * {@inheritdoc}
   */
  public function loadVoc($vocabulary) {
    $terms = $this->entityTypeManager->getStorage('taxonomy_term')->loadTree($vocabulary);
    $tree = [];
    foreach ($terms as $tree_object) {
      $this->buildTree($tree, $tree_object, $vocabulary);
    }

    return $tree;
  }

  /**
   * Populates a tree array given a taxonomy term tree object.
   *
   * {@inheritdoc}
   */
  protected function buildTree(&$tree, $object, $vocabulary, $level = 1) {
    if ($object->depth != 0 || $object->status == 0) {
      return;
    }
    $tree[$object->tid] = $object->name;
    $children = $this->entityTypeManager->getStorage('taxonomy_term')
      ->loadChildren($object->tid);
    if (!$children) {
      return;
    }

    $child_tree_objects = $this->entityTypeManager->getStorage('taxonomy_term')
      ->loadTree($vocabulary, $object->tid);

    foreach ($children as $child) {
      foreach ($child_tree_objects as $child_tree_object) {
        if ($child_tree_object->tid == $child->id()) {
          $child_tree_object->name = str_repeat('-', $level) . $child_tree_object->name;
          $this->buildTree($tree, $child_tree_object, $vocabulary, $level + 1);
        }
      }
    }
  }

}

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

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