Revert "Issue #2485385 by phenaproxima, quietone, Berdir, blazey, hussainweb, mikeryan, benjy, alexpott: Move highwater field support to the source plugin, and do not expose its internals on MigrationInterface"
This reverts commit 0308eb77d4
.
8.3.x
parent
0308eb77d4
commit
b991ba92c2
|
@ -15,7 +15,7 @@ class CommentSourceWithHighWaterTest extends CommentTestBase {
|
|||
* {@inheritdoc}
|
||||
*/
|
||||
protected function setUp() {
|
||||
$this->migrationConfiguration['source']['high_water_property']['name'] = 'timestamp';
|
||||
$this->migrationConfiguration['highWaterProperty']['field'] = 'timestamp';
|
||||
array_shift($this->expectedResults);
|
||||
parent::setUp();
|
||||
}
|
||||
|
|
|
@ -15,6 +15,7 @@ class FilterFormatTest extends MigrateSqlSourceTestCase {
|
|||
|
||||
protected $migrationConfiguration = array(
|
||||
'id' => 'test',
|
||||
'highWaterProperty' => array('field' => 'test'),
|
||||
'source' => array(
|
||||
'plugin' => 'd6_filter_formats',
|
||||
),
|
||||
|
|
|
@ -1,8 +1,4 @@
|
|||
services:
|
||||
migrate.plugin_event_subscriber:
|
||||
class: Drupal\migrate\Plugin\PluginEventSubscriber
|
||||
tags:
|
||||
- { name: event_subscriber }
|
||||
cache.migrate:
|
||||
class: Drupal\Core\Cache\CacheBackendInterface
|
||||
tags:
|
||||
|
|
|
@ -1,26 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\migrate\Event;
|
||||
|
||||
/**
|
||||
* Interface for plugins that react to pre- or post-import events.
|
||||
*/
|
||||
interface ImportAwareInterface {
|
||||
|
||||
/**
|
||||
* Performs pre-import tasks.
|
||||
*
|
||||
* @param \Drupal\migrate\Event\MigrateImportEvent $event
|
||||
* The pre-import event object.
|
||||
*/
|
||||
public function preImport(MigrateImportEvent $event);
|
||||
|
||||
/**
|
||||
* Performs post-import tasks.
|
||||
*
|
||||
* @param \Drupal\migrate\Event\MigrateImportEvent $event
|
||||
* The post-import event object.
|
||||
*/
|
||||
public function postImport(MigrateImportEvent $event);
|
||||
|
||||
}
|
|
@ -1,26 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\migrate\Event;
|
||||
|
||||
/**
|
||||
* Interface for plugins that react to pre- or post-rollback events.
|
||||
*/
|
||||
interface RollbackAwareInterface {
|
||||
|
||||
/**
|
||||
* Performs pre-rollback tasks.
|
||||
*
|
||||
* @param \Drupal\migrate\Event\MigrateRollbackEvent $event
|
||||
* The pre-rollback event object.
|
||||
*/
|
||||
public function preRollback(MigrateRollbackEvent $event);
|
||||
|
||||
/**
|
||||
* Performs post-rollback tasks.
|
||||
*
|
||||
* @param \Drupal\migrate\Event\MigrateRollbackEvent $event
|
||||
* The post-rollback event object.
|
||||
*/
|
||||
public function postRollback(MigrateRollbackEvent $event);
|
||||
|
||||
}
|
|
@ -262,6 +262,9 @@ class MigrateExecutable implements MigrateExecutableInterface {
|
|||
$this->handleException($e);
|
||||
}
|
||||
}
|
||||
if ($high_water_property = $this->migration->getHighWaterProperty()) {
|
||||
$this->migration->saveHighWater($row->getSourceProperty($high_water_property['name']));
|
||||
}
|
||||
|
||||
// Reset row properties.
|
||||
unset($sourceValues, $destinationValues);
|
||||
|
@ -351,6 +354,10 @@ class MigrateExecutable implements MigrateExecutableInterface {
|
|||
break;
|
||||
}
|
||||
}
|
||||
// If rollback completed successfully, reset the high water mark.
|
||||
if ($return == MigrationInterface::RESULT_COMPLETED) {
|
||||
$this->migration->saveHighWater(NULL);
|
||||
}
|
||||
|
||||
// Notify modules that rollback attempt was complete.
|
||||
$this->getEventDispatcher()->dispatch(MigrateEvents::POST_ROLLBACK, new MigrateRollbackEvent($this->migration));
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\migrate\Plugin;
|
||||
|
||||
use Drupal\Component\Plugin\PluginInspectionInterface;
|
||||
use Drupal\migrate\Row;
|
||||
|
||||
|
|
|
@ -125,6 +125,15 @@ class Migration extends PluginBase implements MigrationInterface, RequirementsIn
|
|||
*/
|
||||
protected $destinationIds = [];
|
||||
|
||||
/**
|
||||
* Information on the property used as the high watermark.
|
||||
*
|
||||
* Array of 'name' & (optional) db 'alias' properties used for high watermark.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $highWaterProperty;
|
||||
|
||||
/**
|
||||
* Indicate whether the primary system of record for this migration is the
|
||||
* source, or the destination (Drupal). In the source case, migration of
|
||||
|
@ -145,6 +154,11 @@ class Migration extends PluginBase implements MigrationInterface, RequirementsIn
|
|||
*/
|
||||
protected $sourceRowStatus = MigrateIdMapInterface::STATUS_IMPORTED;
|
||||
|
||||
/**
|
||||
* @var \Drupal\Core\KeyValueStore\KeyValueStoreInterface
|
||||
*/
|
||||
protected $highWaterStorage;
|
||||
|
||||
/**
|
||||
* Track time of last import if TRUE.
|
||||
*
|
||||
|
@ -429,6 +443,33 @@ class Migration extends PluginBase implements MigrationInterface, RequirementsIn
|
|||
return $this->idMapPlugin;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the high water storage object.
|
||||
*
|
||||
* @return \Drupal\Core\KeyValueStore\KeyValueStoreInterface
|
||||
* The storage object.
|
||||
*/
|
||||
protected function getHighWaterStorage() {
|
||||
if (!isset($this->highWaterStorage)) {
|
||||
$this->highWaterStorage = \Drupal::keyValue('migrate:high_water');
|
||||
}
|
||||
return $this->highWaterStorage;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getHighWater() {
|
||||
return $this->getHighWaterStorage()->get($this->id());
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function saveHighWater($high_water) {
|
||||
$this->getHighWaterStorage()->set($this->id(), $high_water);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
|
@ -681,6 +722,13 @@ class Migration extends PluginBase implements MigrationInterface, RequirementsIn
|
|||
return $this->source;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getHighWaterProperty() {
|
||||
return $this->highWaterProperty;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
|
|
|
@ -152,6 +152,26 @@ interface MigrationInterface extends PluginInspectionInterface, DerivativeInspec
|
|||
*/
|
||||
public function getIdMap();
|
||||
|
||||
/**
|
||||
* The current value of the high water mark.
|
||||
*
|
||||
* The high water mark defines a timestamp stating the time the import was last
|
||||
* run. If the mark is set, only content with a higher timestamp will be
|
||||
* imported.
|
||||
*
|
||||
* @return int
|
||||
* A Unix timestamp representing the high water mark.
|
||||
*/
|
||||
public function getHighWater();
|
||||
|
||||
/**
|
||||
* Save the new high water mark.
|
||||
*
|
||||
* @param int $high_water
|
||||
* The high water timestamp.
|
||||
*/
|
||||
public function saveHighWater($high_water);
|
||||
|
||||
/**
|
||||
* Check if all source rows from this migration have been processed.
|
||||
*
|
||||
|
@ -323,6 +343,18 @@ interface MigrationInterface extends PluginInspectionInterface, DerivativeInspec
|
|||
*/
|
||||
public function getSourceConfiguration();
|
||||
|
||||
/**
|
||||
* Get information on the property used as the high watermark.
|
||||
*
|
||||
* Array of 'name' & (optional) db 'alias' properties used for high watermark.
|
||||
*
|
||||
* @see Drupal\migrate\Plugin\migrate\source\SqlBase::initializeIterator()
|
||||
*
|
||||
* @return array
|
||||
* The property used as the high watermark.
|
||||
*/
|
||||
public function getHighWaterProperty();
|
||||
|
||||
/**
|
||||
* If true, track time of last import.
|
||||
*
|
||||
|
|
|
@ -1,94 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\migrate\Plugin;
|
||||
|
||||
use Drupal\migrate\Event\ImportAwareInterface;
|
||||
use Drupal\migrate\Event\MigrateEvents;
|
||||
use Drupal\migrate\Event\MigrateImportEvent;
|
||||
use Drupal\migrate\Event\MigrateRollbackEvent;
|
||||
use Drupal\migrate\Event\RollbackAwareInterface;
|
||||
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
|
||||
|
||||
/**
|
||||
* Event subscriber to forward Migrate events to source and destination plugins.
|
||||
*/
|
||||
class PluginEventSubscriber implements EventSubscriberInterface {
|
||||
|
||||
/**
|
||||
* Tries to invoke event handling methods on source and destination plugins.
|
||||
*
|
||||
* @param string $method
|
||||
* The method to invoke.
|
||||
* @param \Drupal\migrate\Event\MigrateImportEvent|\Drupal\migrate\Event\MigrateRollbackEvent $event
|
||||
* The event that has triggered the invocation.
|
||||
* @param string $plugin_interface
|
||||
* The interface which plugins must implement in order to be invoked.
|
||||
*/
|
||||
protected function invoke($method, $event, $plugin_interface) {
|
||||
$migration = $event->getMigration();
|
||||
|
||||
$source = $migration->getSourcePlugin();
|
||||
if ($source instanceof $plugin_interface) {
|
||||
call_user_func([$source, $method], $event);
|
||||
}
|
||||
|
||||
$destination = $migration->getDestinationPlugin();
|
||||
if ($destination instanceof $plugin_interface) {
|
||||
call_user_func([$destination, $method], $event);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Forwards pre-import events to the source and destination plugins.
|
||||
*
|
||||
* @param \Drupal\migrate\Event\MigrateImportEvent $event
|
||||
* The import event.
|
||||
*/
|
||||
public function preImport(MigrateImportEvent $event) {
|
||||
$this->invoke('preImport', $event, ImportAwareInterface::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Forwards post-import events to the source and destination plugins.
|
||||
*
|
||||
* @param \Drupal\migrate\Event\MigrateImportEvent $event
|
||||
* The import event.
|
||||
*/
|
||||
public function postImport(MigrateImportEvent $event) {
|
||||
$this->invoke('postImport', $event, ImportAwareInterface::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Forwards pre-rollback events to the source and destination plugins.
|
||||
*
|
||||
* @param \Drupal\migrate\Event\MigrateRollbackEvent $event
|
||||
* The rollback event.
|
||||
*/
|
||||
public function preRollback(MigrateRollbackEvent $event) {
|
||||
$this->invoke('preRollback', $event, RollbackAwareInterface::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Forwards post-rollback events to the source and destination plugins.
|
||||
*
|
||||
* @param \Drupal\migrate\Event\MigrateRollbackEvent $event
|
||||
* The rollback event.
|
||||
*/
|
||||
public function postRollback(MigrateRollbackEvent $event) {
|
||||
$this->invoke('postRollback', $event, RollbackAwareInterface::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static function getSubscribedEvents() {
|
||||
$events = [];
|
||||
$events[MigrateEvents::PRE_IMPORT][] = ['preImport'];
|
||||
$events[MigrateEvents::POST_IMPORT][] = ['postImport'];
|
||||
$events[MigrateEvents::PRE_ROLLBACK][] = ['preRollback'];
|
||||
$events[MigrateEvents::POST_ROLLBACK][] = ['postRollback'];
|
||||
|
||||
return $events;
|
||||
}
|
||||
|
||||
}
|
|
@ -3,8 +3,6 @@
|
|||
namespace Drupal\migrate\Plugin\migrate\source;
|
||||
|
||||
use Drupal\Core\Plugin\PluginBase;
|
||||
use Drupal\migrate\Event\MigrateRollbackEvent;
|
||||
use Drupal\migrate\Event\RollbackAwareInterface;
|
||||
use Drupal\migrate\Plugin\MigrationInterface;
|
||||
use Drupal\migrate\MigrateException;
|
||||
use Drupal\migrate\MigrateSkipRowException;
|
||||
|
@ -22,7 +20,7 @@ use Drupal\migrate\Row;
|
|||
*
|
||||
* @ingroup migration
|
||||
*/
|
||||
abstract class SourcePluginBase extends PluginBase implements MigrateSourceInterface, RollbackAwareInterface {
|
||||
abstract class SourcePluginBase extends PluginBase implements MigrateSourceInterface {
|
||||
|
||||
/**
|
||||
* The module handler service.
|
||||
|
@ -38,6 +36,15 @@ abstract class SourcePluginBase extends PluginBase implements MigrateSourceInter
|
|||
*/
|
||||
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.
|
||||
*
|
||||
|
@ -52,27 +59,10 @@ abstract class SourcePluginBase extends PluginBase implements MigrateSourceInter
|
|||
*/
|
||||
protected $currentSourceIds;
|
||||
|
||||
/**
|
||||
* Information on the property used as the high-water mark.
|
||||
*
|
||||
* Array of 'name' and (optional) db 'alias' properties used for high-water
|
||||
* mark.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $highWaterProperty = [];
|
||||
|
||||
/**
|
||||
* The key-value storage for the high-water value.
|
||||
*
|
||||
* @var \Drupal\Core\KeyValueStore\KeyValueStoreInterface
|
||||
*/
|
||||
protected $highWaterStorage;
|
||||
|
||||
/**
|
||||
* The high water mark at the beginning of the import operation.
|
||||
*
|
||||
* If the source has a property for tracking changes (like Drupal has
|
||||
* 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
|
||||
|
@ -156,11 +146,10 @@ abstract class SourcePluginBase extends PluginBase implements MigrateSourceInter
|
|||
$this->cacheKey = !empty($configuration['cache_key']) ? $configuration['cache_key'] : NULL;
|
||||
$this->trackChanges = !empty($configuration['track_changes']) ? $configuration['track_changes'] : FALSE;
|
||||
$this->idMap = $this->migration->getIdMap();
|
||||
$this->highWaterProperty = !empty($configuration['high_water_property']) ? $configuration['high_water_property'] : FALSE;
|
||||
|
||||
// Pull out the current highwater mark if we have a highwater property.
|
||||
if ($this->highWaterProperty) {
|
||||
$this->originalHighWater = $this->getHighWater();
|
||||
if ($this->highWaterProperty = $this->migration->getHighWaterProperty()) {
|
||||
$this->originalHighWater = $this->migration->getHighWater();
|
||||
}
|
||||
|
||||
// Don't allow the use of both highwater and track changes together.
|
||||
|
@ -335,10 +324,6 @@ abstract class SourcePluginBase extends PluginBase implements MigrateSourceInter
|
|||
if (!$row->getIdMap() || $row->needsUpdate() || $this->aboveHighwater($row) || $this->rowChanged($row)) {
|
||||
$this->currentRow = $row->freezeSource();
|
||||
}
|
||||
|
||||
if ($this->getHighWaterProperty()) {
|
||||
$this->saveHighWater($row->getSourceProperty($this->highWaterProperty['name']));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -352,7 +337,7 @@ abstract class SourcePluginBase extends PluginBase implements MigrateSourceInter
|
|||
* TRUE if the highwater value in the row is greater than our current value.
|
||||
*/
|
||||
protected function aboveHighwater(Row $row) {
|
||||
return $this->getHighWaterProperty() && $row->getSourceProperty($this->highWaterProperty['name']) > $this->originalHighWater;
|
||||
return $this->highWaterProperty && $row->getSourceProperty($this->highWaterProperty['name']) > $this->originalHighWater;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -432,90 +417,4 @@ abstract class SourcePluginBase extends PluginBase implements MigrateSourceInter
|
|||
return $this->cache;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the high water storage object.
|
||||
*
|
||||
* @return \Drupal\Core\KeyValueStore\KeyValueStoreInterface
|
||||
* The storage object.
|
||||
*/
|
||||
protected function getHighWaterStorage() {
|
||||
if (!isset($this->highWaterStorage)) {
|
||||
$this->highWaterStorage = \Drupal::keyValue('migrate:high_water');
|
||||
}
|
||||
return $this->highWaterStorage;
|
||||
}
|
||||
|
||||
/**
|
||||
* The current value of the high water mark.
|
||||
*
|
||||
* The high water mark defines a timestamp stating the time the import was last
|
||||
* run. If the mark is set, only content with a higher timestamp will be
|
||||
* imported.
|
||||
*
|
||||
* @return int|null
|
||||
* A Unix timestamp representing the high water mark, or NULL if no high
|
||||
* water mark has been stored.
|
||||
*/
|
||||
protected function getHighWater() {
|
||||
return $this->getHighWaterStorage()->get($this->migration->id());
|
||||
}
|
||||
|
||||
/**
|
||||
* Save the new high water mark.
|
||||
*
|
||||
* @param int $high_water
|
||||
* The high water timestamp.
|
||||
*/
|
||||
protected function saveHighWater($high_water) {
|
||||
$this->getHighWaterStorage()->set($this->migration->id(), $high_water);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get information on the property used as the high watermark.
|
||||
*
|
||||
* Array of 'name' & (optional) db 'alias' properties used for high watermark.
|
||||
*
|
||||
* @see \Drupal\migrate\Plugin\migrate\source\SqlBase::initializeIterator()
|
||||
*
|
||||
* @return array
|
||||
* The property used as the high watermark.
|
||||
*/
|
||||
protected function getHighWaterProperty() {
|
||||
return $this->highWaterProperty;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the name of the field used as the high watermark.
|
||||
*
|
||||
* The name of the field qualified with an alias if available.
|
||||
*
|
||||
* @see \Drupal\migrate\Plugin\migrate\source\SqlBase::initializeIterator()
|
||||
*
|
||||
* @return string|null
|
||||
* The name of the field for the high water mark, or NULL if not set.
|
||||
*/
|
||||
protected function getHighWaterField() {
|
||||
if (!empty($this->highWaterProperty['name'])) {
|
||||
return !empty($this->highWaterProperty['alias']) ?
|
||||
$this->highWaterProperty['alias'] . '.' . $this->highWaterProperty['name'] :
|
||||
$this->highWaterProperty['name'];
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function preRollback(MigrateRollbackEvent $event) {
|
||||
// Nothing to do in this implementation.
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function postRollback(MigrateRollbackEvent $event) {
|
||||
// Reset the high-water mark.
|
||||
$this->saveHighWater(NULL);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -161,6 +161,7 @@ abstract class SqlBase extends SourcePluginBase implements ContainerFactoryPlugi
|
|||
*/
|
||||
protected function initializeIterator() {
|
||||
$this->prepareQuery();
|
||||
$high_water_property = $this->migration->getHighWaterProperty();
|
||||
|
||||
// Get the key values, for potential use in joining to the map table.
|
||||
$keys = array();
|
||||
|
@ -212,10 +213,15 @@ abstract class SqlBase extends SourcePluginBase implements ContainerFactoryPlugi
|
|||
}
|
||||
// 2. If we are using high water marks, also include rows above the mark.
|
||||
// But, include all rows if the high water mark is not set.
|
||||
if ($this->getHighWaterProperty() && ($high_water = $this->getHighWater()) !== '') {
|
||||
$high_water_field = $this->getHighWaterField();
|
||||
$conditions->condition($high_water_field, $high_water, '>');
|
||||
$this->query->orderBy($high_water_field);
|
||||
if (isset($high_water_property['name']) && ($high_water = $this->migration->getHighWater()) !== '') {
|
||||
if (isset($high_water_property['alias'])) {
|
||||
$high_water = $high_water_property['alias'] . '.' . $high_water_property['name'];
|
||||
}
|
||||
else {
|
||||
$high_water = $high_water_property['name'];
|
||||
}
|
||||
$conditions->condition($high_water, $high_water, '>');
|
||||
$condition_added = TRUE;
|
||||
}
|
||||
if ($condition_added) {
|
||||
$this->query->condition($conditions);
|
||||
|
|
|
@ -1,9 +0,0 @@
|
|||
langcode: en
|
||||
status: true
|
||||
name: High Water import node
|
||||
type: high_water_import_node
|
||||
description: ''
|
||||
help: ''
|
||||
new_revision: false
|
||||
preview_mode: 1
|
||||
display_submitted: true
|
|
@ -1,7 +0,0 @@
|
|||
type: module
|
||||
name: Migrate SQL Source test
|
||||
description: 'Provides a database table and records for SQL import testing.'
|
||||
package: Testing
|
||||
core: 8.x
|
||||
dependencies:
|
||||
- migrate
|
|
@ -1,16 +0,0 @@
|
|||
id: high_water_test
|
||||
label: High water test.
|
||||
source:
|
||||
plugin: high_water_test
|
||||
high_water_property:
|
||||
name: changed
|
||||
destination:
|
||||
plugin: entity:node
|
||||
migration_tags:
|
||||
test: test
|
||||
process:
|
||||
changed: changed
|
||||
title: title
|
||||
type:
|
||||
plugin: default_value
|
||||
default_value: high_water_import_node
|
|
@ -1,50 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\migrate_sql_test\Plugin\migrate\source;
|
||||
|
||||
use Drupal\migrate\Plugin\migrate\source\SqlBase;
|
||||
|
||||
/**
|
||||
* Source plugin for migration high water tests.
|
||||
*
|
||||
* @MigrateSource(
|
||||
* id = "high_water_test"
|
||||
* )
|
||||
*/
|
||||
class HighWaterTest extends SqlBase {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function query() {
|
||||
$query = $this
|
||||
->select('high_water_node', 'm')
|
||||
->fields('m', array_keys($this->fields()));
|
||||
return $query;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function fields() {
|
||||
$fields = [
|
||||
'id' => $this->t('Id'),
|
||||
'title' => $this->t('Title'),
|
||||
'changed' => $this->t('Changed'),
|
||||
];
|
||||
|
||||
return $fields;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getIds() {
|
||||
return [
|
||||
'id' => [
|
||||
'type' => 'integer',
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
}
|
|
@ -1,177 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\Tests\migrate\Kernel;
|
||||
|
||||
/**
|
||||
* Tests migration high water property.
|
||||
*
|
||||
* @group migrate
|
||||
*/
|
||||
class HighWaterTest extends MigrateTestBase {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static $modules = [
|
||||
'system',
|
||||
'user',
|
||||
'node',
|
||||
'migrate',
|
||||
'migrate_sql_test',
|
||||
'field',
|
||||
];
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function setUp() {
|
||||
parent::setUp();
|
||||
// Create source test table.
|
||||
$this->sourceDatabase->schema()->createTable('high_water_node', [
|
||||
'fields' => [
|
||||
'id' => [
|
||||
'description' => 'Serial',
|
||||
'type' => 'serial',
|
||||
'unsigned' => TRUE,
|
||||
'not null' => TRUE,
|
||||
],
|
||||
'changed' => [
|
||||
'description' => 'Highwater',
|
||||
'type' => 'int',
|
||||
'unsigned' => TRUE,
|
||||
],
|
||||
'title' => [
|
||||
'description' => 'Title',
|
||||
'type' => 'varchar',
|
||||
'length' => 128,
|
||||
'not null' => TRUE,
|
||||
'default' => '',
|
||||
],
|
||||
],
|
||||
'primary key' => [
|
||||
'id',
|
||||
],
|
||||
'description' => 'Contains nodes to import',
|
||||
]);
|
||||
|
||||
// Add 3 items to source table.
|
||||
$this->sourceDatabase->insert('high_water_node')
|
||||
->fields([
|
||||
'title',
|
||||
'changed',
|
||||
])
|
||||
->values([
|
||||
'title' => 'Item 1',
|
||||
'changed' => 1,
|
||||
])
|
||||
->values([
|
||||
'title' => 'Item 2',
|
||||
'changed' => 2,
|
||||
])
|
||||
->values([
|
||||
'title' => 'Item 3',
|
||||
'changed' => 3,
|
||||
])
|
||||
->execute();
|
||||
|
||||
$this->installEntitySchema('node');
|
||||
$this->installEntitySchema('user');
|
||||
$this->installSchema('node', 'node_access');
|
||||
|
||||
$this->executeMigration('high_water_test');
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests high water property of SqlBase.
|
||||
*/
|
||||
public function testHighWater() {
|
||||
// Assert all of the nodes have been imported.
|
||||
$this->assertNodeExists('Item 1');
|
||||
$this->assertNodeExists('Item 2');
|
||||
$this->assertNodeExists('Item 3');
|
||||
|
||||
// Update Item 1 setting its high_water_property to value that is below
|
||||
// current high water mark.
|
||||
$this->sourceDatabase->update('high_water_node')
|
||||
->fields([
|
||||
'title' => 'Item 1 updated',
|
||||
'changed' => 2,
|
||||
])
|
||||
->condition('title', 'Item 1')
|
||||
->execute();
|
||||
|
||||
// Update Item 2 setting its high_water_property to value equal to
|
||||
// current high water mark.
|
||||
$this->sourceDatabase->update('high_water_node')
|
||||
->fields([
|
||||
'title' => 'Item 2 updated',
|
||||
'changed' => 3,
|
||||
])
|
||||
->condition('title', 'Item 2')
|
||||
->execute();
|
||||
|
||||
// Update Item 3 setting its high_water_property to value that is above
|
||||
// current high water mark.
|
||||
$this->sourceDatabase->update('high_water_node')
|
||||
->fields([
|
||||
'title' => 'Item 3 updated',
|
||||
'changed' => 4,
|
||||
])
|
||||
->condition('title', 'Item 3')
|
||||
->execute();
|
||||
|
||||
// Execute migration again.
|
||||
$this->executeMigration('high_water_test');
|
||||
|
||||
// Item with lower highwater should not be updated.
|
||||
$this->assertNodeExists('Item 1');
|
||||
$this->assertNodeDoesNotExist('Item 1 updated');
|
||||
|
||||
// Item with equal highwater should not be updated.
|
||||
$this->assertNodeExists('Item 2');
|
||||
$this->assertNodeDoesNotExist('Item 2 updated');
|
||||
|
||||
// Item with greater highwater should be updated.
|
||||
$this->assertNodeExists('Item 3 updated');
|
||||
$this->assertNodeDoesNotExist('Item 3');
|
||||
}
|
||||
|
||||
/**
|
||||
* Assert that node with given title exists.
|
||||
*
|
||||
* @param string $title
|
||||
* Title of the node.
|
||||
*/
|
||||
protected function assertNodeExists($title) {
|
||||
self::assertTrue($this->nodeExists($title));
|
||||
}
|
||||
|
||||
/**
|
||||
* Assert that node with given title does not exist.
|
||||
*
|
||||
* @param string $title
|
||||
* Title of the node.
|
||||
*/
|
||||
protected function assertNodeDoesNotExist($title) {
|
||||
self::assertFalse($this->nodeExists($title));
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if node with given title exists.
|
||||
*
|
||||
* @param string $title
|
||||
* Title of the node.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
protected function nodeExists($title) {
|
||||
$query = \Drupal::entityQuery('node');
|
||||
$result = $query
|
||||
->condition('title', $title)
|
||||
->range(0, 1)
|
||||
->execute();
|
||||
|
||||
return !empty($result);
|
||||
}
|
||||
|
||||
}
|
|
@ -114,9 +114,9 @@ class MigrateExecutableTest extends MigrateTestCase {
|
|||
->with($row, array('test'))
|
||||
->will($this->returnValue(array('id' => 'test')));
|
||||
|
||||
$this->migration
|
||||
$this->migration->expects($this->once())
|
||||
->method('getDestinationPlugin')
|
||||
->willReturn($destination);
|
||||
->will($this->returnValue($destination));
|
||||
|
||||
$this->assertSame(MigrationInterface::RESULT_COMPLETED, $this->executable->import());
|
||||
}
|
||||
|
@ -156,9 +156,9 @@ class MigrateExecutableTest extends MigrateTestCase {
|
|||
->with($row, array('test'))
|
||||
->will($this->returnValue(TRUE));
|
||||
|
||||
$this->migration
|
||||
$this->migration->expects($this->once())
|
||||
->method('getDestinationPlugin')
|
||||
->willReturn($destination);
|
||||
->will($this->returnValue($destination));
|
||||
|
||||
$this->idMap->expects($this->never())
|
||||
->method('saveIdMapping');
|
||||
|
@ -196,9 +196,9 @@ class MigrateExecutableTest extends MigrateTestCase {
|
|||
->with($row, array('test'))
|
||||
->will($this->returnValue(array()));
|
||||
|
||||
$this->migration
|
||||
$this->migration->expects($this->once())
|
||||
->method('getDestinationPlugin')
|
||||
->willReturn($destination);
|
||||
->will($this->returnValue($destination));
|
||||
|
||||
$this->idMap->expects($this->once())
|
||||
->method('saveIdMapping')
|
||||
|
@ -256,9 +256,9 @@ class MigrateExecutableTest extends MigrateTestCase {
|
|||
->with($row, array('test'))
|
||||
->will($this->throwException(new MigrateException($exception_message)));
|
||||
|
||||
$this->migration
|
||||
$this->migration->expects($this->once())
|
||||
->method('getDestinationPlugin')
|
||||
->willReturn($destination);
|
||||
->will($this->returnValue($destination));
|
||||
|
||||
$this->idMap->expects($this->once())
|
||||
->method('saveIdMapping')
|
||||
|
@ -306,7 +306,7 @@ class MigrateExecutableTest extends MigrateTestCase {
|
|||
$destination->expects($this->never())
|
||||
->method('import');
|
||||
|
||||
$this->migration
|
||||
$this->migration->expects($this->once())
|
||||
->method('getDestinationPlugin')
|
||||
->willReturn($destination);
|
||||
|
||||
|
@ -354,9 +354,9 @@ class MigrateExecutableTest extends MigrateTestCase {
|
|||
->with($row, array('test'))
|
||||
->will($this->throwException(new \Exception($exception_message)));
|
||||
|
||||
$this->migration
|
||||
$this->migration->expects($this->once())
|
||||
->method('getDestinationPlugin')
|
||||
->willReturn($destination);
|
||||
->will($this->returnValue($destination));
|
||||
|
||||
$this->idMap->expects($this->once())
|
||||
->method('saveIdMapping')
|
||||
|
|
|
@ -10,8 +10,6 @@ namespace Drupal\Tests\migrate\Unit;
|
|||
use Drupal\Core\Cache\CacheBackendInterface;
|
||||
use Drupal\Core\DependencyInjection\ContainerBuilder;
|
||||
use Drupal\Core\Extension\ModuleHandlerInterface;
|
||||
use Drupal\Core\KeyValueStore\KeyValueFactoryInterface;
|
||||
use Drupal\Core\KeyValueStore\KeyValueStoreInterface;
|
||||
use Drupal\migrate\MigrateExecutable;
|
||||
use Drupal\migrate\MigrateSkipRowException;
|
||||
use Drupal\migrate\Plugin\migrate\source\SourcePluginBase;
|
||||
|
@ -77,21 +75,7 @@ class MigrateSourceTest extends MigrateTestCase {
|
|||
* @return \Drupal\migrate\Plugin\MigrateSourceInterface
|
||||
* A mocked source plugin.
|
||||
*/
|
||||
protected function getSource($configuration = [], $migrate_config = [], $status = MigrateIdMapInterface::STATUS_NEEDS_UPDATE, $high_water_value = NULL) {
|
||||
$container = new ContainerBuilder();
|
||||
\Drupal::setContainer($container);
|
||||
|
||||
$key_value = $this->getMock(KeyValueStoreInterface::class);
|
||||
|
||||
$key_value_factory = $this->getMock(KeyValueFactoryInterface::class);
|
||||
$key_value_factory
|
||||
->method('get')
|
||||
->with('migrate:high_water')
|
||||
->willReturn($key_value);
|
||||
$container->set('keyvalue', $key_value_factory);
|
||||
|
||||
$container->set('cache.migrate', $this->getMock(CacheBackendInterface::class));
|
||||
|
||||
protected function getSource($configuration = [], $migrate_config = [], $status = MigrateIdMapInterface::STATUS_NEEDS_UPDATE) {
|
||||
$this->migrationConfiguration = $this->defaultMigrationConfiguration + $migrate_config;
|
||||
$this->migration = parent::getMigration();
|
||||
$this->executable = $this->getMigrateExecutable($this->migration);
|
||||
|
@ -106,45 +90,47 @@ class MigrateSourceTest extends MigrateTestCase {
|
|||
->willReturn($id_map_array);
|
||||
|
||||
$constructor_args = [$configuration, 'd6_action', [], $this->migration];
|
||||
$methods = ['getModuleHandler', 'fields', 'getIds', '__toString', 'prepareRow', 'initializeIterator'];
|
||||
$source_plugin = $this->getMock(SourcePluginBase::class, $methods, $constructor_args);
|
||||
$methods = ['getModuleHandler', 'fields', 'getIds', '__toString', 'getIterator', 'prepareRow', 'initializeIterator', 'calculateDependencies'];
|
||||
$source_plugin = $this->getMock('\Drupal\migrate\Plugin\migrate\source\SourcePluginBase', $methods, $constructor_args);
|
||||
|
||||
$source_plugin
|
||||
->expects($this->any())
|
||||
->method('fields')
|
||||
->willReturn([]);
|
||||
$source_plugin
|
||||
->expects($this->any())
|
||||
->method('getIds')
|
||||
->willReturn([]);
|
||||
$source_plugin
|
||||
->expects($this->any())
|
||||
->method('__toString')
|
||||
->willReturn('');
|
||||
$source_plugin
|
||||
->expects($this->any())
|
||||
->method('prepareRow')
|
||||
->willReturn(empty($migrate_config['prepare_row_false']));
|
||||
|
||||
$rows = [$this->row];
|
||||
if (isset($configuration['high_water_property']) && isset($high_water_value)) {
|
||||
$property = $configuration['high_water_property']['name'];
|
||||
$rows = array_filter($rows, function (array $row) use ($property, $high_water_value) {
|
||||
return $row[$property] >= $high_water_value;
|
||||
});
|
||||
}
|
||||
$iterator = new \ArrayIterator($rows);
|
||||
|
||||
$source_plugin
|
||||
->expects($this->any())
|
||||
->method('initializeIterator')
|
||||
->willReturn([]);
|
||||
$iterator = new \ArrayIterator([$this->row]);
|
||||
$source_plugin
|
||||
->expects($this->any())
|
||||
->method('getIterator')
|
||||
->willReturn($iterator);
|
||||
|
||||
$module_handler = $this->getMock(ModuleHandlerInterface::class);
|
||||
$module_handler = $this->getMock('\Drupal\Core\Extension\ModuleHandlerInterface');
|
||||
$source_plugin
|
||||
->expects($this->any())
|
||||
->method('getModuleHandler')
|
||||
->willReturn($module_handler);
|
||||
|
||||
$this->migration
|
||||
->expects($this->any())
|
||||
->method('getSourcePlugin')
|
||||
->willReturn($source_plugin);
|
||||
|
||||
return $source_plugin;
|
||||
return $this->migration->getSourcePlugin();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -152,8 +138,9 @@ class MigrateSourceTest extends MigrateTestCase {
|
|||
* @expectedException \Drupal\migrate\MigrateException
|
||||
*/
|
||||
public function testHighwaterTrackChangesIncompatible() {
|
||||
$source_config = ['track_changes' => TRUE, 'high_water_property' => ['name' => 'something']];
|
||||
$this->getSource($source_config);
|
||||
$source_config = ['track_changes' => TRUE];
|
||||
$migration_config = ['highWaterProperty' => ['name' => 'something']];
|
||||
$this->getSource($source_config, $migration_config);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -232,12 +219,14 @@ class MigrateSourceTest extends MigrateTestCase {
|
|||
* Test that an outdated highwater mark does not cause a row to be imported.
|
||||
*/
|
||||
public function testOutdatedHighwater() {
|
||||
$configuration = [
|
||||
'high_water_property' => [
|
||||
'name' => 'timestamp',
|
||||
],
|
||||
];
|
||||
$source = $this->getSource($configuration, [], MigrateIdMapInterface::STATUS_IMPORTED, $this->row['timestamp'] + 1);
|
||||
|
||||
$source = $this->getSource([], [], MigrateIdMapInterface::STATUS_IMPORTED);
|
||||
|
||||
// Set the originalHighwater to something higher than our timestamp.
|
||||
$this->migration
|
||||
->expects($this->any())
|
||||
->method('getHighwater')
|
||||
->willReturn($this->row['timestamp'] + 1);
|
||||
|
||||
// The current highwater mark is now higher than the row timestamp so no row
|
||||
// is expected.
|
||||
|
@ -251,17 +240,13 @@ class MigrateSourceTest extends MigrateTestCase {
|
|||
* @throws \Exception
|
||||
*/
|
||||
public function testNewHighwater() {
|
||||
$configuration = [
|
||||
'high_water_property' => [
|
||||
'name' => 'timestamp',
|
||||
],
|
||||
];
|
||||
|
||||
// Set a highwater property field for source. Now we should have a row
|
||||
// because the row timestamp is greater than the current highwater mark.
|
||||
$source = $this->getSource($configuration, [], MigrateIdMapInterface::STATUS_IMPORTED, $this->row['timestamp'] - 1);
|
||||
$source = $this->getSource([], ['highWaterProperty' => ['name' => 'timestamp']], MigrateIdMapInterface::STATUS_IMPORTED);
|
||||
|
||||
$source->rewind();
|
||||
$this->assertInstanceOf(Row::class, $source->current(), 'Incoming row timestamp is greater than current highwater mark so we have a row.');
|
||||
$this->assertTrue(is_a($source->current(), 'Drupal\migrate\Row'), 'Incoming row timestamp is greater than current highwater mark so we have a row.');
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -3,10 +3,6 @@
|
|||
namespace Drupal\Tests\migrate\Unit;
|
||||
|
||||
use Drupal\Core\Database\Query\SelectInterface;
|
||||
use Drupal\Core\DependencyInjection\ContainerBuilder;
|
||||
use Drupal\Core\DependencyInjection\ContainerNotInitializedException;
|
||||
use Drupal\Core\KeyValueStore\KeyValueFactoryInterface;
|
||||
use Drupal\Core\KeyValueStore\KeyValueStoreInterface;
|
||||
|
||||
/**
|
||||
* Base class for Migrate module source unit tests.
|
||||
|
@ -48,9 +44,9 @@ abstract class MigrateSqlSourceTestCase extends MigrateTestCase {
|
|||
* Once the migration is run, we save a mark of the migrated sources, so the
|
||||
* migration can run again and update only new sources or changed sources.
|
||||
*
|
||||
* @var mixed
|
||||
* @var string
|
||||
*/
|
||||
const ORIGINAL_HIGH_WATER = NULL;
|
||||
const ORIGINAL_HIGH_WATER = '';
|
||||
|
||||
/**
|
||||
* Expected results after the source parsing.
|
||||
|
@ -81,27 +77,6 @@ abstract class MigrateSqlSourceTestCase extends MigrateTestCase {
|
|||
$state = $this->getMock('Drupal\Core\State\StateInterface');
|
||||
$entity_manager = $this->getMock('Drupal\Core\Entity\EntityManagerInterface');
|
||||
|
||||
// Mock a key-value store to return high-water values.
|
||||
$key_value = $this->getMock(KeyValueStoreInterface::class);
|
||||
|
||||
// SourcePluginBase does not yet support full dependency injection so we
|
||||
// need to make sure that \Drupal::keyValue() works as expected by mocking
|
||||
// the keyvalue service.
|
||||
$key_value_factory = $this->getMock(KeyValueFactoryInterface::class);
|
||||
$key_value_factory
|
||||
->method('get')
|
||||
->with('migrate:high_water')
|
||||
->willReturn($key_value);
|
||||
|
||||
try {
|
||||
$container = \Drupal::getContainer();
|
||||
}
|
||||
catch (ContainerNotInitializedException $e) {
|
||||
$container = new ContainerBuilder();
|
||||
}
|
||||
$container->set('keyvalue', $key_value_factory);
|
||||
\Drupal::setContainer($container);
|
||||
|
||||
$migration = $this->getMigration();
|
||||
$migration->expects($this->any())
|
||||
->method('getHighWater')
|
||||
|
|
|
@ -80,7 +80,7 @@ abstract class MigrateTestCase extends UnitTestCase {
|
|||
|
||||
$migration->method('getHighWaterProperty')
|
||||
->willReturnCallback(function () use ($configuration) {
|
||||
return isset($configuration['high_water_property']) ? $configuration['high_water_property'] : '';
|
||||
return isset($configuration['highWaterProperty']) ? $configuration['highWaterProperty'] : '';
|
||||
});
|
||||
|
||||
$migration->method('set')
|
||||
|
|
|
@ -15,6 +15,7 @@ class UrlAliasTest extends UrlAliasTestBase {
|
|||
|
||||
protected $migrationConfiguration = array(
|
||||
'id' => 'test',
|
||||
'highWaterProperty' => array('field' => 'test'),
|
||||
'source' => array(
|
||||
'plugin' => 'd6_url_alias',
|
||||
),
|
||||
|
|
|
@ -13,6 +13,7 @@ abstract class TermTestBase extends MigrateSqlSourceTestCase {
|
|||
|
||||
protected $migrationConfiguration = array(
|
||||
'id' => 'test',
|
||||
'highWaterProperty' => array('field' => 'test'),
|
||||
'source' => array(
|
||||
'plugin' => 'd6_taxonomy_term',
|
||||
),
|
||||
|
|
Loading…
Reference in New Issue