PageRenderTime 29ms CodeModel.GetById 16ms RepoModel.GetById 0ms app.codeStats 0ms

/core/modules/file/tests/src/Kernel/UsageTest.php

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