external_entities-8.x-2.x-dev/src/Plugin/ExternalEntities/PropertyMapper/PropertyMultiMapping.php

src/Plugin/ExternalEntities/PropertyMapper/PropertyMultiMapping.php
<?php

namespace Drupal\external_entities\Plugin\ExternalEntities\PropertyMapper;

use Drupal\Component\Plugin\PluginManagerInterface;
use Drupal\Component\Utility\NestedArray;
use Drupal\Core\Entity\EntityFieldManagerInterface;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Logger\LoggerChannelFactoryInterface;
use Drupal\Core\StringTranslation\TranslationInterface;
use Drupal\external_entities\FieldMapper\FieldMapperBase;
use Drupal\external_entities\Form\AjaxFormTrait;
use Drupal\external_entities\PropertyMapper\MultiMapperTrait;
use Drupal\external_entities\PropertyMapper\PropertyMapperBase;
use Symfony\Component\DependencyInjection\ContainerInterface;

/**
 * This mapper enables to use multiple property mapper for same property.
 *
 * @PropertyMapper(
 *   id = "multi",
 *   label = @Translation("Multiple mapping"),
 *   description = @Translation("Applies multiple mappings on a same property and allows asymetry between loading and saving."),
 *   field_properties = {
 *     "*:*"
 *   }
 * )
 *
 * @package Drupal\external_entities\Plugin\ExternalEntities\PropertyMapper
 */
class PropertyMultiMapping extends PropertyMapperBase {

  use AjaxFormTrait;
  use MultiMapperTrait;

  /**
   * Only aggregate first non-empty mapping.
   */
  const AGGREGATE_FIRST = 'first';

  /**
   * Merge all mappings.
   */
  const AGGREGATE_MERGE = 'merge';

  /**
   * {@inheritdoc}
   */
  public function __construct(
    array $configuration,
    string $plugin_id,
    $plugin_definition,
    TranslationInterface $string_translation,
    LoggerChannelFactoryInterface $logger_factory,
    EntityFieldManagerInterface $entity_field_manager,
    PluginManagerInterface $data_processor_manager,
    PluginManagerInterface $property_mapper_manager,
  ) {
    parent::__construct(
      $configuration,
      $plugin_id,
      $plugin_definition,
      $string_translation,
      $logger_factory,
      $entity_field_manager,
      $data_processor_manager
    );
    $this->setPropertyMapperManager($property_mapper_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('entity_field.manager'),
      $container->get('plugin.manager.external_entities.data_processor'),
      $container->get('plugin.manager.external_entities.property_mapper')
    );
  }

  /**
   * {@inheritdoc}
   */
  public function defaultConfiguration() {
    return [
      'load' => [],
      'save' => [],
      'aggregation' => static::AGGREGATE_MERGE,
      // Do not provide default property mappers as we later use
      // NestedArray::mergeDeep() which could lead into invalid
      // 'property_mappers' configuration.
      'property_mappers' => [],
      'required_field' => FALSE,
      'main_property' => FALSE,
    ];
  }

