external_entities-8.x-2.x-dev/src/Plugin/ExternalEntities/DataProcessor/DefaultProcessor.php

src/Plugin/ExternalEntities/DataProcessor/DefaultProcessor.php
<?php

namespace Drupal\external_entities\Plugin\ExternalEntities\DataProcessor;

use Drupal\Core\Datetime\DrupalDateTime;
use Drupal\Core\Field\FieldDefinitionInterface;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Logger\LoggerChannelFactoryInterface;
use Drupal\Core\StringTranslation\TranslationInterface;
use Drupal\Core\TypedData\Plugin\DataType\DateTimeIso8601;
use Drupal\Core\TypedData\PrimitiveInterface;
use Drupal\Core\TypedData\Type\DateTimeInterface;
use Drupal\Core\TypedData\TypedDataManagerInterface;
use Drupal\datetime\Plugin\Field\FieldType\DateTimeItem;
use Drupal\datetime\Plugin\Field\FieldType\DateTimeItemInterface;
use Drupal\external_entities\DataProcessor\DataProcessorBase;
use Symfony\Component\DependencyInjection\ContainerInterface;

/**
 * This plugin handles field property data type auto-detection for type cast.
 *
 * @DataProcessor(
 *   id = "default",
 *   label = @Translation("Auto detect datatype with default"),
 *   description = @Translation("Data processor using Drupal field definition to auto-detect datatype to use. The datatype can also be forced. A default value can be provided if the external value is missing (NULL).")
 * )
 *
 * @package Drupal\external_entities\Plugin\ExternalEntities\DataProcessor
 */
class DefaultProcessor extends DataProcessorBase {

  /**
   * The typed data manager.
   *
   * @var \Drupal\Core\TypedData\TypedDataManagerInterface
   */
  protected $typedDataManager;

  /**
   * Constructs a DefaultProcessor object.
   *
   * The configuration parameters is expected to contain the external entity
   * type (key ExternalEntityTypeInterface::XNTT_TYPE_PROP), the field name
   * (key 'field_name') and the property name (key 'property_name') this data
   * processor will work on.
   *
   * @param array $configuration
   *   A configuration array containing information about the plugin instance.
   * @param string $plugin_id
   *   The identifier for the plugin instance.
   * @param mixed $plugin_definition
   *   The plugin implementation definition.
   * @param \Drupal\Core\StringTranslation\TranslationInterface $string_translation
   *   The string translation service.
   * @param \Drupal\Core\Logger\LoggerChannelFactoryInterface $logger_factory
   *   The logger channel factory.
   * @param \Drupal\Core\TypedData\TypedDataManagerInterface $typed_data_manager
   *   The typed data manager.
   */
  public function __construct(
    array $configuration,
    string $plugin_id,
    $plugin_definition,
    TranslationInterface $string_translation,
    LoggerChannelFactoryInterface $logger_factory,
    TypedDataManagerInterface $typed_data_manager,
  ) {
    parent::__construct(
      $configuration,
      $plugin_id,
      $plugin_definition,
      $string_translation,
      $logger_factory
    );
    $this->typedDataManager = $typed_data_manager;
  }

  /**
   * {@inheritdoc}
   */
  public static function create(
    ContainerInterface $container,
    array $configuration,
    $plugin_id,
    $plugin_definition,
  ) {
    return new static(
      $configuration,
      $plugin_id,
      $plugin_definition,
      $container->get('string_translation'),
      $container->get('logger.factory'),
      $container->get('typed_data_manager')
    );
  }

  /**
   * {@inheritdoc}
   */
  public function defaultConfiguration() {
    return [
      'datatype' => '',
      'default' => NULL,
    ];
  }

