drupalGetTestFiles($type) as $file) { $this->files[$type][] = file_save($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; } /** * 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. */ protected 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, ), ); } /** * 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; } /** * 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()) { $file = new stdClass(); // 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; } /** * 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()); } } 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(); } /** * 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; } /** * 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.')); } } class FileEntityUnitTestCase extends FileEntityTestHelper { public static function getInfo() { return array( 'name' => 'File entity unit tests', 'description' => 'Test basic file entity functionality.', 'group' => 'File entity', ); } function setUp() { parent::setUp(); parent::setUpFiles(); } /** * 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); } } function testFileEntity() { $file = reset($this->files['text']); // 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}"); } function testImageDimensions() { $files = array(); $text_fids = array(); // Test hook_file_insert(). // Files have been saved as part of setup (in FileEntityTestHelper::setUpFiles). foreach ($this->files['image'] as $file) { $files[$file->fid] = $file->metadata; $this->assertTrue(isset($file->metadata['height']), 'Image height retrieved on file_save() for an image file.'); $this->assertTrue(isset($file->metadata['width']), 'Image width retrieved on file_save() for an image file.'); } foreach ($this->files['text'] as $file) { $text_fids[] = $file->fid; $this->assertFalse(isset($file->metadata['height']), 'No image height retrieved on file_save() for an text file.'); $this->assertFalse(isset($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(); foreach (file_load_multiple(array_keys($files)) as $file) { $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'], $files[$file->fid]['height'], 'Loaded image height is equal to saved image height.'); $this->assertEqual($file->metadata['width'], $files[$file->fid]['width'], 'Loaded image width is equal to saved image width.'); } foreach (file_load_multiple($text_fids) as $file) { $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. $image_files = array_keys($files); $file = file_load(reset($image_files)); $image = image_load($file->uri); image_resize($image, $file->metadata['width'] / 2, $file->metadata['height'] / 2); image_save($image); file_save($file); $this->assertEqual($file->metadata['height'], $files[$file->fid]['height'] / 2, 'Image file height updated by file_save().'); $this->assertEqual($file->metadata['width'], $files[$file->fid]['width'] / 2, 'Image file width updated by file_save().'); // Clear the cache and reload the file. entity_get_controller('file')->resetCache(); $file = file_load($file->fid); $this->assertEqual($file->metadata['height'], $files[$file->fid]['height'] / 2, 'Updated image height retrieved by file_load().'); $this->assertEqual($file->metadata['width'], $files[$file->fid]['width'] / 2, 'Updated image width retrieved by file_load().'); //Test hook_file_delete(). file_delete($file, TRUE); $this->assertFalse(db_query('SELECT COUNT(*) FROM {file_metadata} WHERE fid = :fid', array(':fid' => 'fid'))->fetchField(), 'Row deleted in {file_dimensions} on file_delete().'); } } 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'); } } class FileEntityCreationTestCase extends FileEntityTestHelper { public static function getInfo() { return array( 'name' => 'File entity creation', 'description' => 'Create a file and test saving it.', 'group' => 'File entity', ); } function setUp() { parent::setUp(); $web_user = $this->drupalCreateUser(array('create files', 'edit own document files')); $this->drupalLogin($web_user); } /** * Create a "document" file and verify its consistency in the database. */ function testFileEntityCreation() { $test_file = $this->getTestFile('text'); // 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')); } // Check that the document file has been uploaded. $this->assertRaw(t('!type %name was uploaded.', array('!type' => 'Document', '%name' => $test_file->filename)), t('Document file uploaded.')); // Check that the file exists in the database. $file = $this->getFileByFilename($test_file->filename); $this->assertTrue($file, t('File found in database.')); } } /** * 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, 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 . '/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 . '/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 . '/edit'); $this->assertLinkByHref('file/' . $file->fid . '/delete'); } } } 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(); parent::setUpFiles(); } /** * @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 = reset($this->files['text']); // 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 the next text file to use as a replacement. $original = clone $file; $replacement = next($this->files['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($replacement->uri), file_get_contents($file->uri), 'Updated file contents matches uploaded file.'); // Get an image file. $image = reset($this->files['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]'); } } 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(); parent::setUpFiles(); } function testFileEntityTokens() { $tokens = array( 'type' => 'Document', 'type:name' => 'Document', 'type:machine-name' => 'document', 'type:count' => count($this->files['text']), ); $this->assertTokens('file', array('file' => $this->files['text'][0]), $tokens); $tokens = array( 'type' => 'Image', 'type:name' => 'Image', 'type:machine-name' => 'image', 'type:count' => count($this->files['image']), ); $this->assertTokens('file', array('file' => $this->files['image'][0]), $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; } } 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(); parent::setUpFiles(); } /** * 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."); } /** * Ensures that the weight is respected when types are created. * @return unknown_type */ function testOrder() { // $type = $this->createFileType(array('name' => 'last', 'label' => 'Last', 'weight' => 100)); // $type = $this->createFileType(array('name' => 'first', 'label' => 'First')); // $types = media_type_get_types(); // $keys = array_keys($types); // $this->assertTrue(isset($types['last']) && isset($types['first']), "Both types saved"); // $this->assertTrue(array_search('last', $keys) > array_search('first', $keys), 'Type which was supposed to be first came first'); } /** * Test view mode assignment. Currently fails, don't know why. * @return unknown_type */ function testViewModesAssigned() { } /** * Make sure candidates are presented in the case of multiple * file types. */ function testTypeWithCandidates() { // Create multiple file types with the same mime types. $types = array( 'image1' => $this->createFileType(array('type' => 'image1', 'label' => 'Image 1')), 'image2' => $this->createFileType(array('type' => 'image2', 'label' => 'Image 2')) ); // Attach a text field to one of the file types. $field = array( 'field_name' => drupal_strtolower($this->randomName()), 'type' => 'text', 'settings' => array( 'max_length' => 255, ) ); field_create_field($field); $instance = array( 'field_name' => $field['field_name'], 'entity_type' => 'file', 'bundle' => 'image2', 'widget' => array( 'type' => 'text_textfield', ), 'display' => array( 'default' => array( 'type' => 'text_default', ), ), ); field_create_instance($instance); // Create a user with file creation access. $user = $this->drupalCreateUser(array('create files')); $this->drupalLogin($user); // Step 1: Upload file $file = reset($this->files['image']); $edit = array(); $edit['files[upload]'] = drupal_realpath($file->uri); $this->drupalPost('file/add', $edit, t('Next')); // Step 2: Select file type candidate $this->assertText('Image 1', 'File type candidate list item found.'); $this->assertText('Image 2', 'File type candidate list item found.'); $edit = array(); $edit['type'] = 'image2'; $this->drupalPost(NULL, $edit, t('Next')); // Step 3: Select file scheme candidate $this->assertText('Public local files served by the webserver.', 'File scheme candidate list item found.'); $this->assertText('Private local files served by Drupal.', 'File scheme candidate list item found.'); $edit = array(); $edit['scheme'] = 'public'; $this->drupalPost(NULL, $edit, t('Next')); // Step 4: Complete field widgets $langcode = LANGUAGE_NONE; $edit = array(); $edit["{$field['field_name']}[$langcode][0][value]"] = $this->randomName(); $this->drupalPost(NULL, $edit, t('Save')); $this->assertRaw(t('!type %name was uploaded.', array('!type' => 'Image 2', '%name' => $file->filename)), t('Image 2 file updated.')); $this->assertText($field['field_name'], 'File text field was found.'); } /** * Make sure no candidates appear when only one mime type is available. * NOTE: Depends on file_entity.module default 'image' type. */ function testTypeWithoutCandidates() { // Attach a text field to the default image file type. $field = array( 'field_name' => drupal_strtolower($this->randomName()), 'type' => 'text', 'settings' => array( 'max_length' => 255, ) ); field_create_field($field); $instance = array( 'field_name' => $field['field_name'], 'entity_type' => 'file', 'bundle' => 'image', 'widget' => array( 'type' => 'text_textfield', ), 'display' => array( 'default' => array( 'type' => 'text_default', ), ), ); field_create_instance($instance); // Create a user with file creation access. $user = $this->drupalCreateUser(array('create files')); $this->drupalLogin($user); // Step 1: Upload file $file = reset($this->files['image']); $edit = array(); $edit['files[upload]'] = drupal_realpath($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: Complete field widgets $langcode = LANGUAGE_NONE; $edit = array(); $edit["{$field['field_name']}[$langcode][0][value]"] = $this->randomName(); $this->drupalPost(NULL, $edit, t('Save')); $this->assertRaw(t('!type %name was uploaded.', array('!type' => 'Image', '%name' => $file->filename)), t('Image file uploaded.')); $this->assertText($field['field_name'], 'File text field was found.'); } /** * 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.'); } } 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(); parent::setUpFiles(); } /** * Asserts file_entity_access correctly grants or denies access. */ function assertFileEntityAccess($ops, $file, $account) { 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); } } /** * Runs basic tests for file_entity_access function. */ function testFileEntityAccess() { $file = reset($this->files['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; $file->status = FILE_STATUS_PERMANENT; file_save($file); $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; $file->status = FILE_STATUS_PERMANENT; file_save($file); $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; $file->status = FILE_STATUS_PERMANENT; file_save($file); $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; $file->status = FILE_STATUS_PERMANENT; file_save($file); $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); } /** * Test to see if we have access to view files when granted the permissions. * In this test we aim to prove the permissions work in the following pages: * file/add * file/%/view * file/%/download * file/%/edit * file/%/delete */ function testFileEntityPageAccess() { $web_user = $this->drupalCreateUser(array()); $this->drupalLogin($web_user); $this->drupalGet('file/add'); $this->assertResponse(403, 'Users without access can not access the file add page'); $web_user = $this->drupalCreateUser(array('create files')); $this->drupalLogin($web_user); $this->drupalGet('file/add'); $this->assertResponse(200, 'Users with access can access the file add page'); $file = reset($this->files['text']); $file->status = FILE_STATUS_PERMANENT; file_save($file); // This fails.. No clue why but, tested manually and works as should. //$web_user = $this->drupalCreateUser(array('view own files')); //$this->drupalLogin($web_user); //$this->drupalGet("file/{$file->fid}/view"); //$this->assertResponse(403, 'Users without access can not access the file view page'); $web_user = $this->drupalCreateUser(array('view files')); $this->drupalLogin($web_user); $this->drupalGet("file/{$file->fid}/view"); $this->assertResponse(200, 'Users with access can access the file view page'); $url = "file/{$file->fid}/download"; $web_user = $this->drupalCreateUser(array()); $this->drupalLogin($web_user); $this->drupalGet($url, array('query' => array('token' => $this->drupalGetToken($url)))); $this->assertResponse(403, 'Users without access can not download the file'); $web_user = $this->drupalCreateUser(array('download any document files')); $this->drupalLogin($web_user); $this->drupalGet($url, array('query' => array('token' => $this->drupalGetToken($url)))); $this->assertResponse(200, 'Users with access can download the file'); $this->drupalGet($url, array('query' => array('token' => 'invalid-token'))); $this->assertResponse(403, 'Cannot download file with in invalid token.'); $this->drupalGet($url); $this->assertResponse(403, 'Cannot download file without a token.'); $web_user = $this->drupalCreateUser(array()); $this->drupalLogin($web_user); $this->drupalGet("file/{$file->fid}/edit"); $this->assertResponse(403, 'Users without access can not access the file edit page'); $web_user = $this->drupalCreateUser(array('edit any document files')); $this->drupalLogin($web_user); $this->drupalGet("file/{$file->fid}/edit"); $this->assertResponse(200, 'Users with access can access the file add page'); $web_user = $this->drupalCreateUser(array()); $this->drupalLogin($web_user); $this->drupalGet("file/{$file->fid}/delete"); $this->assertResponse(403, 'Users without access can not access the file view page'); $web_user = $this->drupalCreateUser(array('delete any document files')); $this->drupalLogin($web_user); $this->drupalGet("file/{$file->fid}/delete"); $this->assertResponse(200, 'Users with access can access the file add page'); } /** * 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 = next($this->files['text']); $file->status = FILE_STATUS_PERMANENT; $file->uid = $account->uid; file_save($file); $file = file_move($file, '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(); } } } }