summaryrefslogtreecommitdiff
path: root/sites/all/modules/file_entity/file_entity.test
diff options
context:
space:
mode:
Diffstat (limited to 'sites/all/modules/file_entity/file_entity.test')
-rw-r--r--sites/all/modules/file_entity/file_entity.test1635
1 files changed, 1635 insertions, 0 deletions
diff --git a/sites/all/modules/file_entity/file_entity.test b/sites/all/modules/file_entity/file_entity.test
new file mode 100644
index 000000000..2c72cbd86
--- /dev/null
+++ b/sites/all/modules/file_entity/file_entity.test
@@ -0,0 +1,1635 @@
+<?php
+
+/**
+ * @file
+ * Test integration for the file_entity module.
+ */
+
+class FileEntityTestHelper extends DrupalWebTestCase {
+ function setUp() {
+ $modules = func_get_args();
+ if (isset($modules[0]) && is_array($modules[0])) {
+ $modules = $modules[0];
+ }
+ $modules[] = 'file_entity';
+ parent::setUp($modules);
+ }
+
+ /**
+ * Retrieves a sample file of the specified type.
+ */
+ function getTestFile($type_name, $size = NULL) {
+ // Get a file to upload.
+ $file = current($this->drupalGetTestFiles($type_name, $size));
+
+ // Add a filesize property to files as would be read by file_load().
+ $file->filesize = filesize($file->uri);
+
+ return $file;
+ }
+
+ /**
+ * Retrieves the fid of the last inserted file.
+ */
+ function getLastFileId() {
+ return (int) db_query('SELECT MAX(fid) FROM {file_managed}')->fetchField();
+ }
+
+ /**
+ * Get a file from the database based on its filename.
+ *
+ * @param $filename
+ * A file filename, usually generated by $this->randomName().
+ * @param $reset
+ * (optional) Whether to reset the internal file_load() cache.
+ *
+ * @return
+ * A file object matching $filename.
+ */
+ function getFileByFilename($filename, $reset = FALSE) {
+ $files = file_load_multiple(array(), array('filename' => $filename), $reset);
+ // Load the first file returned from the database.
+ $returned_file = reset($files);
+ return $returned_file;
+ }
+
+ protected function createFileEntity($settings = array()) {
+ // Populate defaults array.
+ $settings += array(
+ 'filepath' => 'Файл для тестирования ' . $this->randomName(), // Prefix with non-latin characters to ensure that all file-related tests work with international filenames.
+ 'filemime' => 'text/plain',
+ 'uid' => 1,
+ 'timestamp' => REQUEST_TIME,
+ 'status' => FILE_STATUS_PERMANENT,
+ 'contents' => "file_put_contents() doesn't seem to appreciate empty strings so let's put in some data.",
+ 'scheme' => file_default_scheme(),
+ 'type' => NULL,
+ );
+
+ $filepath = $settings['scheme'] . '://' . $settings['filepath'];
+
+ file_put_contents($filepath, $settings['contents']);
+ $this->assertTrue(is_file($filepath), t('The test file exists on the disk.'), 'Create test file');
+
+ $file = new stdClass();
+ $file->uri = $filepath;
+ $file->filename = drupal_basename($file->uri);
+ $file->filemime = $settings['filemime'];
+ $file->uid = $settings['uid'];
+ $file->timestamp = $settings['timestamp'];
+ $file->filesize = filesize($file->uri);
+ $file->status = $settings['status'];
+ $file->type = $settings['type'];
+
+ // The file type is used as a bundle key, and therefore, must not be NULL.
+ if (!isset($file->type)) {
+ $file->type = FILE_TYPE_NONE;
+ }
+
+ // If the file isn't already assigned a real type, determine what type should
+ // be assigned to it.
+ if ($file->type === FILE_TYPE_NONE) {
+ $type = file_get_type($file);
+ if (isset($type)) {
+ $file->type = $type;
+ }
+ }
+
+ // Write the record directly rather than calling file_save() so we don't
+ // invoke the hooks.
+ $this->assertNotIdentical(drupal_write_record('file_managed', $file), FALSE, t('The file was added to the database.'), 'Create test file');
+
+ return $file;
+ }
+
+ protected function createFileType($overrides = array()) {
+ $type = new stdClass();
+ $type->type = 'test';
+ $type->label = "Test";
+ $type->description = '';
+ $type->mimetypes = array('image/jpeg', 'image/gif', 'image/png', 'image/tiff');
+
+ foreach ($overrides as $k => $v) {
+ $type->$k = $v;
+ }
+
+ file_type_save($type);
+ return $type;
+ }
+
+ /**
+ * Overrides DrupalWebTestCase::drupalGetToken() to support the hash salt.
+ *
+ * @todo Remove when http://drupal.org/node/1555862 is fixed in core.
+ */
+ protected function drupalGetToken($value = '') {
+ $private_key = drupal_get_private_key();
+ return drupal_hmac_base64($value, $this->session_id . $private_key . drupal_get_hash_salt());
+ }
+}
+
+/**
+ * Tests file type classification functionality.
+ */
+class FileEntityFileTypeClassificationTestCase extends DrupalWebTestCase {
+ public static function getInfo() {
+ return array(
+ 'name' => 'File entity classification',
+ 'description' => 'Test existing file entity classification functionality.',
+ 'group' => 'File entity',
+ );
+ }
+
+ function setUp() {
+ parent::setUp();
+ }
+
+ /**
+ * Test that existing files are properly classified by file type.
+ */
+ function testFileTypeClassification() {
+ // Get test text and image files.
+ $file = current($this->drupalGetTestFiles('text'));
+ $text_file = file_save($file);
+ $file = current($this->drupalGetTestFiles('image'));
+ $image_file = file_save($file);
+
+ // Enable file entity which adds adds a file type property to files and
+ // queues up existing files for classification.
+ module_enable(array('file_entity'));
+
+ // Existing files have yet to be classified and should have an undefined
+ // file type.
+ $file_type = $this->getFileType($text_file);
+ $this->assertEqual($file_type['type'], 'undefined', t('The text file has an undefined file type.'));
+ $file_type = $this->getFileType($image_file);
+ $this->assertEqual($file_type['type'], 'undefined', t('The image file has an undefined file type.'));
+
+ // The classification queue is processed during cron runs. Run cron to
+ // trigger the classification process.
+ $this->cronRun();
+
+ // The classification process should assign a file type to any file whose
+ // MIME type is assigned to a file type. Check to see if each file was
+ // assigned a proper file type.
+ $file_type = $this->getFileType($text_file);
+ $this->assertEqual($file_type['type'], 'document', t('The text file was properly assigned the Document file type.'));
+ $file_type = $this->getFileType($image_file);
+ $this->assertEqual($file_type['type'], 'image', t('The image file was properly assigned the Image file type.'));
+ }
+
+ /**
+ * Get the file type of a given file.
+ *
+ * @param $file
+ * A file object.
+ *
+ * @return
+ * The file's file type as a string.
+ */
+ function getFileType($file) {
+ $type = db_select('file_managed', 'fm')
+ ->fields('fm', array('type'))
+ ->condition('fid', $file->fid, '=')
+ ->execute()
+ ->fetchAssoc();
+
+ return $type;
+ }
+}
+
+/**
+ * Tests basic file entity functionality.
+ */
+class FileEntityUnitTestCase extends FileEntityTestHelper {
+ public static function getInfo() {
+ return array(
+ 'name' => 'File entity unit tests',
+ 'description' => 'Test basic file entity functionality.',
+ 'group' => 'File entity',
+ );
+ }
+
+ /**
+ * Regression tests for core issue http://drupal.org/node/1239376.
+ */
+ function testMimeTypeMappings() {
+ $tests = array(
+ 'public://test.ogg' => 'audio/ogg',
+ 'public://test.mkv' => 'video/x-m4v',
+ 'public://test.mka' => 'audio/x-matroska',
+ 'public://test.mkv' => 'video/x-matroska',
+ 'public://test.webp' => 'image/webp',
+ );
+ foreach ($tests as $input => $expected) {
+ $this->assertEqual(file_get_mimetype($input), $expected);
+ }
+ }
+
+ /**
+ * Tests basic file entity properties.
+ */
+ function testFileEntity() {
+ // Save a raw file, turning it into a file entity.
+ $file = $this->getTestFile('text');
+ $file->uid = 1;
+ $file->status = FILE_STATUS_PERMANENT;
+ file_save($file);
+
+ // Test entity ID, revision ID, and bundle.
+ $ids = entity_extract_ids('file', $file);
+ $this->assertIdentical($ids, array($file->fid, NULL, 'document'));
+
+ // Test the entity URI callback.
+ $uri = entity_uri('file', $file);
+ $this->assertEqual($uri['path'], "file/{$file->fid}");
+ }
+
+ /**
+ * Tests storing image height and width as file metadata.
+ */
+ function testImageDimensions() {
+ // Test hook_file_insert().
+ $file = current($this->drupalGetTestFiles('image'));
+ $image_file = file_save($file);
+ $this->assertTrue(isset($image_file->metadata['height']), 'Image height retrieved on file_save() for an image file.');
+ $this->assertTrue(isset($image_file->metadata['width']), 'Image width retrieved on file_save() for an image file.');
+
+ $file = current($this->drupalGetTestFiles('text'));
+ $text_file = file_save($file);
+ $this->assertFalse(isset($text_file->metadata['height']), 'No image height retrieved on file_save() for an text file.');
+ $this->assertFalse(isset($text_file->metadata['width']), 'No image width retrieved on file_save() for an text file.');
+
+ // Test hook_file_load().
+ // Clear the cache and load fresh files objects to test file_load behavior.
+ entity_get_controller('file')->resetCache();
+
+ $file = file_load($image_file->fid);
+ $this->assertTrue(isset($file->metadata['height']), 'Image dimensions retrieved on file_load() for an image file.');
+ $this->assertTrue(isset($file->metadata['width']), 'Image dimensions retrieved on file_load() for an image file.');
+
+ $this->assertEqual($file->metadata['height'], $image_file->metadata['height'], 'Loaded image height is equal to saved image height.');
+ $this->assertEqual($file->metadata['width'], $image_file->metadata['width'], 'Loaded image width is equal to saved image width.');
+
+ $file = file_load($text_file->fid);
+ $this->assertFalse(isset($file->metadata['height']), 'No image height retrieved on file_load() for an text file.');
+ $this->assertFalse(isset($file->metadata['width']), 'No image width retrieved on file_load() for an text file.');
+
+ // Test hook_file_update().
+ // Load the first image file and resize it.
+ $height = $image_file->metadata['width'] / 2;
+ $width = $image_file->metadata['height'] / 2;
+ $image = image_load($image_file->uri);
+ image_resize($image, $width, $height);
+ image_save($image);
+ file_save($image_file);
+
+ $this->assertEqual($image_file->metadata['height'], $height, 'Image file height updated by file_save().');
+ $this->assertEqual($image_file->metadata['width'], $width, 'Image file width updated by file_save().');
+
+ // Clear the cache and reload the file.
+ entity_get_controller('file')->resetCache();
+
+ $file = file_load($image_file->fid);
+ $this->assertEqual($file->metadata['height'], $height, 'Updated image height retrieved by file_load().');
+ $this->assertEqual($file->metadata['width'], $width, 'Updated image width retrieved by file_load().');
+
+ // Verify that the image dimension metadata is removed on file deletion.
+ file_delete($file, TRUE);
+ $this->assertFalse(db_query('SELECT COUNT(*) FROM {file_metadata} WHERE fid = :fid', array(':fid' => 'fid'))->fetchField(), 'Row deleted in {file_metadata} on file_delete().');
+ }
+}
+
+/**
+ * Tests editing existing file entities.
+ */
+class FileEntityEditTestCase extends FileEntityTestHelper {
+ protected $web_user;
+ protected $admin_user;
+
+ public static function getInfo() {
+ return array(
+ 'name' => 'File entity edit',
+ 'description' => 'Create a file and test file edit functionality.',
+ 'group' => 'File entity',
+ );
+ }
+
+ function setUp() {
+ parent::setUp();
+
+ $this->web_user = $this->drupalCreateUser(array('edit own document files', 'create files'));
+ $this->admin_user = $this->drupalCreateUser(array('bypass file access', 'administer files'));
+ }
+
+ /**
+ * Check file edit functionality.
+ */
+ function testFileEntityEdit() {
+ $this->drupalLogin($this->web_user);
+
+ $test_file = $this->getTestFile('text');
+ $name_key = "filename";
+
+ // Create file to edit.
+ $edit = array();
+ $edit['files[upload]'] = drupal_realpath($test_file->uri);
+ $this->drupalPost('file/add', $edit, t('Next'));
+ if ($this->xpath('//input[@name="scheme"]')) {
+ $this->drupalPost(NULL, array(), t('Next'));
+ }
+
+ // Check that the file exists in the database.
+ $file = $this->getFileByFilename($test_file->filename);
+ $this->assertTrue($file, t('File found in database.'));
+
+ // Check that "edit" link points to correct page.
+ $this->clickLink(t('Edit'));
+ $edit_url = url("file/$file->fid/edit", array('absolute' => TRUE));
+ $actual_url = $this->getURL();
+ $this->assertEqual($edit_url, $actual_url, t('On edit page.'));
+
+ // Check that the name field is displayed with the correct value.
+ $active = '<span class="element-invisible">' . t('(active tab)') . '</span>';
+ $link_text = t('!local-task-title!active', array('!local-task-title' => t('Edit'), '!active' => $active));
+ $this->assertText(strip_tags($link_text), 0, t('Edit tab found and marked active.'));
+ $this->assertFieldByName($name_key, $file->filename, t('Name field displayed.'));
+
+ // The user does not have "delete" permissions so no delete button should be found.
+ $this->assertNoFieldByName('op', t('Delete'), 'Delete button not found.');
+
+ // Edit the content of the file.
+ $edit = array();
+ $edit[$name_key] = $this->randomName(8);
+ // Stay on the current page, without reloading.
+ $this->drupalPost(NULL, $edit, t('Save'));
+
+ // Check that the name field is displayed with the updated values.
+ $this->assertText($edit[$name_key], t('Name displayed.'));
+ }
+
+ /**
+ * Check changing file associated user fields.
+ */
+ function testFileEntityAssociatedUser() {
+ $this->drupalLogin($this->admin_user);
+
+ // Create file to edit.
+ $test_file = $this->getTestFile('text');
+ $name_key = "filename";
+ $edit = array();
+ $edit['files[upload]'] = drupal_realpath($test_file->uri);
+ $this->drupalPost('file/add', $edit, t('Next'));
+
+ // Check that the file was associated with the currently logged in user.
+ $file = $this->getFileByFilename($test_file->filename);
+ $this->assertIdentical($file->uid, $this->admin_user->uid, 'File associated with admin user.');
+
+ // Try to change the 'associated user' field to an invalid user name.
+ $edit = array(
+ 'name' => 'invalid-name',
+ );
+ $this->drupalPost('file/' . $file->fid . '/edit', $edit, t('Save'));
+ $this->assertText('The username invalid-name does not exist.');
+
+ // Change the associated user field to an empty string, which should assign
+ // association to the anonymous user (uid 0).
+ $edit['name'] = '';
+ $this->drupalPost('file/' . $file->fid . '/edit', $edit, t('Save'));
+ $file = file_load($file->fid);
+ $this->assertIdentical($file->uid, '0', 'File associated with anonymous user.');
+
+ // Change the associated user field to another user's name (that is not
+ // logged in).
+ $edit['name'] = $this->web_user->name;
+ $this->drupalPost('file/' . $file->fid . '/edit', $edit, t('Save'));
+ $file = file_load($file->fid);
+ $this->assertIdentical($file->uid, $this->web_user->uid, 'File associated with normal user.');
+
+ // Check that normal users cannot change the associated user information.
+ $this->drupalLogin($this->web_user);
+ $this->drupalGet('file/' . $file->fid . '/edit');
+ $this->assertNoFieldByName('name');
+ }
+}
+
+/**
+ * Tests creating new file entities through the file upload wizard.
+ */
+class FileEntityUploadWizardTestCase extends FileEntityTestHelper {
+ public static function getInfo() {
+ return array(
+ 'name' => 'File entity upload wizard',
+ 'description' => 'Upload a file using the multi-step wizard.',
+ 'group' => 'File entity',
+ 'dependencies' => array('token'),
+ );
+ }
+
+ function setUp() {
+ parent::setUp('token');
+
+ // Disable the private file system which is automatically enabled by
+ // DrupalTestCase so we can test the upload wizard correctly.
+ variable_del('file_private_path');
+
+ $web_user = $this->drupalCreateUser(array('create files', 'view own private files'));
+ $this->drupalLogin($web_user);
+ }
+
+ /**
+ * Test the basic file upload wizard functionality.
+ */
+ function testFileEntityUploadWizardBasic() {
+ $test_file = $this->getTestFile('text');
+
+ // Step 1: Upload a basic document file.
+ $edit = array();
+ $edit['files[upload]'] = drupal_realpath($test_file->uri);
+ $this->drupalPost('file/add', $edit, t('Next'));
+
+ // Check that the file exists in the database.
+ $fid = $this->getLastFileId();
+ $file = file_load($fid);
+ $this->assertTrue($file, t('File found in database.'));
+
+ // Check that the document file has been uploaded.
+ $this->assertRaw(t('!type %name was uploaded.', array('!type' => 'Document', '%name' => $file->filename)), t('Document file uploaded.'));
+ }
+
+ /**
+ * Test the file upload wizard type step.
+ */
+ function testFileEntityUploadWizardTypes() {
+ $test_file = $this->getTestFile('text');
+
+ // Create multiple file types with the same mime types.
+ $this->createFileType(array('type' => 'document1', 'label' => 'Document 1', 'mimetypes' => array('text/plain')));
+ $this->createFileType(array('type' => 'document2', 'label' => 'Document 2', 'mimetypes' => array('text/plain')));
+
+ // Step 1: Upload a basic document file.
+ $edit = array();
+ $edit['files[upload]'] = drupal_realpath($test_file->uri);
+ $this->drupalPost('file/add', $edit, t('Next'));
+
+ // Step 2: File type selection.
+ $edit = array();
+ $edit['type'] = 'document2';
+ $this->drupalPost(NULL, $edit, t('Next'));
+
+ // Check that the file exists in the database.
+ $fid = $this->getLastFileId();
+ $file = file_load($fid);
+ $this->assertTrue($file, t('File found in database.'));
+
+ // Check that the document file has been uploaded.
+ $this->assertRaw(t('!type %name was uploaded.', array('!type' => 'Document 2', '%name' => $file->filename)), t('Document 2 file uploaded.'));
+ }
+
+ /**
+ * Test the file upload wizard scheme step.
+ */
+ function testFileEntityUploadWizardSchemes() {
+ $test_file = $this->getTestFile('text');
+
+ // Enable the private file system.
+ variable_set('file_private_path', $this->private_files_directory);
+
+ // Step 1: Upload a basic document file.
+ $edit = array();
+ $edit['files[upload]'] = drupal_realpath($test_file->uri);
+ $this->drupalPost('file/add', $edit, t('Next'));
+
+ // Step 3: Scheme selection.
+ $edit = array();
+ $edit['scheme'] = 'private';
+ $this->drupalPost(NULL, $edit, t('Next'));
+
+ // Check that the file exists in the database.
+ $fid = $this->getLastFileId();
+ $file = file_load($fid);
+ $this->assertTrue($file, t('File found in database.'));
+
+ // Check that the document file has been uploaded.
+ $this->assertRaw(t('!type %name was uploaded.', array('!type' => 'Document', '%name' => $file->filename)), t('Document file uploaded.'));
+ }
+
+ /**
+ * Test the file upload wizard field step.
+ */
+ function testFileEntityUploadWizardFields() {
+ $test_file = $this->getTestFile('image');
+ $filename = $this->randomName();
+ $alt = $this->randomName();
+ $title = $this->randomName();
+
+ // Step 1: Upload a basic image file.
+ $edit = array();
+ $edit['files[upload]'] = drupal_realpath($test_file->uri);
+ $this->drupalPost('file/add', $edit, t('Next'));
+
+ // Step 4: Attached fields.
+ $edit = array();
+ $edit['filename'] = $filename;
+ $edit['field_file_image_alt_text[' . LANGUAGE_NONE . '][0][value]'] = $alt;
+ $edit['field_file_image_title_text[' . LANGUAGE_NONE . '][0][value]'] = $title;
+ $this->drupalPost(NULL, $edit, t('Save'));
+
+ // Check that the file exists in the database.
+ $fid = $this->getLastFileId();
+ $file = file_load($fid);
+ $this->assertTrue($file, t('File found in database.'));
+
+ // Check that the image file has been uploaded.
+ $this->assertRaw(t('!type %name was uploaded.', array('!type' => 'Image', '%name' => $filename)), t('Image file uploaded.'));
+
+ // Check that the alt and title text was loaded from the fields.
+ $this->assertEqual($file->alt, $alt, t('Alt text was stored as file metadata.'));
+ $this->assertEqual($file->title, $title, t('Title text was stored as file metadata.'));
+ }
+
+ /**
+ * Test skipping each of the file upload wizard steps.
+ */
+ function testFileEntityUploadWizardStepSkipping() {
+ $test_file = $this->getTestFile('image');
+ $filename = $this->randomName();
+
+ // Ensure that the file is affected by every step.
+ variable_set('file_private_path', $this->private_files_directory);
+
+ $this->createFileType(array('type' => 'image1', 'label' => 'Image 1', 'mimetypes' => array('image/jpeg', 'image/gif', 'image/png', 'image/tiff')));
+ $this->createFileType(array('type' => 'image2', 'label' => 'Image 2', 'mimetypes' => array('image/jpeg', 'image/gif', 'image/png', 'image/tiff')));
+
+ $field_name = drupal_strtolower($this->randomName() . '_field_name');
+ $field = array('field_name' => $field_name, 'type' => 'text');
+ field_create_field($field);
+ $instance = array(
+ 'field_name' => $field_name,
+ 'entity_type' => 'file',
+ 'bundle' => 'image2',
+ 'label' => $this->randomName() . '_label',
+ );
+ field_create_instance($instance);
+
+ // Test skipping each upload wizard step.
+ foreach (array('types', 'schemes', 'fields') as $step) {
+ // Step to skip.
+ switch ($step) {
+ case 'types':
+ variable_set('file_entity_file_upload_wizard_skip_file_type', TRUE);
+ break;
+ case 'schemes':
+ variable_set('file_entity_file_upload_wizard_skip_scheme', TRUE);
+ break;
+ case 'fields':
+ variable_set('file_entity_file_upload_wizard_skip_fields', TRUE);
+ break;
+ }
+
+ // Step 1: Upload a basic image file.
+ $edit = array();
+ $edit['files[upload]'] = drupal_realpath($test_file->uri);
+ $this->drupalPost('file/add', $edit, t('Next'));
+
+ // Step 2: File type selection.
+ if ($step != 'types') {
+ $edit = array();
+ $edit['type'] = 'image2';
+ $this->drupalPost(NULL, $edit, t('Next'));
+ }
+
+ // Step 3: Scheme selection.
+ if ($step != 'schemes') {
+ $edit = array();
+ $edit['scheme'] = 'private';
+ $this->drupalPost(NULL, $edit, t('Next'));
+ }
+
+ // Step 4: Attached fields.
+ if ($step != 'fields') {
+ // Skipping file type selection essentially skips this step as well
+ // because the file will not be assigned a type so no fields will be
+ // available.
+ if ($step != 'types') {
+ $edit = array();
+ $edit['filename'] = $filename;
+ $edit[$field_name . '[' . LANGUAGE_NONE . '][0][value]'] = $this->randomName();
+ $this->drupalPost(NULL, $edit, t('Save'));
+ }
+ }
+
+ // Check that the file exists in the database.
+ $fid = $this->getLastFileId();
+ $file = file_load($fid);
+ $this->assertTrue($file, t('File found in database.'));
+
+ // Determine the file's file type.
+ $type = file_type_load($file->type);
+
+ // Check that the image file has been uploaded.
+ $this->assertRaw(t('!type %name was uploaded.', array('!type' => $type->label, '%name' => $file->filename)), t('Image file uploaded.'));
+
+ // Reset 'skip' variables.
+ variable_del('file_entity_file_upload_wizard_skip_file_type');
+ variable_del('file_entity_file_upload_wizard_skip_scheme');
+ variable_del('file_entity_file_upload_wizard_skip_fields');
+ }
+ }
+}
+
+/**
+ * Test file administration page functionality.
+ */
+class FileEntityAdminTestCase extends FileEntityTestHelper {
+ public static function getInfo() {
+ return array(
+ 'name' => 'File administration',
+ 'description' => 'Test file administration page functionality.',
+ 'group' => 'File entity',
+ );
+ }
+
+ function setUp() {
+ parent::setUp();
+
+ // Remove the "view files" permission which is set
+ // by default for all users so we can test this permission
+ // correctly.
+ $roles = user_roles();
+ foreach ($roles as $rid => $role) {
+ user_role_revoke_permissions($rid, array('view files'));
+ }
+
+ $this->admin_user = $this->drupalCreateUser(array('administer files', 'bypass file access'));
+ $this->base_user_1 = $this->drupalCreateUser(array('administer files'));
+ $this->base_user_2 = $this->drupalCreateUser(array('administer files', 'view own private files'));
+ $this->base_user_3 = $this->drupalCreateUser(array('administer files', 'view private files'));
+ $this->base_user_4 = $this->drupalCreateUser(array('administer files', 'edit any document files', 'delete any document files', 'edit any image files', 'delete any image files'));
+ }
+
+ /**
+ * Tests that the table sorting works on the files admin pages.
+ */
+ function testFilesAdminSort() {
+ $this->drupalLogin($this->admin_user);
+ $i = 0;
+ foreach (array('dd', 'aa', 'DD', 'bb', 'cc', 'CC', 'AA', 'BB') as $prefix) {
+ $this->createFileEntity(array('filepath' => $prefix . $this->randomName(6), 'timestamp' => $i));
+ $i++;
+ }
+
+ // Test that the default sort by file_managed.timestamp DESC actually fires properly.
+ $files_query = db_select('file_managed', 'fm')
+ ->fields('fm', array('fid'))
+ ->orderBy('timestamp', 'DESC')
+ ->execute()
+ ->fetchCol();
+
+ $files_form = array();
+ $this->drupalGet('admin/content/file');
+ foreach ($this->xpath('//table/tbody/tr/td/div/input/@value') as $input) {
+ $files_form[] = $input;
+ }
+ $this->assertEqual($files_query, $files_form, 'Files are sorted in the form according to the default query.');
+
+ // Compare the rendered HTML node list to a query for the files ordered by
+ // filename to account for possible database-dependent sort order.
+ $files_query = db_select('file_managed', 'fm')
+ ->fields('fm', array('fid'))
+ ->orderBy('filename')
+ ->execute()
+ ->fetchCol();
+
+ $files_form = array();
+ $this->drupalGet('admin/content/file', array('query' => array('sort' => 'asc', 'order' => 'Title')));
+ foreach ($this->xpath('//table/tbody/tr/td/div/input/@value') as $input) {
+ $files_form[] = $input;
+ }
+ $this->assertEqual($files_query, $files_form, 'Files are sorted in the form the same as they are in the query.');
+ }
+
+ /**
+ * Tests files overview with different user permissions.
+ */
+ function testFilesAdminPages() {
+ $this->drupalLogin($this->admin_user);
+
+ $files['public_image'] = $this->createFileEntity(array('scheme' => 'public', 'uid' => $this->base_user_1->uid, 'type' => 'image'));
+ $files['public_document'] = $this->createFileEntity(array('scheme' => 'public', 'uid' => $this->base_user_2->uid, 'type' => 'document'));
+ $files['private_image'] = $this->createFileEntity(array('scheme' => 'private', 'uid' => $this->base_user_1->uid, 'type' => 'image'));
+ $files['private_document'] = $this->createFileEntity(array('scheme' => 'private', 'uid' => $this->base_user_2->uid, 'type' => 'document'));
+
+ // Verify view, usage, edit, and delete links for any file.
+ $this->drupalGet('admin/content/file');
+ $this->assertResponse(200);
+ foreach ($files as $file) {
+ $this->assertLinkByHref('file/' . $file->fid);
+ $this->assertLinkByHref('file/' . $file->fid . '/usage');
+ $this->assertLinkByHref('file/' . $file->fid . '/edit');
+ $this->assertLinkByHref('file/' . $file->fid . '/delete');
+ // Verify tableselect.
+ $this->assertFieldByName('files[' . $file->fid . ']', '', t('Tableselect found.'));
+ }
+
+ // Verify no operation links are displayed for regular users.
+ $this->drupalLogout();
+ $this->drupalLogin($this->base_user_1);
+ $this->drupalGet('admin/content/file');
+ $this->assertResponse(200);
+ $this->assertLinkByHref('file/' . $files['public_image']->fid);
+ $this->assertLinkByHref('file/' . $files['public_document']->fid);
+ $this->assertNoLinkByHref('file/' . $files['public_image']->fid . '/edit');
+ $this->assertNoLinkByHref('file/' . $files['public_image']->fid . '/delete');
+ $this->assertNoLinkByHref('file/' . $files['public_document']->fid . '/edit');
+ $this->assertNoLinkByHref('file/' . $files['public_document']->fid . '/delete');
+
+ // Verify no tableselect.
+ $this->assertNoFieldByName('files[' . $files['public_image']->fid . ']', '', t('No tableselect found.'));
+
+ // Verify private file is displayed with permission.
+ $this->drupalLogout();
+ $this->drupalLogin($this->base_user_2);
+ $this->drupalGet('admin/content/file');
+ $this->assertResponse(200);
+ $this->assertLinkByHref('file/' . $files['private_document']->fid);
+ // Verify no operation links are displayed.
+ $this->assertNoLinkByHref('file/' . $files['private_document']->fid . '/edit');
+ $this->assertNoLinkByHref('file/' . $files['private_document']->fid . '/delete');
+
+ // Verify user cannot see private file of other users.
+ $this->assertNoLinkByHref('file/' . $files['private_image']->fid);
+ $this->assertNoLinkByHref('file/' . $files['private_image']->fid . '/edit');
+ $this->assertNoLinkByHref('file/' . $files['private_image']->fid . '/delete');
+
+ // Verify no tableselect.
+ $this->assertNoFieldByName('files[' . $files['private_document']->fid . ']', '', t('No tableselect found.'));
+
+ // Verify private file is displayed with permission.
+ $this->drupalLogout();
+ $this->drupalLogin($this->base_user_3);
+ $this->drupalGet('admin/content/file');
+ $this->assertResponse(200);
+
+ // Verify user can see private file of other users.
+ $this->assertLinkByHref('file/' . $files['private_document']->fid);
+ $this->assertLinkByHref('file/' . $files['private_image']->fid);
+
+ // Verify operation links are displayed for users with appropriate permission.
+ $this->drupalLogout();
+ $this->drupalLogin($this->base_user_4);
+ $this->drupalGet('admin/content/file');
+ $this->assertResponse(200);
+ foreach ($files as $file) {
+ $this->assertLinkByHref('file/' . $file->fid);
+ $this->assertLinkByHref('file/' . $file->fid . '/usage');
+ $this->assertLinkByHref('file/' . $file->fid . '/edit');
+ $this->assertLinkByHref('file/' . $file->fid . '/delete');
+ }
+
+ // Verify file access can be bypassed.
+ $this->drupalLogout();
+ $this->drupalLogin($this->admin_user);
+ $this->drupalGet('admin/content/file');
+ $this->assertResponse(200);
+ foreach ($files as $file) {
+ $this->assertLinkByHref('file/' . $file->fid);
+ $this->assertLinkByHref('file/' . $file->fid . '/usage');
+ $this->assertLinkByHref('file/' . $file->fid . '/edit');
+ $this->assertLinkByHref('file/' . $file->fid . '/delete');
+ }
+ }
+}
+
+/**
+ * Tests the file usage page.
+ */
+class FileEntityUsageTestCase extends FileEntityTestHelper {
+ public static function getInfo() {
+ return array(
+ 'name' => 'File entity usage',
+ 'description' => 'Create a file and verify its usage.',
+ 'group' => 'File entity',
+ );
+ }
+
+ function setUp() {
+ parent::setUp();
+
+ $web_user = $this->drupalCreateUser(array('create files', 'bypass file access', 'edit own article content'));
+ $this->drupalLogin($web_user);
+ }
+
+ /**
+ * Create a file and verify its usage information.
+ */
+ function testFileEntityUsagePage() {
+ $image_field = 'field_image';
+ $image = $this->getTestFile('image');
+
+ // Create a node, save it, then edit it to upload a file.
+ $edit = array(
+ "files[" . $image_field . "_" . LANGUAGE_NONE . "_0]" => drupal_realpath($image->uri),
+ );
+ $node = $this->drupalCreateNode(array('type' => 'article'));
+ $this->drupalPost('node/' . $node->nid . '/edit', $edit, t('Save'));
+
+ // Load the uploaded file.
+ $fid = $this->getLastFileId();
+ $file = file_load($fid);
+
+ // View the file's usage page.
+ $this->drupalGet('file/' . $file->fid . '/usage');
+
+ // Verify that a link to the entity is available.
+ $this->assertLink($node->title);
+ $this->assertLinkByHref('node/' . $node->nid);
+
+ // Verify that the entity type and use count information is also present.
+ $expected_values = array(
+ 'type' => 'node',
+ 'count' => 1,
+ );
+ foreach ($expected_values as $name => $value) {
+ $this->assertTrue($this->xpath('//table/tbody/tr/td[normalize-space(text())=:text]', array(':text' => $value)), t('File usage @name was found in the table.', array('@name' => $name)));
+ }
+
+ // Add a reference to the file from the same entity but registered by a
+ // different module to ensure that the usage count is incremented and no
+ // additional table rows are created.
+ file_usage_add($file, 'example_module', 'node', $node->nid, 2);
+
+ // Reload the page and verify that the expected values are present.
+ $this->drupalGet('file/' . $file->fid . '/usage');
+ $expected_values['count'] = 3;
+ foreach ($expected_values as $name => $value) {
+ $this->assertTrue($this->xpath('//table/tbody/tr/td[normalize-space(text())=:text]', array(':text' => $value)), t('File usage @name was found in the table.', array('@name' => $name)));
+ }
+
+ // Add a reference to the file from an entity that doesn't exist to ensure
+ // that this case is handled.
+ file_usage_add($file, 'test_module', 'imaginary', 1);
+
+ // Reload the page.
+ $this->drupalGet('file/' . $file->fid . '/usage');
+
+ // Verify that the module name is used in place of a link to the entity.
+ $this->assertNoLink('test_module');
+ $this->assertRaw('test_module', 'Module name used in place of link to the entity.');
+
+ // Verify that the entity type and use count information is also present.
+ $expected_values = array(
+ 'type' => 'imaginary',
+ 'count' => 1,
+ );
+ foreach ($expected_values as $name => $value) {
+ $this->assertTrue($this->xpath('//table/tbody/tr/td[normalize-space(text())=:text]', array(':text' => $value)), t('File usage @name was found in the table.', array('@name' => $name)));
+ }
+ }
+}
+
+/**
+ * Tests image alt and title text.
+ */
+class FileEntityAltTitleTestCase extends FileEntityTestHelper {
+ public static function getInfo() {
+ return array(
+ 'name' => 'File entity alt and title text',
+ 'description' => 'Create an image file with alt and title text.',
+ 'group' => 'File entity',
+ 'dependencies' => array('token'),
+ );
+ }
+
+ function setUp() {
+ parent::setUp('token');
+
+ $web_user = $this->drupalCreateUser(array('create files', 'edit own image files'));
+ $this->drupalLogin($web_user);
+ }
+
+ /**
+ * Create an "image" file and verify its associated alt and title text.
+ */
+ function testFileEntityAltTitle() {
+ $test_file = $this->getTestFile('image');
+ $alt_field_name = 'field_file_image_alt_text'; // Name of the default alt text field added to the image file type.
+ $title_field_name = 'field_file_image_title_text'; // Name of the default title text field added to the image file type.
+
+ // Create a file.
+ $edit = array();
+ $edit['files[upload]'] = drupal_realpath($test_file->uri);
+ $this->drupalPost('file/add', $edit, t('Next'));
+
+ // Step 2: Scheme selection.
+ if ($this->xpath('//input[@name="scheme"]')) {
+ $this->drupalPost(NULL, array(), t('Next'));
+ }
+
+ // Step 3: Attached fields.
+ $alt = 'Quote&quot; Amp&amp; ' . 'Файл для тестирования ' . $this->randomName(); // Generate alt text containing HTML entities, spaces and non-latin characters.
+ $title = 'Quote&quot; Amp&amp; ' . 'Файл для тестирования ' . $this->randomName(); // Generate title text containing HTML entities, spaces and non-latin characters.
+
+ $edit = array();
+ $edit[$alt_field_name . '[' . LANGUAGE_NONE . '][0][value]'] = $alt;
+ $edit[$title_field_name . '[' . LANGUAGE_NONE . '][0][value]'] = $title;
+ $this->drupalPost(NULL, $edit, t('Save'));
+
+ // Check that the image file has been uploaded.
+ $this->assertRaw(t('!type %name was uploaded.', array('!type' => 'Image', '%name' => $test_file->filename)), t('Image file uploaded.'));
+
+ // Check that the file exists in the database.
+ $file = $this->getFileByFilename($test_file->filename);
+ $this->assertTrue($file, t('File found in database.'));
+
+ // Check that the alt and title text was loaded from the fields.
+ $this->assertEqual($file->alt, $alt, t('Alt text was stored as file metadata.'));
+ $this->assertEqual($file->title, $title, t('Title text was stored as file metadata.'));
+
+ // Verify that the alt and title text is present on the page.
+ $image_info = array(
+ 'path' => $file->uri,
+ 'alt' => $alt,
+ 'title' => $title,
+ 'width' => $file->width,
+ 'height' => $file->height,
+ );
+ $default_output = theme('image', $image_info);
+ $this->assertRaw($default_output, 'Image displayed using user supplied alt and title attributes.');
+
+ // Verify that the alt and title text can be edited.
+ $new_alt = $this->randomName();
+ $new_title = $this->randomName();
+
+ $edit = array();
+ $edit[$alt_field_name . '[' . LANGUAGE_NONE . '][0][value]'] = $new_alt;
+ $edit[$title_field_name . '[' . LANGUAGE_NONE . '][0][value]'] = $new_title;
+ $this->drupalPost('file/' . $file->fid . '/edit', $edit, t('Save'));
+
+ $image_info = array(
+ 'path' => $file->uri,
+ 'alt' => $new_alt,
+ 'title' => $new_title,
+ 'width' => $file->width,
+ 'height' => $file->height,
+ );
+ $default_output = theme('image', $image_info);
+ $this->assertRaw($default_output, 'Image displayed using updated alt and title attributes.');
+ }
+}
+
+/**
+ * Tests replacing the file associated with a file entity.
+ */
+class FileEntityReplaceTestCase extends FileEntityTestHelper {
+ public static function getInfo() {
+ return array(
+ 'name' => 'File replacement',
+ 'description' => 'Test file replace functionality.',
+ 'group' => 'File entity',
+ );
+ }
+
+ function setUp() {
+ parent::setUp();
+ }
+
+ /**
+ * @todo Test image dimensions for an image field are reset when a file is replaced.
+ * @todo Test image styles are cleared when an image is updated.
+ */
+ function testReplaceFile() {
+ // Select the first text test file to use.
+ $file = $this->createFileEntity(array('type' => 'document'));
+
+ // Create a user with file edit permissions.
+ $user = $this->drupalCreateUser(array('edit any document files'));
+ $this->drupalLogin($user);
+
+ // Test that the Upload widget appears for a local file.
+ $this->drupalGet('file/' . $file->fid . '/edit');
+ $this->assertFieldByName('files[replace_upload]');
+
+ // Test that file saves without uploading a file.
+ $this->drupalPost(NULL, array(), t('Save'));
+ $this->assertText(t('Document @file has been updated.', array('@file' => $file->filename)), 'File was updated without file upload.');
+
+ // Get a text file to use as a replacement.
+ $original = clone $file;
+ $replacement = $this->getTestFile('text');
+
+ // Test that the file saves when uploading a replacement file.
+ $edit = array();
+ $edit['files[replace_upload]'] = drupal_realpath($replacement->uri);
+ $this->drupalPost('file/' . $file->fid . '/edit', $edit, t('Save'));
+ $this->assertText(t('Document @file has been updated.', array('@file' => $file->filename)), 'File was updated with file upload.');
+
+ // Re-load the file from the database.
+ $file = file_load($file->fid);
+
+ // Test how file properties changed after the file has been replaced.
+ $this->assertEqual($file->filename, $original->filename, 'Updated file name did not change.');
+ $this->assertNotEqual($file->filesize, $original->filesize, 'Updated file size changed from previous file.');
+ $this->assertEqual($file->filesize, $replacement->filesize, 'Updated file size matches uploaded file.');
+ $this->assertEqual(file_get_contents($file->uri), file_get_contents($replacement->uri), 'Updated file contents matches uploaded file.');
+ $this->assertFalse(entity_load('file', FALSE, array('status' => 0)), 'Temporary file used for replacement was deleted.');
+
+ // Get an image file.
+ $image = $this->getTestFile('image');
+ $edit['files[replace_upload]'] = drupal_realpath($image->uri);
+
+ // Test that validation works by uploading a non-text file as a replacement.
+ $this->drupalPost('file/' . $file->fid . '/edit', $edit, t('Save'));
+ $this->assertRaw(t('The specified file %file could not be uploaded. Only files with the following extensions are allowed:', array('%file' => $image->filename)), 'File validation works, upload failed correctly.');
+
+ // Create a non-local file record.
+ $file2 = new stdClass();
+ $file2->uri = 'oembed://' . $this->randomName();
+ $file2->filename = drupal_basename($file2->uri);
+ $file2->filemime = 'image/oembed';
+ $file2->type = 'image';
+ $file2->uid = 1;
+ $file2->timestamp = REQUEST_TIME;
+ $file2->filesize = 0;
+ $file2->status = 0;
+ // Write the record directly rather than calling file_save() so we don't
+ // invoke the hooks.
+ $this->assertTrue(drupal_write_record('file_managed', $file2), 'Non-local file was added to the database.');
+
+ // Test that Upload widget does not appear for non-local file.
+ $this->drupalGet('file/' . $file2->fid . '/edit');
+ $this->assertNoFieldByName('files[replace_upload]');
+ }
+}
+
+/**
+ * Tests file entity tokens.
+ */
+class FileEntityTokenTestCase extends FileEntityTestHelper {
+ public static function getInfo() {
+ return array(
+ 'name' => 'File entity tokens',
+ 'description' => 'Test the file entity tokens.',
+ 'group' => 'File entity',
+ );
+ }
+
+ function setUp() {
+ parent::setUp();
+ }
+
+ function testFileEntityTokens() {
+ $file = $this->createFileEntity(array('type' => 'document'));
+ $tokens = array(
+ 'type' => 'Document',
+ 'type:name' => 'Document',
+ 'type:machine-name' => 'document',
+ 'type:count' => 1,
+ );
+ $this->assertTokens('file', array('file' => $file), $tokens);
+
+ $file = $this->createFileEntity(array('type' => 'image'));
+ $tokens = array(
+ 'type' => 'Image',
+ 'type:name' => 'Image',
+ 'type:machine-name' => 'image',
+ 'type:count' => 1,
+ );
+ $this->assertTokens('file', array('file' => $file), $tokens);
+ }
+
+ function assertTokens($type, array $data, array $tokens, array $options = array()) {
+ $token_input = drupal_map_assoc(array_keys($tokens));
+ $values = token_generate($type, $token_input, $data, $options);
+ foreach ($tokens as $token => $expected) {
+ if (!isset($expected)) {
+ $this->assertTrue(!isset($values[$token]), t("Token value for [@type:@token] was not generated.", array('@type' => $type, '@token' => $token)));
+ }
+ elseif (!isset($values[$token])) {
+ $this->fail(t("Token value for [@type:@token] was not generated.", array('@type' => $type, '@token' => $token)));
+ }
+ elseif (!empty($options['regex'])) {
+ $this->assertTrue(preg_match('/^' . $expected . '$/', $values[$token]), t("Token value for [@type:@token] was '@actual', matching regular expression pattern '@expected'.", array('@type' => $type, '@token' => $token, '@actual' => $values[$token], '@expected' => $expected)));
+ }
+ else {
+ $this->assertIdentical($values[$token], $expected, t("Token value for [@type:@token] was '@actual', expected value '@expected'.", array('@type' => $type, '@token' => $token, '@actual' => $values[$token], '@expected' => $expected)));
+ }
+ }
+
+ return $values;
+ }
+}
+
+/**
+ * Tests adding support for bundles to the core 'file' entity.
+ */
+class FileEntityTypeTestCase extends FileEntityTestHelper {
+ public static function getInfo() {
+ return array(
+ 'name' => 'File entity types',
+ 'description' => 'Test the file entity types.',
+ 'group' => 'File entity',
+ );
+ }
+
+ function setUp() {
+ parent::setUp();
+ }
+
+ /**
+ * Test admin pages access and functionality.
+ */
+ function testAdminPages() {
+ // Create a user with file type administration access.
+ $user = $this->drupalCreateUser(array('administer file types'));
+ $this->drupalLogin($user);
+
+ $this->drupalGet('admin/structure/file-types');
+ $this->assertResponse(200, 'File types admin page is accessible');
+ }
+
+ /**
+ * Test creating a new type. Basic CRUD.
+ */
+ function testCreate() {
+ $type_machine_type = 'foo';
+ $type_machine_label = 'foobar';
+ $type = $this->createFileType(array('type' => $type_machine_type, 'label' => $type_machine_label));
+ $loaded_type = file_type_load($type_machine_type);
+ $this->assertEqual($loaded_type->label, $type_machine_label, "Was able to create a type and retreive it.");
+ }
+
+ /**
+ * Test file types CRUD UI.
+ */
+ function testTypesCrudUi() {
+ $this->drupalGet('admin/structure/file-types');
+ $this->assertResponse(403, 'File types UI page is not accessible to unauthorized users.');
+
+ $user = $this->drupalCreateUser(array('administer file types'));
+ $this->drupalLogin($user);
+
+ $this->drupalGet('admin/structure/file-types');
+ $this->assertResponse(200, 'File types UI page is accessible to users with adequate permission.');
+
+ // Create new file type.
+ $edit = array(
+ 'label' => t('Test type'),
+ 'type' => 'test_type',
+ 'description' => t('This is dummy file type used just for testing.'),
+ 'mimetypes' => 'image/png',
+ );
+ $this->drupalGet('admin/structure/file-types/add');
+ $this->drupalPost(NULL, $edit, t('Save'));
+ $this->assertText(t('The file type @type has been updated.', array('@type' => $edit['label'])), 'New file type successfully created.');
+ $this->assertText($edit['label'], 'New file type created: label found.');
+ $this->assertText($edit['description'], 'New file type created: description found.');
+ $this->assertFieldByXPath("//table//tr[1]//td[7]", t('Normal'), 'Newly created file type is stored in DB.');
+ $this->assertLink(t('disable'), 0, 'Able to disable newly created file type.');
+ $this->assertLink(t('delete'), 0, 'Able to delete newly created file type.');
+ $this->assertLinkByHref('admin/structure/file-types/manage/' . $edit['type'] . '/disable', 0, 'Disable link points to disable confirmation page.');
+ $this->assertLinkByHref('admin/structure/file-types/manage/' . $edit['type'] . '/delete', 0, 'Delete link points to delete confirmation page.');
+
+ // Edit file type.
+ $this->drupalGet('admin/structure/file-types/manage/' . $edit['type'] . '/edit');
+ $this->assertRaw(t('Save'), 'Save button found on edit page.');
+ $this->assertRaw(t('Delete'), 'Delete button found on edit page.');
+ $this->assertRaw($edit['label'], 'Label found on file type edit page');
+ $this->assertText($edit['description'], 'Description found on file type edit page');
+ $this->assertText($edit['mimetypes'], 'Mime-type configuration found on file type edit page');
+ $this->assertText(t('Mimetype List'), 'Mimetype list present on edit form.');
+
+ // Modify file type.
+ $edit['label'] = t('New type label');
+ $this->drupalPost(NULL, array('label' => $edit['label']), t('Save'));
+ $this->assertText(t('The file type @type has been updated.', array('@type' => $edit['label'])), 'File type was modified.');
+ $this->assertText($edit['label'], 'Modified label found on file types list.');
+
+ // Disable and re-enable file type.
+ $this->drupalGet('admin/structure/file-types/manage/' . $edit['type'] . '/disable');
+ $this->assertText(t('Are you sure you want to disable the file type @type?', array('@type' => $edit['label'])), 'Disable confirmation page found.');
+ $this->drupalPost(NULL, array(), t('Disable'));
+ $this->assertText(t('The file type @type has been disabled.', array('@type' => $edit['label'])), 'Disable confirmation message found.');
+ $this->assertFieldByXPath("//table//tr[5]//td[1]", $edit['label'], 'Disabled type moved to the tail of the list.');
+ $this->assertLink(t('enable'), 0, 'Able to re-enable newly created file type.');
+ $this->assertLinkByHref('admin/structure/file-types/manage/' . $edit['type'] . '/enable', 0, 'Enable link points to enable confirmation page.');
+ $this->drupalGet('admin/structure/file-types/manage/' . $edit['type'] . '/enable');
+ $this->assertText(t('Are you sure you want to enable the file type @type?', array('@type' => $edit['label'])), 'Enable confirmation page found.');
+ $this->drupalPost(NULL, array(), t('Enable'));
+ $this->assertText(t('The file type @type has been enabled.', array('@type' => $edit['label'])), 'Enable confirmation message found.');
+ $this->assertFieldByXPath("//table//tr[1]//td[1]", $edit['label'], 'Enabled type moved to the top of the list.');
+
+ // Delete newly created type.
+ $this->drupalGet('admin/structure/file-types/manage/' . $edit['type'] . '/delete');
+ $this->assertText(t('Are you sure you want to delete the file type @type?', array('@type' => $edit['label'])), 'Delete confirmation page found.');
+ $this->drupalPost(NULL, array(), t('Delete'));
+ $this->assertText(t('The file type @type has been deleted.', array('@type' => $edit['label'])), 'Delete confirmation message found.');
+ $this->drupalGet('admin/structure/file-types');
+ $this->assertNoText($edit['label'], 'File type successfully deleted.');
+
+ // Edit exported file type.
+ $this->drupalGet('admin/structure/file-types/manage/image/edit');
+ $this->assertRaw(t('Image'), 'Label found on file type edit page');
+ $this->assertText("image/*", 'Mime-type configuration found on file type edit page');
+ $this->drupalPost(NULL, array('label' => t('Funky images')), t('Save'));
+ $this->assertText(t('The file type @type has been updated.', array('@type' => t('Funky images'))), 'File type was modified.');
+ $this->assertText(t('Funky image'), 'Modified label found on file types list.');
+ $this->assertFieldByXPath("//table//tr[1]//td[7]", t('Overridden'), 'Modified type overrides configuration from code.');
+ $this->assertLink(t('revert'), 0, 'Able to revert overridden file type.');
+ $this->assertLinkByHref('admin/structure/file-types/manage/image/revert', 0, 'Revert link points to revert confirmation page.');
+
+ // Revert file type.
+ $this->drupalGet('admin/structure/file-types/manage/image/revert');
+ $this->assertText(t('Are you sure you want to revert the file type @type?', array('@type' => t('Funky images'))), 'Revert confirmation page found.');
+ $this->drupalPost(NULL, array(), t('Revert'));
+ $this->assertText(t('The file type @type has been reverted.', array('@type' => t('Funky images'))), 'Revert confirmation message found.');
+ $this->assertText(t('Image'), 'Reverted file type found in list.');
+ $this->assertFieldByXPath("//table//tr[1]//td[7]", t('Default'), 'Reverted file type shows correct state.');
+ }
+}
+
+/**
+ * Tests the file entity access API.
+ */
+class FileEntityAccessTestCase extends FileEntityTestHelper {
+
+ public static function getInfo() {
+ return array(
+ 'name' => 'File entity access',
+ 'description' => 'Test the access aspects of file entity.',
+ 'group' => 'File entity',
+ );
+ }
+
+ function setUp() {
+ parent::setUp();
+
+ // Remove the "view files" permission which is set by default for all users
+ // so we can test this permission correctly.
+ $roles = user_roles();
+ foreach ($roles as $rid => $role) {
+ user_role_revoke_permissions($rid, array('view files'));
+ }
+ }
+
+ /**
+ * Runs basic tests for file_entity_access function.
+ */
+ function testFileEntityAccess() {
+ $file = $this->createFileEntity(array('type' => 'image'));
+
+ // Ensures user with 'bypass file access' permission can do everything.
+ $web_user = $this->drupalCreateUser(array('bypass file access'));
+ $this->assertFileEntityAccess(array('create' => TRUE), NULL, $web_user);
+ $this->assertFileEntityAccess(array('view' => TRUE, 'download' => TRUE, 'update' => TRUE, 'delete' => TRUE), $file, $web_user);
+
+ // A user with 'administer files' should not access CRUD operations.
+ $web_user = $this->drupalCreateUser(array('administer files'));
+ $this->assertFileEntityAccess(array('view' => FALSE, 'download' => FALSE, 'update' => FALSE, 'delete' => FALSE), $file, $web_user);
+
+ // User cannot 'view files'.
+ $web_user = $this->drupalCreateUser(array('create files'));
+ $this->assertFileEntityAccess(array('view' => FALSE), $file, $web_user);
+ // But can upload new ones.
+ $this->assertFileEntityAccess(array('create' => TRUE), NULL, $web_user);
+
+ // User can view own files but no other files.
+ $web_user = $this->drupalCreateUser(array('create files', 'view own files'));
+ $this->assertFileEntityAccess(array('view' => FALSE), $file, $web_user);
+ $file->uid = $web_user->uid;
+ $this->assertFileEntityAccess(array('view' => TRUE), $file, $web_user);
+
+ // User can download own files but no other files.
+ $web_user = $this->drupalCreateUser(array('create files', 'download own image files'));
+ $this->assertFileEntityAccess(array('download' => FALSE), $file, $web_user);
+ $file->uid = $web_user->uid;
+ $this->assertFileEntityAccess(array('download' => TRUE), $file, $web_user);
+
+ // User can update own files but no other files.
+ $web_user = $this->drupalCreateUser(array('create files', 'view own files', 'edit own image files'));
+ $this->assertFileEntityAccess(array('update' => FALSE), $file, $web_user);
+ $file->uid = $web_user->uid;
+ $this->assertFileEntityAccess(array('update' => TRUE), $file, $web_user);
+
+ // User can delete own files but no other files.
+ $web_user = $this->drupalCreateUser(array('create files', 'view own files', 'edit own image files', 'delete own image files'));
+ $this->assertFileEntityAccess(array('delete' => FALSE), $file, $web_user);
+ $file->uid = $web_user->uid;
+ $this->assertFileEntityAccess(array('delete' => TRUE), $file, $web_user);
+
+ // User can view any file.
+ $web_user = $this->drupalCreateUser(array('create files', 'view files'));
+ $this->assertFileEntityAccess(array('view' => TRUE), $file, $web_user);
+
+ // User can download any file.
+ $web_user = $this->drupalCreateUser(array('create files', 'download any image files'));
+ $this->assertFileEntityAccess(array('download' => TRUE), $file, $web_user);
+
+ // User can edit any file.
+ $web_user = $this->drupalCreateUser(array('create files', 'view files', 'edit any image files'));
+ $this->assertFileEntityAccess(array('update' => TRUE), $file, $web_user);
+
+ // User can delete any file.
+ $web_user = $this->drupalCreateUser(array('create files', 'view files', 'edit any image files', 'delete any image files'));
+ $this->assertFileEntityAccess(array('delete' => TRUE), $file, $web_user);
+ }
+
+ /**
+ * Tests page access.
+ *
+ * Verifies the privileges required to access the following pages:
+ * file/add
+ * file/%/view
+ * file/%/download
+ * file/%/edit
+ * file/%/usage
+ * file/%/delete
+ */
+ function testFileEntityPageAccess() {
+ // Test creating files without permission.
+ $web_user = $this->drupalCreateUser();
+ $this->drupalLogin($web_user);
+ $this->drupalGet('file/add');
+ $this->assertResponse(403, 'Users without access can not access the file add page');
+
+ // Test creating files with permission.
+ user_role_change_permissions(DRUPAL_AUTHENTICATED_RID, array(
+ 'create files' => TRUE,
+ ));
+ $this->drupalGet('file/add');
+ $this->assertResponse(200, 'Users with access can access the file add page');
+
+ $file = $this->createFileEntity(array('type' => 'document','uid' => $web_user->uid));
+
+ // Test viewing own files without permission.
+ $this->drupalGet("file/{$file->fid}/view");
+ $this->assertResponse(403, 'Users without access can not view their own files');
+
+ // Test viewing own files with permission.
+ user_role_change_permissions(DRUPAL_AUTHENTICATED_RID, array(
+ 'view own files' => TRUE,
+ ));
+ $this->drupalGet("file/{$file->fid}/view");
+ $this->assertResponse(200, 'Users with access can view their own files');
+
+ // Test viewing any files without permission.
+ $file->uid = 1;
+ file_save($file);
+ $this->drupalGet("file/{$file->fid}/view");
+ $this->assertResponse(403, 'Users with access can not view any file');
+
+ // Test viewing any files with permission.
+ user_role_change_permissions(DRUPAL_AUTHENTICATED_RID, array(
+ 'view files' => TRUE,
+ ));
+ $this->drupalGet("file/{$file->fid}/view");
+ $this->assertResponse(200, 'Users with access can view any file');
+
+ // Test downloading own files without permission.
+ $file->uid = $web_user->uid;
+ file_save($file);
+ $url = "file/{$file->fid}/download";
+ $this->drupalGet($url, array('query' => array('token' => file_entity_get_download_token($file))));
+ $this->assertResponse(403, 'Users without access can not download their own files');
+
+ // Test downloading own files with permission.
+ user_role_change_permissions(DRUPAL_AUTHENTICATED_RID, array(
+ 'download own document files' => TRUE,
+ ));
+ $this->drupalGet($url, array('query' => array('token' => file_entity_get_download_token($file))));
+ $this->assertResponse(200, 'Users with access can download their own files');
+
+ // Test downloading any files without permission.
+ $file->uid = 1;
+ file_save($file);
+ $url = "file/{$file->fid}/download";
+ $this->drupalGet($url, array('query' => array('token' => file_entity_get_download_token($file))));
+ $this->assertResponse(403, 'Users without access can not download any file');
+
+ // Test downloading any files with permission.
+ user_role_change_permissions(DRUPAL_AUTHENTICATED_RID, array(
+ 'download any document files' => TRUE,
+ ));
+ $this->drupalGet($url, array('query' => array('token' => file_entity_get_download_token($file))));
+ $this->assertResponse(200, 'Users with access can download any file');
+
+ // Test downloading files with an invalid token.
+ $this->drupalGet($url, array('query' => array('token' => 'invalid-token')));
+ $this->assertResponse(403, 'Cannot download file with an invalid token.');
+
+ // Test downloading files without a token.
+ $this->drupalGet($url);
+ $this->assertResponse(403, 'Cannot download file without a token.');
+ variable_set('file_entity_allow_insecure_download', TRUE);
+
+ // Test downloading files with permission but without a token when insecure
+ // downloads are enabled.
+ $this->drupalGet($url);
+ $this->assertResponse(200, 'Users with access can download the file without a token when file_entity_allow_insecure_download is set.');
+
+ // Tests editing own files without permission.
+ $file->uid = $web_user->uid;
+ file_save($file);
+ $this->drupalGet("file/{$file->fid}/edit");
+ $this->assertResponse(403, 'Users without access can not edit own files');
+
+ // Tests checking the usage of their own files without permission.
+ $this->drupalGet("file/{$file->fid}/usage");
+ $this->assertResponse(403, 'Users without access can not check the usage of their own files');
+
+ // Tests editing own files with permission.
+ user_role_change_permissions(DRUPAL_AUTHENTICATED_RID, array(
+ 'edit own document files' => TRUE,
+ ));
+ $this->drupalGet("file/{$file->fid}/edit");
+ $this->assertResponse(200, 'Users with access can edit own files');
+
+ // Tests checking the usage of their own files without permission.
+ $this->drupalGet("file/{$file->fid}/usage");
+ $this->assertResponse(200, 'Users with access can check the usage of their own files');
+
+ // Tests editing any files without permission.
+ $file->uid = 1;
+ file_save($file);
+ $this->drupalGet("file/{$file->fid}/edit");
+ $this->assertResponse(403, 'Users without access can not edit any file');
+
+ // Tests checking the usage of any files without permission.
+ $this->drupalGet("file/{$file->fid}/usage");
+ $this->assertResponse(403, 'Users without access can not check the usage of any file');
+
+ // Tests editing any files with permission.
+ user_role_change_permissions(DRUPAL_AUTHENTICATED_RID, array(
+ 'edit any document files' => TRUE,
+ ));
+ $this->drupalGet("file/{$file->fid}/edit");
+ $this->assertResponse(200, 'Users with access can edit any file');
+
+ // Tests checking the usage of any files with permission.
+ $this->drupalGet("file/{$file->fid}/usage");
+ $this->assertResponse(200, 'Users with access can check the usage of any file');
+
+ // Tests deleting own files without permission.
+ $file->uid = $web_user->uid;
+ file_save($file);
+ $this->drupalGet("file/{$file->fid}/delete");
+ $this->assertResponse(403, 'Users without access can not delete their own files');
+
+ // Tests deleting own files with permission.
+ user_role_change_permissions(DRUPAL_AUTHENTICATED_RID, array(
+ 'delete own document files' => TRUE,
+ ));
+ $this->drupalGet("file/{$file->fid}/delete");
+ $this->assertResponse(200, 'Users with access can delete their own files');
+
+ // Tests deleting any files without permission.
+ $file->uid = 1;
+ file_save($file);
+ $this->drupalGet("file/{$file->fid}/delete");
+ $this->assertResponse(403, 'Users without access can not delete any file');
+
+ // Tests deleting any files with permission.
+ user_role_change_permissions(DRUPAL_AUTHENTICATED_RID, array(
+ 'delete any document files' => TRUE,
+ ));
+ $this->drupalGet("file/{$file->fid}/delete");
+ $this->assertResponse(200, 'Users with access can delete any file');
+ }
+
+ /**
+ * Test to see if we have access to download private files when granted the permissions.
+ */
+ function testFileEntityPrivateDownloadAccess() {
+ foreach ($this->getPrivateDownloadAccessCases() as $case) {
+ // Create users and login only if non-anonymous.
+ $authenticated_user = !is_null($case['permissions']);
+ if ($authenticated_user) {
+ $account = $this->drupalCreateUser($case['permissions']);
+ $this->drupalLogin($account);
+ }
+
+ // Create private, permanent files owned by this user only he's an owner.
+ if (!empty($case['owner'])) {
+ $file = $this->createFileEntity(array('type' => 'document', 'uid' => $account->uid, 'scheme' => 'private'));
+
+ // Check if the physical file is there.
+ $arguments = array('%name' => $file->filename, '%username' => $account->name, '%uri' => $file->uri);
+ $this->assertTrue(is_file($file->uri), format_string('File %name owned by %username successfully created at %uri.', $arguments));
+ $url = file_create_url($file->uri);
+ $message_file_info = ' ' . format_string('File %uri was checked.', array('%uri' => $file->uri));
+ }
+
+ // Try to download the file.
+ $this->drupalGet($url);
+ $this->assertResponse($case['expect'], $case['message'] . $message_file_info);
+
+ // Logout authenticated users.
+ if ($authenticated_user) {
+ $this->drupalLogout();
+ }
+ }
+ }
+
+ /**
+ * Asserts file_entity_access correctly grants or denies access.
+ */
+ function assertFileEntityAccess($ops, $file, $account) {
+ drupal_static_reset('file_entity_access');
+ foreach ($ops as $op => $result) {
+ $msg = t("file_entity_access returns @result with operation '@op'.", array('@result' => $result ? 'true' : 'false', '@op' => $op));
+ $this->assertEqual($result, file_entity_access($op, $file, $account), $msg);
+ }
+ }
+
+ /**
+ * Helper for testFileEntityPrivateDownloadAccess() test.
+ *
+ * Defines several cases for accesing private files.
+ *
+ * @return array
+ * Array of associative arrays, each one having the next keys:
+ * - "message" string with the assertion message.
+ * - "permissions" array of permissions or NULL for anonymous user.
+ * - "expect" expected HTTP response code.
+ * - "owner" Optional boolean indicating if the user is a file owner.
+ */
+ function getPrivateDownloadAccessCases() {
+ return array(
+ array(
+ 'message' => "File owners cannot download their own files unless they are granted the 'view own private files' permission.",
+ 'permissions' => array(),
+ 'expect' => 403,
+ 'owner' => TRUE,
+ ),
+ array(
+ 'message' => "File owners can download their own files as they have been granted the 'view own private files' permission.",
+ 'permissions' => array('view own private files'),
+ 'expect' => 200,
+ 'owner' => TRUE,
+ ),
+ array(
+ 'message' => "Anonymous users cannot download private files.",
+ 'permissions' => NULL,
+ 'expect' => 403,
+ ),
+ array(
+ 'message' => "Authenticated users cannot download each other's private files.",
+ 'permissions' => array(),
+ 'expect' => 403,
+ ),
+ array(
+ 'message' => "Users who can view public files are not able to download private files.",
+ 'permissions' => array('view files'),
+ 'expect' => 403,
+ ),
+ array(
+ 'message' => "Users who bypass file access can download any file.",
+ 'permissions' => array('bypass file access'),
+ 'expect' => 200,
+ ),
+ );
+ }
+}
+
+/**
+ * Tests overriding file attributes.
+ */
+class FileEntityAttributeOverrideTestCase extends FileEntityTestHelper {
+
+ public static function getInfo() {
+ return array(
+ 'name' => 'File entity attribute override',
+ 'description' => 'Test overriding file entity attributes.',
+ 'group' => 'File entity',
+ );
+ }
+
+ /**
+ * Test to see if file attributes can be overridden.
+ */
+ function testFileEntityFileAttributeOverrides() {
+ $overrides = array(
+ 'width' => 40,
+ 'height' => 20,
+ 'alt' => $this->randomName(),
+ 'title' => $this->randomName(),
+
+ );
+
+ // Create an image file entity for testing.
+ $file = $this->createFileEntity(array('type' => 'image'));
+
+ // Override a variety of attributes.
+ foreach ($overrides as $override => $value) {
+ $file->override['attributes'][$override] = $value;
+ }
+
+ // Build just the file portion of a file entity.
+ $build = file_view_file($file, 'full');
+
+ // Verify that all of the overrides replaced the attributes.
+ foreach ($overrides as $attribute => $expected_value) {
+ $this->assertEqual($build['#file']->$attribute, $expected_value, format_string('The %attribute was overridden correctly.', array('%attribute' => $attribute)));
+ }
+ }
+}