  /**
   * {@inheritdoc}
   */
  public function buildConfigurationForm(
    array $form,
    FormStateInterface $form_state,
  ) {
    $form += parent::buildConfigurationForm($form, $form_state);
    $config = $this->getConfiguration();
    unset($form['mapping']);
    unset($form['data_processors']);

    $property_mappers_count = max(
        1,
        $form_state->get('pmc_' . $this->getPropertyMapperFormIdentifier($form))
        ?? count($config['property_mappers'] ?? []),
    );
    $form_state->set(
      'pmc_' . $this->getPropertyMapperFormIdentifier($form),
      $property_mappers_count
    );
    $form['property_mappers'] = [
      '#type' => 'container',
      // If #parents is not set here, sub-element names will not follow the tree
      // structure.
      '#parents' => [...($form['#parents'] ?? []), 'property_mappers'],
      '#attributes' => [
        'id' => $this->getPropertyMapperFormIdentifier($form) . '_mul',
      ],
    ];
    for ($i = 0; $i < $property_mappers_count; ++$i) {
      if (!isset($form['property_mappers'][$i])) {
        $form['property_mappers'][$i] = [
          '#type' => 'fieldset',
          '#title' => $this->t('Mapping "@num"', ['@num' => $i + 1]),
          '#parents' => [...($form['#parents'] ?? []), 'property_mappers', $i],
          '#attributes' => [
            'id' => $this->getPropertyMapperFormIdentifier($form) . '_mul' . $i,
          ],
          'id' => [],
          'config' => [],
        ];
        if (1 < $property_mappers_count) {
          $form['property_mappers'][$i]['remove_mapper'] = [
            '#type' => 'submit',
            '#value' => $this->t('Remove this mapping'),
            '#name' => 'rempm_' . $this->getPropertyMapperFormIdentifier($form) . '_' . $i,
            '#ajax' => [
              'callback' => '::buildAjaxParentSubForm',
              'wrapper' => $form['property_mappers']['#attributes']['id'],
              'method' => 'replaceWith',
              'effect' => 'fade',
            ],
          ];
        }
      }
      $property_mapper_id = $form_state->getValue(
      ['property_mappers', $i, 'id'],
      $config['property_mappers'][$i]['id']
          ?? FieldMapperBase::DEFAULT_PROPERTY_MAPPER
      );
      $this->buildPropertyMapperSelectForm($form, $form_state, $property_mapper_id, $i);
      $this->buildPropertyMapperConfigForm($form, $form_state, $property_mapper_id, $i);
    }
    $form['property_mappers']['add_mapper'] = [
      '#type' => 'submit',
      '#value' => $this->t('Add another mapping'),
      '#name' => 'addpm_' . $this->getPropertyMapperFormIdentifier($form),
      '#ajax' => [
        'callback' => '::buildAjaxParentSubForm',
        'wrapper' => $form['property_mappers']['#attributes']['id'],
        'method' => 'replaceWith',
        'effect' => 'fade',
      ],
    ];

    $load_mappers = implode(
      ',',
      array_map(
        function ($element) {
          return $element + 1;
        },
        $config['load'] ?? [0]
      )
    );
    $form['load_list'] = [
      '#type' => 'textfield',
      '#title' => $this->t('Property mappers used for loading'),
      '#description' => $this->t('Ordered list of property mapper indexes to use when loading data, separated by commas. Use the numbers of the mappers above.'),
      '#default_value' => $load_mappers,
    ];
    $form['aggregation'] = [
      '#type' => 'radios',
      '#title' => $this->t('How to handle multiple mapping when loading?'),
      '#default_value' => $config['aggregation'],
      '#options' => [
        static::AGGREGATE_FIRST => $this->t('stop at first non-empty mapping'),
        static::AGGREGATE_MERGE => $this->t('merge all mappings'),
      ],
    ];
    $save_mappers = implode(
      ',',
      array_map(
        function ($element) {
          return $element + 1;
        },
        $config['save'] ?? []
      )
    );
    $form['save_list'] = [
      '#type' => 'textfield',
      '#title' => $this->t('Property mappers used for saving'),
      '#description' => $this->t('Ordered list of property mapper indexes to use when saving data, separated by commas. Use the numbers of the mappers above.'),
      '#default_value' => $save_mappers,
    ];

    $form['#attached']['library'][] = 'external_entities/external_entities';
    return $form;
  }

  /**
   * {@inheritdoc}
   */
  public function validateConfigurationForm(array &$form, FormStateInterface $form_state) {
    // Check for Ajax events.
    $pmc_count_prop = 'pmc_' . $this->getPropertyMapperFormIdentifier($form);
    $property_mappers_count = $form_state->get($pmc_count_prop);
    if ($trigger = $form_state->getTriggeringElement()) {
      $pm_id = $form['#attributes']['id'] ?? '';
      if ("addpm_$pm_id" == $trigger['#name']) {
        ++$property_mappers_count;
        $form_state->set($pmc_count_prop, $property_mappers_count);
        $form_state->setRebuild(TRUE);
      }
      elseif (preg_match("#^rempm_\\Q$pm_id\\E_(\\d+)\$#", $trigger['#name'], $matches)) {
        $mapper_number = $matches[1];
        if (isset($mapper_number)) {
          --$property_mappers_count;
          $form_state->set($pmc_count_prop, $property_mappers_count);
          // Reorder property mapper configs.
          $user_input = $form_state->getUserInput();
          $property_mappers = NestedArray::getValue(
            $user_input,
            $form['property_mappers']['#parents'] ?? []
          );
          for ($config_number = $mapper_number; $config_number < $property_mappers_count; ++$config_number) {
            // Shift form values.
            $form_state->setValueForElement(
              $form['property_mappers'][$config_number],
              $form_state->getValue(
                ['property_mappers', $config_number + 1]
                )
              );
            $property_mappers[$config_number] =
              $property_mappers[$config_number + 1];
          }
          NestedArray::setValue(
            $user_input,
            $form['property_mappers']['#parents'] ?? [],
            $property_mappers
          );
          $form_state->setUserInput($user_input);
          $form_state->setRebuild(TRUE);
        }
      }
    }

    parent::validateConfigurationForm($form, $form_state);
    for ($i = 0; $i < $property_mappers_count; ++$i) {
      $this->validatePropertyMapperConfigurationForm($form, $form_state, $i);
    }

    $load_mappers = [];
    $load_list = explode(',', $form_state->getValue('load_list', ''));
    foreach ($load_list as $load_mapper) {
      $value = trim($load_mapper);
      if (!is_numeric($value)
          || ($value < 1)
          || ($value > $property_mappers_count)
      ) {
        $form_state->setErrorByName(
          'load_list',
          $this->t(
            'Invalid property mapper index "@index" in load list.',
            ['@index' => $load_mapper]
          )
        );
        continue;
      }
      $load_mappers[] = $value - 1;
    }
    $form_state->setValue('load', $load_mappers);

    $save_mappers = [];
    $save_list = explode(',', $form_state->getValue('save_list', ''));
    foreach ($save_list as $save_mapper) {
      $value = trim($save_mapper);
      if (!is_numeric($value)
          || ($value < 1)
          || ($value > $property_mappers_count)
      ) {
        $form_state->setErrorByName(
          'save_list',
          $this->t(
            'Invalid property mapper index "@index" in save list.',
            ['@index' => $save_mapper]
          )
        );
        continue;
      }
      $save_mappers[] = $value - 1;
    }
    $form_state->setValue('save', $save_mappers);

    // If rebuild needed, ignore validation.
    if ($form_state->isRebuilding()) {
      $form_state->clearErrors();
    }
  }

  /**
   * {@inheritdoc}
   */
  public function submitConfigurationForm(array &$form, FormStateInterface $form_state) {
    $property_mappers = $form_state->getValue('property_mappers', []);
    unset($property_mappers['add_mapper']);
    $form_state->setValue('property_mappers', $property_mappers);
    $property_mappers_count = $form_state->get('pmc_' . $this->getPropertyMapperFormIdentifier($form));
    for ($i = 0; $i < $property_mappers_count; ++$i) {
      $this->submitPropertyMapperConfigurationForm($form, $form_state, $i);
    }
    $form_state->unsetValue('load_list');
    $form_state->unsetValue('save_list');
    $form_state->unsetValue('data_processors');

    parent::submitConfigurationForm($form, $form_state);
  }

  /**
   * {@inheritdoc}
   */
  public function addPropertyValuesToRawData(
    array $property_values,
    array &$raw_data,
    array &$context,
  ) {
    $config = $this->getConfiguration();
    // If saving is disabled, stop here.
    if (empty($config['save'])) {
      return;
    }

    foreach ($config['save'] as $index) {
      if (empty($config['property_mappers'][$index]['id'])) {
        // Invalid index, skip it.
        continue;
      }
      $property_mapper = $this->getPropertyMapper($index);
      $property_mapper->addPropertyValuesToRawData(
        $property_values,
        $raw_data,
        $context
      );
    }
  }

  /**
   * {@inheritdoc}
   */
  public function getMappedSourceFieldName() :?string {
    if ($this->isProcessed()) {
      return NULL;
    }
    return NULL;
  }

  /**
   * {@inheritdoc}
   */
  public function extractPropertyValuesFromRawData(
    array $raw_data,
    array &$context = [],
  ) :array {
    $config = $this->getConfiguration();
    // If loading is disabled, stop here.
    if (empty($config['load'])) {
      return [];
    }

    $result_data = [];
    foreach ($config['load'] as $index) {
      if (empty($config['property_mappers'][$index]['id'])) {
        // Invalid index, skip it.
        continue;
      }
      $property_mapper = $this->getPropertyMapper($index);
      if (static::AGGREGATE_MERGE === $config['aggregation']) {
        $result_data = NestedArray::mergeDeep(
          $result_data,
          $property_mapper->extractPropertyValuesFromRawData(
            $raw_data,
            $context
          )
        );
      }
      elseif (static::AGGREGATE_FIRST === $config['aggregation']) {
        $result_data = $property_mapper->extractPropertyValuesFromRawData(
            $raw_data,
            $context
        );
        foreach ($result_data ?? [] as $value) {
          if (!empty($value) || is_numeric($value)) {
            break 2;
          }
        }
      }
    }
    return $result_data;
  }

}

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

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