abstract class SourcePluginBase in Zircon Profile 8
Same name and namespace in other branches
- 8.0 core/modules/migrate/src/Plugin/migrate/source/SourcePluginBase.php \Drupal\migrate\Plugin\migrate\source\SourcePluginBase
The base class for all source plugins.
Hierarchy
- class \Drupal\Component\Plugin\PluginBase implements DerivativeInspectionInterface, PluginInspectionInterface- class \Drupal\Core\Plugin\PluginBase uses DependencySerializationTrait, StringTranslationTrait- class \Drupal\migrate\Plugin\migrate\source\SourcePluginBase implements MigrateSourceInterface
 
 
- class \Drupal\Core\Plugin\PluginBase uses DependencySerializationTrait, StringTranslationTrait
Expanded class hierarchy of SourcePluginBase
See also
\Drupal\migrate\Plugin\MigratePluginManager
\Drupal\migrate\Annotation\MigrateSource
\Drupal\migrate\Plugin\MigrateSourceInterface
Related topics
1 file declares its use of SourcePluginBase
- MigrateSourceTest.php in core/modules/ migrate/ tests/ src/ Unit/ MigrateSourceTest.php 
- Contains \Drupal\Tests\migrate\Unit\MigrateSourceTest.
File
- core/modules/ migrate/ src/ Plugin/ migrate/ source/ SourcePluginBase.php, line 28 
- Contains \Drupal\migrate\Plugin\migrate\source\SourcePluginBase.
Namespace
Drupal\migrate\Plugin\migrate\sourceView source
abstract class SourcePluginBase extends PluginBase implements MigrateSourceInterface {
  /**
   * @var \Drupal\Core\Extension\ModuleHandlerInterface
   */
  protected $moduleHandler;
  /**
   * @var \Drupal\migrate\Entity\MigrationInterface
   */
  protected $migration;
  /**
   * The name and type of the highwater property in the source.
   *
   * @var array
   *
   * @see $originalHighwater
   */
  protected $highWaterProperty;
  /**
   * The current row from the query
   *
   * @var \Drupal\Migrate\Row
   */
  protected $currentRow;
  /**
   * The primary key of the current row
   *
   * @var array
   */
  protected $currentSourceIds;
  /**
   * The high water mark at the beginning of the import operation.
   *
   * If the source has a property for tracking changes (like Drupal ha
   * node.changed) then this is the highest value of those imported so far.
   *
   * @var int
   */
  protected $originalHighWater;
  /**
   * Whether this instance should cache the source count.
   *
   * @var bool
   */
  protected $cacheCounts = FALSE;
  /**
   * Key to use for caching counts.
   *
   * @var string
   */
  protected $cacheKey;
  /**
   * Whether this instance should not attempt to count the source.
   *
   * @var bool
   */
  protected $skipCount = FALSE;
  /**
   * If TRUE, we will maintain hashed source rows to determine whether incoming
   * data has changed.
   *
   * @var bool
   */
  protected $trackChanges = FALSE;
  /**
   * By default, next() will directly read the map row and add it to the data
   * row. A source plugin implementation may do this itself (in particular, the
   * SQL source can incorporate the map table into the query) - if so, it should
   * set this TRUE so we don't duplicate the effort.
   *
   * @var bool
   */
  protected $mapRowAdded = FALSE;
  /**
   * @var \Drupal\Core\Cache\CacheBackendInterface
   */
  protected $cache;
  /**
   * @var \Drupal\migrate\Plugin\MigrateIdMapInterface
   */
  protected $idMap;
  /**
   * @var \Iterator
   */
  protected $iterator;
  /**
   * {@inheritdoc}
   */
  public function __construct(array $configuration, $plugin_id, $plugin_definition, MigrationInterface $migration) {
    parent::__construct($configuration, $plugin_id, $plugin_definition);
    $this->migration = $migration;
    // Set up some defaults based on the source configuration.
    $this->cacheCounts = !empty($configuration['cache_counts']);
    $this->skipCount = !empty($configuration['skip_count']);
    $this->cacheKey = !empty($configuration['cache_key']) ? !empty($configuration['cache_key']) : NULL;
    $this->trackChanges = !empty($configuration['track_changes']) ? $configuration['track_changes'] : FALSE;
    $this->idMap = $this->migration
      ->getIdMap();
    // Pull out the current highwater mark if we have a highwater property.
    if ($this->highWaterProperty = $this->migration
      ->get('highWaterProperty')) {
      $this->originalHighWater = $this->migration
        ->getHighWater();
    }
    // Don't allow the use of both highwater and track changes together.
    if ($this->highWaterProperty && $this->trackChanges) {
      throw new MigrateException('You should either use a highwater mark or track changes not both. They are both designed to solve the same problem');
    }
  }
  /**
   * Initialize the iterator with the source data.
   *
   * @return array
   *   An array of the data for this source.
   */
  protected abstract function initializeIterator();
  /**
   * Get the module handler.
   *
   * @return \Drupal\Core\Extension\ModuleHandlerInterface
   *   The module handler.
   */
  protected function getModuleHandler() {
    if (!isset($this->moduleHandler)) {
      $this->moduleHandler = \Drupal::moduleHandler();
    }
    return $this->moduleHandler;
  }
  /**
   * {@inheritdoc}
   */
  public function prepareRow(Row $row) {
    $result = TRUE;
    try {
      $result_hook = $this
        ->getModuleHandler()
        ->invokeAll('migrate_prepare_row', array(
        $row,
        $this,
        $this->migration,
      ));
      $result_named_hook = $this
        ->getModuleHandler()
        ->invokeAll('migrate_' . $this->migration
        ->id() . '_prepare_row', array(
        $row,
        $this,
        $this->migration,
      ));
      // We will skip if any hook returned FALSE.
      $skip = $result_hook && in_array(FALSE, $result_hook) || $result_named_hook && in_array(FALSE, $result_named_hook);
      $save_to_map = TRUE;
    } catch (MigrateSkipRowException $e) {
      $skip = TRUE;
      $save_to_map = $e
        ->getSaveToMap();
    }
    // We're explicitly skipping this row - keep track in the map table.
    if ($skip) {
      // Make sure we replace any previous messages for this item with any
      // new ones.
      if ($save_to_map) {
        $this->idMap
          ->saveIdMapping($row, array(), MigrateIdMapInterface::STATUS_IGNORED);
        $this->currentRow = NULL;
        $this->currentSourceIds = NULL;
      }
      $result = FALSE;
    }
    elseif ($this->trackChanges) {
      // When tracking changed data, We want to quietly skip (rather than
      // "ignore") rows with changes. The caller needs to make that decision,
      // so we need to provide them with the necessary information (before and
      // after hashes).
      $row
        ->rehash();
    }
    return $result;
  }
  /**
   * Returns the iterator that will yield the row arrays to be processed.
   *
   * @return \Iterator
   */
  protected function getIterator() {
    if (!isset($this->iterator)) {
      $this->iterator = $this
        ->initializeIterator();
    }
    return $this->iterator;
  }
  /**
   * {@inheritdoc}
   */
  public function current() {
    return $this->currentRow;
  }
  /**
   * Get the iterator key.
   *
   * Implementation of Iterator::key - called when entering a loop iteration,
   * returning the key of the current row. It must be a scalar - we will
   * serialize to fulfill the requirement, but using getCurrentIds() is
   * preferable.
   */
  public function key() {
    return serialize($this->currentSourceIds);
  }
  /**
   * Whether the iterator is currently valid.
   *
   * Implementation of Iterator::valid() - called at the top of the loop,
   * returning TRUE to process the loop and FALSE to terminate it
   */
  public function valid() {
    return isset($this->currentRow);
  }
  /**
   * Rewind the iterator.
   *
   * Implementation of Iterator::rewind() - subclasses of MigrateSource should
   * implement performRewind() to do any class-specific setup for iterating
   * source records.
   */
  public function rewind() {
    $this
      ->getIterator()
      ->rewind();
    $this
      ->next();
  }
  /**
   * {@inheritdoc}
   *
   * The migration iterates over rows returned by the source plugin. This
   * method determines the next row which will be processed and imported into
   * the system.
   *
   * The method tracks the source and destination IDs using the ID map plugin.
   *
   * This also takes care about highwater support. Highwater allows to reimport
   * rows from a previous migration run, which got changed in the meantime.
   * This is done by specifying a highwater field, which is compared with the
   * last time, the migration got executed (originalHighWater).
   */
  public function next() {
    $this->currentSourceIds = NULL;
    $this->currentRow = NULL;
    // In order to find the next row we want to process, we ask the source
    // plugin for the next possible row.
    while (!isset($this->currentRow) && $this
      ->getIterator()
      ->valid()) {
      $row_data = $this
        ->getIterator()
        ->current() + $this->configuration;
      $this
        ->getIterator()
        ->next();
      $row = new Row($row_data, $this->migration
        ->getSourcePlugin()
        ->getIds(), $this->migration
        ->get('destinationIds'));
      // Populate the source key for this row.
      $this->currentSourceIds = $row
        ->getSourceIdValues();
      // Pick up the existing map row, if any, unless getNextRow() did it.
      if (!$this->mapRowAdded && ($id_map = $this->idMap
        ->getRowBySource($this->currentSourceIds))) {
        $row
          ->setIdMap($id_map);
      }
      // Clear any previous messages for this row before potentially adding
      // new ones.
      if (!empty($this->currentSourceIds)) {
        $this->idMap
          ->delete($this->currentSourceIds, TRUE);
      }
      // Preparing the row gives source plugins the chance to skip.
      if ($this
        ->prepareRow($row) === FALSE) {
        continue;
      }
      // Check whether the row needs processing.
      // 1. This row has not been imported yet.
      // 2. Explicitly set to update.
      // 3. The row is newer than the current highwater mark.
      // 4. If no such property exists then try by checking the hash of the row.
      if (!$row
        ->getIdMap() || $row
        ->needsUpdate() || $this
        ->aboveHighwater($row) || $this
        ->rowChanged($row)) {
        $this->currentRow = $row
          ->freezeSource();
      }
    }
  }
  /**
   * Check if the incoming data is newer than what we've previously imported.
   *
   * @param \Drupal\migrate\Row $row
   *   The row we're importing.
   *
   * @return bool
   *   TRUE if the highwater value in the row is greater than our current value.
   */
  protected function aboveHighwater(Row $row) {
    return $this->highWaterProperty && $row
      ->getSourceProperty($this->highWaterProperty['name']) > $this->originalHighWater;
  }
  /**
   * Check if the incoming row has changed since our last import.
   *
   * @param \Drupal\migrate\Row $row
   *   The row we're importing.
   *
   * @return bool
   *   TRUE if the row has changed otherwise FALSE.
   */
  protected function rowChanged(Row $row) {
    return $this->trackChanges && $row
      ->changed();
  }
  /**
   * Getter for currentSourceIds data member.
   */
  public function getCurrentIds() {
    return $this->currentSourceIds;
  }
  /**
   * Get the source count.
   *
   * Return a count of available source records, from the cache if appropriate.
   * Returns -1 if the source is not countable.
   *
   * @param bool $refresh
   *   Whether or not to refresh the count.
   *
   * @return int
   *   The count.
   */
  public function count($refresh = FALSE) {
    if ($this->skipCount) {
      return -1;
    }
    if (!isset($this->cacheKey)) {
      $this->cacheKey = hash('sha256', $this
        ->getPluginId());
    }
    // If a refresh is requested, or we're not caching counts, ask the derived
    // class to get the count from the source.
    if ($refresh || !$this->cacheCounts) {
      $count = $this
        ->getIterator()
        ->count();
      $this
        ->getCache()
        ->set($this->cacheKey, $count);
    }
    else {
      // Caching is in play, first try to retrieve a cached count.
      $cache_object = $this
        ->getCache()
        ->get($this->cacheKey, 'cache');
      if (is_object($cache_object)) {
        // Success.
        $count = $cache_object->data;
      }
      else {
        // No cached count, ask the derived class to count 'em up, and cache
        // the result.
        $count = $this
          ->getIterator()
          ->count();
        $this
          ->getCache()
          ->set($this->cacheKey, $count);
      }
    }
    return $count;
  }
  /**
   * Get the cache object.
   *
   * @return \Drupal\Core\Cache\CacheBackendInterface
   *   The cache object.
   */
  protected function getCache() {
    if (!isset($this->cache)) {
      $this->cache = \Drupal::cache('migrate');
    }
    return $this->cache;
  }
}Members
| Name   | Modifiers | Type | Description | Overrides | 
|---|---|---|---|---|
| DependencySerializationTrait:: | protected | property | An array of service IDs keyed by property name used for serialization. | |
| DependencySerializationTrait:: | public | function | 1 | |
| DependencySerializationTrait:: | public | function | 2 | |
| MigrateSourceInterface:: | public | function | Returns available fields on the source. | 64 | 
| MigrateSourceInterface:: | public | function | Defines the source fields uniquely identifying a source row. None of these fields should contain a NULL value - if necessary, use prepareRow() or hook_migrate_prepare_row() to rewrite NULL values to appropriate empty values (such as '' or 0). | 64 | 
| MigrateSourceInterface:: | public | function | 4 | |
| PluginBase:: | protected | property | Configuration information passed into the plugin. | 2 | 
| PluginBase:: | protected | property | The plugin implementation definition. | |
| PluginBase:: | protected | property | The plugin_id. | |
| PluginBase:: | constant | A string which is used to separate base plugin IDs from the derivative ID. | ||
| PluginBase:: | public | function | Gets the base_plugin_id of the plugin instance. Overrides DerivativeInspectionInterface:: | |
| PluginBase:: | public | function | Gets the derivative_id of the plugin instance. Overrides DerivativeInspectionInterface:: | |
| PluginBase:: | public | function | Gets the definition of the plugin implementation. Overrides PluginInspectionInterface:: | |
| PluginBase:: | public | function | Gets the plugin_id of the plugin instance. Overrides PluginInspectionInterface:: | |
| SourcePluginBase:: | protected | property | ||
| SourcePluginBase:: | protected | property | Whether this instance should cache the source count. | |
| SourcePluginBase:: | protected | property | Key to use for caching counts. | |
| SourcePluginBase:: | protected | property | The current row from the query | |
| SourcePluginBase:: | protected | property | The primary key of the current row | |
| SourcePluginBase:: | protected | property | The name and type of the highwater property in the source. | |
| SourcePluginBase:: | protected | property | ||
| SourcePluginBase:: | protected | property | ||
| SourcePluginBase:: | protected | property | By default, next() will directly read the map row and add it to the data row. A source plugin implementation may do this itself (in particular, the SQL source can incorporate the map table into the query) - if so, it should set this TRUE so we… | |
| SourcePluginBase:: | protected | property | ||
| SourcePluginBase:: | protected | property | ||
| SourcePluginBase:: | protected | property | The high water mark at the beginning of the import operation. | |
| SourcePluginBase:: | protected | property | Whether this instance should not attempt to count the source. | |
| SourcePluginBase:: | protected | property | If TRUE, we will maintain hashed source rows to determine whether incoming data has changed. | |
| SourcePluginBase:: | protected | function | Check if the incoming data is newer than what we've previously imported. | |
| SourcePluginBase:: | public | function | Get the source count. | 3 | 
| SourcePluginBase:: | public | function | ||
| SourcePluginBase:: | protected | function | Get the cache object. | |
| SourcePluginBase:: | public | function | Getter for currentSourceIds data member. | |
| SourcePluginBase:: | protected | function | Returns the iterator that will yield the row arrays to be processed. | |
| SourcePluginBase:: | protected | function | Get the module handler. | |
| SourcePluginBase:: | abstract protected | function | Initialize the iterator with the source data. | 4 | 
| SourcePluginBase:: | public | function | Get the iterator key. | |
| SourcePluginBase:: | public | function | The migration iterates over rows returned by the source plugin. This method determines the next row which will be processed and imported into the system. | |
| SourcePluginBase:: | public | function | Add additional data to the row. Overrides MigrateSourceInterface:: | 33 | 
| SourcePluginBase:: | public | function | Rewind the iterator. | |
| SourcePluginBase:: | protected | function | Check if the incoming row has changed since our last import. | |
| SourcePluginBase:: | public | function | Whether the iterator is currently valid. | |
| SourcePluginBase:: | public | function | Constructs a Drupal\Component\Plugin\PluginBase object. Overrides PluginBase:: | 3 | 
| StringTranslationTrait:: | protected | property | The string translation service. | |
| StringTranslationTrait:: | protected | function | Formats a string containing a count of items. | |
| StringTranslationTrait:: | protected | function | Returns the number of plurals supported by a given language. | |
| StringTranslationTrait:: | protected | function | Gets the string translation service. | |
| StringTranslationTrait:: | public | function | Sets the string translation service to use. | 2 | 
| StringTranslationTrait:: | protected | function | Translates a string to the current language or to a given language. | 
