Commit f9863929 authored by heddn's avatar heddn Committed by heddn

Issue #3100463 by heddn: Support Drupal 9

parent 4e257500
{
"name": "drupal/migrate_plus",
"description": "Enhancements to core migration support.",
"type": "drupal-module",
"license": "GPL-2.0+",
"homepage": "https://www.drupal.org/project/migrate_plus",
"authors": [
{
"name": "Mike Ryan",
"homepage":"https://www.drupal.org/u/mikeryan",
"role": "Maintainer"
"name": "drupal/migrate_plus",
"description": "Enhancements to core migration support.",
"type": "drupal-module",
"license": "GPL-2.0+",
"homepage": "https://www.drupal.org/project/migrate_plus",
"authors": [
{
"name": "Mike Ryan",
"homepage":"https://www.drupal.org/u/mikeryan",
"role": "Maintainer"
},
{
"name": "Lucas Hedding",
"homepage": "https://www.drupal.org/u/heddn",
"role": "Maintainer"
}
],
"support": {
"issues": "https://www.drupal.org/project/issues/migrate_plus",
"slack": "#migrate",
"source": "https://git.drupalcode.org/project/migrate_plus"
},
"minimum-stability": "dev",
"suggest": {
"sainsburys/guzzle-oauth2-plugin": "3.0 required for the OAuth2 authentication plugin",
"ext-soap": "*"
}
],
"support": {
"issues": "https://www.drupal.org/project/issues/migrate_plus",
"irc": "irc://irc.freenode.org/drupal-migrate",
"source": "https://cgit.drupalcode.org/migrate_plus"
},
"minimum-stability": "dev",
"suggest": {
"sainsburys/guzzle-oauth2-plugin": "3.0 required for the OAuth2 authentication plugin",
"ext-soap": "*"
}
}
......@@ -6,4 +6,3 @@ core: 8.x
dependencies:
- drupal:migrate
- migrate_plus:migrate_plus
- migrate_tools:migrate_tools
......@@ -12,25 +12,11 @@ use Drupal\Core\File\FileSystemInterface;
*/
function migrate_json_example_install() {
// Create the example file directory and ensure it's writable.
$directory = file_default_scheme() . '://migrate_json_example';
// TODO: remove after 8.6 is no longer supported in
// https://www.drupal.org/project/migrate_plus/issues/3035587
if (version_compare(\Drupal::VERSION, '8.7', '>=')) {
\Drupal::service('file_system')->prepareDirectory($directory, FileSystemInterface::CREATE_DIRECTORY | FileSystemInterface::MODIFY_PERMISSIONS);
}
else {
file_prepare_directory($directory, FILE_CREATE_DIRECTORY | FILE_MODIFY_PERMISSIONS);
}
$directory = \Drupal::config('system.file')->get('default_scheme') . '://migrate_json_example';
\Drupal::service('file_system')->prepareDirectory($directory, FileSystemInterface::CREATE_DIRECTORY | FileSystemInterface::MODIFY_PERMISSIONS);
// Copy the example file to example directory.
$module_path = drupal_get_path('module', 'migrate_json_example');
$file_source = $module_path . '/artifacts/products.json';
// TODO: remove after 8.6 is no longer supported in
// https://www.drupal.org/project/migrate_plus/issues/3035587
if (version_compare(\Drupal::VERSION, '8.7', '>=')) {
\Drupal::service('file_system')->copy($file_source, $directory . '/products.json', FileSystemInterface::EXISTS_REPLACE);
}
else {
file_unmanaged_copy($file_source, $directory . '/products.json', FILE_EXISTS_REPLACE);
}
\Drupal::service('file_system')->copy($file_source, $directory . '/products.json', FileSystemInterface::EXISTS_REPLACE);
}
......@@ -5,7 +5,7 @@ package: Migration
core: 8.x
core_version_requirement: ^8 || ^9
dependencies:
- drupal:migrate (>=8.3)
- drupal:migrate
test_dependencies:
- entity
- profile
......@@ -159,7 +159,7 @@ abstract class DataParserPluginBase extends PluginBase implements DataParserPlug
}
else {
// Increment the activeUrl so we try to load the next source.
$this->activeUrl = $this->activeUrl + 1;
++$this->activeUrl;
if ($this->activeUrl >= count($this->urls)) {
return FALSE;
}
......
......@@ -2,8 +2,8 @@
namespace Drupal\migrate_plus\Event;
use Drupal\migrate\Plugin\MigrationInterface;
use Drupal\migrate\Plugin\MigrateSourceInterface;
use Drupal\migrate\Plugin\MigrationInterface;
use Drupal\migrate\Row;
use Symfony\Component\EventDispatcher\Event;
......
......@@ -9,8 +9,8 @@ use Drupal\migrate\Event\ImportAwareInterface;
use Drupal\migrate\Event\MigrateImportEvent;
use Drupal\migrate\MigrateException;
use Drupal\migrate\MigrateSkipProcessException;
use Drupal\migrate\Plugin\MigrationInterface;
use Drupal\migrate\Plugin\migrate\destination\DestinationBase;
use Drupal\migrate\Plugin\MigrationInterface;
use Drupal\migrate\Row;
use Symfony\Component\DependencyInjection\ContainerInterface;
......@@ -133,7 +133,6 @@ class Table extends DestinationBase implements ContainerFactoryPluginInterface,
* {@inheritdoc}
*/
public function import(Row $row, array $old_destination_id_values = []) {
$ids = [];
// Skip batching (if configured) for updates.
$batch_inserts = ($this->batchSize > 1 && empty($old_destination_id_values));
$ids = [];
......
......@@ -150,7 +150,7 @@ class Dom extends ProcessPluginBase {
}
if ($this->logMessages) {
set_error_handler(function ($errno, $errstr) use ($migrate_executable) {
set_error_handler(static function ($errno, $errstr) use ($migrate_executable) {
$migrate_executable->saveMessage($errstr, MigrationInterface::MESSAGE_WARNING);
});
}
......
......@@ -177,7 +177,7 @@ class DomApplyStyles extends DomProcessBase implements ContainerFactoryPluginInt
// An entry in $this->styles has the format element(\.class)*: for example,
// 'p' or 'a.button' or 'div.col-xs-6.col-md-4'.
// @see setStyles()
list($element, $classes) = explode('.', $this->styles[$rule['style']] . '.', 2);
[$element, $classes] = explode('.', $this->styles[$rule['style']] . '.', 2);
$classes = trim(str_replace('.', ' ', $classes));
foreach ($this->xpath->query($rule['xpath']) as $node) {
......
......@@ -182,7 +182,7 @@ class DomStrReplace extends DomProcessBase {
$function = 'str_ireplace';
}
else {
$function = "str_replace";
$function = 'str_replace';
}
$new_subject = $function($search, $replace, $subject);
$this->postReplace($html_node, $new_subject);
......
......@@ -142,15 +142,7 @@ class EntityGenerate extends EntityLookup {
// Gather any additional properties/fields.
if (isset($this->configuration['values']) && is_array($this->configuration['values'])) {
foreach ($this->configuration['values'] as $key => $property) {
// TODO: Remove this logic once 8.6 is no longer supported.
// See https://www.drupal.org/project/migrate_plus/issues/3043199
if (version_compare(\Drupal::VERSION, '8.7', '>=')) {
$source_value = $this->row->get($property);
}
else {
$getProcessPlugin = $this->processPluginManager->createInstance('get', ['source' => $property]);
$source_value = $getProcessPlugin->transform(NULL, $this->migrateExecutable, $this->row, $property);
}
$source_value = $this->row->get($property);
NestedArray::setValue($entity_values, explode(Row::PROPERTY_SEPARATOR, $key), $source_value, TRUE);
}
}
......
......@@ -4,9 +4,9 @@ namespace Drupal\migrate_plus\Plugin\migrate\process;
use Drupal\Core\Config\Entity\ConfigEntityInterface;
use Drupal\Core\Plugin\ContainerFactoryPluginInterface;
use Drupal\migrate\Plugin\MigrationInterface;
use Drupal\migrate\MigrateException;
use Drupal\migrate\MigrateExecutableInterface;
use Drupal\migrate\Plugin\MigrationInterface;
use Drupal\migrate\ProcessPluginBase;
use Drupal\migrate\Row;
use Symfony\Component\DependencyInjection\ContainerInterface;
......
......@@ -122,7 +122,7 @@ class FileBlob extends ProcessPluginBase implements ContainerFactoryPluginInterf
if ($row->isStub()) {
return NULL;
}
list($destination, $blob) = $value;
[$destination, $blob] = $value;
// Determine if we going to overwrite existing files or not touch them.
$replace = $this->getOverwriteMode();
......@@ -133,17 +133,11 @@ class FileBlob extends ProcessPluginBase implements ContainerFactoryPluginInterf
return $destination;
}
$dir = $this->getDirectory($destination);
// TODO: remove after 8.6 is no longer supported in
// https://www.drupal.org/project/migrate_plus/issues/3035587
if (version_compare(\Drupal::VERSION, '8.7', '>=')) {
$success = $this->fileSystem->prepareDirectory($dir, FileSystemInterface::CREATE_DIRECTORY | FileSystemInterface::MODIFY_PERMISSIONS);
if (!$success) {
throw new MigrateSkipProcessException("Could not create directory '$dir'");
}
}
elseif (file_prepare_directory($dir, FILE_CREATE_DIRECTORY | FILE_MODIFY_PERMISSIONS)) {
$success = $this->fileSystem->prepareDirectory($dir, FileSystemInterface::CREATE_DIRECTORY | FileSystemInterface::MODIFY_PERMISSIONS);
if (!$success) {
throw new MigrateSkipProcessException("Could not create directory '$dir'");
}
if ($this->putFile($destination, $blob, $replace)) {
return $destination;
}
......@@ -165,18 +159,7 @@ class FileBlob extends ProcessPluginBase implements ContainerFactoryPluginInterf
* File path on success, FALSE on failure.
*/
protected function putFile($destination, $blob, $replace = FileSystemInterface::EXISTS_REPLACE) {
// TODO: remove after 8.6 is no longer supported in
// https://www.drupal.org/project/migrate_plus/issues/3035587
if (!isset($replace)) {
$replace = FILE_EXISTS_REPLACE;
}
if (version_compare(\Drupal::VERSION, '8.7', '>=')) {
$path = $this->fileSystem->getDestinationFilename($destination, $replace);
}
else {
$path = file_destination($destination, $replace);
}
$path = $this->fileSystem->getDestinationFilename($destination, $replace);
if ($path) {
if (file_put_contents($path, $blob)) {
return $path;
......@@ -198,24 +181,10 @@ class FileBlob extends ProcessPluginBase implements ContainerFactoryPluginInterf
* FileSystemInterface::EXISTS_ERROR, depending on the configuration.
*/
protected function getOverwriteMode() {
// TODO: remove after 8.6 is no longer supported in
// https://www.drupal.org/project/migrate_plus/issues/3035587
if (isset($this->configuration['reuse']) && !empty($this->configuration['reuse'])) {
if (version_compare(\Drupal::VERSION, '8.7', '>=')) {
return FileSystemInterface::EXISTS_ERROR;
}
else {
return FILE_EXISTS_ERROR;
}
}
if (version_compare(\Drupal::VERSION, '8.7', '>=')) {
return FileSystemInterface::EXISTS_REPLACE;
}
else {
return FILE_EXISTS_REPLACE;
return FileSystemInterface::EXISTS_ERROR;
}
return FileSystemInterface::EXISTS_REPLACE;
}
/**
......
......@@ -2,9 +2,9 @@
namespace Drupal\migrate_plus\Plugin\migrate\process;
use Drupal\migrate\ProcessPluginBase;
use Drupal\migrate\MigrateException;
use Drupal\migrate\MigrateExecutableInterface;
use Drupal\migrate\ProcessPluginBase;
use Drupal\migrate\Row;
/**
......
......@@ -93,7 +93,7 @@ class StrReplace extends ProcessPluginBase {
'case_insensitive' => FALSE,
'regex' => FALSE,
];
$function = "str_replace";
$function = 'str_replace';
if ($this->configuration['case_insensitive']) {
$function = 'str_ireplace';
}
......
......@@ -5,8 +5,8 @@ namespace Drupal\migrate_plus\Plugin\migrate\process;
use Drupal\Component\Transliteration\TransliterationInterface;
use Drupal\Core\Language\LanguageInterface;
use Drupal\Core\Plugin\ContainerFactoryPluginInterface;
use Drupal\migrate\ProcessPluginBase;
use Drupal\migrate\MigrateExecutableInterface;
use Drupal\migrate\ProcessPluginBase;
use Drupal\migrate\Row;
use Symfony\Component\DependencyInjection\ContainerInterface;
......
......@@ -2,8 +2,8 @@
namespace Drupal\migrate_plus\Plugin\migrate\source;
use Drupal\migrate\Plugin\MigrationInterface;
use Drupal\migrate\Plugin\migrate\source\SourcePluginBase;
use Drupal\migrate\Plugin\MigrationInterface;
/**
* Generally-useful extensions to the core SourcePluginBase.
......
<?php
namespace Drupal\Tests\migrate_plus\Functional;
use Drupal\entity_test\Entity\EntityTest;
use Drupal\migrate\MigrateExecutable;
use Drupal\migrate\Row;
use Drupal\Tests\BrowserTestBase;
use Drupal\user\Entity\User;
/**
* Tests entity lookup access check.
*
* @group migrate_plus
*/
class EntityLookupAccessTest extends BrowserTestBase {
/**
* {@inheritdoc}
*/
protected static $modules = [
'migrate_plus',
'entity_test',
];
/**
* A user.
*
* @var \Drupal\user\Entity\User
*/
protected $user;
/**
* A test entity.
*
* @var \Drupal\entity_test\Entity\EntityTest
*/
protected $entity;
/**
* {@inheritdoc}
*/
protected $defaultTheme = 'stark';
/**
* {@inheritdoc}
*/
protected function setUp() {
parent::setUp();
$this->user = $this->createUser(['view all entity_test_query_access entities']);
$this->entity = EntityTest::create(['name' => $this->randomMachineName(8)]);
}
/**
* Tests that access is honored for entity lookups.
*/
public function testEntityLookupAccessCheck() {
$definition = [
'source' => [
'plugin' => 'embedded_data',
'data_rows' => [
['id' => 1],
],
'ids' => [
'id' => ['type' => 'integer'],
],
],
'process' => [],
'destination' => [
'plugin' => 'entity:entity_test',
],
];
$migration = \Drupal::service('plugin.manager.migration')->createStubMigration($definition);
$executable = new MigrateExecutable($migration);
$row = new Row();
$configuration_base = [
'entity_type' => 'entity_test',
'value_key' => 'id',
];
// Set access_check true.
$configuration = $configuration_base + ['access_check' => TRUE];
$anonymous = User::getAnonymousUser();
$this->setCurrentUser($anonymous);
$plugin = \Drupal::service('plugin.manager.migrate.process')
->createInstance('entity_lookup', $configuration, $migration);
// Check the entity is not found.
$value = $plugin->transform($this->entity->id(), $executable, $row, 'id');
$this->assertNull($value);
// Retest with access check false.
$configuration = $configuration_base + ['access_check' => FALSE];
$plugin = \Drupal::service('plugin.manager.migrate.process')
->createInstance('entity_lookup', $configuration, $migration);
// Check the entity is found.
$value = $plugin->transform($this->entity->id(), $executable, $row, 'id');
$this->assertSame($this->entity->id(), $value);
}
}
......@@ -12,12 +12,11 @@ use Drupal\Tests\BrowserTestBase;
*/
class LoadTest extends BrowserTestBase {
/**
* Modules to enable.
*
* @var array
* {@inheritdoc}
*/
public static $modules = [
protected static $modules = [
'migrate_plus',
'migrate_example',
'migrate_example_setup',
......
......@@ -88,7 +88,7 @@ class MigrationGroupTest extends KernelTestBase {
$loaded_migration = $this->container->get('plugin.manager.migration')
->createInstance('specific_migration');
foreach ($expected_config as $method => $expected_value) {
$actual_value = call_user_func([$loaded_migration, $method]);
$actual_value = $loaded_migration->$method();
$this->assertEquals($expected_value, $actual_value);
}
}
......
<?php
namespace Drupal\Tests\migrate_plus\Kernel\Plugin\migrate\process;
use Drupal\KernelTests\KernelTestBase;
use Drupal\Tests\user\Traits\UserCreationTrait;
use Drupal\migrate\MigrateExecutableInterface;
use Drupal\migrate\Plugin\MigrateDestinationInterface;
use Drupal\migrate\Plugin\MigrationInterface;
use Drupal\migrate\Row;
use Drupal\profile\Entity\Profile;
use Drupal\profile\Entity\ProfileType;
/**
* Tests Entity Lookup access check.
*
* @group migrate_plus
*
* @requires entity
* @requires profile
*/
class EntityLookupAccessTest extends KernelTestBase {
use UserCreationTrait;
/**
* {@inheritdoc}
*/
public static $modules = [
'entity',
'field',
'migrate',
'migrate_plus',
'node',
'profile',
'system',
'user',
'views',
'text',
];
/**
* The mocked migration.
*
* @var \Drupal\migrate\Plugin\MigrationInterface|\Prophecy\Prophecy\ObjectProphecy
*/
protected $migration;
/**
* The mocked migrate executable.
*
* @var \Drupal\migrate\MigrateExecutable|\Prophecy\Prophecy\ObjectProphecy
*/
protected $executable;
/**
* The migrate row.
*
* @var \Drupal\migrate\Row
*/
protected $row;
/**
* {@inheritdoc}
*/
protected function setUp() {
parent::setUp();
$this->installSchema('system', 'sequences');
$this->installEntitySchema('profile');
$this->installEntitySchema('user');
$this->installConfig(['profile', 'system']);
$known_user = $this->createUser([], 'lucuma');
// Create a profile entity.
ProfileType::create(['id' => 'default']);
Profile::create([
'uid' => $known_user->id(),
'type' => 'default',
])->save();
$migration_prophecy = $this->prophesize(MigrationInterface::class);
$migrate_destination_prophecy = $this->prophesize(MigrateDestinationInterface::class);
$migrate_destination_prophecy->getPluginId()->willReturn('profile');
$migrate_destination = $migrate_destination_prophecy->reveal();
$migration_prophecy->getDestinationPlugin()
->willReturn($migrate_destination);
$migration_prophecy->getProcess()->willReturn([]);
$this->migration = $migration_prophecy->reveal();
$this->executable = $this->prophesize(MigrateExecutableInterface::class)
->reveal();
$this->row = new Row();
}
/**
* Tests entity_lookup access_check configuration key.
*/
public function testEntityLookupAccessCheck() {
$configuration_base = [
'entity_type' => 'profile',
'value_key' => 'profile_id',
];
// Set access_check true.
$configuration = $configuration_base +
[
'access_check' => TRUE,
];
$plugin = \Drupal::service('plugin.manager.migrate.process')
->createInstance('entity_lookup', $configuration, $this->migration);
// Check the profile is not found.
$value = $plugin->transform('1', $this->executable, $this->row, 'profile_id');
$this->assertNull($value);
// Retest with access check false.
$configuration = $configuration_base +
[
'access_check' => FALSE,
];
$plugin = \Drupal::service('plugin.manager.migrate.process')
->createInstance('entity_lookup', $configuration, $this->migration);
// Check the profile is found.
$value = $plugin->transform('1', $this->executable, $this->row, 'profile_id');
$this->assertSame('1', $value);
}
}
......@@ -210,18 +210,9 @@ EOT;
$file = $file_blob->transform($value, $executable, $row, 'destination_property');
$this->assertEquals('public://cat.jpeg', $file);
$this->assertEquals($this->sha1sum, sha1_file($file));
// TODO: remove after 8.6 is no longer supported in
// https://www.drupal.org/project/migrate_plus/issues/3035587
if (version_compare(\Drupal::VERSION, '8.7', '>=')) {
$configuration = [
'reuse' => FileSystemInterface::EXISTS_ERROR,
];
}
else {
$configuration = [
'reuse' => FILE_EXISTS_ERROR,
];
}
$configuration = [
'reuse' => FileSystemInterface::EXISTS_ERROR,
];
/** @var \Drupal\migrate_plus\Plugin\migrate\process\FileBlob $file_blob */
$file_blob = $this->pluginManager->createInstance('file_blob', $configuration);
/** @var \Drupal\migrate\MigrateExecutableInterface $executable */
......
......@@ -2,8 +2,8 @@
namespace Drupal\Tests\migrate_plus\Kernel\Plugin\migrate_plus\data_parser;
use Drupal\Migrate\MigrateException;
use Drupal\KernelTests\KernelTestBase;
use Drupal\Migrate\MigrateException;
/**
* Test of the data_parser SimpleXml migrate_plus plugin.
......
......@@ -2,9 +2,9 @@
namespace Drupal\Tests\migrate_plus\Unit\process;
use Drupal\Tests\migrate\Unit\process\MigrateProcessTestCase;
use Drupal\migrate_plus\Plugin\migrate\process\ArrayPop;
use Drupal\migrate\MigrateException;
use Drupal\migrate_plus\Plugin\migrate\process\ArrayPop;
use Drupal\Tests\migrate\Unit\process\MigrateProcessTestCase;