Commit 73bfe912 authored by catch's avatar catch

Issue #2505283 by quietone, maxocub, Jo Fitzgerald, mikeryan, Pavan B S,...

Issue #2505283 by quietone, maxocub, Jo Fitzgerald, mikeryan, Pavan B S, penyaskito, chriscalip, phenaproxima: Handle import of private files
parent fa54442c
......@@ -6,6 +6,7 @@ migration_tags:
- Drupal 7
source:
plugin: d7_file
scheme: public
constants:
# The tool configuring this migration must set source_base_path. It
# represents the fully qualified path relative to which URIs in the files
......
id: d7_file_private
label: Files
migration_tags:
- Drupal 7
source:
plugin: d7_file
scheme: private
constants:
# source_base_path must be set by the tool configuring this migration.
# It represents the fully qualified path relative to which uris in the files
# table are specified, and must end with a /. See source_full_path
# configuration in this migration's process pipeline as an example.
source_base_path: ''
process:
# If you are using this file to build a custom migration consider removing
# the fid field to allow incremental migrations.
fid: fid
filename: filename
source_full_path:
-
plugin: concat
delimiter: /
source:
- constants/source_base_path
- filepath
uri:
plugin: file_copy
source:
- '@source_full_path'
- uri
filemime: filemime
status: status
# Drupal 7 didn't keep track of the file's creation or update time -- all it
# had was the vague "timestamp" column. So we'll use it for both.
created: timestamp
changed: timestamp
uid: uid
destination:
plugin: entity:file
<?php
namespace Drupal\Tests\file\Kernel\Migrate\d7;
use Drupal\Core\DependencyInjection\ContainerBuilder;
use Drupal\file\Entity\File;
use Drupal\file\FileInterface;
use Drupal\Tests\migrate_drupal\Kernel\d7\MigrateDrupal7TestBase;
/**
* Tests private files migration.
*
* @group file
*/
class MigratePrivateFileTest extends MigrateDrupal7TestBase {
/**
* {@inheritdoc}
*/
public static $modules = ['file'];
/**
* {@inheritdoc}
*/
protected function setUp() {
parent::setUp();
$this->setSetting('file_private_path', $this->container->get('site.path') . '/private');
$this->installEntitySchema('file');
$fs = $this->container->get('file_system');
// Ensure that the private files directory exists.
$fs->mkdir('private://sites/default/private/', NULL, TRUE);
// Put test file in the source directory.
file_put_contents('private://sites/default/private/Babylon5.txt', str_repeat('*', 3));
/** @var \Drupal\migrate\Plugin\Migration $migration */
$migration = $this->getMigration('d7_file_private');
// Set the source plugin's source_file_private_path configuration value,
// which would normally be set by the user running the migration.
$source = $migration->getSourceConfiguration();
$source['constants']['source_base_path'] = $fs->realpath('private://');
$migration->set('source', $source);
$this->executeMigration($migration);
}
/**
* {@inheritdoc}
*/
public function register(ContainerBuilder $container) {
parent::register($container);
$container->register('stream_wrapper.private', 'Drupal\Core\StreamWrapper\PrivateStream')
->addTag('stream_wrapper', ['scheme' => 'private']);
}
/**
* Tests a single file entity.
*
* @param int $id
* The file ID.
* @param string $name
* The expected file name.
* @param string $uri
* The expected URI.
* @param string $mime
* The expected MIME type.
* @param int $size
* The expected file size.
* @param int $created
* The expected creation time.
* @param int $changed
* The expected modification time.
* @param int $uid
* The expected owner ID.
*/
protected function assertEntity($id, $name, $uri, $mime, $size, $created, $changed, $uid) {
/** @var \Drupal\file\FileInterface $file */
$file = File::load($id);
$this->assertInstanceOf(FileInterface::class, $file);
$this->assertSame($name, $file->getFilename());
$this->assertSame($uri, $file->getFileUri());
$this->assertFileExists($uri);
$this->assertSame($mime, $file->getMimeType());
$this->assertSame($size, $file->getSize());
// isPermanent(), isTemporary(), etc. are determined by the status column.
$this->assertTrue($file->isPermanent());
$this->assertSame($created, $file->getCreatedTime());
$this->assertSame($changed, $file->getChangedTime());
$this->assertSame($uid, $file->getOwnerId());
}
/**
* Tests that all expected files are migrated.
*/
public function testFileMigration() {
$this->assertEntity(3, 'Babylon5.txt', 'private://Babylon5.txt', 'text/plain', '3', '1486104045', '1486104045', '1');
}
}
......@@ -104,6 +104,9 @@ public static function run($initial_ids, $config, &$context) {
// @todo Find a way to avoid this in https://www.drupal.org/node/2804611.
if ($definition['destination']['plugin'] === 'entity:file') {
// Make sure we have a single trailing slash.
if ($definition['source']['plugin'] === 'd7_file_private') {
$configuration['source']['constants']['source_base_path'] = rtrim($config['source_private_file_path'], '/') . '/';
}
$configuration['source']['constants']['source_base_path'] = rtrim($config['source_base_path'], '/') . '/';
}
......
......@@ -250,6 +250,10 @@ class MigrateUpgradeForm extends ConfirmFormBase {
'source_module' => 'file',
'destination_module' => 'file',
],
'd7_file_private' => [
'source_module' => 'file',
'destination_module' => 'file',
],
'd6_filter_format' => [
'source_module' => 'filter',
'destination_module' => 'filter',
......@@ -885,6 +889,15 @@ public function buildCredentialForm(array $form, FormStateInterface $form_state)
$default_options = [];
$form['version'] = [
'#type' => 'radios',
'#default_value' => 7,
'#title' => $this->t('Drupal version of the source site'),
'#options' => [6 => $this->t('Drupal 6'), 7 => $this->t('Drupal 7')],
'#required' => TRUE,
];
$form['database'] = [
'#type' => 'details',
'#title' => $this->t('Source database'),
......@@ -938,10 +951,38 @@ public function buildCredentialForm(array $form, FormStateInterface $form_state)
'#title' => $this->t('Source files'),
'#open' => TRUE,
];
$form['source']['source_base_path'] = [
$form['source']['d6_source_base_path'] = [
'#type' => 'textfield',
'#title' => $this->t('Files directory'),
'#description' => $this->t('To import files from your current Drupal site, enter a local file directory containing your site (e.g. /var/www/docroot), or your site address (for example http://example.com).'),
'#states' => [
'visible' => [
':input[name="version"]' => ['value' => 6],
],
],
];
$form['source']['source_base_path'] = [
'#type' => 'textfield',
'#title' => $this->t('Public files directory'),
'#description' => $this->t('To import public files from your current Drupal site, enter a local file directory containing your site (e.g. /var/www/docroot), or your site address (for example http://example.com).'),
'#states' => [
'visible' => [
':input[name="version"]' => ['value' => 7],
],
],
];
$form['source']['source_private_file_path'] = [
'#type' => 'textfield',
'#title' => $this->t('Private file directory'),
'#default_value' => '',
'#description' => $this->t('To import private files from your current Drupal site, enter a local file directory containing your site (e.g. /var/www/docroot).'),
'#states' => [
'visible' => [
':input[name="version"]' => ['value' => 7],
],
],
];
$form['actions'] = ['#type' => 'actions'];
......@@ -992,6 +1033,12 @@ public function validateCredentialForm(array &$form, FormStateInterface $form_st
if (!$version) {
$form_state->setErrorByName($database['driver'] . '][0', $this->t('Source database does not contain a recognizable Drupal version.'));
}
elseif ($version != $form_state->getValue('version')) {
$form_state->setErrorByName($database['driver'] . '][0', $this->t('Source database is Drupal version @version but version @selected was selected.', [
'@version' => $version,
'@selected' => $form_state->getValue('version'),
]));
}
else {
$this->createDatabaseStateSettings($database, $version);
$migrations = $this->getMigrations('migrate_drupal_' . $version, $version);
......@@ -1009,6 +1056,7 @@ public function validateCredentialForm(array &$form, FormStateInterface $form_st
// Store the retrieved migration IDs in form storage.
$form_state->set('migrations', $migration_array);
$form_state->set('source_base_path', $form_state->getValue('source_base_path'));
$form_state->set('source_private_file_path', $form_state->getValue('source_private_file_path'));
// Store the retrived system data in form storage.
$form_state->set('system_data', $system_data);
......
......@@ -127,9 +127,12 @@ public function testMigrateUpgrade() {
$drivers = drupal_get_database_types();
$form = $drivers[$driver]->getFormOptions($connection_options);
$connection_options = array_intersect_key($connection_options, $form + $form['advanced_options']);
$version = $this->getLegacyDrupalVersion($this->sourceDatabase);
$edit = [
$driver => $connection_options,
'source_base_path' => $this->getSourceBasePath(),
'source_private_file_path' => $this->getSourceBasePath(),
'version' => $version,
];
if (count($drivers) !== 1) {
$edit['driver'] = $driver;
......@@ -159,10 +162,9 @@ public function testMigrateUpgrade() {
$this->assertEqual($expected_count, $real_count, "Found $real_count $entity_type entities, expected $expected_count.");
}
$version_tag = 'Drupal ' . $this->getLegacyDrupalVersion($this->sourceDatabase);
$plugin_manager = \Drupal::service('plugin.manager.migration');
/** @var \Drupal\migrate\Plugin\Migration[] $all_migrations */
$all_migrations = $plugin_manager->createInstancesByTag($version_tag);
$all_migrations = $plugin_manager->createInstancesByTag('Drupal ' . $version);
foreach ($all_migrations as $migration) {
$id_map = $migration->getIdMap();
foreach ($id_map as $source_id => $map) {
......
......@@ -14,6 +14,11 @@
*/
class MigrateUpgrade7Test extends MigrateUpgradeTestBase {
/**
* {@inheritdoc}
*/
public static $modules = ['file'];
/**
* {@inheritdoc}
*/
......@@ -45,9 +50,9 @@ protected function getEntityCounts() {
'configurable_language' => 4,
'contact_form' => 3,
'editor' => 2,
'field_config' => 52,
'field_storage_config' => 39,
'file' => 2,
'field_config' => 53,
'field_storage_config' => 40,
'file' => 3,
'filter_format' => 7,
'image_style' => 6,
'language_content_settings' => 2,
......
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