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

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

namespace Drupal\external_entities\Plugin\ExternalEntities\PropertyMapper;

use Drupal\Component\Utility\NestedArray;
use Drupal\Core\Form\FormStateInterface;
use Drupal\external_entities\FieldMapper\FieldMapperInterface;
use Drupal\external_entities\PropertyMapper\PropertyMapperBase;

/**
 * This is a simple field expression property mapper.
 *
 * It uses a basic syntax to select a single sub-field or set of sub-fields.
 * Sub-fields are selected using a "dot" syntax (".") and multiple sub-fields
 * using a jocker symbol "*".
 * Examples:
 * - 'some_field'
 * - 'some_field.*'
 * - 'field_level_1.sub_field_a.*.value'
 *
 * @PropertyMapper(
 *   id = "simple",
 *   label = @Translation("Simple"),
 *   description = @Translation("Maps a property to a raw data field using a simple field path expression. Use dots (.) to separate sub-field names and stars (*) to map all keys or all values at a given level. Ex.: 'some_field' or 'some_field.*' or 'field_level_1.sub_field_a.*.value'."),
 *   field_properties = {
 *     "*:*"
 *   }
 * )
 *
 * @package Drupal\external_entities\Plugin\ExternalEntities\PropertyMapper
 */
class SimplePropertyMapper extends PropertyMapperBase {

  /**
   * {@inheritdoc}
   */
  public function getMappedSourceFieldName() :?string {
    if ($this->isProcessed()) {
      return NULL;
    }
    $source_field = NULL;
    if (FALSE === strpos($this->getConfiguration()['mapping'], '*')) {
      $source_field = $this->getConfiguration()['mapping'];
    }
    return $source_field;
  }

  /**
   * {@inheritdoc}
   */
  public function addPropertyValuesToRawData(
    array $property_values,
    array &$raw_data,
    array &$context,
  ) {
    $config = $this->getConfiguration();
    if (isset($config['mapping'])
      && ('' != $config['mapping'])
    ) {
      // Reverse data processing.
      $mapping_keys = explode('.', $config['mapping'] ?? '');
      $original_data =
        $context[FieldMapperInterface::CONTEXT_SOURCE_KEY]
        ?? NULL;
      if (!isset($original_data)) {
        $original_data = [];
      }
      elseif (!is_array($original_data)) {
        $original_data = [$original_data];
      }
      $original_data = $this->recursiveMapSourceFieldFromRawData(
        $original_data,
        $mapping_keys,
        [],
        0
      );
      $property_values = $this->reverseDataProcessing(
        $property_values,
        $original_data,
      );

      // Map property values back to raw data.
      $delta_index = 0;
      foreach ($property_values as $value) {
        $qualified_mapping = str_replace('*', $delta_index, $config['mapping']);
        $mapping_keys = explode('.', $qualified_mapping);
        NestedArray::setValue($raw_data, $mapping_keys, $value);
        $delta_index++;
      }
      // Clear remaining extra items if some.
      if (FALSE !== strpos($config['mapping'], '*')) {
        do {
          $qualified_mapping = str_replace('*', $delta_index, $config['mapping']);
          $mapping_keys = explode('.', $qualified_mapping);
          NestedArray::unsetValue($raw_data, $mapping_keys, $unset);
          $delta_index++;
        } while ($unset);
      }
    }
  }

