external_entities-8.x-2.x-dev/src/PropertyMapper/MultiMapperTrait.php

src/PropertyMapper/MultiMapperTrait.php
<?php

namespace Drupal\external_entities\PropertyMapper;

use Drupal\Component\Plugin\PluginManagerInterface;
use Drupal\Component\Utility\NestedArray;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Plugin\PluginFormInterface;
use Drupal\external_entities\Entity\ExternalEntityTypeInterface;
use Drupal\external_entities\FieldMapper\FieldMapperBase;
use Drupal\external_entities\Form\XnttSubformState;

/**
 * Trait to handle multiple mappings.
 *
 * Classes using this trait should set the property mapper manager in their
 * constructor using method ::setPropertyMapperManager(). Otherwise it will
 * rely on \Drupal::service() to get it.
 *
 * Their configuration must include a 'property_mappers' array with a list of
 * property mappers arrays (['id' => '<property_mapper_id>', 'config => [...]]).
 *
 * @package Drupal\external_entities\Plugin\ExternalEntities\PropertyMapper
 */
trait MultiMapperTrait {

  /**
   * The property mapper manager.
   *
   * @var \Drupal\Component\Plugin\PluginManagerInterface
   */
  protected $propertyMapperManager;

  /**
   * Gets the property mapper manager.
   *
   * @return \Drupal\Component\Plugin\PluginManagerInterface
   *   The property mapper manager.
   */
  protected function getPropertyMapperManager(): PluginManagerInterface {
    if (!$this->propertyMapperManager) {
      $this->propertyMapperManager = \Drupal::service('plugin.manager.external_entities.property_mapper');
    }
    return $this->propertyMapperManager;
  }

  /**
   * Sets the property mapper manager.
   *
   * @param \Drupal\Component\Plugin\PluginManagerInterface $property_mapper_manager
   *   The property mapper manager.
   */
  public function setPropertyMapperManager(PluginManagerInterface $property_mapper_manager): void {
    $this->propertyMapperManager = $property_mapper_manager;
  }

  /**
   * Returns an option list of property mappers.
   *
   * @return array
   *   An array of property mapper options, keyed by property mapper ID.
   */
  protected function getPropertyMapperOptions(): array {
    // Get field definition to list compatible property mappers.
    $xntt_type_id = $this->externalEntityType->getDerivedEntityTypeId();
    $field_definition = $this
      ->entityFieldManager
      ->getFieldDefinitions($xntt_type_id, $xntt_type_id)[$this->fieldName]
      ?? NULL;
    if (empty($field_definition)) {
      return [];
    }
    $field_type = $field_definition->getType();
    $property_mappers = $this
      ->propertyMapperManager
      ->getCompatiblePropertyMappers($field_type, $this->propertyName);
    if (empty($property_mappers)) {
      return [];
    }

    // Generate the list of compatible property mappers.
    $property_mapper_options = [];
    foreach ($property_mappers as $property_mapper_id => $definition) {
      $property_mapper_config = $this->getPropertyMapperDefaultConfiguration();
      $property_mapper = $this->propertyMapperManager->createInstance(
        $property_mapper_id,
        $property_mapper_config
      );
      $property_mapper_options[$property_mapper_id] =
        $property_mapper->getLabel();
    }

    return $property_mapper_options;
  }

  /**
   * Build a form element for selecting a field property mapper.
   *
   * @param array &$form
   *   The form array.
   * @param \Drupal\Core\Form\FormStateInterface $form_state
   *   The form state.
   * @param string $selected_property_mapper_id
   *   Selected property mapper.
   * @param int|string $index
   *   Index of the property mapper to configure.
   */
  public function buildPropertyMapperSelectForm(
    array &$form,
    FormStateInterface $form_state,
    string $selected_property_mapper_id,
    int|string $index,
  ) {

    $property_mapper_options = $this->getPropertyMapperOptions();

    $config_wrapper_id =
      $this->getPropertyMapperFormIdentifier($form)
      . '_'
      . $index
      . '_config';

    $form['property_mappers'][$index]['id'] = [
      '#type' => 'select',
      '#title' => $this->t('Mapping type:'),
      '#default_value' => $selected_property_mapper_id,
      '#options' => $property_mapper_options,
      '#sort_options' => TRUE,
      '#empty_value' => NULL,
      '#empty_option' => NULL,
      '#required' => TRUE,
      '#wrapper_attributes' => ['class' => ['xntt-inline']],
      '#attributes' => [
        'class' => ['xntt-field'],
        'autocomplete' => 'off',
      ],
      '#label_attributes' => ['class' => ['xntt-label']],
      '#ajax' => [
        'callback' => [get_class($this), 'buildAjaxParentSubForm'],
        'wrapper' => $config_wrapper_id,
        'method' => 'replaceWith',
        'effect' => 'fade',
      ],
    ];
  }

  /**
   * Build a form element for configuring a field property mapping.
   *
   * @param array &$form
   *   The form array.
   * @param \Drupal\Core\Form\FormStateInterface $form_state
   *   The form state.
   * @param string $selected_property_mapper_id
   *   Selected property mapper.
   * @param int|string $index
   *   Index of the property mapper to configure.
   */
  public function buildPropertyMapperConfigForm(
    array &$form,
    FormStateInterface $form_state,
    string $selected_property_mapper_id,
    int|string $index,
  ) {
    if (empty($selected_property_mapper_id)) {
      // No property mapper, do not change the form and stop here.
      return;
    }

    $config = $this->getConfiguration();
    if (!empty($config['property_mappers'][$index]['id'])
      && $config['property_mappers'][$index]['id'] === $selected_property_mapper_id
    ) {
      $property_mapper_config = NestedArray::mergeDeep(
        $this->getPropertyMapperDefaultConfiguration(),
        ($config['property_mappers'][$index]['config'] ?? [])
      );
    }
    else {
      $property_mapper_config = $this->getPropertyMapperDefaultConfiguration();
    }

    // Generate a new property mapper instance.
    $property_mapper = $this->propertyMapperManager->createInstance(
      $selected_property_mapper_id,
      $property_mapper_config
    );

    $property_mapper_form_state = XnttSubformState::createForSubform(
      ['property_mappers', $index, 'config'],
      $form,
      $form_state
    );
    $config_wrapper_id =
      $this->getPropertyMapperFormIdentifier($form)
      . '_'
      . $index
      . '_config';
    $form['property_mappers'][$index]['config'] = [
      '#type' => 'container',
      // If #parents is not set here, sub-element names will not follow the tree
      // structure.
      '#parents' => [...($form['#parents'] ?? []), 'property_mappers', $index, 'config'],
      '#attributes' => [
        'id' => $config_wrapper_id,
      ],
    ];
    $form['property_mappers'][$index]['config'] =
      $property_mapper->buildConfigurationForm(
        $form['property_mappers'][$index]['config'],
        $property_mapper_form_state
      );
  }

  /**
   * Returns default values to create a property mapper.
   *
   * This configuration includes internal elements that must not be serialized
   * such as the reference to current external entity.
   *
   * @return array
   *   The property mapper default configuration with internal elements.
   */
  protected function getPropertyMapperDefaultConfiguration() :array {
    $external_entity_type = $this->getExternalEntityType();
    return [
      ExternalEntityTypeInterface::XNTT_TYPE_PROP => $external_entity_type,
      'field_name' => $this->fieldName,
      'property_name' => $this->propertyName,
      'main_property' => $this->getConfiguration()['main_property'] ?? FALSE,
      'required_field' => in_array($this->fieldName, $external_entity_type->getRequiredFields()),
      'debug_level' => $this->getDebugLevel(),
    ];
  }

  /**
   * Return the property mapper instance to use.
   *
   * @param int|string $index
   *   Index of the property mapper to get (default 0).
   *
   * @return \Drupal\external_entities\PropertyMapper\PropertyMapperInterface
   *   The configured property mapper instance.
   */
  protected function getPropertyMapper(int|string $index = 0) :PropertyMapperInterface {
    $config = $this->getConfiguration();
    $property_mapper_config = NestedArray::mergeDeep(
      $this->getPropertyMapperDefaultConfiguration(),
      ($config['property_mappers'][$index]['config'] ?? [])
    );
    $property_mapper = $this->propertyMapperManager->createInstance(
      $config['property_mappers'][$index]['id']
        ?? FieldMapperBase::DEFAULT_PROPERTY_MAPPER,
      $property_mapper_config
    );
    return $property_mapper;
  }

  /**
   * Validate handler for property mapper configuration forms.
   *
   * @param array &$form
   *   The form array.
   * @param \Drupal\Core\Form\FormStateInterface $form_state
   *   The form state.
   * @param int|string $index
   *   Index of the property mapper to validate (default 0).
   */
  public function validatePropertyMapperConfigurationForm(
    array &$form,
    FormStateInterface $form_state,
    int|string $index = 0,
  ) {
    $property_mapper_id = $form_state->getValue(
      ['property_mappers', $index, 'id']
    );
    if (!empty($property_mapper_id)) {
      $property_mapper_config = $this->getPropertyMapperDefaultConfiguration();
      $property_mapper = $this->propertyMapperManager->createInstance(
        $property_mapper_id,
        $property_mapper_config
      );
      if ($property_mapper instanceof PluginFormInterface) {
        $property_mapper_form_state = XnttSubformState::createForSubform(
          ['property_mappers', $index, 'config'],
          $form,
          $form_state
        );
        $property_mapper->validateConfigurationForm(
          $form['property_mappers'][$index]['config'],
          $property_mapper_form_state
        );
      }
    }
  }

  /**
   * Submit handler for property mapper configuration forms.
   *
   * @param array &$form
   *   The form array.
   * @param \Drupal\Core\Form\FormStateInterface $form_state
   *   The form state.
   * @param int|string $index
   *   Index of the property mapper to submit (default 0).
   */
  public function submitPropertyMapperConfigurationForm(
    array &$form,
    FormStateInterface $form_state,
    int|string $index = 0,
  ) {
    $property_mappers = $form_state->getValue('property_mappers', []);
    $property_mapper_id = $form_state->getValue(
      ['property_mappers', $index, 'id']
    );

    if (!empty($property_mapper_id)) {
      $property_mapper_config = $this->getPropertyMapperDefaultConfiguration();
      $property_mapper = $this->propertyMapperManager->createInstance(
        $property_mapper_id,
        $property_mapper_config
      );
      if ($property_mapper instanceof PluginFormInterface) {
        $property_mapper_form_state = XnttSubformState::createForSubform(
          ['property_mappers', $index, 'config'],
          $form,
          $form_state
        );
        $property_mapper->submitConfigurationForm(
          $form['property_mappers'][$index]['config'],
          $property_mapper_form_state
        );
        $property_mappers[$index] = [
          'id' => $property_mapper_id,
          'config' => $property_mapper->getConfiguration(),
        ];
      }
    }
    $form_state->setValue('property_mappers', $property_mappers);
  }

}

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

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