Tests creating multiple revisions of a node and managing attached files.
Expected behaviors:
function testRevisions() {
$type_name = 'article';
$field_name = strtolower($this
->randomName());
$this
->createFileField($field_name, $type_name);
$field = field_info_field($field_name);
$instance = field_info_instance('node', $field_name, $type_name);
// Attach the same fields to users.
$this
->attachFileField($field_name, 'user', 'user');
$test_file = $this
->getTestFile('text');
// Create a new node with the uploaded file.
$nid = $this
->uploadNodeFile($test_file, $field_name, $type_name);
// Check that the file exists on disk and in the database.
$node = node_load($nid, TRUE);
$node_file_r1 = file_load($node->{$field_name}[LANGUAGE_NOT_SPECIFIED][0]['fid']);
$node_vid_r1 = $node->vid;
$this
->assertFileExists($node_file_r1, t('New file saved to disk on node creation.'));
$this
->assertFileEntryExists($node_file_r1, t('File entry exists in database on node creation.'));
$this
->assertFileIsPermanent($node_file_r1, t('File is permanent.'));
// Upload another file to the same node in a new revision.
$this
->replaceNodeFile($test_file, $field_name, $nid);
$node = node_load($nid, TRUE);
$node_file_r2 = file_load($node->{$field_name}[LANGUAGE_NOT_SPECIFIED][0]['fid']);
$node_vid_r2 = $node->vid;
$this
->assertFileExists($node_file_r2, t('Replacement file exists on disk after creating new revision.'));
$this
->assertFileEntryExists($node_file_r2, t('Replacement file entry exists in database after creating new revision.'));
$this
->assertFileIsPermanent($node_file_r2, t('Replacement file is permanent.'));
// Check that the original file is still in place on the first revision.
$node = node_revision_load($node_vid_r1);
$this
->assertEqual($node_file_r1, file_load($node->{$field_name}[LANGUAGE_NOT_SPECIFIED][0]['fid']), t('Original file still in place after replacing file in new revision.'));
$this
->assertFileExists($node_file_r1, t('Original file still in place after replacing file in new revision.'));
$this
->assertFileEntryExists($node_file_r1, t('Original file entry still in place after replacing file in new revision'));
$this
->assertFileIsPermanent($node_file_r1, t('Original file is still permanent.'));
// Save a new version of the node without any changes.
// Check that the file is still the same as the previous revision.
$this
->drupalPost('node/' . $nid . '/edit', array(
'revision' => '1',
), t('Save'));
$node = node_load($nid, TRUE);
$node_file_r3 = file_load($node->{$field_name}[LANGUAGE_NOT_SPECIFIED][0]['fid']);
$node_vid_r3 = $node->vid;
$this
->assertEqual($node_file_r2, $node_file_r3, t('Previous revision file still in place after creating a new revision without a new file.'));
$this
->assertFileIsPermanent($node_file_r3, t('New revision file is permanent.'));
// Revert to the first revision and check that the original file is active.
$this
->drupalPost('node/' . $nid . '/revisions/' . $node_vid_r1 . '/revert', array(), t('Revert'));
$node = node_load($nid, TRUE);
$node_file_r4 = file_load($node->{$field_name}[LANGUAGE_NOT_SPECIFIED][0]['fid']);
$node_vid_r4 = $node->vid;
$this
->assertEqual($node_file_r1, $node_file_r4, t('Original revision file still in place after reverting to the original revision.'));
$this
->assertFileIsPermanent($node_file_r4, t('Original revision file still permanent after reverting to the original revision.'));
// Delete the second revision and check that the file is kept (since it is
// still being used by the third revision).
$this
->drupalPost('node/' . $nid . '/revisions/' . $node_vid_r2 . '/delete', array(), t('Delete'));
$this
->assertFileExists($node_file_r3, t('Second file is still available after deleting second revision, since it is being used by the third revision.'));
$this
->assertFileEntryExists($node_file_r3, t('Second file entry is still available after deleting second revision, since it is being used by the third revision.'));
$this
->assertFileIsPermanent($node_file_r3, t('Second file entry is still permanent after deleting second revision, since it is being used by the third revision.'));
// Attach the second file to a user.
$user = $this
->drupalCreateUser();
$user->{$field_name}[LANGUAGE_NOT_SPECIFIED][0]['fid'] = $node_file_r3->fid;
$user->{$field_name}[LANGUAGE_NOT_SPECIFIED][0]['display'] = 1;
$user
->save();
$this
->drupalGet('user/' . $user->uid . '/edit');
// Delete the third revision and check that the file is not deleted yet.
$this
->drupalPost('node/' . $nid . '/revisions/' . $node_vid_r3 . '/delete', array(), t('Delete'));
$this
->assertFileExists($node_file_r3, t('Second file is still available after deleting third revision, since it is being used by the user.'));
$this
->assertFileEntryExists($node_file_r3, t('Second file entry is still available after deleting third revision, since it is being used by the user.'));
$this
->assertFileIsPermanent($node_file_r3, t('Second file entry is still permanent after deleting third revision, since it is being used by the user.'));
// Delete the user and check that the file is also deleted.
user_delete($user->uid);
// TODO: This seems like a bug in File API. Clearing the stat cache should
// not be necessary here. The file really is deleted, but stream wrappers
// doesn't seem to think so unless we clear the PHP file stat() cache.
clearstatcache($node_file_r1->uri);
clearstatcache($node_file_r2->uri);
clearstatcache($node_file_r3->uri);
clearstatcache($node_file_r4->uri);
// Call system_cron() to clean up the file. Make sure the timestamp
// of the file is older than DRUPAL_MAXIMUM_TEMP_FILE_AGE.
db_update('file_managed')
->fields(array(
'timestamp' => REQUEST_TIME - (DRUPAL_MAXIMUM_TEMP_FILE_AGE + 1),
))
->condition('fid', $node_file_r3->fid)
->execute();
drupal_cron_run();
$this
->assertFileNotExists($node_file_r3, t('Second file is now deleted after deleting third revision, since it is no longer being used by any other nodes.'));
$this
->assertFileEntryNotExists($node_file_r3, t('Second file entry is now deleted after deleting third revision, since it is no longer being used by any other nodes.'));
// Delete the entire node and check that the original file is deleted.
$this
->drupalPost('node/' . $nid . '/delete', array(), t('Delete'));
// Call system_cron() to clean up the file. Make sure the timestamp
// of the file is older than DRUPAL_MAXIMUM_TEMP_FILE_AGE.
db_update('file_managed')
->fields(array(
'timestamp' => REQUEST_TIME - (DRUPAL_MAXIMUM_TEMP_FILE_AGE + 1),
))
->condition('fid', $node_file_r1->fid)
->execute();
drupal_cron_run();
$this
->assertFileNotExists($node_file_r1, t('Original file is deleted after deleting the entire node with two revisions remaining.'));
$this
->assertFileEntryNotExists($node_file_r1, t('Original file entry is deleted after deleting the entire node with two revisions remaining.'));
}