644371e5f5d35c4b7556177dde1b082b934f3a15
[yaffs-website] / web / core / modules / migrate / tests / src / Kernel / process / FileCopyTest.php
1 <?php
2
3 namespace Drupal\Tests\migrate\Kernel\process;
4
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;
12
13 /**
14  * Tests the file_copy process plugin.
15  *
16  * @coversDefaultClass \Drupal\migrate\Plugin\migrate\process\FileCopy
17  *
18  * @group migrate
19  */
20 class FileCopyTest extends FileTestBase {
21
22   /**
23    * {@inheritdoc}
24    */
25   public static $modules = ['migrate', 'system'];
26
27   /**
28    * The file system service.
29    *
30    * @var \Drupal\Core\File\FileSystemInterface
31    */
32   protected $fileSystem;
33
34   /**
35    * {@inheritdoc}
36    */
37   protected function setUp() {
38     parent::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);
41   }
42
43   /**
44    * Test successful imports/copies.
45    */
46   public function testSuccessfulCopies() {
47     $file = $this->createUri(NULL, NULL, 'temporary');
48     $file_absolute = $this->fileSystem->realpath($file);
49     $data_sets = [
50       // Test a local to local copy.
51       [
52         $this->root . '/core/modules/simpletest/files/image-test.jpg',
53         'public://file1.jpg'
54       ],
55       // Test a temporary file using an absolute path.
56       [
57         $file_absolute,
58         'temporary://test.jpg'
59       ],
60       // Test a temporary file using a relative path.
61       [
62         $file_absolute,
63         'temporary://core/modules/simpletest/files/test.jpg'
64       ],
65     ];
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.');
74     }
75   }
76
77   /**
78    * Test successful file reuse.
79    */
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);
86
87     // We need to make sure the modified timestamp on the file is sooner than
88     // the attempted migration.
89     sleep(1);
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);
95
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);
101   }
102
103   /**
104    * Test successful moves.
105    */
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');
112     $data_sets = [
113       // Test a local to local copy.
114       [
115         $local_file,
116         'public://file1.jpg'
117       ],
118       // Test a temporary file using an absolute path.
119       [
120         $file_1_absolute,
121         'temporary://test.jpg'
122       ],
123       // Test a temporary file using a relative path.
124       [
125         $file_2_absolute,
126         'temporary://core/modules/simpletest/files/test.jpg'
127       ],
128     ];
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.');
137     }
138   }
139
140   /**
141    * Test that non-existent files throw an exception.
142    */
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');
147   }
148
149   /**
150    * Tests that non-writable destination throw an exception.
151    *
152    * @covers ::transform
153    */
154   public function testNonWritableDestination() {
155     $source = $this->createUri('file.txt', NULL, 'temporary');
156
157     // Create the parent location.
158     $this->createDirectory('public://dir');
159
160     // Copy the file under public://dir/subdir1/.
161     $this->doTransform($source, 'public://dir/subdir1/file.txt');
162
163     // Check that 'subdir1' was created and the file was successfully migrated.
164     $this->assertFileExists('public://dir/subdir1/file.txt');
165
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);
169
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');
173   }
174
175   /**
176    * Test the 'rename' overwrite mode.
177    */
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.');
185   }
186
187   /**
188    * Tests that remote URIs are delegated to the download plugin.
189    */
190   public function testDownloadRemoteUri() {
191     $download_plugin = $this->getMock(MigrateProcessInterface::class);
192     $download_plugin->expects($this->once())->method('transform');
193
194     $plugin = new FileCopy(
195       [],
196       $this->randomMachineName(),
197       [],
198       $this->container->get('stream_wrapper_manager'),
199       $this->container->get('file_system'),
200       $download_plugin
201     );
202
203     $plugin->transform(
204       ['http://drupal.org/favicon.ico', '/destination/path'],
205       $this->getMock(MigrateExecutableInterface::class),
206       new Row([], []),
207       $this->randomMachineName()
208     );
209   }
210
211   /**
212    * Do an import using the destination.
213    *
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.
220    *
221    * @return string
222    *   The URI of the copied file.
223    */
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([], []);
228
229     return $plugin->transform([$source_path, $destination_path], $executable, $row, 'foobaz');
230   }
231
232 }