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 = '' . t('(active tab)') . ''; $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" Amp& ' . 'Файл для тестирования ' . $this->randomName(); // Generate alt text containing HTML entities, spaces and non-latin characters. $title = 'Quote" 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.'); } } /** * Test changing the scheme of a file. */ class FileEntityChangeSchemeTestCase extends FileEntityTestHelper { public static function getInfo() { return array( 'name' => 'Changing file scheme', 'description' => 'Test changing the scheme of a file.', 'group' => 'File entity', ); } function testChangeScheme() { // Select the first text test file to use. $file = $this->createFileEntity(array('type' => 'document')); $this->assertEqual(file_uri_scheme($file->uri), 'public', 'File is public.'); // Create a user with file edit permissions. $user = $this->drupalCreateUser(array('edit any document files')); $this->drupalLogin($user); $this->drupalGet('file/' . $file->fid . '/edit'); $this->assertNoFieldByName('scheme'); // Create a user with file admin permissions. $user = $this->drupalCreateUser(array('edit any document files', 'administer files')); $this->drupalLogin($user); $this->drupalGet('file/' . $file->fid . '/edit'); $this->assertFieldByName('scheme', 'public'); $this->drupalPost(NULL, array('scheme' => 'private'), 'Save'); $file = entity_load_unchanged('file', $file->fid); $this->assertEqual(file_uri_scheme($file->uri), 'private', 'File has changed to private.'); } } /** * 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 retrieve 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', 'administer fields')); $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))); } } }