  /**
   * Populates the values of a field raw by recursively navigating mapping keys.
   *
   * @param array $raw_data
   *   The raw values to map into the output.
   * @param array $remaining_mapping_keys
   *   All the mapping keys that remain to be examined recursively.
   * @param array $seen_mapping_keys
   *   All the mapping keys that have been examined so far.
   * @param int $field_delta
   *   The current delta within the field being populated.
   *
   * @return array
   *   The list of property values or an empty array.
   */
  protected function recursiveMapSourceFieldFromRawData(
    array $raw_data,
    array $remaining_mapping_keys,
    array $seen_mapping_keys,
    int $field_delta,
  ): array {
    $current_mapping_key = array_shift($remaining_mapping_keys);

    // Case 1: End of recursion -- set the field property value.
    if ($current_mapping_key === NULL) {
      return $this->extractRawData(
        $raw_data,
        $seen_mapping_keys,
        $field_delta
      );
    }
    // Case 2: Iterate and recurse over a list of values.
    elseif ($current_mapping_key == '*') {
      return $this->recursiveMapListFieldFromRawData(
        $raw_data,
        $remaining_mapping_keys,
        $seen_mapping_keys
      );
    }
    // Case 3: Recurse into a single-valued key of the raw data.
    else {
      $new_seen_mapping_keys =
        array_merge($seen_mapping_keys, [$current_mapping_key]);

      return $this->recursiveMapSourceFieldFromRawData(
        $raw_data,
        $remaining_mapping_keys,
        $new_seen_mapping_keys,
        $field_delta
      );
    }
  }

  /**
   * Populates the field property based on the provided keys.
   *
   * This function takes the provided keys as input and
   * populates the corresponding field property.
   *
   * @param array $raw_data
   *   The raw values from which to obtain the field value.
   * @param array $raw_keys
   *   The nested array keys of the raw data that designate the location in the
   *   raw data where the value is to be extracted.
   * @param int $field_delta
   *   The current delta within the field being populated.
   *
   * @return array
   *   List of property values.
   */
  protected function extractRawData(
    array $raw_data,
    array $raw_keys,
    int $field_delta,
  ): array {
    $property_value = NestedArray::getValue($raw_data, $raw_keys);
    return is_array($property_value) ? $property_value : [$property_value];
  }

  /**
   * Extracts a list of values from the raw data and populates the equivalent.
   *
   * @param array $raw_data
   *   The raw values from which to obtain the list values.
   * @param array $remaining_mapping_keys
   *   All the mapping keys that remain to be examined recursively.
   * @param array $seen_mapping_keys
   *   All the mapping keys that have been examined so far.
   */
  protected function recursiveMapListFieldFromRawData(
    array $raw_data,
    array $remaining_mapping_keys,
    array $seen_mapping_keys,
  ): array {
    $raw_values = NestedArray::getValue($raw_data, $seen_mapping_keys);
    $field_values = [];

    if (!is_array($raw_values)) {
      $raw_values = [$raw_values];
    }

    for ($delta_index = 0; $delta_index < count($raw_values); ++$delta_index) {
      // Map both numeric and text keys to values.
      $raw_keys = array_keys($raw_values);
      $new_seen_mapping_keys = array_merge(
        $seen_mapping_keys,
        [$raw_keys[$delta_index]]
      );

      $values = $this->recursiveMapSourceFieldFromRawData(
        $raw_data,
        $remaining_mapping_keys,
        $new_seen_mapping_keys,
        $delta_index
      );
      $field_values[] = reset($values);
    }
    return $field_values;
  }

  /**
   * {@inheritdoc}
   */
  public function extractPropertyValuesFromRawData(
    array $raw_data,
    array &$context = [],
  ) :array {
    $config = $this->getConfiguration();
    if (!empty($config['mapping'])) {
      $mapping_keys = explode('.', $config['mapping'] ?? '');
      $raw_data = $this->recursiveMapSourceFieldFromRawData(
        $raw_data,
        $mapping_keys,
        [],
        0
      );
    }
    else {
      $raw_data = [];
    }
    return $this->processData($raw_data);
  }

  /**
   * {@inheritdoc}
   */
  public function submitConfigurationForm(array &$form, FormStateInterface $form_state) {
    $mapping = $form_state->getValue('mapping', '');
    // Replace old field separation syntax.
    $mapping = str_replace('/', '.', $mapping);
    $form_state->setValue('mapping', $mapping);
    parent::submitConfigurationForm($form, $form_state);
  }

}

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

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