annotate core/modules/file/tests/src/Kernel/UsageTest.php @ 5:12f9dff5fda9 tip

Update to Drupal core 8.7.1
author Chris Cannam
date Thu, 09 May 2019 15:34:47 +0100
parents a9cd425dd02b
children
rev   line source
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 }