1. 8.2.x core/modules/file/src/Tests/FileFieldRevisionTest.php
  2. 8.0.x core/modules/file/src/Tests/FileFieldRevisionTest.php
  3. 8.1.x core/modules/file/src/Tests/FileFieldRevisionTest.php
  4. 8.3.x core/modules/file/src/Tests/FileFieldRevisionTest.php

Namespace

Drupal\file\Tests

File

core/modules/file/src/Tests/FileFieldRevisionTest.php
View source
  1. <?php
  2. namespace Drupal\file\Tests;
  3. use Drupal\file\Entity\File;
  4. /**
  5. * Tests creating and deleting revisions with files attached.
  6. *
  7. * @group file
  8. */
  9. class FileFieldRevisionTest extends FileFieldTestBase {
  10. /**
  11. * Tests creating multiple revisions of a node and managing attached files.
  12. *
  13. * Expected behaviors:
  14. * - Adding a new revision will make another entry in the field table, but
  15. * the original file will not be duplicated.
  16. * - Deleting a revision should not delete the original file if the file
  17. * is in use by another revision.
  18. * - When the last revision that uses a file is deleted, the original file
  19. * should be deleted also.
  20. */
  21. function testRevisions() {
  22. $node_storage = $this->container->get('entity.manager')->getStorage('node');
  23. $type_name = 'article';
  24. $field_name = strtolower($this->randomMachineName());
  25. $this->createFileField($field_name, 'node', $type_name);
  26. // Create the same fields for users.
  27. $this->createFileField($field_name, 'user', 'user');
  28. $test_file = $this->getTestFile('text');
  29. // Create a new node with the uploaded file.
  30. $nid = $this->uploadNodeFile($test_file, $field_name, $type_name);
  31. // Check that the file exists on disk and in the database.
  32. $node_storage->resetCache(array($nid));
  33. $node = $node_storage->load($nid);
  34. $node_file_r1 = File::load($node->{$field_name}->target_id);
  35. $node_vid_r1 = $node->getRevisionId();
  36. $this->assertFileExists($node_file_r1, 'New file saved to disk on node creation.');
  37. $this->assertFileEntryExists($node_file_r1, 'File entry exists in database on node creation.');
  38. $this->assertFileIsPermanent($node_file_r1, 'File is permanent.');
  39. // Upload another file to the same node in a new revision.
  40. $this->replaceNodeFile($test_file, $field_name, $nid);
  41. $node_storage->resetCache(array($nid));
  42. $node = $node_storage->load($nid);
  43. $node_file_r2 = File::load($node->{$field_name}->target_id);
  44. $node_vid_r2 = $node->getRevisionId();
  45. $this->assertFileExists($node_file_r2, 'Replacement file exists on disk after creating new revision.');
  46. $this->assertFileEntryExists($node_file_r2, 'Replacement file entry exists in database after creating new revision.');
  47. $this->assertFileIsPermanent($node_file_r2, 'Replacement file is permanent.');
  48. // Check that the original file is still in place on the first revision.
  49. $node = node_revision_load($node_vid_r1);
  50. $current_file = File::load($node->{$field_name}->target_id);
  51. $this->assertEqual($node_file_r1->id(), $current_file->id(), 'Original file still in place after replacing file in new revision.');
  52. $this->assertFileExists($node_file_r1, 'Original file still in place after replacing file in new revision.');
  53. $this->assertFileEntryExists($node_file_r1, 'Original file entry still in place after replacing file in new revision');
  54. $this->assertFileIsPermanent($node_file_r1, 'Original file is still permanent.');
  55. // Save a new version of the node without any changes.
  56. // Check that the file is still the same as the previous revision.
  57. $this->drupalPostForm('node/' . $nid . '/edit', array('revision' => '1'), t('Save and keep published'));
  58. $node_storage->resetCache(array($nid));
  59. $node = $node_storage->load($nid);
  60. $node_file_r3 = File::load($node->{$field_name}->target_id);
  61. $node_vid_r3 = $node->getRevisionId();
  62. $this->assertEqual($node_file_r2->id(), $node_file_r3->id(), 'Previous revision file still in place after creating a new revision without a new file.');
  63. $this->assertFileIsPermanent($node_file_r3, 'New revision file is permanent.');
  64. // Revert to the first revision and check that the original file is active.
  65. $this->drupalPostForm('node/' . $nid . '/revisions/' . $node_vid_r1 . '/revert', array(), t('Revert'));
  66. $node_storage->resetCache(array($nid));
  67. $node = $node_storage->load($nid);
  68. $node_file_r4 = File::load($node->{$field_name}->target_id);
  69. $this->assertEqual($node_file_r1->id(), $node_file_r4->id(), 'Original revision file still in place after reverting to the original revision.');
  70. $this->assertFileIsPermanent($node_file_r4, 'Original revision file still permanent after reverting to the original revision.');
  71. // Delete the second revision and check that the file is kept (since it is
  72. // still being used by the third revision).
  73. $this->drupalPostForm('node/' . $nid . '/revisions/' . $node_vid_r2 . '/delete', array(), t('Delete'));
  74. $this->assertFileExists($node_file_r3, 'Second file is still available after deleting second revision, since it is being used by the third revision.');
  75. $this->assertFileEntryExists($node_file_r3, 'Second file entry is still available after deleting second revision, since it is being used by the third revision.');
  76. $this->assertFileIsPermanent($node_file_r3, 'Second file entry is still permanent after deleting second revision, since it is being used by the third revision.');
  77. // Attach the second file to a user.
  78. $user = $this->drupalCreateUser();
  79. $user->$field_name->target_id = $node_file_r3->id();
  80. $user->$field_name->display = 1;
  81. $user->save();
  82. $this->drupalGet('user/' . $user->id() . '/edit');
  83. // Delete the third revision and check that the file is not deleted yet.
  84. $this->drupalPostForm('node/' . $nid . '/revisions/' . $node_vid_r3 . '/delete', array(), t('Delete'));
  85. $this->assertFileExists($node_file_r3, 'Second file is still available after deleting third revision, since it is being used by the user.');
  86. $this->assertFileEntryExists($node_file_r3, 'Second file entry is still available after deleting third revision, since it is being used by the user.');
  87. $this->assertFileIsPermanent($node_file_r3, 'Second file entry is still permanent after deleting third revision, since it is being used by the user.');
  88. // Delete the user and check that the file is also deleted.
  89. $user->delete();
  90. // TODO: This seems like a bug in File API. Clearing the stat cache should
  91. // not be necessary here. The file really is deleted, but stream wrappers
  92. // doesn't seem to think so unless we clear the PHP file stat() cache.
  93. clearstatcache($node_file_r1->getFileUri());
  94. clearstatcache($node_file_r2->getFileUri());
  95. clearstatcache($node_file_r3->getFileUri());
  96. clearstatcache($node_file_r4->getFileUri());
  97. // Call file_cron() to clean up the file. Make sure the changed timestamp
  98. // of the file is older than the system.file.temporary_maximum_age
  99. // configuration value.
  100. db_update('file_managed')
  101. ->fields(array(
  102. 'changed' => REQUEST_TIME - ($this->config('system.file')->get('temporary_maximum_age') + 1),
  103. ))
  104. ->condition('fid', $node_file_r3->id())
  105. ->execute();
  106. \Drupal::service('cron')->run();
  107. $this->assertFileNotExists($node_file_r3, 'Second file is now deleted after deleting third revision, since it is no longer being used by any other nodes.');
  108. $this->assertFileEntryNotExists($node_file_r3, 'Second file entry is now deleted after deleting third revision, since it is no longer being used by any other nodes.');
  109. // Delete the entire node and check that the original file is deleted.
  110. $this->drupalPostForm('node/' . $nid . '/delete', array(), t('Delete'));
  111. // Call file_cron() to clean up the file. Make sure the changed timestamp
  112. // of the file is older than the system.file.temporary_maximum_age
  113. // configuration value.
  114. db_update('file_managed')
  115. ->fields(array(
  116. 'changed' => REQUEST_TIME - ($this->config('system.file')->get('temporary_maximum_age') + 1),
  117. ))
  118. ->condition('fid', $node_file_r1->id())
  119. ->execute();
  120. \Drupal::service('cron')->run();
  121. $this->assertFileNotExists($node_file_r1, 'Original file is deleted after deleting the entire node with two revisions remaining.');
  122. $this->assertFileEntryNotExists($node_file_r1, 'Original file entry is deleted after deleting the entire node with two revisions remaining.');
  123. }
  124. }

Classes

Namesort descending Description
FileFieldRevisionTest Tests creating and deleting revisions with files attached.