3 namespace Drupal\Tests\migrate\Kernel\process;
5 use Drupal\Core\StreamWrapper\StreamWrapperInterface;
6 use Drupal\KernelTests\Core\File\FileTestBase;
7 use Drupal\migrate\MigrateException;
8 use Drupal\migrate\Plugin\migrate\process\FileCopy;
9 use Drupal\migrate\MigrateExecutableInterface;
10 use Drupal\migrate\Plugin\MigrateProcessInterface;
11 use Drupal\migrate\Row;
14 * Tests the file_copy process plugin.
16 * @coversDefaultClass \Drupal\migrate\Plugin\migrate\process\FileCopy
20 class FileCopyTest extends FileTestBase {
25 public static $modules = ['migrate', 'system'];
28 * The file system service.
30 * @var \Drupal\Core\File\FileSystemInterface
32 protected $fileSystem;
37 protected function setUp() {
39 $this->fileSystem = $this->container->get('file_system');
40 $this->container->get('stream_wrapper_manager')->registerWrapper('temporary', 'Drupal\Core\StreamWrapper\TemporaryStream', StreamWrapperInterface::LOCAL_NORMAL);
44 * Test successful imports/copies.
46 public function testSuccessfulCopies() {
47 $file = $this->createUri(NULL, NULL, 'temporary');
48 $file_absolute = $this->fileSystem->realpath($file);
50 // Test a local to local copy.
52 $this->root . '/core/modules/simpletest/files/image-test.jpg',
55 // Test a temporary file using an absolute path.
58 'temporary://test.jpg'
60 // Test a temporary file using a relative path.
63 'temporary://core/modules/simpletest/files/test.jpg'
66 foreach ($data_sets as $data) {
67 list($source_path, $destination_path) = $data;
68 $actual_destination = $this->doTransform($source_path, $destination_path);
69 $message = sprintf('File %s exists', $destination_path);
70 $this->assertFileExists($destination_path, $message);
71 // Make sure we didn't accidentally do a move.
72 $this->assertFileExists($source_path, $message);
73 $this->assertSame($actual_destination, $destination_path, 'The import returned the copied filename.');
78 * Test successful file reuse.
80 public function testSuccessfulReuse() {
81 $source_path = $this->root . '/core/modules/simpletest/files/image-test.jpg';
82 $destination_path = 'public://file1.jpg';
83 $file_reuse = file_unmanaged_copy($source_path, $destination_path);
84 $timestamp = (new \SplFileInfo($file_reuse))->getMTime();
85 $this->assertInternalType('int', $timestamp);
87 // We need to make sure the modified timestamp on the file is sooner than
88 // the attempted migration.
90 $configuration = ['reuse' => TRUE];
91 $this->doTransform($source_path, $destination_path, $configuration);
92 clearstatcache(TRUE, $destination_path);
93 $modified_timestamp = (new \SplFileInfo($destination_path))->getMTime();
94 $this->assertEquals($timestamp, $modified_timestamp);
96 $configuration = ['reuse' => FALSE];
97 $this->doTransform($source_path, $destination_path, $configuration);
98 clearstatcache(TRUE, $destination_path);
99 $modified_timestamp = (new \SplFileInfo($destination_path))->getMTime();
100 $this->assertGreaterThan($timestamp, $modified_timestamp);
104 * Test successful moves.
106 public function testSuccessfulMoves() {
107 $file_1 = $this->createUri(NULL, NULL, 'temporary');
108 $file_1_absolute = $this->fileSystem->realpath($file_1);
109 $file_2 = $this->createUri(NULL, NULL, 'temporary');
110 $file_2_absolute = $this->fileSystem->realpath($file_2);
111 $local_file = $this->createUri(NULL, NULL, 'public');
113 // Test a local to local copy.
118 // Test a temporary file using an absolute path.
121 'temporary://test.jpg'
123 // Test a temporary file using a relative path.
126 'temporary://core/modules/simpletest/files/test.jpg'
129 foreach ($data_sets as $data) {
130 list($source_path, $destination_path) = $data;
131 $actual_destination = $this->doTransform($source_path, $destination_path, ['move' => TRUE]);
132 $message = sprintf('File %s exists', $destination_path);
133 $this->assertFileExists($destination_path, $message);
134 $message = sprintf('File %s does not exist', $source_path);
135 $this->assertFileNotExists($source_path, $message);
136 $this->assertSame($actual_destination, $destination_path, 'The importer returned the moved filename.');
141 * Test that non-existent files throw an exception.
143 public function testNonExistentSourceFile() {
144 $source = '/non/existent/file';
145 $this->setExpectedException(MigrateException::class, "File '/non/existent/file' does not exist");
146 $this->doTransform($source, 'public://wontmatter.jpg');
150 * Tests that non-writable destination throw an exception.
152 * @covers ::transform
154 public function testNonWritableDestination() {
155 $source = $this->createUri('file.txt', NULL, 'temporary');
157 // Create the parent location.
158 $this->createDirectory('public://dir');
160 // Copy the file under public://dir/subdir1/.
161 $this->doTransform($source, 'public://dir/subdir1/file.txt');
163 // Check that 'subdir1' was created and the file was successfully migrated.
164 $this->assertFileExists('public://dir/subdir1/file.txt');
166 // Remove all permissions from public://dir to trigger a failure when
167 // trying to create a subdirectory 'subdir2' inside public://dir.
168 $this->fileSystem->chmod('public://dir', 0);
170 // Check that the proper exception is raised.
171 $this->setExpectedException(MigrateException::class, "Could not create or write to directory 'public://dir/subdir2'");
172 $this->doTransform($source, 'public://dir/subdir2/file.txt');
176 * Test the 'rename' overwrite mode.
178 public function testRenameFile() {
179 $source = $this->createUri(NULL, NULL, 'temporary');
180 $destination = $this->createUri('foo.txt', NULL, 'public');
181 $expected_destination = 'public://foo_0.txt';
182 $actual_destination = $this->doTransform($source, $destination, ['rename' => TRUE]);
183 $this->assertFileExists($expected_destination, 'File was renamed on import');
184 $this->assertSame($actual_destination, $expected_destination, 'The importer returned the renamed filename.');
188 * Tests that remote URIs are delegated to the download plugin.
190 public function testDownloadRemoteUri() {
191 $download_plugin = $this->getMock(MigrateProcessInterface::class);
192 $download_plugin->expects($this->once())->method('transform');
194 $plugin = new FileCopy(
196 $this->randomMachineName(),
198 $this->container->get('stream_wrapper_manager'),
199 $this->container->get('file_system'),
204 ['http://drupal.org/favicon.ico', '/destination/path'],
205 $this->getMock(MigrateExecutableInterface::class),
207 $this->randomMachineName()
212 * Do an import using the destination.
214 * @param string $source_path
215 * Source path to copy from.
216 * @param string $destination_path
217 * The destination path to copy to.
218 * @param array $configuration
219 * Process plugin configuration settings.
222 * The URI of the copied file.
224 protected function doTransform($source_path, $destination_path, $configuration = []) {
225 $plugin = FileCopy::create($this->container, $configuration, 'file_copy', []);
226 $executable = $this->prophesize(MigrateExecutableInterface::class)->reveal();
227 $row = new Row([], []);
229 return $plugin->transform([$source_path, $destination_path], $executable, $row, 'foobaz');