Chris@0
|
1 <?php
|
Chris@0
|
2
|
Chris@0
|
3 namespace Drupal\Tests\file\Kernel;
|
Chris@0
|
4
|
Chris@5
|
5 use Drupal\Core\Database\Database;
|
Chris@0
|
6 use Drupal\field\Entity\FieldConfig;
|
Chris@0
|
7 use Drupal\field\Entity\FieldStorageConfig;
|
Chris@0
|
8 use Drupal\language\Entity\ConfigurableLanguage;
|
Chris@0
|
9 use Drupal\language\Entity\ContentLanguageSettings;
|
Chris@0
|
10 use Drupal\node\Entity\Node;
|
Chris@0
|
11 use Drupal\node\Entity\NodeType;
|
Chris@0
|
12
|
Chris@0
|
13 /**
|
Chris@0
|
14 * Tests file usage functions.
|
Chris@0
|
15 *
|
Chris@0
|
16 * @group file
|
Chris@0
|
17 */
|
Chris@0
|
18 class UsageTest extends FileManagedUnitTestBase {
|
Chris@4
|
19
|
Chris@0
|
20 /**
|
Chris@0
|
21 * Tests \Drupal\file\FileUsage\DatabaseFileUsageBackend::listUsage().
|
Chris@0
|
22 */
|
Chris@0
|
23 public function testGetUsage() {
|
Chris@0
|
24 $file = $this->createFile();
|
Chris@5
|
25 $connection = Database::getConnection();
|
Chris@5
|
26 $connection->insert('file_usage')
|
Chris@0
|
27 ->fields([
|
Chris@0
|
28 'fid' => $file->id(),
|
Chris@0
|
29 'module' => 'testing',
|
Chris@0
|
30 'type' => 'foo',
|
Chris@0
|
31 'id' => 1,
|
Chris@4
|
32 'count' => 1,
|
Chris@0
|
33 ])
|
Chris@0
|
34 ->execute();
|
Chris@5
|
35 $connection->insert('file_usage')
|
Chris@0
|
36 ->fields([
|
Chris@0
|
37 'fid' => $file->id(),
|
Chris@0
|
38 'module' => 'testing',
|
Chris@0
|
39 'type' => 'bar',
|
Chris@0
|
40 'id' => 2,
|
Chris@4
|
41 'count' => 2,
|
Chris@0
|
42 ])
|
Chris@0
|
43 ->execute();
|
Chris@0
|
44
|
Chris@0
|
45 $usage = $this->container->get('file.usage')->listUsage($file);
|
Chris@0
|
46
|
Chris@0
|
47 $this->assertEqual(count($usage['testing']), 2, 'Returned the correct number of items.');
|
Chris@0
|
48 $this->assertTrue(isset($usage['testing']['foo'][1]), 'Returned the correct id.');
|
Chris@0
|
49 $this->assertTrue(isset($usage['testing']['bar'][2]), 'Returned the correct id.');
|
Chris@0
|
50 $this->assertEqual($usage['testing']['foo'][1], 1, 'Returned the correct count.');
|
Chris@0
|
51 $this->assertEqual($usage['testing']['bar'][2], 2, 'Returned the correct count.');
|
Chris@0
|
52 }
|
Chris@0
|
53
|
Chris@0
|
54 /**
|
Chris@0
|
55 * Tests \Drupal\file\FileUsage\DatabaseFileUsageBackend::add().
|
Chris@0
|
56 */
|
Chris@0
|
57 public function testAddUsage() {
|
Chris@0
|
58 $file = $this->createFile();
|
Chris@0
|
59 $file_usage = $this->container->get('file.usage');
|
Chris@0
|
60 $file_usage->add($file, 'testing', 'foo', 1);
|
Chris@0
|
61 // Add the file twice to ensure that the count is incremented rather than
|
Chris@0
|
62 // creating additional records.
|
Chris@0
|
63 $file_usage->add($file, 'testing', 'bar', 2);
|
Chris@0
|
64 $file_usage->add($file, 'testing', 'bar', 2);
|
Chris@0
|
65
|
Chris@5
|
66 $usage = Database::getConnection()->select('file_usage', 'f')
|
Chris@0
|
67 ->fields('f')
|
Chris@0
|
68 ->condition('f.fid', $file->id())
|
Chris@0
|
69 ->execute()
|
Chris@0
|
70 ->fetchAllAssoc('id');
|
Chris@0
|
71 $this->assertEqual(count($usage), 2, 'Created two records');
|
Chris@0
|
72 $this->assertEqual($usage[1]->module, 'testing', 'Correct module');
|
Chris@0
|
73 $this->assertEqual($usage[2]->module, 'testing', 'Correct module');
|
Chris@0
|
74 $this->assertEqual($usage[1]->type, 'foo', 'Correct type');
|
Chris@0
|
75 $this->assertEqual($usage[2]->type, 'bar', 'Correct type');
|
Chris@0
|
76 $this->assertEqual($usage[1]->count, 1, 'Correct count');
|
Chris@0
|
77 $this->assertEqual($usage[2]->count, 2, 'Correct count');
|
Chris@0
|
78 }
|
Chris@0
|
79
|
Chris@0
|
80 /**
|
Chris@0
|
81 * Tests file usage deletion when files are made temporary.
|
Chris@0
|
82 */
|
Chris@0
|
83 public function testRemoveUsageTemporary() {
|
Chris@0
|
84 $this->config('file.settings')
|
Chris@0
|
85 ->set('make_unused_managed_files_temporary', TRUE)
|
Chris@0
|
86 ->save();
|
Chris@0
|
87 $file = $this->doTestRemoveUsage();
|
Chris@0
|
88 $this->assertTrue($file->isTemporary());
|
Chris@0
|
89 }
|
Chris@0
|
90
|
Chris@0
|
91 /**
|
Chris@0
|
92 * Tests file usage deletion when files are made temporary.
|
Chris@0
|
93 */
|
Chris@0
|
94 public function testRemoveUsageNonTemporary() {
|
Chris@0
|
95 $this->config('file.settings')
|
Chris@0
|
96 ->set('make_unused_managed_files_temporary', FALSE)
|
Chris@0
|
97 ->save();
|
Chris@0
|
98 $file = $this->doTestRemoveUsage();
|
Chris@0
|
99 $this->assertFalse($file->isTemporary());
|
Chris@0
|
100 }
|
Chris@0
|
101
|
Chris@0
|
102 /**
|
Chris@0
|
103 * Tests \Drupal\file\FileUsage\DatabaseFileUsageBackend::delete().
|
Chris@0
|
104 */
|
Chris@0
|
105 public function doTestRemoveUsage() {
|
Chris@0
|
106 $file = $this->createFile();
|
Chris@0
|
107 $file->setPermanent();
|
Chris@0
|
108 $file_usage = $this->container->get('file.usage');
|
Chris@5
|
109 $connection = Database::getConnection();
|
Chris@5
|
110 $connection->insert('file_usage')
|
Chris@0
|
111 ->fields([
|
Chris@0
|
112 'fid' => $file->id(),
|
Chris@0
|
113 'module' => 'testing',
|
Chris@0
|
114 'type' => 'bar',
|
Chris@0
|
115 'id' => 2,
|
Chris@0
|
116 'count' => 3,
|
Chris@0
|
117 ])
|
Chris@0
|
118 ->execute();
|
Chris@0
|
119
|
Chris@0
|
120 // Normal decrement.
|
Chris@0
|
121 $file_usage->delete($file, 'testing', 'bar', 2);
|
Chris@5
|
122 $count = $connection->select('file_usage', 'f')
|
Chris@0
|
123 ->fields('f', ['count'])
|
Chris@0
|
124 ->condition('f.fid', $file->id())
|
Chris@0
|
125 ->execute()
|
Chris@0
|
126 ->fetchField();
|
Chris@0
|
127 $this->assertEqual(2, $count, 'The count was decremented correctly.');
|
Chris@0
|
128
|
Chris@0
|
129 // Multiple decrement and removal.
|
Chris@0
|
130 $file_usage->delete($file, 'testing', 'bar', 2, 2);
|
Chris@5
|
131 $count = $connection->select('file_usage', 'f')
|
Chris@0
|
132 ->fields('f', ['count'])
|
Chris@0
|
133 ->condition('f.fid', $file->id())
|
Chris@0
|
134 ->execute()
|
Chris@0
|
135 ->fetchField();
|
Chris@0
|
136 $this->assertIdentical(FALSE, $count, 'The count was removed entirely when empty.');
|
Chris@0
|
137
|
Chris@0
|
138 // Non-existent decrement.
|
Chris@0
|
139 $file_usage->delete($file, 'testing', 'bar', 2);
|
Chris@5
|
140 $count = $connection->select('file_usage', 'f')
|
Chris@0
|
141 ->fields('f', ['count'])
|
Chris@0
|
142 ->condition('f.fid', $file->id())
|
Chris@0
|
143 ->execute()
|
Chris@0
|
144 ->fetchField();
|
Chris@0
|
145 $this->assertIdentical(FALSE, $count, 'Decrementing non-exist record complete.');
|
Chris@0
|
146 return $file;
|
Chris@0
|
147 }
|
Chris@0
|
148
|
Chris@0
|
149 /**
|
Chris@0
|
150 * Create files for all the possible combinations of age and status.
|
Chris@0
|
151 *
|
Chris@0
|
152 * We are using UPDATE statements because using the API would set the
|
Chris@0
|
153 * timestamp.
|
Chris@0
|
154 */
|
Chris@0
|
155 public function createTempFiles() {
|
Chris@0
|
156 // Temporary file that is old.
|
Chris@0
|
157 $temp_old = file_save_data('');
|
Chris@5
|
158 $connection = Database::getConnection();
|
Chris@5
|
159 $connection->update('file_managed')
|
Chris@0
|
160 ->fields([
|
Chris@0
|
161 'status' => 0,
|
Chris@0
|
162 'changed' => REQUEST_TIME - $this->config('system.file')->get('temporary_maximum_age') - 1,
|
Chris@0
|
163 ])
|
Chris@0
|
164 ->condition('fid', $temp_old->id())
|
Chris@0
|
165 ->execute();
|
Chris@0
|
166 $this->assertTrue(file_exists($temp_old->getFileUri()), 'Old temp file was created correctly.');
|
Chris@0
|
167
|
Chris@0
|
168 // Temporary file that is new.
|
Chris@0
|
169 $temp_new = file_save_data('');
|
Chris@5
|
170 $connection->update('file_managed')
|
Chris@0
|
171 ->fields(['status' => 0])
|
Chris@0
|
172 ->condition('fid', $temp_new->id())
|
Chris@0
|
173 ->execute();
|
Chris@0
|
174 $this->assertTrue(file_exists($temp_new->getFileUri()), 'New temp file was created correctly.');
|
Chris@0
|
175
|
Chris@0
|
176 // Permanent file that is old.
|
Chris@0
|
177 $perm_old = file_save_data('');
|
Chris@5
|
178 $connection->update('file_managed')
|
Chris@0
|
179 ->fields(['changed' => REQUEST_TIME - $this->config('system.file')->get('temporary_maximum_age') - 1])
|
Chris@0
|
180 ->condition('fid', $temp_old->id())
|
Chris@0
|
181 ->execute();
|
Chris@0
|
182 $this->assertTrue(file_exists($perm_old->getFileUri()), 'Old permanent file was created correctly.');
|
Chris@0
|
183
|
Chris@0
|
184 // Permanent file that is new.
|
Chris@0
|
185 $perm_new = file_save_data('');
|
Chris@0
|
186 $this->assertTrue(file_exists($perm_new->getFileUri()), 'New permanent file was created correctly.');
|
Chris@0
|
187 return [$temp_old, $temp_new, $perm_old, $perm_new];
|
Chris@0
|
188 }
|
Chris@0
|
189
|
Chris@0
|
190 /**
|
Chris@0
|
191 * Ensure that temporary files are removed by default.
|
Chris@0
|
192 */
|
Chris@0
|
193 public function testTempFileCleanupDefault() {
|
Chris@0
|
194 list($temp_old, $temp_new, $perm_old, $perm_new) = $this->createTempFiles();
|
Chris@0
|
195
|
Chris@0
|
196 // Run cron and then ensure that only the old, temp file was deleted.
|
Chris@0
|
197 $this->container->get('cron')->run();
|
Chris@0
|
198 $this->assertFalse(file_exists($temp_old->getFileUri()), 'Old temp file was correctly removed.');
|
Chris@0
|
199 $this->assertTrue(file_exists($temp_new->getFileUri()), 'New temp file was correctly ignored.');
|
Chris@0
|
200 $this->assertTrue(file_exists($perm_old->getFileUri()), 'Old permanent file was correctly ignored.');
|
Chris@0
|
201 $this->assertTrue(file_exists($perm_new->getFileUri()), 'New permanent file was correctly ignored.');
|
Chris@0
|
202 }
|
Chris@0
|
203
|
Chris@0
|
204 /**
|
Chris@0
|
205 * Ensure that temporary files are kept as configured.
|
Chris@0
|
206 */
|
Chris@0
|
207 public function testTempFileNoCleanup() {
|
Chris@0
|
208 list($temp_old, $temp_new, $perm_old, $perm_new) = $this->createTempFiles();
|
Chris@0
|
209
|
Chris@0
|
210 // Set the max age to 0, meaning no temporary files will be deleted.
|
Chris@0
|
211 $this->config('system.file')
|
Chris@0
|
212 ->set('temporary_maximum_age', 0)
|
Chris@0
|
213 ->save();
|
Chris@0
|
214
|
Chris@0
|
215 // Run cron and then ensure that no file was deleted.
|
Chris@0
|
216 $this->container->get('cron')->run();
|
Chris@0
|
217 $this->assertTrue(file_exists($temp_old->getFileUri()), 'Old temp file was correctly ignored.');
|
Chris@0
|
218 $this->assertTrue(file_exists($temp_new->getFileUri()), 'New temp file was correctly ignored.');
|
Chris@0
|
219 $this->assertTrue(file_exists($perm_old->getFileUri()), 'Old permanent file was correctly ignored.');
|
Chris@0
|
220 $this->assertTrue(file_exists($perm_new->getFileUri()), 'New permanent file was correctly ignored.');
|
Chris@0
|
221 }
|
Chris@0
|
222
|
Chris@0
|
223 /**
|
Chris@0
|
224 * Ensure that temporary files are kept as configured.
|
Chris@0
|
225 */
|
Chris@0
|
226 public function testTempFileCustomCleanup() {
|
Chris@0
|
227 list($temp_old, $temp_new, $perm_old, $perm_new) = $this->createTempFiles();
|
Chris@0
|
228
|
Chris@0
|
229 // Set the max age to older than default.
|
Chris@0
|
230 $this->config('system.file')
|
Chris@0
|
231 ->set('temporary_maximum_age', 21600 + 2)
|
Chris@0
|
232 ->save();
|
Chris@0
|
233
|
Chris@0
|
234 // Run cron and then ensure that more files were deleted.
|
Chris@0
|
235 $this->container->get('cron')->run();
|
Chris@0
|
236 $this->assertTrue(file_exists($temp_old->getFileUri()), 'Old temp file was correctly ignored.');
|
Chris@0
|
237 $this->assertTrue(file_exists($temp_new->getFileUri()), 'New temp file was correctly ignored.');
|
Chris@0
|
238 $this->assertTrue(file_exists($perm_old->getFileUri()), 'Old permanent file was correctly ignored.');
|
Chris@0
|
239 $this->assertTrue(file_exists($perm_new->getFileUri()), 'New permanent file was correctly ignored.');
|
Chris@0
|
240 }
|
Chris@0
|
241
|
Chris@0
|
242 /**
|
Chris@0
|
243 * Tests file usage with translated entities.
|
Chris@0
|
244 */
|
Chris@0
|
245 public function testFileUsageWithEntityTranslation() {
|
Chris@0
|
246 /** @var \Drupal\file\FileUsage\FileUsageInterface $file_usage */
|
Chris@0
|
247 $file_usage = $this->container->get('file.usage');
|
Chris@0
|
248
|
Chris@0
|
249 $this->enableModules(['node', 'language']);
|
Chris@0
|
250 $this->installEntitySchema('node');
|
Chris@0
|
251 $this->installSchema('node', ['node_access']);
|
Chris@0
|
252
|
Chris@0
|
253 // Activate English and Romanian languages.
|
Chris@0
|
254 ConfigurableLanguage::create(['id' => 'en'])->save();
|
Chris@0
|
255 ConfigurableLanguage::create(['id' => 'ro'])->save();
|
Chris@0
|
256
|
Chris@0
|
257 NodeType::create(['type' => 'page'])->save();
|
Chris@0
|
258 ContentLanguageSettings::loadByEntityTypeBundle('node', 'page')
|
Chris@0
|
259 ->setLanguageAlterable(FALSE)
|
Chris@0
|
260 ->setDefaultLangcode('en')
|
Chris@0
|
261 ->save();
|
Chris@0
|
262 // Create a file field attached to 'page' node-type.
|
Chris@0
|
263 FieldStorageConfig::create([
|
Chris@0
|
264 'type' => 'file',
|
Chris@0
|
265 'entity_type' => 'node',
|
Chris@0
|
266 'field_name' => 'file',
|
Chris@0
|
267 ])->save();
|
Chris@0
|
268 FieldConfig::create([
|
Chris@0
|
269 'entity_type' => 'node',
|
Chris@0
|
270 'bundle' => 'page',
|
Chris@0
|
271 'field_name' => 'file',
|
Chris@0
|
272 'label' => 'File',
|
Chris@0
|
273 ])->save();
|
Chris@0
|
274
|
Chris@0
|
275 // Create a node, attach a file and add a Romanian translation.
|
Chris@0
|
276 $node = Node::create(['type' => 'page', 'title' => 'Page']);
|
Chris@0
|
277 $node
|
Chris@0
|
278 ->set('file', $file = $this->createFile())
|
Chris@0
|
279 ->addTranslation('ro', $node->getTranslation('en')->toArray())
|
Chris@0
|
280 ->save();
|
Chris@0
|
281
|
Chris@0
|
282 // Check that the file is used twice.
|
Chris@0
|
283 $usage = $file_usage->listUsage($file);
|
Chris@0
|
284 $this->assertEquals(2, $usage['file']['node'][$node->id()]);
|
Chris@0
|
285
|
Chris@0
|
286 // Remove the Romanian translation.
|
Chris@0
|
287 $node->removeTranslation('ro');
|
Chris@0
|
288 $node->save();
|
Chris@0
|
289
|
Chris@0
|
290 // Check that one usage has been removed and is used only once now.
|
Chris@0
|
291 $usage = $file_usage->listUsage($file);
|
Chris@0
|
292 $this->assertEquals(1, $usage['file']['node'][$node->id()]);
|
Chris@0
|
293 }
|
Chris@0
|
294
|
Chris@0
|
295 }
|