migrate_plus-8.x-5.x-dev/src/DataParserPluginBase.php

src/DataParserPluginBase.php
<?php

declare(strict_types=1);

namespace Drupal\migrate_plus;

use Drupal\Core\Plugin\ContainerFactoryPluginInterface;
use Drupal\Core\Plugin\PluginBase;
use Symfony\Component\DependencyInjection\ContainerInterface;

/**
 * Defines a base data parser implementation.
 *
 * @see \Drupal\migrate_plus\Annotation\DataParser
 * @see \Drupal\migrate_plus\DataParserPluginInterface
 * @see \Drupal\migrate_plus\DataParserPluginManager
 * @see plugin_api
 */
abstract class DataParserPluginBase extends PluginBase implements DataParserPluginInterface, ContainerFactoryPluginInterface {

  /**
   * List of source urls.
   *
   * @var string[]
   */
  protected ?array $urls;

  /**
   * Index of the currently-open url.
   */
  protected ?int $activeUrl = NULL;

  /**
   * String indicating how to select an item's data from the source.
   *
   * @var string|int
   */
  protected $itemSelector;

  /**
   * Current item when iterating.
   *
   * @var mixed
   */
  protected $currentItem = NULL;

  /**
   * Value of the ID for the current item when iterating.
   */
  protected ?array $currentId = NULL;

  /**
   * The data retrieval client.
   */
  protected DataFetcherPluginInterface $dataFetcher;

  public function __construct(
    array $configuration,
    $plugin_id,
    $plugin_definition,
    protected DataFetcherPluginManager $fetcherPluginManager,
  ) {
    parent::__construct($configuration, $plugin_id, $plugin_definition);
    $this->urls = $configuration['urls'];
    $this->itemSelector = $configuration['item_selector'] ?? '';
  }

  /**
   * {@inheritdoc}
   */
  public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition): self {
    return new static(
      $configuration,
      $plugin_id,
      $plugin_definition,
      $container->get('plugin.manager.migrate_plus.data_fetcher'),
    );
  }

  /**
   * Returns the initialized data fetcher plugin.
   */
  public function getDataFetcherPlugin(): DataFetcherPluginInterface {
    if (!isset($this->dataFetcher)) {
      $this->dataFetcher = $this->fetcherPluginManager->createInstance($this->configuration['data_fetcher_plugin'], $this->configuration);
    }
    return $this->dataFetcher;
  }

  /**
   * {@inheritdoc}
   */
  public function rewind(): void {
    $this->activeUrl = NULL;
    $this->next();
  }

  /**
   * {@inheritdoc}
   */
  public function next(): void {
    $this->currentItem = $this->currentId = NULL;
    if (is_null($this->activeUrl)) {
      if (!$this->nextSource()) {
        // No data to import.
        return;
      }
    }
    // At this point, we have a valid open source url, try to fetch a row from
    // it.
    $this->fetchNextRow();
    // If there was no valid row there, try the next url (if any).
    if (is_null($this->currentItem)) {
      while ($this->nextSource()) {
        $this->fetchNextRow();
        if ($this->valid()) {
          break;
        }
      }
    }
    if ($this->valid()) {
      foreach ($this->configuration['ids'] as $id_field_name => $id_info) {
        $this->currentId[$id_field_name] = $this->currentItem[$id_field_name];
      }
    }
  }

  /**
   * Opens the specified URL.
   *
   * @param string $url
   *   URL to open.
   */
  abstract protected function openSourceUrl(string $url): bool;

  /**
   * Retrieves the next row of data. populating currentItem.
   */
  abstract protected function fetchNextRow(): void;

  /**
   * Advances the data parser to the next source url.
   */
  protected function nextSource(): bool {
    if (empty($this->urls)) {
      return FALSE;
    }

    while ($this->activeUrl === NULL || (count($this->urls) - 1) > $this->activeUrl) {
      if (is_null($this->activeUrl)) {
        $this->activeUrl = 0;
      }
      else {
        // Increment the activeUrl so we try to load the next source.
        ++$this->activeUrl;
        if ($this->activeUrl >= count($this->urls)) {
          return FALSE;
        }
      }

      if ($this->openSourceUrl($this->urls[$this->activeUrl])) {
        if (!empty($this->configuration['pager'])) {
          $this->addNextUrls($this->activeUrl);
        }
        // We have a valid source.
        return TRUE;
      }
    }

    return FALSE;
  }

  /**
   * Add next page of source data following the active URL.
   *
   * @param int $activeUrl
   *   The index within the source URL array to insert the next URL resource.
   *   This is parameterized to enable custom plugins to control the ordering of
   *   next URLs injected into the source URL backlog.
   */
  protected function addNextUrls(int $activeUrl = 0): void {
    $next_urls = $this->getNextUrls($this->urls[$this->activeUrl]);

    if (!empty($next_urls)) {
      array_splice($this->urls, $activeUrl + 1, 0, $next_urls);
      $this->urls = array_values(array_unique($this->urls));
    }
  }

  /**
   * Collected the next urls from a paged response.
   *
   * @param string $url
   *   URL of the currently active source.
   *
   * @return array
   *   Array of URLs representing next paged resources.
   */
  protected function getNextUrls(string $url): array {
    return $this->getDataFetcherPlugin()->getNextUrls($url);
  }

  /**
   * {@inheritdoc}
   */
  public function current(): mixed {
    return $this->currentItem;
  }

  /**
   * {@inheritdoc}
   */
  public function currentUrl(): ?string {
    $index = $this->activeUrl ?: \array_key_first($this->urls);

    return $this->urls[$index] ?? NULL;
  }

  /**
   * {@inheritdoc}
   */
  public function key(): ?array {
    return $this->currentId;
  }

  /**
   * {@inheritdoc}
   */
  public function valid(): bool {
    return !empty($this->currentItem);
  }

  /**
   * {@inheritdoc}
   */
  public function count(): int {
    return iterator_count($this);
  }

  /**
   * Return the selectors used to populate each configured field.
   *
   * @return string[]
   *   Array of selectors, keyed by field name.
   */
  protected function fieldSelectors(): array {
    $fields = [];
    foreach ($this->configuration['fields'] as $field_info) {
      if (isset($field_info['selector'])) {
        $fields[$field_info['name']] = $field_info['selector'];
      }
    }
    return $fields;
  }

}

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

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