Commit 004d26ce authored by webchick's avatar webchick

Issue #2429085 by mikeryan, benjy: Track current state of migrations

parent 508bbb55
......@@ -246,6 +246,19 @@ class Migration extends ConfigEntityBase implements MigrationInterface, Requirem
*/
protected $entityManager;
/**
* Labels corresponding to each defined status.
*
* @var array
*/
protected $statusLabels = [
self::STATUS_IDLE => 'Idle',
self::STATUS_IMPORTING => 'Importing',
self::STATUS_ROLLING_BACK => 'Rolling back',
self::STATUS_STOPPING => 'Stopping',
self::STATUS_DISABLED => 'Disabled',
];
/**
* {@inheritdoc}
*/
......@@ -404,20 +417,45 @@ protected function getEntityManager() {
return $this->entityManager;
}
/**
* {@inheritdoc}
*/
public function setStatus($status) {
\Drupal::keyValue('migrate_status')->set($this->id(), $status);
}
/**
* {@inheritdoc}
*/
public function getStatus() {
return \Drupal::keyValue('migrate_status')->get($this->id(), static::STATUS_IDLE);
}
/**
* {@inheritdoc}
*/
public function getStatusLabel() {
$status = $this->getStatus();
if (isset($this->statusLabels[$status])) {
return $this->statusLabels[$status];
}
else {
return '';
}
}
/**
* {@inheritdoc}
*/
public function setMigrationResult($result) {
$migrate_result_store = \Drupal::keyValue('migrate_result');
$migrate_result_store->set($this->id(), $result);
\Drupal::keyValue('migrate_result')->set($this->id(), $result);
}
/**
* {@inheritdoc}
*/
public function getMigrationResult() {
$migrate_result_store = \Drupal::keyValue('migrate_result');
return $migrate_result_store->get($this->id(), static::RESULT_INCOMPLETE);
return \Drupal::keyValue('migrate_result')->get($this->id(), static::RESULT_INCOMPLETE);
}
/**
......
......@@ -166,6 +166,30 @@ public function saveHighWater($high_water);
*/
public function isComplete();
/**
* Set the current migration status.
*
* @param int $result
* One of the STATUS_* constants.
*/
public function setStatus($status);
/**
* Get the current migration status.
*
* @return int
* The current migration status. Defaults to STATUS_IDLE.
*/
public function getStatus();
/**
* Retrieve a label for the current status.
*
* @return string
* User-friendly string corresponding to a STATUS_ constant.
*/
public function getStatusLabel();
/**
* Set the migration result.
*
......
......@@ -202,6 +202,15 @@ protected function getEventDispatcher() {
* {@inheritdoc}
*/
public function import() {
// Only begin the import operation if the migration is currently idle.
if ($this->migration->getStatus() !== MigrationInterface::STATUS_IDLE) {
$this->message->display($this->t('Migration @id is busy with another operation: @status',
array(
'@id' => $this->migration->id(),
'@status' => $this->t($this->migration->getStatusLabel()),
)), 'error');
return MigrationInterface::RESULT_FAILED;
}
$this->getEventDispatcher()->dispatch(MigrateEvents::PRE_IMPORT, new MigrateImportEvent($this->migration));
// Knock off migration if the requirements haven't been met.
......@@ -218,6 +227,7 @@ public function import() {
return MigrationInterface::RESULT_FAILED;
}
$this->migration->setStatus(MigrationInterface::STATUS_IMPORTING);
$return = MigrationInterface::RESULT_COMPLETED;
$source = $this->getSource();
$id_map = $this->migration->getIdMap();
......@@ -228,6 +238,7 @@ public function import() {
catch (\Exception $e) {
$this->message->display(
$this->t('Migration failed with source plugin exception: !e', array('!e' => $e->getMessage())), 'error');
$this->migration->setStatus(MigrationInterface::STATUS_IDLE);
return MigrationInterface::RESULT_FAILED;
}
......@@ -298,12 +309,14 @@ public function import() {
$this->message->display(
$this->t('Migration failed with source plugin exception: !e',
array('!e' => $e->getMessage())), 'error');
$this->migration->setStatus(MigrationInterface::STATUS_IDLE);
return MigrationInterface::RESULT_FAILED;
}
}
$this->migration->setMigrationResult($return);
$this->getEventDispatcher()->dispatch(MigrateEvents::POST_IMPORT, new MigrateImportEvent($this->migration));
$this->migration->setStatus(MigrationInterface::STATUS_IDLE);
return $return;
}
......
<?php
/**
* @file
* Contains \Drupal\migrate\Tests\MigrateStatusTest
*/
namespace Drupal\migrate\Tests;
use Drupal\migrate\Entity\Migration;
use Drupal\migrate\Entity\MigrationInterface;
/**
* Test migration status tracking.
*
* @group migrate
*/
class MigrateStatusTest extends MigrateTestBase {
/**
* Test different connection types.
*/
public function testStatus() {
// Create a minimally valid migration.
$configuration = [
'id' => 'migration_status_test',
'migration_tags' => ['Testing'],
'source' => ['plugin' => 'empty'],
'destination' => [
'plugin' => 'config',
'config_name' => 'migrate_test.settings',
],
'process' => ['foo' => 'bar'],
'load' => ['plugin' => 'null'],
];
$migration = Migration::create($configuration);
$migration->save();
// Default status is idle.
$status = $migration->getStatus();
$this->assertIdentical($status, MigrationInterface::STATUS_IDLE);
// Test setting and retrieving all known status values.
$status_list = array(
MigrationInterface::STATUS_IDLE,
MigrationInterface::STATUS_IMPORTING,
MigrationInterface::STATUS_ROLLING_BACK,
MigrationInterface::STATUS_STOPPING,
MigrationInterface::STATUS_DISABLED,
);
foreach ($status_list as $status) {
$migration->setStatus($status);
$this->assertIdentical($migration->getStatus(), $status);
}
}
}
......@@ -9,6 +9,7 @@
use Drupal\Core\Database\Driver\sqlite\Connection;
use Drupal\Core\DependencyInjection\ContainerBuilder;
use Drupal\migrate\Entity\MigrationInterface;
use Drupal\Tests\UnitTestCase;
/**
......@@ -18,6 +19,13 @@ abstract class MigrateTestCase extends UnitTestCase {
protected $migrationConfiguration = [];
/**
* Local store for mocking setStatus()/getStatus().
*
* @var \Drupal\migrate\Entity\MigrationInterface::STATUS_*
*/
protected $migrationStatus = MigrationInterface::STATUS_IDLE;
/**
* Retrieve a mocked migration.
*
......@@ -42,6 +50,19 @@ protected function getMigration() {
$migration->method('getIdMap')
->willReturn($this->idMap);
// We need the state to be toggled throughout the test so we store the value
// on the test class and use a return callback.
$migration->expects($this->any())
->method('getStatus')
->willReturnCallback(function() {
return $this->migrationStatus;
});
$migration->expects($this->any())
->method('setStatus')
->willReturnCallback(function($status) {
$this->migrationStatus = $status;
});
$migration->method('getMigrationDependencies')
->willReturn([
'required' => [],
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment