diff --git a/core/modules/file/src/Plugin/migrate/destination/EntityFile.php b/core/modules/file/src/Plugin/migrate/destination/EntityFile.php index 383b2834be7fb14a7db097eeb23d5f74f4679b5a..57529e1d990c8788bc14e4f72a7c01644c1f49c9 100644 --- a/core/modules/file/src/Plugin/migrate/destination/EntityFile.php +++ b/core/modules/file/src/Plugin/migrate/destination/EntityFile.php @@ -73,6 +73,20 @@ public static function create(ContainerInterface $container, array $configuratio ); } + /** + * {@inheritdoc} + */ + protected function getEntity(Row $row, array $old_destination_id_values) { + $destination = $row->getDestinationProperty($this->configuration['destination_path_property']); + $entity = $this->storage->loadByProperties(['uri' => $destination]); + if ($entity) { + return reset($entity); + } + else { + return parent::getEntity($row, $old_destination_id_values); + } + } + /** * {@inheritdoc} */ diff --git a/core/modules/file/src/Plugin/migrate/process/d6/FileUri.php b/core/modules/file/src/Plugin/migrate/process/d6/FileUri.php index 8668e052b61a06b4a02b9fdb103f136dc39478ec..b464ee00425316abb00ea087fdf33ec0b7ad45d0 100644 --- a/core/modules/file/src/Plugin/migrate/process/d6/FileUri.php +++ b/core/modules/file/src/Plugin/migrate/process/d6/FileUri.php @@ -24,20 +24,19 @@ class FileUri extends ProcessPluginBase { * {@inheritdoc} */ public function transform($value, MigrateExecutableInterface $migrate_executable, Row $row, $destination_property) { - list($filepath, $file_directory_path, $temp_directory_path, $is_public) = $value; // Specific handling using $temp_directory_path for temporary files. if (substr($filepath, 0, strlen($temp_directory_path)) === $temp_directory_path) { $uri = preg_replace('/^' . preg_quote($temp_directory_path, '/') . '/', '', $filepath); - return "temporary://$uri"; + return 'temporary://' . ltrim($uri, '/'); } // Strip the files path from the uri instead of using basename // so any additional folders in the path are preserved. $uri = preg_replace('/^' . preg_quote($file_directory_path, '/') . '/', '', $filepath); - return $is_public ? "public://$uri" : "private://$uri"; + return ($is_public ? 'public' : 'private') . '://' . ltrim($uri, '/'); } } diff --git a/core/modules/file/src/Plugin/migrate/source/d6/File.php b/core/modules/file/src/Plugin/migrate/source/d6/File.php index ab53894f47a656f9838a9318476f719ebb65dd06..3bb7708bf834d2cdfbccb76f2de31cd3538c98a8 100644 --- a/core/modules/file/src/Plugin/migrate/source/d6/File.php +++ b/core/modules/file/src/Plugin/migrate/source/d6/File.php @@ -44,18 +44,13 @@ class File extends DrupalSqlBase { * {@inheritdoc} */ public function query() { - $query = $this->select('files', 'f')->fields('f', array( - 'fid', - 'uid', - 'filename', - 'filepath', - 'filemime', - 'filesize', - 'status', - 'timestamp', - )); - $query->orderBy('timestamp'); - return $query; + return $this->select('files', 'f') + ->fields('f') + ->orderBy('timestamp') + // If two or more files have the same timestamp, they'll end up in a + // non-deterministic order. Ordering by fid (or any other unique field) + // will prevent this. + ->orderBy('fid'); } /** diff --git a/core/modules/file/src/Tests/Migrate/d6/MigrateFileTest.php b/core/modules/file/src/Tests/Migrate/d6/MigrateFileTest.php index 275e43f91f35ec892cbf4808f19278f6db6529c9..4277133e9e6cdab55c320a1387c67f4b5fe5c0e0 100644 --- a/core/modules/file/src/Tests/Migrate/d6/MigrateFileTest.php +++ b/core/modules/file/src/Tests/Migrate/d6/MigrateFileTest.php @@ -8,12 +8,13 @@ namespace Drupal\file\Tests\Migrate\d6; use Drupal\Component\Utility\Random; +use Drupal\file\Entity\File; +use Drupal\file\FileInterface; use Drupal\migrate\Entity\Migration; use Drupal\migrate\Tests\MigrateDumpAlterInterface; use Drupal\Core\Database\Database; use Drupal\migrate_drupal\Tests\d6\MigrateDrupal6TestBase; use Drupal\simpletest\TestBase; -use Drupal\file\Entity\File; /** * file migration. @@ -46,17 +47,41 @@ protected function setUp() { $this->executeMigration($migration); } + /** + * Asserts a file entity. + * + * @param integer $fid + * The file ID. + * @param string $name + * The expected file name. + * @param integer $size + * The expected file size. + * @param string $uri + * The expected file URI. + * @param string $type + * The expected MIME type. + * @param integer $uid + * The expected file owner ID. + */ + protected function assertEntity($fid, $name, $size, $uri, $type, $uid) { + /** @var \Drupal\file\FileInterface $file */ + $file = File::load($fid); + $this->assertTrue($file instanceof FileInterface); + $this->assertIdentical($name, $file->getFilename()); + $this->assertIdentical($size, $file->getSize()); + $this->assertIdentical($uri, $file->getFileUri()); + $this->assertIdentical($type, $file->getMimeType()); + $this->assertIdentical($uid, $file->getOwnerId()); + } + /** * Tests the Drupal 6 files to Drupal 8 migration. */ public function testFiles() { - /** @var \Drupal\file\FileInterface $file */ - $file = File::load(1); - $this->assertIdentical('Image1.png', $file->getFilename()); - $this->assertIdentical('39325', $file->getSize()); - $this->assertIdentical('public://image-1.png', $file->getFileUri()); - $this->assertIdentical('image/png', $file->getMimeType()); - $this->assertIdentical("1", $file->getOwnerId()); + $this->assertEntity(1, 'Image1.png', '39325', 'public://image-1.png', 'image/png', '1'); + $this->assertEntity(2, 'Image2.jpg', '1831', 'public://image-2.jpg', 'image/jpeg', '1'); + $this->assertEntity(3, 'Image-test.gif', '183', 'public://image-test.gif', 'image/jpeg', '1'); + $this->assertEntity(5, 'html-1.txt', '24', 'public://html-1.txt', 'text/plain', '1'); // Test that we can re-import and also test with file_directory_path set. \Drupal::database() @@ -84,6 +109,10 @@ public function testFiles() { // Ensure that a temporary file has been migrated. $file = File::load(6); $this->assertIdentical('temporary://' . static::getUniqueFilename(), $file->getFileUri()); + + // File 7, created in static::migrateDumpAlter(), shares a path with + // file 5, which means it should be skipped entirely. + $this->assertNull(File::load(7)); } /** @@ -105,8 +134,10 @@ public static function migrateDumpAlter(TestBase $test) { static::$tempFilename = $test->getDatabasePrefix() . $random->name() . '.jpg'; $file_path = $temp_directory . '/' . static::$tempFilename; file_put_contents($file_path, ''); - Database::getConnection('default', 'migrate') - ->update('files') + + $db = Database::getConnection('default', 'migrate'); + + $db->update('files') ->condition('fid', 6) ->fields(array( 'filename' => static::$tempFilename, @@ -114,6 +145,14 @@ public static function migrateDumpAlter(TestBase $test) { )) ->execute(); + $file = (array) $db->select('files') + ->fields('files') + ->condition('fid', 5) + ->execute() + ->fetchObject(); + unset($file['fid']); + $db->insert('files')->fields($file)->execute(); + return static::$tempFilename; } diff --git a/core/modules/file/tests/src/Unit/Plugin/migrate/process/d6/FileUriTest.php b/core/modules/file/tests/src/Unit/Plugin/migrate/process/d6/FileUriTest.php new file mode 100644 index 0000000000000000000000000000000000000000..f29e5eeae3bc894e8af5db85893564f18ed5d798 --- /dev/null +++ b/core/modules/file/tests/src/Unit/Plugin/migrate/process/d6/FileUriTest.php @@ -0,0 +1,84 @@ + 'test', + ]; + + public function testPublic() { + $value = [ + 'sites/default/files/foo.jpg', + 'sites/default/files', + '/tmp', + TRUE, + ]; + $this->assertEquals('public://foo.jpg', $this->doTransform($value)); + } + + public function testPublicUnknownBasePath() { + $value = [ + '/path/to/public/files/foo.jpg', + 'sites/default/files', + '/tmp', + TRUE, + ]; + $this->assertEquals('public://path/to/public/files/foo.jpg', $this->doTransform($value)); + } + + public function testPrivate() { + $value = [ + 'sites/default/files/baz.gif', + 'sites/default/files', + '/tmp', + FALSE, + ]; + $this->assertEquals('private://baz.gif', $this->doTransform($value)); + } + + public function testPrivateUnknownBasePath() { + $value = [ + '/path/to/private/files/baz.gif', + 'sites/default/files', + '/tmp', + FALSE, + ]; + $this->assertEquals('private://path/to/private/files/baz.gif', $this->doTransform($value)); + } + + public function testTemporary() { + $value = [ + '/tmp/bar.png', + 'sites/default/files', + '/tmp', + TRUE, + ]; + $this->assertEquals('temporary://bar.png', $this->doTransform($value)); + } + + protected function doTransform(array $value) { + $executable = new MigrateExecutable($this->getMigration(), new MigrateMessage()); + $row = new Row([], []); + + return (new FileUri([], 'file_uri', [])) + ->transform($value, $executable, $row, 'foobaz'); + } + +}