  /**
   * {@inheritdoc}
   */
  public function buildConfigurationForm(
    array $form,
    FormStateInterface $form_state,
  ) {
    $form = parent::buildConfigurationForm($form, $form_state);
    $processor_id = ($form['#attributes']['id'] ??= uniqid('dp', TRUE));
    $config = $this->getConfiguration();
    $primitive_types = array_filter(
      $this->typedDataManager->getDefinitions(),
      function ($d) {
        return is_subclass_of($d['class'], PrimitiveInterface::class);
      }
    );
    $options = ['' => $this->t('- Auto detect -')];
    foreach ($primitive_types as $type => $definition) {
      $options[$type] = $definition['label'];
    }
    sort($options);

    $form['datatype'] = [
      '#type' => 'select',
      '#title' => $this->t('Force data type'),
      '#options' => $options,
      '#default_value' => $config['datatype'] ?? '',
    ];

    $form['set_default'] = [
      '#type' => 'checkbox',
      '#title' => $this->t('Set a default value'),
      '#description' => $this->t('If checked, the default value below will be used if the source data is empty.'),
      '#default_value' => isset($config['default']),
      '#attributes' => [
        'data-xntt-default-processor-selector' => $processor_id . 'sd',
      ],
    ];
    $form['default'] = [
      '#type' => 'textfield',
      '#title' => $this->t('Default value'),
      '#description' => $this->t('Value to use if the source data is empty. Leave empty to not set any default value.'),
      '#default_value' => $config['default'] ?? '',
      '#states' => [
        'visible' => [
          'input[data-xntt-default-processor-selector="' . $processor_id . 'sd"]' => [
            'checked' => TRUE,
          ],
        ],
      ],
    ];

    return $form;
  }

  /**
   * {@inheritdoc}
   */
  public function submitConfigurationForm(
    array &$form,
    FormStateInterface $form_state,
  ) {
    // Check if a default should be set.
    if (!$form_state->getValue('set_default', FALSE)) {
      $form_state->setValue('default', NULL);
    }
    $form_state->unsetValue('set_default');
    parent::submitConfigurationForm($form, $form_state);
  }

  /**
   * {@inheritdoc}
   */
  public function processData(
    array $raw_data,
    FieldDefinitionInterface $field_definition,
    string $property_name,
  ) :array {
    $data = [];
    $config = $this->getConfiguration();

    // Check for a default value to provide.
    if (empty($raw_data) && isset($config['default'])) {
      $raw_data[] = $config['default'];
    }

    if (!empty($config['datatype'])) {
      // Create the typed data instance.
      $typed_data = $this->typedDataManager->create(
        $this->typedDataManager->createDataDefinition($config['datatype'])
      );
    }
    else {
      // Auto-detect.
      // Create the typed data instance.
      $property_definition = $field_definition
        ->getFieldStorageDefinition()
        ->getPropertyDefinition($property_name);
      $typed_data = $this->typedDataManager->create($property_definition);
    }

    foreach ($raw_data as $entry) {
      // Check for NULL.
      $entry ??= $config['default'] ?? NULL;
      if (!isset($entry)) {
        // Do not process a NULL value (but keep delta for other values).
        $data[] = NULL;
        continue;
      }

      // Provide rudimentary support for datetime-based fields by making sure
      // they are in the format as expected by Drupal.
      if (is_subclass_of($typed_data, DateTimeInterface::class)) {
        $timestamp = !is_numeric($entry)
          ? strtotime($entry)
          : $entry;

        if (is_numeric($timestamp)) {
          if ($typed_data instanceof DateTimeIso8601) {
            $datetime_type = $field_definition
              ->getFieldStorageDefinition()
              ->getSetting('datetime_type');

            if ($datetime_type === DateTimeItem::DATETIME_TYPE_DATE) {
              $storage_format = DateTimeItemInterface::DATE_STORAGE_FORMAT;
            }
            else {
              $storage_format = DateTimeItemInterface::DATETIME_STORAGE_FORMAT;
            }

            // Use setValue so timezone is not set.
            $typed_data->setValue(gmdate($storage_format, $timestamp));
          }
          else {
            $typed_data->setDateTime(
              DrupalDateTime::createFromTimestamp($timestamp)
            );
          }
        }
      }
      else {
        $typed_data->setValue($entry);
      }

      // Convert the property value to the correct PHP type as expected by this
      // specific property type.
      if ($typed_data instanceof PrimitiveInterface) {
        $entry = $typed_data->getCastedValue();
      }

      $data[] = $entry;
    }

    return $data;
  }

  /**
   * {@inheritdoc}
   */
  public function reverseDataProcessing(
    array $data,
    array $original_data,
    FieldDefinitionInterface $field_definition,
    string $property_name,
  ) :array|null {
    // @todo Implement...
    return $data;
  }

  /**
   * {@inheritdoc}
   */
  public function couldReverseDataProcessing() :bool {
    return TRUE;
  }

  /**
   * {@inheritdoc}
   */
  public function mayAlterData() :bool {
    // No data alteration, just a type cast.
    return FALSE;
  }

}

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

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