Drupal 8.0.0 beta 12. More info: https://www.drupal.org/node/2514176
This commit is contained in:
commit
9921556621
13277 changed files with 1459781 additions and 0 deletions
147
core/modules/file/src/Tests/CopyTest.php
Normal file
147
core/modules/file/src/Tests/CopyTest.php
Normal file
|
@ -0,0 +1,147 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains \Drupal\file\Tests\CopyTest.
|
||||
*/
|
||||
|
||||
namespace Drupal\file\Tests;
|
||||
|
||||
/**
|
||||
* Tests the file copy function.
|
||||
*
|
||||
* @group file
|
||||
*/
|
||||
class CopyTest extends FileManagedUnitTestBase {
|
||||
/**
|
||||
* Test file copying in the normal, base case.
|
||||
*/
|
||||
function testNormal() {
|
||||
$contents = $this->randomMachineName(10);
|
||||
$source = $this->createFile(NULL, $contents);
|
||||
$desired_uri = 'public://' . $this->randomMachineName();
|
||||
|
||||
// Clone the object so we don't have to worry about the function changing
|
||||
// our reference copy.
|
||||
$result = file_copy(clone $source, $desired_uri, FILE_EXISTS_ERROR);
|
||||
|
||||
// Check the return status and that the contents changed.
|
||||
$this->assertTrue($result, 'File copied successfully.');
|
||||
$this->assertEqual($contents, file_get_contents($result->getFileUri()), 'Contents of file were copied correctly.');
|
||||
|
||||
// Check that the correct hooks were called.
|
||||
$this->assertFileHooksCalled(array('copy', 'insert'));
|
||||
|
||||
$this->assertDifferentFile($source, $result);
|
||||
$this->assertEqual($result->getFileUri(), $desired_uri, 'The copied file entity has the desired filepath.');
|
||||
$this->assertTrue(file_exists($source->getFileUri()), 'The original file still exists.');
|
||||
$this->assertTrue(file_exists($result->getFileUri()), 'The copied file exists.');
|
||||
|
||||
// Reload the file from the database and check that the changes were
|
||||
// actually saved.
|
||||
$this->assertFileUnchanged($result, file_load($result->id(), TRUE));
|
||||
}
|
||||
|
||||
/**
|
||||
* Test renaming when copying over a file that already exists.
|
||||
*/
|
||||
function testExistingRename() {
|
||||
// Setup a file to overwrite.
|
||||
$contents = $this->randomMachineName(10);
|
||||
$source = $this->createFile(NULL, $contents);
|
||||
$target = $this->createFile();
|
||||
$this->assertDifferentFile($source, $target);
|
||||
|
||||
// Clone the object so we don't have to worry about the function changing
|
||||
// our reference copy.
|
||||
$result = file_copy(clone $source, $target->getFileUri(), FILE_EXISTS_RENAME);
|
||||
|
||||
// Check the return status and that the contents changed.
|
||||
$this->assertTrue($result, 'File copied successfully.');
|
||||
$this->assertEqual($contents, file_get_contents($result->getFileUri()), 'Contents of file were copied correctly.');
|
||||
$this->assertNotEqual($result->getFileUri(), $source->getFileUri(), 'Returned file path has changed from the original.');
|
||||
|
||||
// Check that the correct hooks were called.
|
||||
$this->assertFileHooksCalled(array('copy', 'insert'));
|
||||
|
||||
// Load all the affected files to check the changes that actually made it
|
||||
// to the database.
|
||||
$loaded_source = file_load($source->id(), TRUE);
|
||||
$loaded_target = file_load($target->id(), TRUE);
|
||||
$loaded_result = file_load($result->id(), TRUE);
|
||||
|
||||
// Verify that the source file wasn't changed.
|
||||
$this->assertFileUnchanged($source, $loaded_source);
|
||||
|
||||
// Verify that what was returned is what's in the database.
|
||||
$this->assertFileUnchanged($result, $loaded_result);
|
||||
|
||||
// Make sure we end up with three distinct files afterwards.
|
||||
$this->assertDifferentFile($loaded_source, $loaded_target);
|
||||
$this->assertDifferentFile($loaded_target, $loaded_result);
|
||||
$this->assertDifferentFile($loaded_source, $loaded_result);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test replacement when copying over a file that already exists.
|
||||
*/
|
||||
function testExistingReplace() {
|
||||
// Setup a file to overwrite.
|
||||
$contents = $this->randomMachineName(10);
|
||||
$source = $this->createFile(NULL, $contents);
|
||||
$target = $this->createFile();
|
||||
$this->assertDifferentFile($source, $target);
|
||||
|
||||
// Clone the object so we don't have to worry about the function changing
|
||||
// our reference copy.
|
||||
$result = file_copy(clone $source, $target->getFileUri(), FILE_EXISTS_REPLACE);
|
||||
|
||||
// Check the return status and that the contents changed.
|
||||
$this->assertTrue($result, 'File copied successfully.');
|
||||
$this->assertEqual($contents, file_get_contents($result->getFileUri()), 'Contents of file were overwritten.');
|
||||
$this->assertDifferentFile($source, $result);
|
||||
|
||||
// Check that the correct hooks were called.
|
||||
$this->assertFileHooksCalled(array('load', 'copy', 'update'));
|
||||
|
||||
// Load all the affected files to check the changes that actually made it
|
||||
// to the database.
|
||||
$loaded_source = file_load($source->id(), TRUE);
|
||||
$loaded_target = file_load($target->id(), TRUE);
|
||||
$loaded_result = file_load($result->id(), TRUE);
|
||||
|
||||
// Verify that the source file wasn't changed.
|
||||
$this->assertFileUnchanged($source, $loaded_source);
|
||||
|
||||
// Verify that what was returned is what's in the database.
|
||||
$this->assertFileUnchanged($result, $loaded_result);
|
||||
|
||||
// Target file was reused for the result.
|
||||
$this->assertFileUnchanged($loaded_target, $loaded_result);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test that copying over an existing file fails when FILE_EXISTS_ERROR is
|
||||
* specified.
|
||||
*/
|
||||
function testExistingError() {
|
||||
$contents = $this->randomMachineName(10);
|
||||
$source = $this->createFile();
|
||||
$target = $this->createFile(NULL, $contents);
|
||||
$this->assertDifferentFile($source, $target);
|
||||
|
||||
// Clone the object so we don't have to worry about the function changing
|
||||
// our reference copy.
|
||||
$result = file_copy(clone $source, $target->getFileUri(), FILE_EXISTS_ERROR);
|
||||
|
||||
// Check the return status and that the contents were not changed.
|
||||
$this->assertFalse($result, 'File copy failed.');
|
||||
$this->assertEqual($contents, file_get_contents($target->getFileUri()), 'Contents of file were not altered.');
|
||||
|
||||
// Check that the correct hooks were called.
|
||||
$this->assertFileHooksCalled(array());
|
||||
|
||||
$this->assertFileUnchanged($source, file_load($source->id(), TRUE));
|
||||
$this->assertFileUnchanged($target, file_load($target->id(), TRUE));
|
||||
}
|
||||
}
|
74
core/modules/file/src/Tests/DeleteTest.php
Normal file
74
core/modules/file/src/Tests/DeleteTest.php
Normal file
|
@ -0,0 +1,74 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains \Drupal\file\Tests\DeleteTest.
|
||||
*/
|
||||
|
||||
namespace Drupal\file\Tests;
|
||||
|
||||
/**
|
||||
* Tests the file delete function.
|
||||
*
|
||||
* @group file
|
||||
*/
|
||||
class DeleteTest extends FileManagedUnitTestBase {
|
||||
/**
|
||||
* Tries deleting a normal file (as opposed to a directory, symlink, etc).
|
||||
*/
|
||||
function testUnused() {
|
||||
$file = $this->createFile();
|
||||
|
||||
// Check that deletion removes the file and database record.
|
||||
$this->assertTrue(is_file($file->getFileUri()), 'File exists.');
|
||||
$file->delete();
|
||||
$this->assertFileHooksCalled(array('delete'));
|
||||
$this->assertFalse(file_exists($file->getFileUri()), 'Test file has actually been deleted.');
|
||||
$this->assertFalse(file_load($file->id()), 'File was removed from the database.');
|
||||
}
|
||||
|
||||
/**
|
||||
* Tries deleting a file that is in use.
|
||||
*/
|
||||
function testInUse() {
|
||||
$file = $this->createFile();
|
||||
$file_usage = $this->container->get('file.usage');
|
||||
$file_usage->add($file, 'testing', 'test', 1);
|
||||
$file_usage->add($file, 'testing', 'test', 1);
|
||||
|
||||
$file_usage->delete($file, 'testing', 'test', 1);
|
||||
$usage = $file_usage->listUsage($file);
|
||||
$this->assertEqual($usage['testing']['test'], array(1 => 1), 'Test file is still in use.');
|
||||
$this->assertTrue(file_exists($file->getFileUri()), 'File still exists on the disk.');
|
||||
$this->assertTrue(file_load($file->id()), 'File still exists in the database.');
|
||||
|
||||
// Clear out the call to hook_file_load().
|
||||
file_test_reset();
|
||||
|
||||
$file_usage->delete($file, 'testing', 'test', 1);
|
||||
$usage = $file_usage->listUsage($file);
|
||||
$this->assertFileHooksCalled(array('load', 'update'));
|
||||
$this->assertTrue(empty($usage), 'File usage data was removed.');
|
||||
$this->assertTrue(file_exists($file->getFileUri()), 'File still exists on the disk.');
|
||||
$file = file_load($file->id());
|
||||
$this->assertTrue($file, 'File still exists in the database.');
|
||||
$this->assertTrue($file->isTemporary(), 'File is temporary.');
|
||||
file_test_reset();
|
||||
|
||||
// Call file_cron() to clean up the file. Make sure the changed timestamp
|
||||
// of the file is older than the system.file.temporary_maximum_age
|
||||
// configuration value.
|
||||
db_update('file_managed')
|
||||
->fields(array(
|
||||
'changed' => REQUEST_TIME - ($this->config('system.file')->get('temporary_maximum_age') + 1),
|
||||
))
|
||||
->condition('fid', $file->id())
|
||||
->execute();
|
||||
\Drupal::service('cron')->run();
|
||||
|
||||
// file_cron() loads
|
||||
$this->assertFileHooksCalled(array('delete'));
|
||||
$this->assertFalse(file_exists($file->getFileUri()), 'File has been deleted after its last usage was removed.');
|
||||
$this->assertFalse(file_load($file->id()), 'File was removed from the database.');
|
||||
}
|
||||
}
|
167
core/modules/file/src/Tests/DownloadTest.php
Normal file
167
core/modules/file/src/Tests/DownloadTest.php
Normal file
|
@ -0,0 +1,167 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains \Drupal\file\Tests\DownloadTest.
|
||||
*/
|
||||
|
||||
namespace Drupal\file\Tests;
|
||||
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
|
||||
/**
|
||||
* Tests for download/file transfer functions.
|
||||
*
|
||||
* @group file
|
||||
*/
|
||||
class DownloadTest extends FileManagedTestBase {
|
||||
protected function setUp() {
|
||||
parent::setUp();
|
||||
// Clear out any hook calls.
|
||||
file_test_reset();
|
||||
}
|
||||
|
||||
/**
|
||||
* Test the public file transfer system.
|
||||
*/
|
||||
function testPublicFileTransfer() {
|
||||
// Test generating an URL to a created file.
|
||||
$file = $this->createFile();
|
||||
$url = file_create_url($file->getFileUri());
|
||||
// URLs can't contain characters outside the ASCII set so $filename has to be
|
||||
// encoded.
|
||||
$filename = $GLOBALS['base_url'] . '/' . file_stream_wrapper_get_instance_by_scheme('public')->getDirectoryPath() . '/' . rawurlencode($file->getFilename());
|
||||
$this->assertEqual($filename, $url, 'Correctly generated a URL for a created file.');
|
||||
$this->drupalHead($url);
|
||||
$this->assertResponse(200, 'Confirmed that the generated URL is correct by downloading the created file.');
|
||||
|
||||
// Test generating an URL to a shipped file (i.e. a file that is part of
|
||||
// Drupal core, a module or a theme, for example a JavaScript file).
|
||||
$filepath = 'core/assets/vendor/jquery/jquery.min.js';
|
||||
$url = file_create_url($filepath);
|
||||
$this->assertEqual($GLOBALS['base_url'] . '/' . $filepath, $url, 'Correctly generated a URL for a shipped file.');
|
||||
$this->drupalHead($url);
|
||||
$this->assertResponse(200, 'Confirmed that the generated URL is correct by downloading the shipped file.');
|
||||
}
|
||||
|
||||
/**
|
||||
* Test the private file transfer system.
|
||||
*/
|
||||
public function testPrivateFileTransferWithoutPageCache() {
|
||||
$this->doPrivateFileTransferTest();
|
||||
}
|
||||
|
||||
/**
|
||||
* Test the private file transfer system.
|
||||
*/
|
||||
protected function doPrivateFileTransferTest() {
|
||||
// Set file downloads to private so handler functions get called.
|
||||
|
||||
// Create a file.
|
||||
$contents = $this->randomMachineName(8);
|
||||
$file = $this->createFile(NULL, $contents, 'private');
|
||||
// Created private files without usage are by default not accessible
|
||||
// for a user different from the owner, but createFile always uses uid 1
|
||||
// as the owner of the files. Therefore make it permanent to allow access
|
||||
// if a module allows it.
|
||||
$file->setPermanent();
|
||||
$file->save();
|
||||
|
||||
$url = file_create_url($file->getFileUri());
|
||||
|
||||
// Set file_test access header to allow the download.
|
||||
file_test_set_return('download', array('x-foo' => 'Bar'));
|
||||
$this->drupalGet($url);
|
||||
$this->assertEqual($this->drupalGetHeader('x-foo'), 'Bar', 'Found header set by file_test module on private download.');
|
||||
$this->assertFalse($this->drupalGetHeader('x-drupal-cache'), 'Page cache is disabled on private file download.');
|
||||
$this->assertResponse(200, 'Correctly allowed access to a file when file_test provides headers.');
|
||||
|
||||
// Test that the file transferred correctly.
|
||||
$this->assertEqual($contents, $this->content, 'Contents of the file are correct.');
|
||||
|
||||
// Deny access to all downloads via a -1 header.
|
||||
file_test_set_return('download', -1);
|
||||
$this->drupalHead($url);
|
||||
$this->assertResponse(403, 'Correctly denied access to a file when file_test sets the header to -1.');
|
||||
|
||||
// Try non-existent file.
|
||||
$url = file_create_url('private://' . $this->randomMachineName());
|
||||
$this->drupalHead($url);
|
||||
$this->assertResponse(404, 'Correctly returned 404 response for a non-existent file.');
|
||||
}
|
||||
|
||||
/**
|
||||
* Test file_create_url().
|
||||
*/
|
||||
function testFileCreateUrl() {
|
||||
|
||||
// Tilde (~) is excluded from this test because it is encoded by
|
||||
// rawurlencode() in PHP 5.2 but not in PHP 5.3, as per RFC 3986.
|
||||
// @see http://www.php.net/manual/function.rawurlencode.php#86506
|
||||
$basename = " -._!$'\"()*@[]?&+%#,;=:\n\x00" . // "Special" ASCII characters.
|
||||
"%23%25%26%2B%2F%3F" . // Characters that look like a percent-escaped string.
|
||||
"éøïвβ中國書۞"; // Characters from various non-ASCII alphabets.
|
||||
$basename_encoded = '%20-._%21%24%27%22%28%29%2A%40%5B%5D%3F%26%2B%25%23%2C%3B%3D%3A__' .
|
||||
'%2523%2525%2526%252B%252F%253F' .
|
||||
'%C3%A9%C3%B8%C3%AF%D0%B2%CE%B2%E4%B8%AD%E5%9C%8B%E6%9B%B8%DB%9E';
|
||||
|
||||
// Public files should not be served by Drupal, so their URLs should not be
|
||||
// routed through Drupal, whereas private files should be served by Drupal,
|
||||
// so they need to be. The difference is most apparent when $script_path
|
||||
// is not empty (i.e., when not using clean URLs).
|
||||
$clean_url_settings = array(
|
||||
'clean' => '',
|
||||
'unclean' => 'index.php/',
|
||||
);
|
||||
foreach ($clean_url_settings as $clean_url_setting => $script_path) {
|
||||
$clean_urls = $clean_url_setting == 'clean';
|
||||
$request = $this->prepareRequestForGenerator($clean_urls);
|
||||
$base_path = $request->getSchemeAndHttpHost() . $request->getBasePath();
|
||||
$this->checkUrl('public', '', $basename, $base_path . '/' . file_stream_wrapper_get_instance_by_scheme('public')->getDirectoryPath() . '/' . $basename_encoded);
|
||||
$this->checkUrl('private', '', $basename, $base_path . '/' . $script_path . 'system/files/' . $basename_encoded);
|
||||
}
|
||||
$this->assertEqual(file_create_url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAHElEQVQI12P4//8/w38GIAXDIBKE0DHxgljNBAAO9TXL0Y4OHwAAAABJRU5ErkJggg=='), 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAHElEQVQI12P4//8/w38GIAXDIBKE0DHxgljNBAAO9TXL0Y4OHwAAAABJRU5ErkJggg==', t('Generated URL matches expected URL.'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Download a file from the URL generated by file_create_url().
|
||||
*
|
||||
* Create a file with the specified scheme, directory and filename; check that
|
||||
* the URL generated by file_create_url() for the specified file equals the
|
||||
* specified URL; fetch the URL and then compare the contents to the file.
|
||||
*
|
||||
* @param string $scheme
|
||||
* A scheme, e.g. "public".
|
||||
* @param string $directory
|
||||
* A directory, possibly "".
|
||||
* @param string $filename
|
||||
* A filename.
|
||||
* @param string $expected_url
|
||||
* The expected URL.
|
||||
*/
|
||||
private function checkUrl($scheme, $directory, $filename, $expected_url) {
|
||||
// Convert $filename to a valid filename, i.e. strip characters not
|
||||
// supported by the filesystem, and create the file in the specified
|
||||
// directory.
|
||||
$filepath = file_create_filename($filename, $directory);
|
||||
$directory_uri = $scheme . '://' . dirname($filepath);
|
||||
file_prepare_directory($directory_uri, FILE_CREATE_DIRECTORY);
|
||||
$file = $this->createFile($filepath, NULL, $scheme);
|
||||
|
||||
$url = file_create_url($file->getFileUri());
|
||||
$this->assertEqual($url, $expected_url);
|
||||
|
||||
if ($scheme == 'private') {
|
||||
// Tell the implementation of hook_file_download() in file_test.module
|
||||
// that this file may be downloaded.
|
||||
file_test_set_return('download', array('x-foo' => 'Bar'));
|
||||
}
|
||||
|
||||
$this->drupalGet($url);
|
||||
if ($this->assertResponse(200) == 'pass') {
|
||||
$this->assertRaw(file_get_contents($file->getFileUri()), 'Contents of the file are correct.');
|
||||
}
|
||||
|
||||
$file->delete();
|
||||
}
|
||||
}
|
163
core/modules/file/src/Tests/FileFieldDisplayTest.php
Normal file
163
core/modules/file/src/Tests/FileFieldDisplayTest.php
Normal file
|
@ -0,0 +1,163 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains \Drupal\file\Tests\FileFieldDisplayTest.
|
||||
*/
|
||||
|
||||
namespace Drupal\file\Tests;
|
||||
|
||||
use Drupal\Core\Field\FieldStorageDefinitionInterface;
|
||||
|
||||
/**
|
||||
* Tests the display of file fields in node and views.
|
||||
*
|
||||
* @group file
|
||||
*/
|
||||
class FileFieldDisplayTest extends FileFieldTestBase {
|
||||
|
||||
/**
|
||||
* Tests normal formatter display on node display.
|
||||
*/
|
||||
function testNodeDisplay() {
|
||||
$field_name = strtolower($this->randomMachineName());
|
||||
$type_name = 'article';
|
||||
$field_storage_settings = array(
|
||||
'display_field' => '1',
|
||||
'display_default' => '1',
|
||||
'cardinality' => FieldStorageDefinitionInterface::CARDINALITY_UNLIMITED,
|
||||
);
|
||||
$field_settings = array(
|
||||
'description_field' => '1',
|
||||
);
|
||||
$widget_settings = array();
|
||||
$this->createFileField($field_name, 'node', $type_name, $field_storage_settings, $field_settings, $widget_settings);
|
||||
|
||||
// Create a new node *without* the file field set, and check that the field
|
||||
// is not shown for each node display.
|
||||
$node = $this->drupalCreateNode(array('type' => $type_name));
|
||||
// Check file_default last as the assertions below assume that this is the
|
||||
// case.
|
||||
$file_formatters = array('file_table', 'file_url_plain', 'hidden', 'file_default');
|
||||
foreach ($file_formatters as $formatter) {
|
||||
$edit = array(
|
||||
"fields[$field_name][type]" => $formatter,
|
||||
);
|
||||
$this->drupalPostForm("admin/structure/types/manage/$type_name/display", $edit, t('Save'));
|
||||
$this->drupalGet('node/' . $node->id());
|
||||
$this->assertNoText($field_name, format_string('Field label is hidden when no file attached for formatter %formatter', array('%formatter' => $formatter)));
|
||||
}
|
||||
|
||||
$test_file = $this->getTestFile('text');
|
||||
|
||||
// Create a new node with the uploaded file.
|
||||
$nid = $this->uploadNodeFile($test_file, $field_name, $type_name);
|
||||
|
||||
// Check that the default formatter is displaying with the file name.
|
||||
$node_storage = $this->container->get('entity.manager')->getStorage('node');
|
||||
$node_storage->resetCache(array($nid));
|
||||
$node = $node_storage->load($nid);
|
||||
$node_file = file_load($node->{$field_name}->target_id);
|
||||
$file_link = array(
|
||||
'#theme' => 'file_link',
|
||||
'#file' => $node_file,
|
||||
);
|
||||
$default_output = \Drupal::service('renderer')->renderRoot($file_link);
|
||||
$this->assertRaw($default_output, 'Default formatter displaying correctly on full node view.');
|
||||
|
||||
// Turn the "display" option off and check that the file is no longer displayed.
|
||||
$edit = array($field_name . '[0][display]' => FALSE);
|
||||
$this->drupalPostForm('node/' . $nid . '/edit', $edit, t('Save and keep published'));
|
||||
|
||||
$this->assertNoRaw($default_output, 'Field is hidden when "display" option is unchecked.');
|
||||
|
||||
// Add a description and make sure that it is displayed.
|
||||
$description = $this->randomMachineName();
|
||||
$edit = array(
|
||||
$field_name . '[0][description]' => $description,
|
||||
$field_name . '[0][display]' => TRUE,
|
||||
);
|
||||
$this->drupalPostForm('node/' . $nid . '/edit', $edit, t('Save and keep published'));
|
||||
$this->assertText($description);
|
||||
|
||||
// Test that fields appear as expected after during the preview.
|
||||
// Add a second file.
|
||||
$name = 'files[' . $field_name . '_1][]';
|
||||
$edit[$name] = drupal_realpath($test_file->getFileUri());
|
||||
|
||||
// Uncheck the display checkboxes and go to the preview.
|
||||
$edit[$field_name . '[0][display]'] = FALSE;
|
||||
$edit[$field_name . '[1][display]'] = FALSE;
|
||||
$this->drupalPostForm("node/$nid/edit", $edit, t('Preview'));
|
||||
$this->clickLink(t('Back to content editing'));
|
||||
$this->assertRaw($field_name . '[0][display]', 'First file appears as expected.');
|
||||
$this->assertRaw($field_name . '[1][display]', 'Second file appears as expected.');
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests default display of File Field.
|
||||
*/
|
||||
function testDefaultFileFieldDisplay() {
|
||||
$field_name = strtolower($this->randomMachineName());
|
||||
$type_name = 'article';
|
||||
$field_storage_settings = array(
|
||||
'display_field' => '1',
|
||||
'display_default' => '0',
|
||||
'cardinality' => FieldStorageDefinitionInterface::CARDINALITY_UNLIMITED,
|
||||
);
|
||||
$field_settings = array(
|
||||
'description_field' => '1',
|
||||
);
|
||||
$widget_settings = array();
|
||||
$this->createFileField($field_name, 'node', $type_name, $field_storage_settings, $field_settings, $widget_settings);
|
||||
|
||||
$test_file = $this->getTestFile('text');
|
||||
|
||||
// Create a new node with the uploaded file.
|
||||
$nid = $this->uploadNodeFile($test_file, $field_name, $type_name);
|
||||
|
||||
$this->drupalGet('node/' . $nid . '/edit');
|
||||
$this->assertFieldByXPath('//input[@type="checkbox" and @name="' . $field_name . '[0][display]"]', NULL, 'Default file display checkbox field exists.');
|
||||
$this->assertFieldByXPath('//input[@type="checkbox" and @name="' . $field_name . '[0][display]" and not(@checked)]', NULL, 'Default file display is off.');
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests description toggle for field instance configuration.
|
||||
*/
|
||||
function testDescToggle() {
|
||||
$type_name = 'test';
|
||||
$field_type = 'file';
|
||||
$field_name = strtolower($this->randomMachineName());
|
||||
// Use the UI to add a new content type that also contains a file field.
|
||||
$edit = array(
|
||||
'name' => $type_name,
|
||||
'type' => $type_name,
|
||||
);
|
||||
$this->drupalPostForm('admin/structure/types/add', $edit, t('Save and manage fields'));
|
||||
$edit = array(
|
||||
'new_storage_type' => $field_type,
|
||||
'field_name' => $field_name,
|
||||
'label' => $this->randomString(),
|
||||
);
|
||||
$this->drupalPostForm('/admin/structure/types/manage/' . $type_name . '/fields/add-field', $edit, t('Save and continue'));
|
||||
$this->drupalPostForm(NULL, array(), t('Save field settings'));
|
||||
// Ensure the description field is selected on the field instance settings
|
||||
// form. That's what this test is all about.
|
||||
$edit = array(
|
||||
'settings[description_field]' => TRUE,
|
||||
);
|
||||
$this->drupalPostForm(NULL, $edit, t('Save settings'));
|
||||
// Add a node of our new type and upload a file to it.
|
||||
$file = current($this->drupalGetTestFiles('text'));
|
||||
$title = $this->randomString();
|
||||
$edit = array(
|
||||
'title[0][value]' => $title,
|
||||
'files[field_' . $field_name . '_0]' => drupal_realpath($file->uri),
|
||||
);
|
||||
$this->drupalPostForm('node/add/' . $type_name, $edit, t('Save and publish'));
|
||||
$node = $this->drupalGetNodeByTitle($title);
|
||||
$this->drupalGet('node/' . $node->id() . '/edit');
|
||||
$this->assertText(t('The description may be used as the label of the link to the file.'));
|
||||
}
|
||||
|
||||
}
|
38
core/modules/file/src/Tests/FileFieldFormatterAccessTest.php
Normal file
38
core/modules/file/src/Tests/FileFieldFormatterAccessTest.php
Normal file
|
@ -0,0 +1,38 @@
|
|||
<?php
|
||||
/**
|
||||
* @file
|
||||
* Contains \Drupal\file\Tests\FileFieldFormatterAccessTest.
|
||||
*/
|
||||
|
||||
namespace Drupal\file\Tests;
|
||||
|
||||
|
||||
/**
|
||||
* Tests file formatter access.
|
||||
* @group file
|
||||
*/
|
||||
class FileFieldFormatterAccessTest extends FileFieldTestBase {
|
||||
|
||||
/**
|
||||
* Modules to enable.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public static $modules = ['node', 'file', 'field_ui', 'file_test'];
|
||||
|
||||
/**
|
||||
* Tests the custom access handler is invoked.
|
||||
*/
|
||||
public function testFileAccessHandler() {
|
||||
$type_name = 'article';
|
||||
$field_name = strtolower($this->randomMachineName());
|
||||
$this->createFileField($field_name, 'node', $type_name);
|
||||
\Drupal::state()->set('file_test_alternate_access_handler', TRUE);
|
||||
\Drupal::entityManager()->clearCachedDefinitions();
|
||||
$test_file = $this->getTestFile('text');
|
||||
$nid = $this->uploadNodeFile($test_file, $field_name, $type_name);
|
||||
$this->drupalGet('node/' . $nid);
|
||||
$this->assertTrue(\Drupal::state()->get('file_access_formatter_check', FALSE));
|
||||
}
|
||||
|
||||
}
|
86
core/modules/file/src/Tests/FileFieldPathTest.php
Normal file
86
core/modules/file/src/Tests/FileFieldPathTest.php
Normal file
|
@ -0,0 +1,86 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains \Drupal\file\Tests\FileFieldPathTest.
|
||||
*/
|
||||
|
||||
namespace Drupal\file\Tests;
|
||||
|
||||
/**
|
||||
* Tests that files are uploaded to proper locations.
|
||||
*
|
||||
* @group file
|
||||
*/
|
||||
class FileFieldPathTest extends FileFieldTestBase {
|
||||
/**
|
||||
* Tests the normal formatter display on node display.
|
||||
*/
|
||||
function testUploadPath() {
|
||||
$node_storage = $this->container->get('entity.manager')->getStorage('node');
|
||||
$field_name = strtolower($this->randomMachineName());
|
||||
$type_name = 'article';
|
||||
$this->createFileField($field_name, 'node', $type_name);
|
||||
$test_file = $this->getTestFile('text');
|
||||
|
||||
// Create a new node.
|
||||
$nid = $this->uploadNodeFile($test_file, $field_name, $type_name);
|
||||
|
||||
// Check that the file was uploaded to the file root.
|
||||
$node_storage->resetCache(array($nid));
|
||||
$node = $node_storage->load($nid);
|
||||
$node_file = file_load($node->{$field_name}->target_id);
|
||||
$this->assertPathMatch('public://' . $test_file->getFilename(), $node_file->getFileUri(), format_string('The file %file was uploaded to the correct path.', array('%file' => $node_file->getFileUri())));
|
||||
|
||||
// Change the path to contain multiple subdirectories.
|
||||
$this->updateFileField($field_name, $type_name, array('file_directory' => 'foo/bar/baz'));
|
||||
|
||||
// Upload a new file into the subdirectories.
|
||||
$nid = $this->uploadNodeFile($test_file, $field_name, $type_name);
|
||||
|
||||
// Check that the file was uploaded into the subdirectory.
|
||||
$node_storage->resetCache(array($nid));
|
||||
$node = $node_storage->load($nid);
|
||||
$node_file = file_load($node->{$field_name}->target_id, TRUE);
|
||||
$this->assertPathMatch('public://foo/bar/baz/' . $test_file->getFilename(), $node_file->getFileUri(), format_string('The file %file was uploaded to the correct path.', array('%file' => $node_file->getFileUri())));
|
||||
|
||||
// Check the path when used with tokens.
|
||||
// Change the path to contain multiple token directories.
|
||||
$this->updateFileField($field_name, $type_name, array('file_directory' => '[current-user:uid]/[current-user:name]'));
|
||||
|
||||
// Upload a new file into the token subdirectories.
|
||||
$nid = $this->uploadNodeFile($test_file, $field_name, $type_name);
|
||||
|
||||
// Check that the file was uploaded into the subdirectory.
|
||||
$node_storage->resetCache(array($nid));
|
||||
$node = $node_storage->load($nid);
|
||||
$node_file = file_load($node->{$field_name}->target_id);
|
||||
// Do token replacement using the same user which uploaded the file, not
|
||||
// the user running the test case.
|
||||
$data = array('user' => $this->adminUser);
|
||||
$subdirectory = \Drupal::token()->replace('[user:uid]/[user:name]', $data);
|
||||
$this->assertPathMatch('public://' . $subdirectory . '/' . $test_file->getFilename(), $node_file->getFileUri(), format_string('The file %file was uploaded to the correct path with token replacements.', array('%file' => $node_file->getFileUri())));
|
||||
}
|
||||
|
||||
/**
|
||||
* Asserts that a file is uploaded to the right location.
|
||||
*
|
||||
* @param string $expected_path
|
||||
* The location where the file is expected to be uploaded. Duplicate file
|
||||
* names to not need to be taken into account.
|
||||
* @param string $actual_path
|
||||
* Where the file was actually uploaded.
|
||||
* @param string $message
|
||||
* The message to display with this assertion.
|
||||
*/
|
||||
function assertPathMatch($expected_path, $actual_path, $message) {
|
||||
// Strip off the extension of the expected path to allow for _0, _1, etc.
|
||||
// suffixes when the file hits a duplicate name.
|
||||
$pos = strrpos($expected_path, '.');
|
||||
$base_path = substr($expected_path, 0, $pos);
|
||||
$extension = substr($expected_path, $pos + 1);
|
||||
|
||||
$result = preg_match('/' . preg_quote($base_path, '/') . '(_[0-9]+)?\.' . preg_quote($extension, '/') . '/', $actual_path);
|
||||
$this->assertTrue($result, $message);
|
||||
}
|
||||
}
|
79
core/modules/file/src/Tests/FileFieldRSSContentTest.php
Normal file
79
core/modules/file/src/Tests/FileFieldRSSContentTest.php
Normal file
|
@ -0,0 +1,79 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains \Drupal\file\Tests\FileFieldRSSContentTest.
|
||||
*/
|
||||
|
||||
namespace Drupal\file\Tests;
|
||||
|
||||
use Drupal\node\Entity\Node;
|
||||
|
||||
/**
|
||||
* Ensure that files added to nodes appear correctly in RSS feeds.
|
||||
*
|
||||
* @group file
|
||||
*/
|
||||
class FileFieldRSSContentTest extends FileFieldTestBase {
|
||||
|
||||
/**
|
||||
* Modules to enable.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public static $modules = array('node', 'views');
|
||||
|
||||
/**
|
||||
* Tests RSS enclosure formatter display for RSS feeds.
|
||||
*/
|
||||
function testFileFieldRSSContent() {
|
||||
$node_storage = $this->container->get('entity.manager')->getStorage('node');
|
||||
$field_name = strtolower($this->randomMachineName());
|
||||
$type_name = 'article';
|
||||
$field_settings = array(
|
||||
'display_field' => '1',
|
||||
'display_default' => '1',
|
||||
);
|
||||
$field_settings = array(
|
||||
'description_field' => '1',
|
||||
);
|
||||
$widget_settings = array();
|
||||
$this->createFileField($field_name, 'node', $type_name, $field_settings, $field_settings, $widget_settings);
|
||||
|
||||
// RSS display must be added manually.
|
||||
$this->drupalGet("admin/structure/types/manage/$type_name/display");
|
||||
$edit = array(
|
||||
"display_modes_custom[rss]" => '1',
|
||||
);
|
||||
$this->drupalPostForm(NULL, $edit, t('Save'));
|
||||
|
||||
// Change the format to 'RSS enclosure'.
|
||||
$this->drupalGet("admin/structure/types/manage/$type_name/display/rss");
|
||||
$edit = array("fields[$field_name][type]" => 'file_rss_enclosure');
|
||||
$this->drupalPostForm(NULL, $edit, t('Save'));
|
||||
|
||||
// Create a new node with a file field set. Promote to frontpage
|
||||
// needs to be set so this node will appear in the RSS feed.
|
||||
$node = $this->drupalCreateNode(array('type' => $type_name, 'promote' => 1));
|
||||
$test_file = $this->getTestFile('text');
|
||||
|
||||
// Create a new node with the uploaded file.
|
||||
$nid = $this->uploadNodeFile($test_file, $field_name, $node->id());
|
||||
|
||||
// Get the uploaded file from the node.
|
||||
$node_storage->resetCache(array($nid));
|
||||
$node = $node_storage->load($nid);
|
||||
$node_file = file_load($node->{$field_name}->target_id);
|
||||
|
||||
// Check that the RSS enclosure appears in the RSS feed.
|
||||
$this->drupalGet('rss.xml');
|
||||
$uploaded_filename = str_replace('public://', '', $node_file->getFileUri());
|
||||
$test_element = sprintf(
|
||||
'<enclosure url="%s" length="%s" type="%s" />',
|
||||
file_create_url("public://$uploaded_filename", array('absolute' => TRUE)),
|
||||
$node_file->getSize(),
|
||||
$node_file->getMimeType()
|
||||
);
|
||||
$this->assertRaw($test_element, 'File field RSS enclosure is displayed when viewing the RSS feed.');
|
||||
}
|
||||
}
|
144
core/modules/file/src/Tests/FileFieldRevisionTest.php
Normal file
144
core/modules/file/src/Tests/FileFieldRevisionTest.php
Normal file
|
@ -0,0 +1,144 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains \Drupal\file\Tests\FileFieldRevisionTest.
|
||||
*/
|
||||
|
||||
namespace Drupal\file\Tests;
|
||||
|
||||
/**
|
||||
* Tests creating and deleting revisions with files attached.
|
||||
*
|
||||
* @group file
|
||||
*/
|
||||
class FileFieldRevisionTest extends FileFieldTestBase {
|
||||
/**
|
||||
* Tests creating multiple revisions of a node and managing attached files.
|
||||
*
|
||||
* Expected behaviors:
|
||||
* - Adding a new revision will make another entry in the field table, but
|
||||
* the original file will not be duplicated.
|
||||
* - Deleting a revision should not delete the original file if the file
|
||||
* is in use by another revision.
|
||||
* - When the last revision that uses a file is deleted, the original file
|
||||
* should be deleted also.
|
||||
*/
|
||||
function testRevisions() {
|
||||
$node_storage = $this->container->get('entity.manager')->getStorage('node');
|
||||
$type_name = 'article';
|
||||
$field_name = strtolower($this->randomMachineName());
|
||||
$this->createFileField($field_name, 'node', $type_name);
|
||||
// Create the same fields for users.
|
||||
$this->createFileField($field_name, 'user', 'user');
|
||||
|
||||
$test_file = $this->getTestFile('text');
|
||||
|
||||
// Create a new node with the uploaded file.
|
||||
$nid = $this->uploadNodeFile($test_file, $field_name, $type_name);
|
||||
|
||||
// Check that the file exists on disk and in the database.
|
||||
$node_storage->resetCache(array($nid));
|
||||
$node = $node_storage->load($nid);
|
||||
$node_file_r1 = file_load($node->{$field_name}->target_id);
|
||||
$node_vid_r1 = $node->getRevisionId();
|
||||
$this->assertFileExists($node_file_r1, 'New file saved to disk on node creation.');
|
||||
$this->assertFileEntryExists($node_file_r1, 'File entry exists in database on node creation.');
|
||||
$this->assertFileIsPermanent($node_file_r1, 'File is permanent.');
|
||||
|
||||
// Upload another file to the same node in a new revision.
|
||||
$this->replaceNodeFile($test_file, $field_name, $nid);
|
||||
$node_storage->resetCache(array($nid));
|
||||
$node = $node_storage->load($nid);
|
||||
$node_file_r2 = file_load($node->{$field_name}->target_id);
|
||||
$node_vid_r2 = $node->getRevisionId();
|
||||
$this->assertFileExists($node_file_r2, 'Replacement file exists on disk after creating new revision.');
|
||||
$this->assertFileEntryExists($node_file_r2, 'Replacement file entry exists in database after creating new revision.');
|
||||
$this->assertFileIsPermanent($node_file_r2, 'Replacement file is permanent.');
|
||||
|
||||
// Check that the original file is still in place on the first revision.
|
||||
$node = node_revision_load($node_vid_r1);
|
||||
$current_file = file_load($node->{$field_name}->target_id);
|
||||
$this->assertEqual($node_file_r1->id(), $current_file->id(), 'Original file still in place after replacing file in new revision.');
|
||||
$this->assertFileExists($node_file_r1, 'Original file still in place after replacing file in new revision.');
|
||||
$this->assertFileEntryExists($node_file_r1, 'Original file entry still in place after replacing file in new revision');
|
||||
$this->assertFileIsPermanent($node_file_r1, 'Original file is still permanent.');
|
||||
|
||||
// Save a new version of the node without any changes.
|
||||
// Check that the file is still the same as the previous revision.
|
||||
$this->drupalPostForm('node/' . $nid . '/edit', array('revision' => '1'), t('Save and keep published'));
|
||||
$node_storage->resetCache(array($nid));
|
||||
$node = $node_storage->load($nid);
|
||||
$node_file_r3 = file_load($node->{$field_name}->target_id);
|
||||
$node_vid_r3 = $node->getRevisionId();
|
||||
$this->assertEqual($node_file_r2->id(), $node_file_r3->id(), 'Previous revision file still in place after creating a new revision without a new file.');
|
||||
$this->assertFileIsPermanent($node_file_r3, 'New revision file is permanent.');
|
||||
|
||||
// Revert to the first revision and check that the original file is active.
|
||||
$this->drupalPostForm('node/' . $nid . '/revisions/' . $node_vid_r1 . '/revert', array(), t('Revert'));
|
||||
$node_storage->resetCache(array($nid));
|
||||
$node = $node_storage->load($nid);
|
||||
$node_file_r4 = file_load($node->{$field_name}->target_id);
|
||||
$this->assertEqual($node_file_r1->id(), $node_file_r4->id(), 'Original revision file still in place after reverting to the original revision.');
|
||||
$this->assertFileIsPermanent($node_file_r4, 'Original revision file still permanent after reverting to the original revision.');
|
||||
|
||||
// Delete the second revision and check that the file is kept (since it is
|
||||
// still being used by the third revision).
|
||||
$this->drupalPostForm('node/' . $nid . '/revisions/' . $node_vid_r2 . '/delete', array(), t('Delete'));
|
||||
$this->assertFileExists($node_file_r3, 'Second file is still available after deleting second revision, since it is being used by the third revision.');
|
||||
$this->assertFileEntryExists($node_file_r3, 'Second file entry is still available after deleting second revision, since it is being used by the third revision.');
|
||||
$this->assertFileIsPermanent($node_file_r3, 'Second file entry is still permanent after deleting second revision, since it is being used by the third revision.');
|
||||
|
||||
// Attach the second file to a user.
|
||||
$user = $this->drupalCreateUser();
|
||||
$user->$field_name->target_id = $node_file_r3->id();
|
||||
$user->$field_name->display = 1;
|
||||
$user->save();
|
||||
$this->drupalGet('user/' . $user->id() . '/edit');
|
||||
|
||||
// Delete the third revision and check that the file is not deleted yet.
|
||||
$this->drupalPostForm('node/' . $nid . '/revisions/' . $node_vid_r3 . '/delete', array(), t('Delete'));
|
||||
$this->assertFileExists($node_file_r3, 'Second file is still available after deleting third revision, since it is being used by the user.');
|
||||
$this->assertFileEntryExists($node_file_r3, 'Second file entry is still available after deleting third revision, since it is being used by the user.');
|
||||
$this->assertFileIsPermanent($node_file_r3, 'Second file entry is still permanent after deleting third revision, since it is being used by the user.');
|
||||
|
||||
// Delete the user and check that the file is also deleted.
|
||||
$user->delete();
|
||||
// TODO: This seems like a bug in File API. Clearing the stat cache should
|
||||
// not be necessary here. The file really is deleted, but stream wrappers
|
||||
// doesn't seem to think so unless we clear the PHP file stat() cache.
|
||||
clearstatcache($node_file_r1->getFileUri());
|
||||
clearstatcache($node_file_r2->getFileUri());
|
||||
clearstatcache($node_file_r3->getFileUri());
|
||||
clearstatcache($node_file_r4->getFileUri());
|
||||
|
||||
// Call file_cron() to clean up the file. Make sure the changed timestamp
|
||||
// of the file is older than the system.file.temporary_maximum_age
|
||||
// configuration value.
|
||||
db_update('file_managed')
|
||||
->fields(array(
|
||||
'changed' => REQUEST_TIME - ($this->config('system.file')->get('temporary_maximum_age') + 1),
|
||||
))
|
||||
->condition('fid', $node_file_r3->id())
|
||||
->execute();
|
||||
\Drupal::service('cron')->run();
|
||||
|
||||
$this->assertFileNotExists($node_file_r3, 'Second file is now deleted after deleting third revision, since it is no longer being used by any other nodes.');
|
||||
$this->assertFileEntryNotExists($node_file_r3, 'Second file entry is now deleted after deleting third revision, since it is no longer being used by any other nodes.');
|
||||
|
||||
// Delete the entire node and check that the original file is deleted.
|
||||
$this->drupalPostForm('node/' . $nid . '/delete', array(), t('Delete'));
|
||||
// Call file_cron() to clean up the file. Make sure the changed timestamp
|
||||
// of the file is older than the system.file.temporary_maximum_age
|
||||
// configuration value.
|
||||
db_update('file_managed')
|
||||
->fields(array(
|
||||
'changed' => REQUEST_TIME - ($this->config('system.file')->get('temporary_maximum_age') + 1),
|
||||
))
|
||||
->condition('fid', $node_file_r1->id())
|
||||
->execute();
|
||||
\Drupal::service('cron')->run();
|
||||
$this->assertFileNotExists($node_file_r1, 'Original file is deleted after deleting the entire node with two revisions remaining.');
|
||||
$this->assertFileEntryNotExists($node_file_r1, 'Original file entry is deleted after deleting the entire node with two revisions remaining.');
|
||||
}
|
||||
}
|
254
core/modules/file/src/Tests/FileFieldTestBase.php
Normal file
254
core/modules/file/src/Tests/FileFieldTestBase.php
Normal file
|
@ -0,0 +1,254 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains \Drupal\file\Tests\FileFieldTestBase.
|
||||
*/
|
||||
|
||||
namespace Drupal\file\Tests;
|
||||
|
||||
use Drupal\field\Entity\FieldStorageConfig;
|
||||
use Drupal\field\Entity\FieldConfig;
|
||||
use Drupal\file\FileInterface;
|
||||
use Drupal\simpletest\WebTestBase;
|
||||
|
||||
/**
|
||||
* Provides methods specifically for testing File module's field handling.
|
||||
*/
|
||||
abstract class FileFieldTestBase extends WebTestBase {
|
||||
|
||||
/**
|
||||
* Modules to enable.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public static $modules = array('node', 'file', 'file_module_test', 'field_ui');
|
||||
|
||||
/**
|
||||
* An user with administration permissions.
|
||||
*
|
||||
* @var \Drupal\user\UserInterface
|
||||
*/
|
||||
protected $adminUser;
|
||||
|
||||
protected function setUp() {
|
||||
parent::setUp();
|
||||
$this->adminUser = $this->drupalCreateUser(array('access content', 'access administration pages', 'administer site configuration', 'administer users', 'administer permissions', 'administer content types', 'administer node fields', 'administer node display', 'administer nodes', 'bypass node access'));
|
||||
$this->drupalLogin($this->adminUser);
|
||||
$this->drupalCreateContentType(array('type' => 'article', 'name' => 'Article'));
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 entity_create('file', (array) $file);
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the fid of the last inserted file.
|
||||
*/
|
||||
function getLastFileId() {
|
||||
return (int) db_query('SELECT MAX(fid) FROM {file_managed}')->fetchField();
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new file field.
|
||||
*
|
||||
* @param string $name
|
||||
* The name of the new field (all lowercase), exclude the "field_" prefix.
|
||||
* @param string $entity_type
|
||||
* The entity type.
|
||||
* @param string $bundle
|
||||
* The bundle that this field will be added to.
|
||||
* @param array $storage_settings
|
||||
* A list of field storage settings that will be added to the defaults.
|
||||
* @param array $field_settings
|
||||
* A list of instance settings that will be added to the instance defaults.
|
||||
* @param array $widget_settings
|
||||
* A list of widget settings that will be added to the widget defaults.
|
||||
*/
|
||||
function createFileField($name, $entity_type, $bundle, $storage_settings = array(), $field_settings = array(), $widget_settings = array()) {
|
||||
$field_storage = entity_create('field_storage_config', array(
|
||||
'entity_type' => $entity_type,
|
||||
'field_name' => $name,
|
||||
'type' => 'file',
|
||||
'settings' => $storage_settings,
|
||||
'cardinality' => !empty($storage_settings['cardinality']) ? $storage_settings['cardinality'] : 1,
|
||||
));
|
||||
$field_storage->save();
|
||||
|
||||
$this->attachFileField($name, $entity_type, $bundle, $field_settings, $widget_settings);
|
||||
return $field_storage;
|
||||
}
|
||||
|
||||
/**
|
||||
* Attaches a file field to an entity.
|
||||
*
|
||||
* @param string $name
|
||||
* The name of the new field (all lowercase), exclude the "field_" prefix.
|
||||
* @param string $entity_type
|
||||
* The entity type this field will be added to.
|
||||
* @param string $bundle
|
||||
* The bundle this field will be added to.
|
||||
* @param array $field_settings
|
||||
* A list of field settings that will be added to the defaults.
|
||||
* @param array $widget_settings
|
||||
* A list of widget settings that will be added to the widget defaults.
|
||||
*/
|
||||
function attachFileField($name, $entity_type, $bundle, $field_settings = array(), $widget_settings = array()) {
|
||||
$field = array(
|
||||
'field_name' => $name,
|
||||
'label' => $name,
|
||||
'entity_type' => $entity_type,
|
||||
'bundle' => $bundle,
|
||||
'required' => !empty($field_settings['required']),
|
||||
'settings' => $field_settings,
|
||||
);
|
||||
entity_create('field_config', $field)->save();
|
||||
|
||||
entity_get_form_display($entity_type, $bundle, 'default')
|
||||
->setComponent($name, array(
|
||||
'type' => 'file_generic',
|
||||
'settings' => $widget_settings,
|
||||
))
|
||||
->save();
|
||||
// Assign display settings.
|
||||
entity_get_display($entity_type, $bundle, 'default')
|
||||
->setComponent($name, array(
|
||||
'label' => 'hidden',
|
||||
'type' => 'file_default',
|
||||
))
|
||||
->save();
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates an existing file field with new settings.
|
||||
*/
|
||||
function updateFileField($name, $type_name, $field_settings = array(), $widget_settings = array()) {
|
||||
$field = FieldConfig::loadByName('node', $type_name, $name);
|
||||
$field->setSettings(array_merge($field->getSettings(), $field_settings));
|
||||
$field->save();
|
||||
|
||||
entity_get_form_display('node', $type_name, 'default')
|
||||
->setComponent($name, array(
|
||||
'settings' => $widget_settings,
|
||||
))
|
||||
->save();
|
||||
}
|
||||
|
||||
/**
|
||||
* Uploads a file to a node.
|
||||
*/
|
||||
function uploadNodeFile($file, $field_name, $nid_or_type, $new_revision = TRUE, $extras = array()) {
|
||||
$edit = array(
|
||||
'title[0][value]' => $this->randomMachineName(),
|
||||
'revision' => (string) (int) $new_revision,
|
||||
);
|
||||
|
||||
if (is_numeric($nid_or_type)) {
|
||||
$nid = $nid_or_type;
|
||||
}
|
||||
else {
|
||||
$node_storage = $this->container->get('entity.manager')->getStorage('node');
|
||||
// Add a new node.
|
||||
$extras['type'] = $nid_or_type;
|
||||
$node = $this->drupalCreateNode($extras);
|
||||
$nid = $node->id();
|
||||
// Save at least one revision to better simulate a real site.
|
||||
$node->setNewRevision();
|
||||
$node->save();
|
||||
$node_storage->resetCache(array($nid));
|
||||
$node = $node_storage->load($nid);
|
||||
$this->assertNotEqual($nid, $node->getRevisionId(), 'Node revision exists.');
|
||||
}
|
||||
|
||||
// Attach a file to the node.
|
||||
$field_storage = FieldStorageConfig::loadByName('node', $field_name);
|
||||
$name = 'files[' . $field_name . '_0]';
|
||||
if ($field_storage->getCardinality() != 1) {
|
||||
$name .= '[]';
|
||||
}
|
||||
$edit[$name] = drupal_realpath($file->getFileUri());
|
||||
$this->drupalPostForm("node/$nid/edit", $edit, t('Save and keep published'));
|
||||
|
||||
return $nid;
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes a file from a node.
|
||||
*
|
||||
* Note that if replacing a file, it must first be removed then added again.
|
||||
*/
|
||||
function removeNodeFile($nid, $new_revision = TRUE) {
|
||||
$edit = array(
|
||||
'revision' => (string) (int) $new_revision,
|
||||
);
|
||||
|
||||
$this->drupalPostForm('node/' . $nid . '/edit', array(), t('Remove'));
|
||||
$this->drupalPostForm(NULL, $edit, t('Save and keep published'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Replaces a file within a node.
|
||||
*/
|
||||
function replaceNodeFile($file, $field_name, $nid, $new_revision = TRUE) {
|
||||
$edit = array(
|
||||
'files[' . $field_name . '_0]' => drupal_realpath($file->getFileUri()),
|
||||
'revision' => (string) (int) $new_revision,
|
||||
);
|
||||
|
||||
$this->drupalPostForm('node/' . $nid . '/edit', array(), t('Remove'));
|
||||
$this->drupalPostForm(NULL, $edit, t('Save and keep published'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Asserts that a file exists physically on disk.
|
||||
*/
|
||||
function assertFileExists($file, $message = NULL) {
|
||||
$message = isset($message) ? $message : format_string('File %file exists on the disk.', array('%file' => $file->getFileUri()));
|
||||
$this->assertTrue(is_file($file->getFileUri()), $message);
|
||||
}
|
||||
|
||||
/**
|
||||
* Asserts that a file exists in the database.
|
||||
*/
|
||||
function assertFileEntryExists($file, $message = NULL) {
|
||||
$this->container->get('entity.manager')->getStorage('file')->resetCache();
|
||||
$db_file = file_load($file->id());
|
||||
$message = isset($message) ? $message : format_string('File %file exists in database at the correct path.', array('%file' => $file->getFileUri()));
|
||||
$this->assertEqual($db_file->getFileUri(), $file->getFileUri(), $message);
|
||||
}
|
||||
|
||||
/**
|
||||
* Asserts that a file does not exist on disk.
|
||||
*/
|
||||
function assertFileNotExists($file, $message = NULL) {
|
||||
$message = isset($message) ? $message : format_string('File %file exists on the disk.', array('%file' => $file->getFileUri()));
|
||||
$this->assertFalse(is_file($file->getFileUri()), $message);
|
||||
}
|
||||
|
||||
/**
|
||||
* Asserts that a file does not exist in the database.
|
||||
*/
|
||||
function assertFileEntryNotExists($file, $message) {
|
||||
$this->container->get('entity.manager')->getStorage('file')->resetCache();
|
||||
$message = isset($message) ? $message : format_string('File %file exists in database at the correct path.', array('%file' => $file->getFileUri()));
|
||||
$this->assertFalse(file_load($file->id()), $message);
|
||||
}
|
||||
|
||||
/**
|
||||
* Asserts that a file's status is set to permanent in the database.
|
||||
*/
|
||||
function assertFileIsPermanent(FileInterface $file, $message = NULL) {
|
||||
$message = isset($message) ? $message : format_string('File %file is permanent.', array('%file' => $file->getFileUri()));
|
||||
$this->assertTrue($file->isPermanent(), $message);
|
||||
}
|
||||
|
||||
}
|
163
core/modules/file/src/Tests/FileFieldValidateTest.php
Normal file
163
core/modules/file/src/Tests/FileFieldValidateTest.php
Normal file
|
@ -0,0 +1,163 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains \Drupal\file\Tests\FileFieldValidateTest.
|
||||
*/
|
||||
|
||||
namespace Drupal\file\Tests;
|
||||
|
||||
use Drupal\Core\Field\FieldStorageDefinitionInterface;
|
||||
use Drupal\field\Entity\FieldConfig;
|
||||
|
||||
/**
|
||||
* Tests validation functions such as file type, max file size, max size per
|
||||
* node, and required.
|
||||
*
|
||||
* @group file
|
||||
*/
|
||||
class FileFieldValidateTest extends FileFieldTestBase {
|
||||
|
||||
/**
|
||||
* Tests the required property on file fields.
|
||||
*/
|
||||
function testRequired() {
|
||||
$node_storage = $this->container->get('entity.manager')->getStorage('node');
|
||||
$type_name = 'article';
|
||||
$field_name = strtolower($this->randomMachineName());
|
||||
$storage = $this->createFileField($field_name, 'node', $type_name, array(), array('required' => '1'));
|
||||
$field = FieldConfig::loadByName('node', $type_name, $field_name);
|
||||
|
||||
$test_file = $this->getTestFile('text');
|
||||
|
||||
// Try to post a new node without uploading a file.
|
||||
$edit = array();
|
||||
$edit['title[0][value]'] = $this->randomMachineName();
|
||||
$this->drupalPostForm('node/add/' . $type_name, $edit, t('Save and publish'));
|
||||
$this->assertText('1 error has been found: ' . $field->label(), 'Node save failed when required file field was empty.');
|
||||
$this->assertIdentical(1, count($this->xpath('//div[contains(concat(" ", normalize-space(@class), " "), :class)]//a', [':class' => ' messages--error '])), 'There is one link in the error message.');
|
||||
|
||||
// Create a new node with the uploaded file.
|
||||
$nid = $this->uploadNodeFile($test_file, $field_name, $type_name);
|
||||
$this->assertTrue($nid !== FALSE, format_string('uploadNodeFile(@test_file, @field_name, @type_name) succeeded', array('@test_file' => $test_file->getFileUri(), '@field_name' => $field_name, '@type_name' => $type_name)));
|
||||
|
||||
$node_storage->resetCache(array($nid));
|
||||
$node = $node_storage->load($nid);
|
||||
|
||||
$node_file = file_load($node->{$field_name}->target_id);
|
||||
$this->assertFileExists($node_file, 'File exists after uploading to the required field.');
|
||||
$this->assertFileEntryExists($node_file, 'File entry exists after uploading to the required field.');
|
||||
|
||||
// Try again with a multiple value field.
|
||||
$storage->delete();
|
||||
$this->createFileField($field_name, 'node', $type_name, array('cardinality' => FieldStorageDefinitionInterface::CARDINALITY_UNLIMITED), array('required' => '1'));
|
||||
|
||||
// Try to post a new node without uploading a file in the multivalue field.
|
||||
$edit = array();
|
||||
$edit['title[0][value]'] = $this->randomMachineName();
|
||||
$this->drupalPostForm('node/add/' . $type_name, $edit, t('Save and publish'));
|
||||
$this->assertText('1 error has been found: ' . $field->label(), 'Node save failed when required multiple value file field was empty.');
|
||||
$this->assertIdentical(1, count($this->xpath('//div[contains(concat(" ", normalize-space(@class), " "), :class)]//a', [':class' => ' messages--error '])), 'There is one link in the error message.');
|
||||
|
||||
// Create a new node with the uploaded file into the multivalue field.
|
||||
$nid = $this->uploadNodeFile($test_file, $field_name, $type_name);
|
||||
$node_storage->resetCache(array($nid));
|
||||
$node = $node_storage->load($nid);
|
||||
$node_file = file_load($node->{$field_name}->target_id);
|
||||
$this->assertFileExists($node_file, 'File exists after uploading to the required multiple value field.');
|
||||
$this->assertFileEntryExists($node_file, 'File entry exists after uploading to the required multiple value field.');
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the max file size validator.
|
||||
*/
|
||||
function testFileMaxSize() {
|
||||
$node_storage = $this->container->get('entity.manager')->getStorage('node');
|
||||
$type_name = 'article';
|
||||
$field_name = strtolower($this->randomMachineName());
|
||||
$this->createFileField($field_name, 'node', $type_name, array(), array('required' => '1'));
|
||||
|
||||
$small_file = $this->getTestFile('text', 131072); // 128KB.
|
||||
$large_file = $this->getTestFile('text', 1310720); // 1.2MB
|
||||
|
||||
// Test uploading both a large and small file with different increments.
|
||||
$sizes = array(
|
||||
'1M' => 1048576,
|
||||
'1024K' => 1048576,
|
||||
'1048576' => 1048576,
|
||||
);
|
||||
|
||||
foreach ($sizes as $max_filesize => $file_limit) {
|
||||
// Set the max file upload size.
|
||||
$this->updateFileField($field_name, $type_name, array('max_filesize' => $max_filesize));
|
||||
|
||||
// Create a new node with the small file, which should pass.
|
||||
$nid = $this->uploadNodeFile($small_file, $field_name, $type_name);
|
||||
$node_storage->resetCache(array($nid));
|
||||
$node = $node_storage->load($nid);
|
||||
$node_file = file_load($node->{$field_name}->target_id);
|
||||
$this->assertFileExists($node_file, format_string('File exists after uploading a file (%filesize) under the max limit (%maxsize).', array('%filesize' => format_size($small_file->getSize()), '%maxsize' => $max_filesize)));
|
||||
$this->assertFileEntryExists($node_file, format_string('File entry exists after uploading a file (%filesize) under the max limit (%maxsize).', array('%filesize' => format_size($small_file->getSize()), '%maxsize' => $max_filesize)));
|
||||
|
||||
// Check that uploading the large file fails (1M limit).
|
||||
$this->uploadNodeFile($large_file, $field_name, $type_name);
|
||||
$error_message = t('The file is %filesize exceeding the maximum file size of %maxsize.', array('%filesize' => format_size($large_file->getSize()), '%maxsize' => format_size($file_limit)));
|
||||
$this->assertRaw($error_message, format_string('Node save failed when file (%filesize) exceeded the max upload size (%maxsize).', array('%filesize' => format_size($large_file->getSize()), '%maxsize' => $max_filesize)));
|
||||
}
|
||||
|
||||
// Turn off the max filesize.
|
||||
$this->updateFileField($field_name, $type_name, array('max_filesize' => ''));
|
||||
|
||||
// Upload the big file successfully.
|
||||
$nid = $this->uploadNodeFile($large_file, $field_name, $type_name);
|
||||
$node_storage->resetCache(array($nid));
|
||||
$node = $node_storage->load($nid);
|
||||
$node_file = file_load($node->{$field_name}->target_id);
|
||||
$this->assertFileExists($node_file, format_string('File exists after uploading a file (%filesize) with no max limit.', array('%filesize' => format_size($large_file->getSize()))));
|
||||
$this->assertFileEntryExists($node_file, format_string('File entry exists after uploading a file (%filesize) with no max limit.', array('%filesize' => format_size($large_file->getSize()))));
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests file extension checking.
|
||||
*/
|
||||
function testFileExtension() {
|
||||
$node_storage = $this->container->get('entity.manager')->getStorage('node');
|
||||
$type_name = 'article';
|
||||
$field_name = strtolower($this->randomMachineName());
|
||||
$this->createFileField($field_name, 'node', $type_name);
|
||||
|
||||
$test_file = $this->getTestFile('image');
|
||||
list(, $test_file_extension) = explode('.', $test_file->getFilename());
|
||||
|
||||
// Disable extension checking.
|
||||
$this->updateFileField($field_name, $type_name, array('file_extensions' => ''));
|
||||
|
||||
// Check that the file can be uploaded with no extension checking.
|
||||
$nid = $this->uploadNodeFile($test_file, $field_name, $type_name);
|
||||
$node_storage->resetCache(array($nid));
|
||||
$node = $node_storage->load($nid);
|
||||
$node_file = file_load($node->{$field_name}->target_id);
|
||||
$this->assertFileExists($node_file, 'File exists after uploading a file with no extension checking.');
|
||||
$this->assertFileEntryExists($node_file, 'File entry exists after uploading a file with no extension checking.');
|
||||
|
||||
// Enable extension checking for text files.
|
||||
$this->updateFileField($field_name, $type_name, array('file_extensions' => 'txt'));
|
||||
|
||||
// Check that the file with the wrong extension cannot be uploaded.
|
||||
$this->uploadNodeFile($test_file, $field_name, $type_name);
|
||||
$error_message = t('Only files with the following extensions are allowed: %files-allowed.', array('%files-allowed' => 'txt'));
|
||||
$this->assertRaw($error_message, 'Node save failed when file uploaded with the wrong extension.');
|
||||
|
||||
// Enable extension checking for text and image files.
|
||||
$this->updateFileField($field_name, $type_name, array('file_extensions' => "txt $test_file_extension"));
|
||||
|
||||
// Check that the file can be uploaded with extension checking.
|
||||
$nid = $this->uploadNodeFile($test_file, $field_name, $type_name);
|
||||
$node_storage->resetCache(array($nid));
|
||||
$node = $node_storage->load($nid);
|
||||
$node_file = file_load($node->{$field_name}->target_id);
|
||||
$this->assertFileExists($node_file, 'File exists after uploading a file with extension checking.');
|
||||
$this->assertFileEntryExists($node_file, 'File entry exists after uploading a file with extension checking.');
|
||||
}
|
||||
|
||||
}
|
377
core/modules/file/src/Tests/FileFieldWidgetTest.php
Normal file
377
core/modules/file/src/Tests/FileFieldWidgetTest.php
Normal file
|
@ -0,0 +1,377 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains \Drupal\file\Tests\FileFieldWidgetTest.
|
||||
*/
|
||||
|
||||
namespace Drupal\file\Tests;
|
||||
|
||||
use Drupal\comment\Entity\Comment;
|
||||
use Drupal\comment\Tests\CommentTestTrait;
|
||||
use Drupal\field\Entity\FieldConfig;
|
||||
use Drupal\field_ui\Tests\FieldUiTestTrait;
|
||||
use Drupal\user\RoleInterface;
|
||||
|
||||
/**
|
||||
* Tests the file field widget, single and multi-valued, with and without AJAX,
|
||||
* with public and private files.
|
||||
*
|
||||
* @group file
|
||||
*/
|
||||
class FileFieldWidgetTest extends FileFieldTestBase {
|
||||
|
||||
use CommentTestTrait;
|
||||
use FieldUiTestTrait;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function setUp() {
|
||||
parent::setUp();
|
||||
$this->drupalPlaceBlock('system_breadcrumb_block');
|
||||
}
|
||||
|
||||
/**
|
||||
* Modules to enable.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public static $modules = array('comment', 'block');
|
||||
|
||||
/**
|
||||
* Tests upload and remove buttons for a single-valued File field.
|
||||
*/
|
||||
function testSingleValuedWidget() {
|
||||
$node_storage = $this->container->get('entity.manager')->getStorage('node');
|
||||
$type_name = 'article';
|
||||
$field_name = strtolower($this->randomMachineName());
|
||||
$this->createFileField($field_name, 'node', $type_name);
|
||||
|
||||
$test_file = $this->getTestFile('text');
|
||||
|
||||
foreach (array('nojs', 'js') as $type) {
|
||||
// Create a new node with the uploaded file and ensure it got uploaded
|
||||
// successfully.
|
||||
// @todo This only tests a 'nojs' submission, because drupalPostAjaxForm()
|
||||
// does not yet support file uploads.
|
||||
$nid = $this->uploadNodeFile($test_file, $field_name, $type_name);
|
||||
$node_storage->resetCache(array($nid));
|
||||
$node = $node_storage->load($nid);
|
||||
$node_file = file_load($node->{$field_name}->target_id);
|
||||
$this->assertFileExists($node_file, 'New file saved to disk on node creation.');
|
||||
|
||||
// Ensure the file can be downloaded.
|
||||
$this->drupalGet(file_create_url($node_file->getFileUri()));
|
||||
$this->assertResponse(200, 'Confirmed that the generated URL is correct by downloading the shipped file.');
|
||||
|
||||
// Ensure the edit page has a remove button instead of an upload button.
|
||||
$this->drupalGet("node/$nid/edit");
|
||||
$this->assertNoFieldByXPath('//input[@type="submit"]', t('Upload'), 'Node with file does not display the "Upload" button.');
|
||||
$this->assertFieldByXpath('//input[@type="submit"]', t('Remove'), 'Node with file displays the "Remove" button.');
|
||||
|
||||
// "Click" the remove button (emulating either a nojs or js submission).
|
||||
switch ($type) {
|
||||
case 'nojs':
|
||||
$this->drupalPostForm(NULL, array(), t('Remove'));
|
||||
break;
|
||||
case 'js':
|
||||
$button = $this->xpath('//input[@type="submit" and @value="' . t('Remove') . '"]');
|
||||
$this->drupalPostAjaxForm(NULL, array(), array((string) $button[0]['name'] => (string) $button[0]['value']));
|
||||
break;
|
||||
}
|
||||
|
||||
// Ensure the page now has an upload button instead of a remove button.
|
||||
$this->assertNoFieldByXPath('//input[@type="submit"]', t('Remove'), 'After clicking the "Remove" button, it is no longer displayed.');
|
||||
$this->assertFieldByXpath('//input[@type="submit"]', t('Upload'), 'After clicking the "Remove" button, the "Upload" button is displayed.');
|
||||
// Test label has correct 'for' attribute.
|
||||
$input = $this->xpath('//input[@name="files[' . $field_name . '_0]"]');
|
||||
$label = $this->xpath('//label[@for="' . (string) $input[0]['id'] . '"]');
|
||||
$this->assertTrue(isset($label[0]), 'Label for upload found.');
|
||||
|
||||
// Save the node and ensure it does not have the file.
|
||||
$this->drupalPostForm(NULL, array(), t('Save and keep published'));
|
||||
$node_storage->resetCache(array($nid));
|
||||
$node = $node_storage->load($nid);
|
||||
$this->assertTrue(empty($node->{$field_name}->target_id), 'File was successfully removed from the node.');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests upload and remove buttons for multiple multi-valued File fields.
|
||||
*/
|
||||
function testMultiValuedWidget() {
|
||||
$node_storage = $this->container->get('entity.manager')->getStorage('node');
|
||||
$type_name = 'article';
|
||||
// Use explicit names instead of random names for those fields, because of a
|
||||
// bug in drupalPostForm() with multiple file uploads in one form, where the
|
||||
// order of uploads depends on the order in which the upload elements are
|
||||
// added to the $form (which, in the current implementation of
|
||||
// FileStorage::listAll(), comes down to the alphabetical order on field
|
||||
// names).
|
||||
$field_name = 'test_file_field_1';
|
||||
$field_name2 = 'test_file_field_2';
|
||||
$this->createFileField($field_name, 'node', $type_name, array('cardinality' => 3));
|
||||
$this->createFileField($field_name2, 'node', $type_name, array('cardinality' => 3));
|
||||
|
||||
$test_file = $this->getTestFile('text');
|
||||
|
||||
foreach (array('nojs', 'js') as $type) {
|
||||
// Visit the node creation form, and upload 3 files for each field. Since
|
||||
// the field has cardinality of 3, ensure the "Upload" button is displayed
|
||||
// until after the 3rd file, and after that, isn't displayed. Because
|
||||
// SimpleTest triggers the last button with a given name, so upload to the
|
||||
// second field first.
|
||||
// @todo This is only testing a non-Ajax upload, because drupalPostAjaxForm()
|
||||
// does not yet emulate jQuery's file upload.
|
||||
//
|
||||
$this->drupalGet("node/add/$type_name");
|
||||
foreach (array($field_name2, $field_name) as $each_field_name) {
|
||||
for ($delta = 0; $delta < 3; $delta++) {
|
||||
$edit = array('files[' . $each_field_name . '_' . $delta . '][]' => drupal_realpath($test_file->getFileUri()));
|
||||
// If the Upload button doesn't exist, drupalPostForm() will automatically
|
||||
// fail with an assertion message.
|
||||
$this->drupalPostForm(NULL, $edit, t('Upload'));
|
||||
}
|
||||
}
|
||||
$this->assertNoFieldByXpath('//input[@type="submit"]', t('Upload'), 'After uploading 3 files for each field, the "Upload" button is no longer displayed.');
|
||||
|
||||
$num_expected_remove_buttons = 6;
|
||||
|
||||
foreach (array($field_name, $field_name2) as $current_field_name) {
|
||||
// How many uploaded files for the current field are remaining.
|
||||
$remaining = 3;
|
||||
// Test clicking each "Remove" button. For extra robustness, test them out
|
||||
// of sequential order. They are 0-indexed, and get renumbered after each
|
||||
// iteration, so array(1, 1, 0) means:
|
||||
// - First remove the 2nd file.
|
||||
// - Then remove what is then the 2nd file (was originally the 3rd file).
|
||||
// - Then remove the first file.
|
||||
foreach (array(1,1,0) as $delta) {
|
||||
// Ensure we have the expected number of Remove buttons, and that they
|
||||
// are numbered sequentially.
|
||||
$buttons = $this->xpath('//input[@type="submit" and @value="Remove"]');
|
||||
$this->assertTrue(is_array($buttons) && count($buttons) === $num_expected_remove_buttons, format_string('There are %n "Remove" buttons displayed (JSMode=%type).', array('%n' => $num_expected_remove_buttons, '%type' => $type)));
|
||||
foreach ($buttons as $i => $button) {
|
||||
$key = $i >= $remaining ? $i - $remaining : $i;
|
||||
$check_field_name = $field_name2;
|
||||
if ($current_field_name == $field_name && $i < $remaining) {
|
||||
$check_field_name = $field_name;
|
||||
}
|
||||
|
||||
$this->assertIdentical((string) $button['name'], $check_field_name . '_' . $key. '_remove_button');
|
||||
}
|
||||
|
||||
// "Click" the remove button (emulating either a nojs or js submission).
|
||||
$button_name = $current_field_name . '_' . $delta . '_remove_button';
|
||||
switch ($type) {
|
||||
case 'nojs':
|
||||
// drupalPostForm() takes a $submit parameter that is the value of the
|
||||
// button whose click we want to emulate. Since we have multiple
|
||||
// buttons with the value "Remove", and want to control which one we
|
||||
// use, we change the value of the other ones to something else.
|
||||
// Since non-clicked buttons aren't included in the submitted POST
|
||||
// data, and since drupalPostForm() will result in $this being updated
|
||||
// with a newly rebuilt form, this doesn't cause problems.
|
||||
foreach ($buttons as $button) {
|
||||
if ($button['name'] != $button_name) {
|
||||
$button['value'] = 'DUMMY';
|
||||
}
|
||||
}
|
||||
$this->drupalPostForm(NULL, array(), t('Remove'));
|
||||
break;
|
||||
case 'js':
|
||||
// drupalPostAjaxForm() lets us target the button precisely, so we don't
|
||||
// require the workaround used above for nojs.
|
||||
$this->drupalPostAjaxForm(NULL, array(), array($button_name => t('Remove')));
|
||||
break;
|
||||
}
|
||||
$num_expected_remove_buttons--;
|
||||
$remaining--;
|
||||
|
||||
// Ensure an "Upload" button for the current field is displayed with the
|
||||
// correct name.
|
||||
$upload_button_name = $current_field_name . '_' . $remaining . '_upload_button';
|
||||
$buttons = $this->xpath('//input[@type="submit" and @value="Upload" and @name=:name]', array(':name' => $upload_button_name));
|
||||
$this->assertTrue(is_array($buttons) && count($buttons) == 1, format_string('The upload button is displayed with the correct name (JSMode=%type).', array('%type' => $type)));
|
||||
|
||||
// Ensure only at most one button per field is displayed.
|
||||
$buttons = $this->xpath('//input[@type="submit" and @value="Upload"]');
|
||||
$expected = $current_field_name == $field_name ? 1 : 2;
|
||||
$this->assertTrue(is_array($buttons) && count($buttons) == $expected, format_string('After removing a file, only one "Upload" button for each possible field is displayed (JSMode=%type).', array('%type' => $type)));
|
||||
}
|
||||
}
|
||||
|
||||
// Ensure the page now has no Remove buttons.
|
||||
$this->assertNoFieldByXPath('//input[@type="submit"]', t('Remove'), format_string('After removing all files, there is no "Remove" button displayed (JSMode=%type).', array('%type' => $type)));
|
||||
|
||||
// Save the node and ensure it does not have any files.
|
||||
$this->drupalPostForm(NULL, array('title[0][value]' => $this->randomMachineName()), t('Save and publish'));
|
||||
$matches = array();
|
||||
preg_match('/node\/([0-9]+)/', $this->getUrl(), $matches);
|
||||
$nid = $matches[1];
|
||||
$node_storage->resetCache(array($nid));
|
||||
$node = $node_storage->load($nid);
|
||||
$this->assertTrue(empty($node->{$field_name}->target_id), 'Node was successfully saved without any files.');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests a file field with a "Private files" upload destination setting.
|
||||
*/
|
||||
function testPrivateFileSetting() {
|
||||
$node_storage = $this->container->get('entity.manager')->getStorage('node');
|
||||
// Grant the admin user required permissions.
|
||||
user_role_grant_permissions($this->adminUser->roles[0]->target_id, array('administer node fields'));
|
||||
|
||||
$type_name = 'article';
|
||||
$field_name = strtolower($this->randomMachineName());
|
||||
$this->createFileField($field_name, 'node', $type_name);
|
||||
$field = FieldConfig::loadByName('node', $type_name, $field_name);
|
||||
$field_id = $field->id();
|
||||
|
||||
$test_file = $this->getTestFile('text');
|
||||
|
||||
// Change the field setting to make its files private, and upload a file.
|
||||
$edit = array('settings[uri_scheme]' => 'private');
|
||||
$this->drupalPostForm("admin/structure/types/manage/$type_name/fields/$field_id/storage", $edit, t('Save field settings'));
|
||||
$nid = $this->uploadNodeFile($test_file, $field_name, $type_name);
|
||||
$node_storage->resetCache(array($nid));
|
||||
$node = $node_storage->load($nid);
|
||||
$node_file = file_load($node->{$field_name}->target_id);
|
||||
$this->assertFileExists($node_file, 'New file saved to disk on node creation.');
|
||||
|
||||
// Ensure the private file is available to the user who uploaded it.
|
||||
$this->drupalGet(file_create_url($node_file->getFileUri()));
|
||||
$this->assertResponse(200, 'Confirmed that the generated URL is correct by downloading the shipped file.');
|
||||
|
||||
// Ensure we can't change 'uri_scheme' field settings while there are some
|
||||
// entities with uploaded files.
|
||||
$this->drupalGet("admin/structure/types/manage/$type_name/fields/$field_id/storage");
|
||||
$this->assertFieldByXpath('//input[@id="edit-settings-uri-scheme-public" and @disabled="disabled"]', 'public', 'Upload destination setting disabled.');
|
||||
|
||||
// Delete node and confirm that setting could be changed.
|
||||
$node->delete();
|
||||
$this->drupalGet("admin/structure/types/manage/$type_name/fields/$field_id/storage");
|
||||
$this->assertFieldByXpath('//input[@id="edit-settings-uri-scheme-public" and not(@disabled)]', 'public', 'Upload destination setting enabled.');
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests that download restrictions on private files work on comments.
|
||||
*/
|
||||
function testPrivateFileComment() {
|
||||
$user = $this->drupalCreateUser(array('access comments'));
|
||||
|
||||
// Grant the admin user required comment permissions.
|
||||
$roles = $this->adminUser->getRoles();
|
||||
user_role_grant_permissions($roles[1], array('administer comment fields', 'administer comments'));
|
||||
|
||||
// Revoke access comments permission from anon user, grant post to
|
||||
// authenticated.
|
||||
user_role_revoke_permissions(RoleInterface::ANONYMOUS_ID, array('access comments'));
|
||||
user_role_grant_permissions(RoleInterface::AUTHENTICATED_ID, array('post comments', 'skip comment approval'));
|
||||
|
||||
// Create a new field.
|
||||
$this->addDefaultCommentField('node', 'article');
|
||||
|
||||
$name = strtolower($this->randomMachineName());
|
||||
$label = $this->randomMachineName();
|
||||
$storage_edit = array('settings[uri_scheme]' => 'private');
|
||||
$this->fieldUIAddNewField('admin/structure/comment/manage/comment', $name, $label, 'file', $storage_edit);
|
||||
|
||||
// Manually clear cache on the tester side.
|
||||
\Drupal::entityManager()->clearCachedFieldDefinitions();
|
||||
|
||||
// Create node.
|
||||
$edit = array(
|
||||
'title[0][value]' => $this->randomMachineName(),
|
||||
);
|
||||
$this->drupalPostForm('node/add/article', $edit, t('Save and publish'));
|
||||
$node = $this->drupalGetNodeByTitle($edit['title[0][value]']);
|
||||
|
||||
// Add a comment with a file.
|
||||
$text_file = $this->getTestFile('text');
|
||||
$edit = array(
|
||||
'files[field_' . $name . '_' . 0 . ']' => drupal_realpath($text_file->getFileUri()),
|
||||
'comment_body[0][value]' => $comment_body = $this->randomMachineName(),
|
||||
);
|
||||
$this->drupalPostForm('node/' . $node->id(), $edit, t('Save'));
|
||||
|
||||
// Get the comment ID.
|
||||
preg_match('/comment-([0-9]+)/', $this->getUrl(), $matches);
|
||||
$cid = $matches[1];
|
||||
|
||||
// Log in as normal user.
|
||||
$this->drupalLogin($user);
|
||||
|
||||
$comment = Comment::load($cid);
|
||||
$comment_file = $comment->{'field_' . $name}->entity;
|
||||
$this->assertFileExists($comment_file, 'New file saved to disk on node creation.');
|
||||
// Test authenticated file download.
|
||||
$url = file_create_url($comment_file->getFileUri());
|
||||
$this->assertNotEqual($url, NULL, 'Confirmed that the URL is valid');
|
||||
$this->drupalGet(file_create_url($comment_file->getFileUri()));
|
||||
$this->assertResponse(200, 'Confirmed that the generated URL is correct by downloading the shipped file.');
|
||||
|
||||
// Test anonymous file download.
|
||||
$this->drupalLogout();
|
||||
$this->drupalGet(file_create_url($comment_file->getFileUri()));
|
||||
$this->assertResponse(403, 'Confirmed that access is denied for the file without the needed permission.');
|
||||
|
||||
// Unpublishes node.
|
||||
$this->drupalLogin($this->adminUser);
|
||||
$this->drupalPostForm('node/' . $node->id() . '/edit', array(), t('Save and unpublish'));
|
||||
|
||||
// Ensures normal user can no longer download the file.
|
||||
$this->drupalLogin($user);
|
||||
$this->drupalGet(file_create_url($comment_file->getFileUri()));
|
||||
$this->assertResponse(403, 'Confirmed that access is denied for the file without the needed permission.');
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests validation with the Upload button.
|
||||
*/
|
||||
function testWidgetValidation() {
|
||||
$type_name = 'article';
|
||||
$field_name = strtolower($this->randomMachineName());
|
||||
$this->createFileField($field_name, 'node', $type_name);
|
||||
$this->updateFileField($field_name, $type_name, array('file_extensions' => 'txt'));
|
||||
|
||||
foreach (array('nojs', 'js') as $type) {
|
||||
// Create node and prepare files for upload.
|
||||
$node = $this->drupalCreateNode(array('type' => 'article'));
|
||||
$nid = $node->id();
|
||||
$this->drupalGet("node/$nid/edit");
|
||||
$test_file_text = $this->getTestFile('text');
|
||||
$test_file_image = $this->getTestFile('image');
|
||||
$name = 'files[' . $field_name . '_0]';
|
||||
|
||||
// Upload file with incorrect extension, check for validation error.
|
||||
$edit[$name] = drupal_realpath($test_file_image->getFileUri());
|
||||
switch ($type) {
|
||||
case 'nojs':
|
||||
$this->drupalPostForm(NULL, $edit, t('Upload'));
|
||||
break;
|
||||
case 'js':
|
||||
$button = $this->xpath('//input[@type="submit" and @value="' . t('Upload') . '"]');
|
||||
$this->drupalPostAjaxForm(NULL, $edit, array((string) $button[0]['name'] => (string) $button[0]['value']));
|
||||
break;
|
||||
}
|
||||
$error_message = t('Only files with the following extensions are allowed: %files-allowed.', array('%files-allowed' => 'txt'));
|
||||
$this->assertRaw($error_message, t('Validation error when file with wrong extension uploaded (JSMode=%type).', array('%type' => $type)));
|
||||
|
||||
// Upload file with correct extension, check that error message is removed.
|
||||
$edit[$name] = drupal_realpath($test_file_text->getFileUri());
|
||||
switch ($type) {
|
||||
case 'nojs':
|
||||
$this->drupalPostForm(NULL, $edit, t('Upload'));
|
||||
break;
|
||||
case 'js':
|
||||
$button = $this->xpath('//input[@type="submit" and @value="' . t('Upload') . '"]');
|
||||
$this->drupalPostAjaxForm(NULL, $edit, array((string) $button[0]['name'] => (string) $button[0]['value']));
|
||||
break;
|
||||
}
|
||||
$this->assertNoRaw($error_message, t('Validation error removed when file with correct extension uploaded (JSMode=%type).', array('%type' => $type)));
|
||||
}
|
||||
}
|
||||
}
|
125
core/modules/file/src/Tests/FileItemTest.php
Normal file
125
core/modules/file/src/Tests/FileItemTest.php
Normal file
|
@ -0,0 +1,125 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains \Drupal\file\Tests\FileItemTest.
|
||||
*/
|
||||
|
||||
namespace Drupal\file\Tests;
|
||||
|
||||
use Drupal\Core\Field\FieldItemInterface;
|
||||
use Drupal\Core\Field\FieldItemListInterface;
|
||||
use Drupal\Core\Field\FieldStorageDefinitionInterface;
|
||||
use Drupal\field\Tests\FieldUnitTestBase;
|
||||
|
||||
/**
|
||||
* Tests using entity fields of the file field type.
|
||||
*
|
||||
* @group file
|
||||
*/
|
||||
class FileItemTest extends FieldUnitTestBase {
|
||||
|
||||
/**
|
||||
* Modules to enable.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public static $modules = array('file');
|
||||
|
||||
/**
|
||||
* Created file entity.
|
||||
*
|
||||
* @var \Drupal\file\Entity\File
|
||||
*/
|
||||
protected $file;
|
||||
|
||||
protected function setUp() {
|
||||
parent::setUp();
|
||||
|
||||
$this->installEntitySchema('file');
|
||||
$this->installSchema('file', array('file_usage'));
|
||||
|
||||
entity_create('field_storage_config', array(
|
||||
'field_name' => 'file_test',
|
||||
'entity_type' => 'entity_test',
|
||||
'type' => 'file',
|
||||
'cardinality' => FieldStorageDefinitionInterface::CARDINALITY_UNLIMITED,
|
||||
))->save();
|
||||
entity_create('field_config', array(
|
||||
'entity_type' => 'entity_test',
|
||||
'field_name' => 'file_test',
|
||||
'bundle' => 'entity_test',
|
||||
))->save();
|
||||
file_put_contents('public://example.txt', $this->randomMachineName());
|
||||
$this->file = entity_create('file', array(
|
||||
'uri' => 'public://example.txt',
|
||||
));
|
||||
$this->file->save();
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests using entity fields of the file field type.
|
||||
*/
|
||||
public function testFileItem() {
|
||||
// Create a test entity with the
|
||||
$entity = entity_create('entity_test');
|
||||
$entity->file_test->target_id = $this->file->id();
|
||||
$entity->file_test->display = 1;
|
||||
$entity->file_test->description = $description = $this->randomMachineName();
|
||||
$entity->name->value = $this->randomMachineName();
|
||||
$entity->save();
|
||||
|
||||
$entity = entity_load('entity_test', $entity->id());
|
||||
$this->assertTrue($entity->file_test instanceof FieldItemListInterface, 'Field implements interface.');
|
||||
$this->assertTrue($entity->file_test[0] instanceof FieldItemInterface, 'Field item implements interface.');
|
||||
$this->assertEqual($entity->file_test->target_id, $this->file->id());
|
||||
$this->assertEqual($entity->file_test->display, 1);
|
||||
$this->assertEqual($entity->file_test->description, $description);
|
||||
$this->assertEqual($entity->file_test->entity->getFileUri(), $this->file->getFileUri());
|
||||
$this->assertEqual($entity->file_test->entity->url(), $url = file_create_url($this->file->getFileUri()));
|
||||
$this->assertEqual($entity->file_test->entity->id(), $this->file->id());
|
||||
$this->assertEqual($entity->file_test->entity->uuid(), $this->file->uuid());
|
||||
|
||||
// Make sure the computed files reflects updates to the file.
|
||||
file_put_contents('public://example-2.txt', $this->randomMachineName());
|
||||
$file2 = entity_create('file', array(
|
||||
'uri' => 'public://example-2.txt',
|
||||
));
|
||||
$file2->save();
|
||||
|
||||
$entity->file_test->target_id = $file2->id();
|
||||
$this->assertEqual($entity->file_test->entity->id(), $file2->id());
|
||||
$this->assertEqual($entity->file_test->entity->getFileUri(), $file2->getFileUri());
|
||||
|
||||
// Test the deletion of an entity having an entity reference field targeting
|
||||
// a non-existing entity.
|
||||
$file2->delete();
|
||||
$entity->delete();
|
||||
|
||||
// Test the generateSampleValue() method.
|
||||
$entity = entity_create('entity_test');
|
||||
$entity->file_test->generateSampleItems();
|
||||
$this->entityValidateAndSave($entity);
|
||||
|
||||
// Make sure the computed files reflects updates to the file.
|
||||
file_put_contents('public://example-3.txt', $this->randomMachineName());
|
||||
// Test unsaved file entity.
|
||||
$file3 = entity_create('file', array(
|
||||
'uri' => 'public://example-3.txt',
|
||||
));
|
||||
$display = entity_get_display('entity_test', 'entity_test', 'default');
|
||||
$display->setComponent('file_test', [
|
||||
'label' => 'above',
|
||||
'type' => 'file_default',
|
||||
'weight' => 1,
|
||||
])->save();
|
||||
$entity = entity_create('entity_test');
|
||||
$entity->file_test = array('entity' => $file3);
|
||||
$uri = $file3->getFileUri();
|
||||
$output = entity_view($entity, 'default');
|
||||
\Drupal::service('renderer')->renderRoot($output);
|
||||
$this->assertTrue(!empty($entity->file_test->entity));
|
||||
$this->assertEqual($entity->file_test->entity->getFileUri(), $uri);
|
||||
}
|
||||
|
||||
}
|
176
core/modules/file/src/Tests/FileListingTest.php
Normal file
176
core/modules/file/src/Tests/FileListingTest.php
Normal file
|
@ -0,0 +1,176 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains \Drupal\file\Tests\FileListingTest.
|
||||
*/
|
||||
|
||||
namespace Drupal\file\Tests;
|
||||
|
||||
use Drupal\node\Entity\Node;
|
||||
|
||||
/**
|
||||
* Tests file listing page functionality.
|
||||
*
|
||||
* @group file
|
||||
*/
|
||||
class FileListingTest extends FileFieldTestBase {
|
||||
|
||||
/**
|
||||
* Modules to enable.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public static $modules = array('views', 'file', 'image');
|
||||
|
||||
/**
|
||||
* An authenticated user.
|
||||
*
|
||||
* @var \Drupal\user\UserInterface
|
||||
*/
|
||||
protected $baseUser;
|
||||
|
||||
protected function setUp() {
|
||||
parent::setUp();
|
||||
|
||||
$this->adminUser = $this->drupalCreateUser(array('access files overview', 'bypass node access'));
|
||||
$this->baseUser = $this->drupalCreateUser();
|
||||
$this->createFileField('file', 'node', 'article', array(), array('file_extensions' => 'txt png'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculates total count of usages for a file.
|
||||
*
|
||||
* @param $usage array
|
||||
* Array of file usage information as returned from file_usage subsystem.
|
||||
* @return int
|
||||
* Total usage count.
|
||||
*/
|
||||
protected function sumUsages($usage) {
|
||||
$count = 0;
|
||||
foreach ($usage as $module) {
|
||||
foreach ($module as $entity_type) {
|
||||
foreach ($entity_type as $entity) {
|
||||
$count += $entity;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $count;
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests file overview with different user permissions.
|
||||
*/
|
||||
function testFileListingPages() {
|
||||
$file_usage = $this->container->get('file.usage');
|
||||
// Users without sufficient permissions should not see file listing.
|
||||
$this->drupalLogin($this->baseUser);
|
||||
$this->drupalGet('admin/content/files');
|
||||
$this->assertResponse(403);
|
||||
|
||||
// Login with user with right permissions and test listing.
|
||||
$this->drupalLogin($this->adminUser);
|
||||
|
||||
for ($i = 0; $i < 5; $i++) {
|
||||
$nodes[] = $this->drupalCreateNode(array('type' => 'article'));
|
||||
}
|
||||
|
||||
$this->drupalGet('admin/content/files');
|
||||
$this->assertResponse(200);
|
||||
$this->assertText('No files available.');
|
||||
$this->drupalGet('admin/content/files');
|
||||
$this->assertResponse(200);
|
||||
|
||||
// Create a file with no usage.
|
||||
$file = $this->createFile();
|
||||
|
||||
$this->drupalGet('admin/content/files/usage/' . $file->id());
|
||||
$this->assertResponse(200);
|
||||
$this->assertTitle(t('File usage information for @file | Drupal', array('@file' => $file->getFilename())));
|
||||
|
||||
foreach ($nodes as &$node) {
|
||||
$this->drupalGet('node/' . $node->id() . '/edit');
|
||||
$file = $this->getTestFile('image');
|
||||
|
||||
$edit = array(
|
||||
'files[file_0]' => drupal_realpath($file->getFileUri()),
|
||||
);
|
||||
$this->drupalPostForm(NULL, $edit, t('Save'));
|
||||
$node = Node::load($node->id());
|
||||
}
|
||||
|
||||
$this->drupalGet('admin/content/files');
|
||||
|
||||
foreach ($nodes as $node) {
|
||||
$file = entity_load('file', $node->file->target_id);
|
||||
$this->assertText($file->getFilename());
|
||||
$this->assertLinkByHref(file_create_url($file->getFileUri()));
|
||||
$this->assertLinkByHref('admin/content/files/usage/' . $file->id());
|
||||
}
|
||||
$this->assertFalse(preg_match('/views-field-status priority-low\">\s*' . t('Temporary') . '/', $this->getRawContent()), 'All files are stored as permanent.');
|
||||
|
||||
// Use one file two times and check usage information.
|
||||
$orphaned_file = $nodes[1]->file->target_id;
|
||||
$used_file = $nodes[0]->file->target_id;
|
||||
$nodes[1]->file->target_id = $used_file;
|
||||
$nodes[1]->save();
|
||||
|
||||
$this->drupalGet('admin/content/files');
|
||||
$file = entity_load('file', $orphaned_file);
|
||||
$usage = $this->sumUsages($file_usage->listUsage($file));
|
||||
$this->assertRaw('admin/content/files/usage/' . $file->id() . '">' . $usage);
|
||||
|
||||
$file = entity_load('file', $used_file);
|
||||
$usage = $this->sumUsages($file_usage->listUsage($file));
|
||||
$this->assertRaw('admin/content/files/usage/' . $file->id() . '">' . $usage);
|
||||
|
||||
$result = $this->xpath("//td[contains(@class, 'views-field-status') and contains(text(), :value)]", array(':value' => t('Temporary')));
|
||||
$this->assertEqual(1, count($result), 'Unused file marked as temporary.');
|
||||
|
||||
// Test file usage page.
|
||||
foreach ($nodes as $node) {
|
||||
$file = entity_load('file', $node->file->target_id);
|
||||
$usage = $file_usage->listUsage($file);
|
||||
$this->drupalGet('admin/content/files/usage/' . $file->id());
|
||||
$this->assertResponse(200);
|
||||
$this->assertText($node->getTitle(), 'Node title found on usage page.');
|
||||
$this->assertText('node', 'Registering entity type found on usage page.');
|
||||
$this->assertText('file', 'Registering module found on usage page.');
|
||||
foreach ($usage as $module) {
|
||||
foreach ($module as $entity_type) {
|
||||
foreach ($entity_type as $entity) {
|
||||
$this->assertText($entity, 'Usage count found on usage page.');
|
||||
}
|
||||
}
|
||||
}
|
||||
$this->assertLinkByHref('node/' . $node->id(), 0, 'Link to registering entity found on usage page.');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates and saves a test file.
|
||||
*
|
||||
* @return \Drupal\Core\Entity\EntityInterface
|
||||
* A file entity.
|
||||
*/
|
||||
protected function createFile() {
|
||||
// Create a new file entity.
|
||||
$file = entity_create('file', array(
|
||||
'uid' => 1,
|
||||
'filename' => 'druplicon.txt',
|
||||
'uri' => 'public://druplicon.txt',
|
||||
'filemime' => 'text/plain',
|
||||
'created' => 1,
|
||||
'changed' => 1,
|
||||
'status' => FILE_STATUS_PERMANENT,
|
||||
));
|
||||
file_put_contents($file->getFileUri(), 'hello world');
|
||||
|
||||
// Save it, inserting a new record.
|
||||
$file->save();
|
||||
|
||||
return $file;
|
||||
}
|
||||
|
||||
}
|
145
core/modules/file/src/Tests/FileManagedFileElementTest.php
Normal file
145
core/modules/file/src/Tests/FileManagedFileElementTest.php
Normal file
|
@ -0,0 +1,145 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains \Drupal\file\Tests\FileManagedFileElementTest.
|
||||
*/
|
||||
|
||||
namespace Drupal\file\Tests;
|
||||
|
||||
/**
|
||||
* Tests the 'managed_file' element type.
|
||||
*
|
||||
* @group file
|
||||
* @todo Create a FileTestBase class and move FileFieldTestBase methods
|
||||
* that aren't related to fields into it.
|
||||
*/
|
||||
class FileManagedFileElementTest extends FileFieldTestBase {
|
||||
/**
|
||||
* Tests the managed_file element type.
|
||||
*/
|
||||
function testManagedFile() {
|
||||
// Check that $element['#size'] is passed to the child upload element.
|
||||
$this->drupalGet('file/test');
|
||||
$this->assertFieldByXpath('//input[@name="files[nested_file]" and @size="13"]', NULL, 'The custom #size attribute is passed to the child upload element.');
|
||||
|
||||
// Perform the tests with all permutations of $form['#tree'],
|
||||
// $element['#extended'], and $element['#multiple'].
|
||||
$test_file = $this->getTestFile('text');
|
||||
foreach (array(0, 1) as $tree) {
|
||||
foreach (array(0, 1) as $extended) {
|
||||
foreach (array(0, 1) as $multiple) {
|
||||
$path = 'file/test/' . $tree . '/' . $extended . '/' . $multiple;
|
||||
$input_base_name = $tree ? 'nested_file' : 'file';
|
||||
$file_field_name = $multiple ? 'files[' . $input_base_name . '][]' : 'files[' . $input_base_name . ']';
|
||||
|
||||
// Submit without a file.
|
||||
$this->drupalPostForm($path, array(), t('Save'));
|
||||
$this->assertRaw(t('The file ids are %fids.', array('%fids' => implode(',', array()))), 'Submitted without a file.');
|
||||
|
||||
// Submit a new file, without using the Upload button.
|
||||
$last_fid_prior = $this->getLastFileId();
|
||||
$edit = array($file_field_name => drupal_realpath($test_file->getFileUri()));
|
||||
$this->drupalPostForm($path, $edit, t('Save'));
|
||||
$last_fid = $this->getLastFileId();
|
||||
$this->assertTrue($last_fid > $last_fid_prior, 'New file got saved.');
|
||||
$this->assertRaw(t('The file ids are %fids.', array('%fids' => implode(',', array($last_fid)))), 'Submit handler has correct file info.');
|
||||
|
||||
// Submit no new input, but with a default file.
|
||||
$this->drupalPostForm($path . '/' . $last_fid, array(), t('Save'));
|
||||
$this->assertRaw(t('The file ids are %fids.', array('%fids' => implode(',', array($last_fid)))), 'Empty submission did not change an existing file.');
|
||||
|
||||
// Now, test the Upload and Remove buttons, with and without Ajax.
|
||||
foreach (array(FALSE, TRUE) as $ajax) {
|
||||
// Upload, then Submit.
|
||||
$last_fid_prior = $this->getLastFileId();
|
||||
$this->drupalGet($path);
|
||||
$edit = array($file_field_name => drupal_realpath($test_file->getFileUri()));
|
||||
if ($ajax) {
|
||||
$this->drupalPostAjaxForm(NULL, $edit, $input_base_name . '_upload_button');
|
||||
}
|
||||
else {
|
||||
$this->drupalPostForm(NULL, $edit, t('Upload'));
|
||||
}
|
||||
$last_fid = $this->getLastFileId();
|
||||
$this->assertTrue($last_fid > $last_fid_prior, 'New file got uploaded.');
|
||||
$this->drupalPostForm(NULL, array(), t('Save'));
|
||||
$this->assertRaw(t('The file ids are %fids.', array('%fids' => implode(',', array($last_fid)))), 'Submit handler has correct file info.');
|
||||
|
||||
// Remove, then Submit.
|
||||
$remove_button_title = $multiple ? t('Remove selected') : t('Remove');
|
||||
$remove_edit = array();
|
||||
if ($multiple) {
|
||||
$selected_checkbox = ($tree ? 'nested[file]' : 'file') . '[file_' . $last_fid . '][selected]';
|
||||
$remove_edit = array($selected_checkbox => '1');
|
||||
}
|
||||
$this->drupalGet($path . '/' . $last_fid);
|
||||
if ($ajax) {
|
||||
$this->drupalPostAjaxForm(NULL, $remove_edit, $input_base_name . '_remove_button');
|
||||
}
|
||||
else {
|
||||
$this->drupalPostForm(NULL, $remove_edit, $remove_button_title);
|
||||
}
|
||||
$this->drupalPostForm(NULL, array(), t('Save'));
|
||||
$this->assertRaw(t('The file ids are %fids.', array('%fids' => '')), 'Submission after file removal was successful.');
|
||||
|
||||
// Upload, then Remove, then Submit.
|
||||
$this->drupalGet($path);
|
||||
$edit = array($file_field_name => drupal_realpath($test_file->getFileUri()));
|
||||
if ($ajax) {
|
||||
$this->drupalPostAjaxForm(NULL, $edit, $input_base_name . '_upload_button');
|
||||
}
|
||||
else {
|
||||
$this->drupalPostForm(NULL, $edit, t('Upload'));
|
||||
}
|
||||
$remove_edit = array();
|
||||
if ($multiple) {
|
||||
$selected_checkbox = ($tree ? 'nested[file]' : 'file') . '[file_' . $this->getLastFileId() . '][selected]';
|
||||
$remove_edit = array($selected_checkbox => '1');
|
||||
}
|
||||
if ($ajax) {
|
||||
$this->drupalPostAjaxForm(NULL, $remove_edit, $input_base_name . '_remove_button');
|
||||
}
|
||||
else {
|
||||
$this->drupalPostForm(NULL, $remove_edit, $remove_button_title);
|
||||
}
|
||||
|
||||
$this->drupalPostForm(NULL, array(), t('Save'));
|
||||
$this->assertRaw(t('The file ids are %fids.', array('%fids' => '')), 'Submission after file upload and removal was successful.');
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// The multiple file upload has additional conditions that need checking.
|
||||
$path = 'file/test/1/1/1';
|
||||
$edit = array('files[nested_file][]' => drupal_realpath($test_file->getFileUri()));
|
||||
$fid_list = array();
|
||||
|
||||
$this->drupalGet($path);
|
||||
|
||||
// Add a single file to the upload field.
|
||||
$this->drupalPostForm(NULL, $edit, t('Upload'));
|
||||
$fid_list[] = $this->getLastFileId();
|
||||
$this->assertFieldByXpath('//input[@name="nested[file][file_' . $fid_list[0] . '][selected]"]', NULL, 'First file successfully uploaded to multiple file element.');
|
||||
|
||||
// Add another file to the same upload field.
|
||||
$this->drupalPostForm(NULL, $edit, t('Upload'));
|
||||
$fid_list[] = $this->getLastFileId();
|
||||
$this->assertFieldByXpath('//input[@name="nested[file][file_' . $fid_list[1] . '][selected]"]', NULL, 'Second file successfully uploaded to multiple file element.');
|
||||
|
||||
// Save the entire form.
|
||||
$this->drupalPostForm(NULL, array(), t('Save'));
|
||||
$this->assertRaw(t('The file ids are %fids.', array('%fids' => implode(',', $fid_list))), 'Two files saved into a single multiple file element.');
|
||||
|
||||
// Delete only the first file.
|
||||
$edit = array(
|
||||
'nested[file][file_' . $fid_list[0] . '][selected]' => '1',
|
||||
);
|
||||
$this->drupalPostForm($path . '/' . implode(',', $fid_list), $edit, t('Remove selected'));
|
||||
|
||||
// Check that the first file has been deleted but not the second.
|
||||
$this->assertNoFieldByXpath('//input[@name="nested[file][file_' . $fid_list[0] . '][selected]"]', NULL, 'An individual file can be deleted from a multiple file element.');
|
||||
$this->assertFieldByXpath('//input[@name="nested[file][file_' . $fid_list[1] . '][selected]"]', NULL, 'Second individual file not deleted when the first file is deleted from a multiple file element.');
|
||||
}
|
||||
}
|
204
core/modules/file/src/Tests/FileManagedTestBase.php
Normal file
204
core/modules/file/src/Tests/FileManagedTestBase.php
Normal file
|
@ -0,0 +1,204 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains \Drupal\file\Tests\FileManagedTestBase.
|
||||
*/
|
||||
|
||||
namespace Drupal\file\Tests;
|
||||
|
||||
use Drupal\file\FileInterface;
|
||||
use Drupal\simpletest\WebTestBase;
|
||||
|
||||
/**
|
||||
* Base class for file tests that use the file_test module to test uploads and
|
||||
* hooks.
|
||||
*/
|
||||
abstract class FileManagedTestBase extends WebTestBase {
|
||||
|
||||
/**
|
||||
* Modules to enable.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public static $modules = array('file_test', 'file');
|
||||
|
||||
protected function setUp() {
|
||||
parent::setUp();
|
||||
// Clear out any hook calls.
|
||||
file_test_reset();
|
||||
}
|
||||
|
||||
/**
|
||||
* Assert that all of the specified hook_file_* hooks were called once, other
|
||||
* values result in failure.
|
||||
*
|
||||
* @param array $expected
|
||||
* Array with string containing with the hook name, e.g. 'load', 'save',
|
||||
* 'insert', etc.
|
||||
*/
|
||||
function assertFileHooksCalled($expected) {
|
||||
\Drupal::state()->resetCache();
|
||||
|
||||
// Determine which hooks were called.
|
||||
$actual = array_keys(array_filter(file_test_get_all_calls()));
|
||||
|
||||
// Determine if there were any expected that were not called.
|
||||
$uncalled = array_diff($expected, $actual);
|
||||
if (count($uncalled)) {
|
||||
$this->assertTrue(FALSE, format_string('Expected hooks %expected to be called but %uncalled was not called.', array('%expected' => implode(', ', $expected), '%uncalled' => implode(', ', $uncalled))));
|
||||
}
|
||||
else {
|
||||
$this->assertTrue(TRUE, format_string('All the expected hooks were called: %expected', array('%expected' => empty($expected) ? '(none)' : implode(', ', $expected))));
|
||||
}
|
||||
|
||||
// Determine if there were any unexpected calls.
|
||||
$unexpected = array_diff($actual, $expected);
|
||||
if (count($unexpected)) {
|
||||
$this->assertTrue(FALSE, format_string('Unexpected hooks were called: %unexpected.', array('%unexpected' => empty($unexpected) ? '(none)' : implode(', ', $unexpected))));
|
||||
}
|
||||
else {
|
||||
$this->assertTrue(TRUE, 'No unexpected hooks were called.');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Assert that a hook_file_* hook was called a certain number of times.
|
||||
*
|
||||
* @param string $hook
|
||||
* String with the hook name, e.g. 'load', 'save', 'insert', etc.
|
||||
* @param int $expected_count
|
||||
* Optional integer count.
|
||||
* @param string|NULL $message
|
||||
* Optional translated string message.
|
||||
*/
|
||||
function assertFileHookCalled($hook, $expected_count = 1, $message = NULL) {
|
||||
$actual_count = count(file_test_get_calls($hook));
|
||||
|
||||
if (!isset($message)) {
|
||||
if ($actual_count == $expected_count) {
|
||||
$message = format_string('hook_file_@name was called correctly.', array('@name' => $hook));
|
||||
}
|
||||
elseif ($expected_count == 0) {
|
||||
$message = \Drupal::translation()->formatPlural($actual_count, 'hook_file_@name was not expected to be called but was actually called once.', 'hook_file_@name was not expected to be called but was actually called @count times.', array('@name' => $hook, '@count' => $actual_count));
|
||||
}
|
||||
else {
|
||||
$message = format_string('hook_file_@name was expected to be called %expected times but was called %actual times.', array('@name' => $hook, '%expected' => $expected_count, '%actual' => $actual_count));
|
||||
}
|
||||
}
|
||||
$this->assertEqual($actual_count, $expected_count, $message);
|
||||
}
|
||||
|
||||
/**
|
||||
* Asserts that two files have the same values (except timestamp).
|
||||
*
|
||||
* @param \Drupal\file\FileInterface $before
|
||||
* File object to compare.
|
||||
* @param \Drupal\file\FileInterface $after
|
||||
* File object to compare.
|
||||
*/
|
||||
function assertFileUnchanged(FileInterface $before, FileInterface $after) {
|
||||
$this->assertEqual($before->id(), $after->id(), t('File id is the same: %file1 == %file2.', array('%file1' => $before->id(), '%file2' => $after->id())), 'File unchanged');
|
||||
$this->assertEqual($before->getOwner()->id(), $after->getOwner()->id(), t('File owner is the same: %file1 == %file2.', array('%file1' => $before->getOwner()->id(), '%file2' => $after->getOwner()->id())), 'File unchanged');
|
||||
$this->assertEqual($before->getFilename(), $after->getFilename(), t('File name is the same: %file1 == %file2.', array('%file1' => $before->getFilename(), '%file2' => $after->getFilename())), 'File unchanged');
|
||||
$this->assertEqual($before->getFileUri(), $after->getFileUri(), t('File path is the same: %file1 == %file2.', array('%file1' => $before->getFileUri(), '%file2' => $after->getFileUri())), 'File unchanged');
|
||||
$this->assertEqual($before->getMimeType(), $after->getMimeType(), t('File MIME type is the same: %file1 == %file2.', array('%file1' => $before->getMimeType(), '%file2' => $after->getMimeType())), 'File unchanged');
|
||||
$this->assertEqual($before->getSize(), $after->getSize(), t('File size is the same: %file1 == %file2.', array('%file1' => $before->getSize(), '%file2' => $after->getSize())), 'File unchanged');
|
||||
$this->assertEqual($before->isPermanent(), $after->isPermanent(), t('File status is the same: %file1 == %file2.', array('%file1' => $before->isPermanent(), '%file2' => $after->isPermanent())), 'File unchanged');
|
||||
}
|
||||
|
||||
/**
|
||||
* Asserts that two files are not the same by comparing the fid and filepath.
|
||||
*
|
||||
* @param \Drupal\file\FileInterface $file1
|
||||
* File object to compare.
|
||||
* @param \Drupal\file\FileInterface $file2
|
||||
* File object to compare.
|
||||
*/
|
||||
function assertDifferentFile(FileInterface $file1, FileInterface $file2) {
|
||||
$this->assertNotEqual($file1->id(), $file2->id(), t('Files have different ids: %file1 != %file2.', array('%file1' => $file1->id(), '%file2' => $file2->id())), 'Different file');
|
||||
$this->assertNotEqual($file1->getFileUri(), $file2->getFileUri(), t('Files have different paths: %file1 != %file2.', array('%file1' => $file1->getFileUri(), '%file2' => $file2->getFileUri())), 'Different file');
|
||||
}
|
||||
|
||||
/**
|
||||
* Asserts that two files are the same by comparing the fid and filepath.
|
||||
*
|
||||
* @param \Drupal\file\FileInterface $file1
|
||||
* File object to compare.
|
||||
* @param \Drupal\file\FileInterface $file2
|
||||
* File object to compare.
|
||||
*/
|
||||
function assertSameFile(FileInterface $file1, FileInterface $file2) {
|
||||
$this->assertEqual($file1->id(), $file2->id(), t('Files have the same ids: %file1 == %file2.', array('%file1' => $file1->id(), '%file2-fid' => $file2->id())), 'Same file');
|
||||
$this->assertEqual($file1->getFileUri(), $file2->getFileUri(), t('Files have the same path: %file1 == %file2.', array('%file1' => $file1->getFileUri(), '%file2' => $file2->getFileUri())), 'Same file');
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a file and save it to the files table and assert that it occurs
|
||||
* correctly.
|
||||
*
|
||||
* @param string $filepath
|
||||
* Optional string specifying the file path. If none is provided then a
|
||||
* randomly named file will be created in the site's files directory.
|
||||
* @param string $contents
|
||||
* Optional contents to save into the file. If a NULL value is provided an
|
||||
* arbitrary string will be used.
|
||||
* @param string $scheme
|
||||
* Optional string indicating the stream scheme to use. Drupal core includes
|
||||
* public, private, and temporary. The public wrapper is the default.
|
||||
* @return \Drupal\file\FileInterface
|
||||
* File entity.
|
||||
*/
|
||||
function createFile($filepath = NULL, $contents = NULL, $scheme = NULL) {
|
||||
// Don't count hook invocations caused by creating the file.
|
||||
\Drupal::state()->set('file_test.count_hook_invocations', FALSE);
|
||||
$file = entity_create('file', array(
|
||||
'uri' => $this->createUri($filepath, $contents, $scheme),
|
||||
'uid' => 1,
|
||||
));
|
||||
$file->save();
|
||||
// Write the record directly rather than using the API so we don't invoke
|
||||
// the hooks.
|
||||
$this->assertTrue($file->id() > 0, 'The file was added to the database.', 'Create test file');
|
||||
|
||||
\Drupal::state()->set('file_test.count_hook_invocations', TRUE);
|
||||
return $file;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a file and returns its URI.
|
||||
*
|
||||
* @param string $filepath
|
||||
* Optional string specifying the file path. If none is provided then a
|
||||
* randomly named file will be created in the site's files directory.
|
||||
* @param string $contents
|
||||
* Optional contents to save into the file. If a NULL value is provided an
|
||||
* arbitrary string will be used.
|
||||
* @param string $scheme
|
||||
* Optional string indicating the stream scheme to use. Drupal core includes
|
||||
* public, private, and temporary. The public wrapper is the default.
|
||||
*
|
||||
* @return string
|
||||
* File URI.
|
||||
*/
|
||||
function createUri($filepath = NULL, $contents = NULL, $scheme = NULL) {
|
||||
if (!isset($filepath)) {
|
||||
// Prefix with non-latin characters to ensure that all file-related
|
||||
// tests work with international filenames.
|
||||
$filepath = 'Файл для тестирования ' . $this->randomMachineName();
|
||||
}
|
||||
if (!isset($scheme)) {
|
||||
$scheme = file_default_scheme();
|
||||
}
|
||||
$filepath = $scheme . '://' . $filepath;
|
||||
|
||||
if (!isset($contents)) {
|
||||
$contents = "file_put_contents() doesn't seem to appreciate empty strings so let's put in some data.";
|
||||
}
|
||||
|
||||
file_put_contents($filepath, $contents);
|
||||
$this->assertTrue(is_file($filepath), t('The test file exists on the disk.'), 'Create test file');
|
||||
return $filepath;
|
||||
}
|
||||
|
||||
}
|
216
core/modules/file/src/Tests/FileManagedUnitTestBase.php
Normal file
216
core/modules/file/src/Tests/FileManagedUnitTestBase.php
Normal file
|
@ -0,0 +1,216 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains \Drupal\file\Tests\FileManagedUnitTestBase.
|
||||
*/
|
||||
|
||||
namespace Drupal\file\Tests;
|
||||
|
||||
use Drupal\file\FileInterface;
|
||||
use Drupal\simpletest\KernelTestBase;
|
||||
|
||||
/**
|
||||
* Base class for file unit tests that use the file_test module to test uploads and
|
||||
* hooks.
|
||||
*/
|
||||
abstract class FileManagedUnitTestBase extends KernelTestBase {
|
||||
|
||||
/**
|
||||
* Modules to enable.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public static $modules = array('file_test', 'file', 'system', 'field', 'user');
|
||||
|
||||
protected function setUp() {
|
||||
parent::setUp();
|
||||
// Clear out any hook calls.
|
||||
file_test_reset();
|
||||
|
||||
$this->installConfig(array('system'));
|
||||
$this->installEntitySchema('file');
|
||||
$this->installEntitySchema('user');
|
||||
$this->installSchema('file', array('file_usage'));
|
||||
|
||||
// Make sure that a user with uid 1 exists, self::createFile() relies on
|
||||
// it.
|
||||
$user = entity_create('user', array('uid' => 1, 'name' => $this->randomMachineName()));
|
||||
$user->enforceIsNew();
|
||||
$user->save();
|
||||
\Drupal::currentUser()->setAccount($user);
|
||||
}
|
||||
|
||||
/**
|
||||
* Assert that all of the specified hook_file_* hooks were called once, other
|
||||
* values result in failure.
|
||||
*
|
||||
* @param array $expected
|
||||
* Array with string containing with the hook name, e.g. 'load', 'save',
|
||||
* 'insert', etc.
|
||||
*/
|
||||
function assertFileHooksCalled($expected) {
|
||||
\Drupal::state()->resetCache();
|
||||
|
||||
// Determine which hooks were called.
|
||||
$actual = array_keys(array_filter(file_test_get_all_calls()));
|
||||
|
||||
// Determine if there were any expected that were not called.
|
||||
$uncalled = array_diff($expected, $actual);
|
||||
if (count($uncalled)) {
|
||||
$this->assertTrue(FALSE, format_string('Expected hooks %expected to be called but %uncalled was not called.', array('%expected' => implode(', ', $expected), '%uncalled' => implode(', ', $uncalled))));
|
||||
}
|
||||
else {
|
||||
$this->assertTrue(TRUE, format_string('All the expected hooks were called: %expected', array('%expected' => empty($expected) ? '(none)' : implode(', ', $expected))));
|
||||
}
|
||||
|
||||
// Determine if there were any unexpected calls.
|
||||
$unexpected = array_diff($actual, $expected);
|
||||
if (count($unexpected)) {
|
||||
$this->assertTrue(FALSE, format_string('Unexpected hooks were called: %unexpected.', array('%unexpected' => empty($unexpected) ? '(none)' : implode(', ', $unexpected))));
|
||||
}
|
||||
else {
|
||||
$this->assertTrue(TRUE, 'No unexpected hooks were called.');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Assert that a hook_file_* hook was called a certain number of times.
|
||||
*
|
||||
* @param string $hook
|
||||
* String with the hook name, e.g. 'load', 'save', 'insert', etc.
|
||||
* @param int $expected_count
|
||||
* Optional integer count.
|
||||
* @param string $message
|
||||
* Optional translated string message.
|
||||
*/
|
||||
function assertFileHookCalled($hook, $expected_count = 1, $message = NULL) {
|
||||
$actual_count = count(file_test_get_calls($hook));
|
||||
|
||||
if (!isset($message)) {
|
||||
if ($actual_count == $expected_count) {
|
||||
$message = format_string('hook_file_@name was called correctly.', array('@name' => $hook));
|
||||
}
|
||||
elseif ($expected_count == 0) {
|
||||
$message = \Drupal::translation()->formatPlural($actual_count, 'hook_file_@name was not expected to be called but was actually called once.', 'hook_file_@name was not expected to be called but was actually called @count times.', array('@name' => $hook, '@count' => $actual_count));
|
||||
}
|
||||
else {
|
||||
$message = format_string('hook_file_@name was expected to be called %expected times but was called %actual times.', array('@name' => $hook, '%expected' => $expected_count, '%actual' => $actual_count));
|
||||
}
|
||||
}
|
||||
$this->assertEqual($actual_count, $expected_count, $message);
|
||||
}
|
||||
|
||||
/**
|
||||
* Asserts that two files have the same values (except timestamp).
|
||||
*
|
||||
* @param \Drupal\file\FileInterface $before
|
||||
* File object to compare.
|
||||
* @param \Drupal\file\FileInterface $after
|
||||
* File object to compare.
|
||||
*/
|
||||
function assertFileUnchanged(FileInterface $before, FileInterface $after) {
|
||||
$this->assertEqual($before->id(), $after->id(), t('File id is the same: %file1 == %file2.', array('%file1' => $before->id(), '%file2' => $after->id())), 'File unchanged');
|
||||
$this->assertEqual($before->getOwner()->id(), $after->getOwner()->id(), t('File owner is the same: %file1 == %file2.', array('%file1' => $before->getOwner()->id(), '%file2' => $after->getOwner()->id())), 'File unchanged');
|
||||
$this->assertEqual($before->getFilename(), $after->getFilename(), t('File name is the same: %file1 == %file2.', array('%file1' => $before->getFilename(), '%file2' => $after->getFilename())), 'File unchanged');
|
||||
$this->assertEqual($before->getFileUri(), $after->getFileUri(), t('File path is the same: %file1 == %file2.', array('%file1' => $before->getFileUri(), '%file2' => $after->getFileUri())), 'File unchanged');
|
||||
$this->assertEqual($before->getMimeType(), $after->getMimeType(), t('File MIME type is the same: %file1 == %file2.', array('%file1' => $before->getMimeType(), '%file2' => $after->getMimeType())), 'File unchanged');
|
||||
$this->assertEqual($before->getSize(), $after->getSize(), t('File size is the same: %file1 == %file2.', array('%file1' => $before->getSize(), '%file2' => $after->getSize())), 'File unchanged');
|
||||
$this->assertEqual($before->isPermanent(), $after->isPermanent(), t('File status is the same: %file1 == %file2.', array('%file1' => $before->isPermanent(), '%file2' => $after->isPermanent())), 'File unchanged');
|
||||
}
|
||||
|
||||
/**
|
||||
* Asserts that two files are not the same by comparing the fid and filepath.
|
||||
*
|
||||
* @param \Drupal\file\FileInterface $file1
|
||||
* File object to compare.
|
||||
* @param \Drupal\file\FileInterface $file2
|
||||
* File object to compare.
|
||||
*/
|
||||
function assertDifferentFile(FileInterface $file1, FileInterface $file2) {
|
||||
$this->assertNotEqual($file1->id(), $file2->id(), t('Files have different ids: %file1 != %file2.', array('%file1' => $file1->id(), '%file2' => $file2->id())), 'Different file');
|
||||
$this->assertNotEqual($file1->getFileUri(), $file2->getFileUri(), t('Files have different paths: %file1 != %file2.', array('%file1' => $file1->getFileUri(), '%file2' => $file2->getFileUri())), 'Different file');
|
||||
}
|
||||
|
||||
/**
|
||||
* Asserts that two files are the same by comparing the fid and filepath.
|
||||
*
|
||||
* @param \Drupal\file\FileInterface $file1
|
||||
* File object to compare.
|
||||
* @param \Drupal\file\FileInterface $file2
|
||||
* File object to compare.
|
||||
*/
|
||||
function assertSameFile(FileInterface $file1, FileInterface $file2) {
|
||||
$this->assertEqual($file1->id(), $file2->id(), t('Files have the same ids: %file1 == %file2.', array('%file1' => $file1->id(), '%file2-fid' => $file2->id())), 'Same file');
|
||||
$this->assertEqual($file1->getFileUri(), $file2->getFileUri(), t('Files have the same path: %file1 == %file2.', array('%file1' => $file1->getFileUri(), '%file2' => $file2->getFileUri())), 'Same file');
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a file and save it to the files table and assert that it occurs
|
||||
* correctly.
|
||||
*
|
||||
* @param string $filepath
|
||||
* Optional string specifying the file path. If none is provided then a
|
||||
* randomly named file will be created in the site's files directory.
|
||||
* @param string $contents
|
||||
* Optional contents to save into the file. If a NULL value is provided an
|
||||
* arbitrary string will be used.
|
||||
* @param string $scheme
|
||||
* Optional string indicating the stream scheme to use. Drupal core includes
|
||||
* public, private, and temporary. The public wrapper is the default.
|
||||
* @return \Drupal\file\FileInterface
|
||||
* File entity.
|
||||
*/
|
||||
function createFile($filepath = NULL, $contents = NULL, $scheme = NULL) {
|
||||
// Don't count hook invocations caused by creating the file.
|
||||
\Drupal::state()->set('file_test.count_hook_invocations', FALSE);
|
||||
$file = entity_create('file', array(
|
||||
'uri' => $this->createUri($filepath, $contents, $scheme),
|
||||
'uid' => 1,
|
||||
));
|
||||
$file->save();
|
||||
// Write the record directly rather than using the API so we don't invoke
|
||||
// the hooks.
|
||||
$this->assertTrue($file->id() > 0, 'The file was added to the database.', 'Create test file');
|
||||
|
||||
\Drupal::state()->set('file_test.count_hook_invocations', TRUE);
|
||||
return $file;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a file and returns its URI.
|
||||
*
|
||||
* @param string $filepath
|
||||
* Optional string specifying the file path. If none is provided then a
|
||||
* randomly named file will be created in the site's files directory.
|
||||
* @param string $contents
|
||||
* Optional contents to save into the file. If a NULL value is provided an
|
||||
* arbitrary string will be used.
|
||||
* @param string $scheme
|
||||
* Optional string indicating the stream scheme to use. Drupal core includes
|
||||
* public, private, and temporary. The public wrapper is the default.
|
||||
*
|
||||
* @return string
|
||||
* File URI.
|
||||
*/
|
||||
function createUri($filepath = NULL, $contents = NULL, $scheme = NULL) {
|
||||
if (!isset($filepath)) {
|
||||
// Prefix with non-latin characters to ensure that all file-related
|
||||
// tests work with international filenames.
|
||||
$filepath = 'Файл для тестирования ' . $this->randomMachineName();
|
||||
}
|
||||
if (!isset($scheme)) {
|
||||
$scheme = file_default_scheme();
|
||||
}
|
||||
$filepath = $scheme . '://' . $filepath;
|
||||
|
||||
if (!isset($contents)) {
|
||||
$contents = "file_put_contents() doesn't seem to appreciate empty strings so let's put in some data.";
|
||||
}
|
||||
|
||||
file_put_contents($filepath, $contents);
|
||||
$this->assertTrue(is_file($filepath), t('The test file exists on the disk.'), 'Create test file');
|
||||
return $filepath;
|
||||
}
|
||||
|
||||
}
|
119
core/modules/file/src/Tests/FilePrivateTest.php
Normal file
119
core/modules/file/src/Tests/FilePrivateTest.php
Normal file
|
@ -0,0 +1,119 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains \Drupal\file\Tests\FilePrivateTest.
|
||||
*/
|
||||
|
||||
namespace Drupal\file\Tests;
|
||||
|
||||
use Drupal\Core\Entity\Plugin\Validation\Constraint\ReferenceAccessConstraint;
|
||||
use Drupal\Component\Utility\SafeMarkup;
|
||||
use Drupal\file\Entity\File;
|
||||
use Drupal\node\Entity\NodeType;
|
||||
|
||||
/**
|
||||
* Uploads a test to a private node and checks access.
|
||||
*
|
||||
* @group file
|
||||
*/
|
||||
class FilePrivateTest extends FileFieldTestBase {
|
||||
|
||||
/**
|
||||
* Modules to enable.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public static $modules = array('node_access_test', 'field_test');
|
||||
|
||||
protected function setUp() {
|
||||
parent::setUp();
|
||||
node_access_test_add_field(NodeType::load('article'));
|
||||
node_access_rebuild();
|
||||
\Drupal::state()->set('node_access_test.private', TRUE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests file access for file uploaded to a private node.
|
||||
*/
|
||||
function testPrivateFile() {
|
||||
$node_storage = $this->container->get('entity.manager')->getStorage('node');
|
||||
$type_name = 'article';
|
||||
$field_name = strtolower($this->randomMachineName());
|
||||
$this->createFileField($field_name, 'node', $type_name, array('uri_scheme' => 'private'));
|
||||
|
||||
$test_file = $this->getTestFile('text');
|
||||
$nid = $this->uploadNodeFile($test_file, $field_name, $type_name, TRUE, array('private' => TRUE));
|
||||
\Drupal::entityManager()->getStorage('node')->resetCache(array($nid));
|
||||
/* @var \Drupal\node\NodeInterface $node */
|
||||
$node = $node_storage->load($nid);
|
||||
$node_file = File::load($node->{$field_name}->target_id);
|
||||
// Ensure the file can be viewed.
|
||||
$this->drupalGet('node/' . $node->id());
|
||||
$this->assertRaw($node_file->getFilename(), 'File reference is displayed after attaching it');
|
||||
// Ensure the file can be downloaded.
|
||||
$this->drupalGet(file_create_url($node_file->getFileUri()));
|
||||
$this->assertResponse(200, 'Confirmed that the generated URL is correct by downloading the shipped file.');
|
||||
$this->drupalLogOut();
|
||||
$this->drupalGet(file_create_url($node_file->getFileUri()));
|
||||
$this->assertResponse(403, 'Confirmed that access is denied for the file without the needed permission.');
|
||||
|
||||
// Create a field with no view access. See
|
||||
// field_test_entity_field_access().
|
||||
$no_access_field_name = 'field_no_view_access';
|
||||
$this->createFileField($no_access_field_name, 'node', $type_name, array('uri_scheme' => 'private'));
|
||||
// Test with the field that should deny access through field access.
|
||||
$this->drupalLogin($this->adminUser);
|
||||
$nid = $this->uploadNodeFile($test_file, $no_access_field_name, $type_name, TRUE, array('private' => TRUE));
|
||||
\Drupal::entityManager()->getStorage('node')->resetCache(array($nid));
|
||||
$node = $node_storage->load($nid);
|
||||
$node_file = File::load($node->{$no_access_field_name}->target_id);
|
||||
|
||||
// Ensure the file cannot be downloaded.
|
||||
$file_url = file_create_url($node_file->getFileUri());
|
||||
$this->drupalGet($file_url);
|
||||
$this->assertResponse(403, 'Confirmed that access is denied for the file without view field access permission.');
|
||||
|
||||
// Attempt to reuse the file when editing a node.
|
||||
$edit = array();
|
||||
$edit['title[0][value]'] = $this->randomMachineName();
|
||||
$this->drupalPostForm('node/add/' . $type_name, $edit, t('Save and publish'));
|
||||
$new_node = $this->drupalGetNodeByTitle($edit['title[0][value]']);
|
||||
$edit[$field_name . '[0][fids]'] = $node_file->id();
|
||||
$this->drupalPostForm('node/' . $new_node->id() .'/edit', $edit, t('Save and keep published'));
|
||||
// Make sure the form submit failed - we stayed on the edit form.
|
||||
$this->assertUrl('node/' . $new_node->id() .'/edit');
|
||||
// Check that we got the expected constraint form error.
|
||||
$constraint = new ReferenceAccessConstraint();
|
||||
$this->assertRaw(SafeMarkup::format($constraint->message, array('%type' => 'file', '%id' => $node_file->id())));
|
||||
// Attempt to reuse the existing file when creating a new node, and confirm
|
||||
// that access is still denied.
|
||||
$edit = array();
|
||||
$edit['title[0][value]'] = $this->randomMachineName();
|
||||
$edit[$field_name . '[0][fids]'] = $node_file->id();
|
||||
$this->drupalPostForm('node/add/' . $type_name, $edit, t('Save and publish'));
|
||||
$new_node = $this->drupalGetNodeByTitle($edit['title[0][value]']);
|
||||
$this->assertTrue(empty($new_node), 'Node was not created.');
|
||||
$this->assertUrl('node/add/' . $type_name);
|
||||
$this->assertRaw(SafeMarkup::format($constraint->message, array('%type' => 'file', '%id' => $node_file->id())));
|
||||
|
||||
// Now make file_test_file_download() return everything.
|
||||
\Drupal::state()->set('file_test.allow_all', TRUE);
|
||||
// Delete the node.
|
||||
$node->delete();
|
||||
// Ensure the file can still be downloaded by the owner.
|
||||
$this->drupalGet($file_url);
|
||||
$this->assertResponse(200, 'Confirmed that the owner still has access to the temporary file.');
|
||||
|
||||
// Ensure the file cannot be downloaded by an anonymous user.
|
||||
$this->drupalLogout();
|
||||
$this->drupalGet($file_url);
|
||||
$this->assertResponse(403, 'Confirmed that access is denied for an anonymous user to the temporary file.');
|
||||
|
||||
// Ensure the file cannot be downloaded by another user.
|
||||
$account = $this->drupalCreateUser();
|
||||
$this->drupalLogin($account);
|
||||
$this->drupalGet($file_url);
|
||||
$this->assertResponse(403, 'Confirmed that access is denied for another user to the temporary file.');
|
||||
}
|
||||
}
|
79
core/modules/file/src/Tests/FileTokenReplaceTest.php
Normal file
79
core/modules/file/src/Tests/FileTokenReplaceTest.php
Normal file
|
@ -0,0 +1,79 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains \Drupal\file\Tests\FileTokenReplaceTest.
|
||||
*/
|
||||
|
||||
namespace Drupal\file\Tests;
|
||||
|
||||
use Drupal\Component\Utility\SafeMarkup;
|
||||
|
||||
/**
|
||||
* Generates text using placeholders for dummy content to check file token
|
||||
* replacement.
|
||||
*
|
||||
* @group file
|
||||
*/
|
||||
class FileTokenReplaceTest extends FileFieldTestBase {
|
||||
/**
|
||||
* Creates a file, then tests the tokens generated from it.
|
||||
*/
|
||||
function testFileTokenReplacement() {
|
||||
$node_storage = $this->container->get('entity.manager')->getStorage('node');
|
||||
$token_service = \Drupal::token();
|
||||
$language_interface = \Drupal::languageManager()->getCurrentLanguage();
|
||||
|
||||
// Create file field.
|
||||
$type_name = 'article';
|
||||
$field_name = 'field_' . strtolower($this->randomMachineName());
|
||||
$this->createFileField($field_name, 'node', $type_name);
|
||||
|
||||
$test_file = $this->getTestFile('text');
|
||||
// Coping a file to test uploads with non-latin filenames.
|
||||
$filename = drupal_dirname($test_file->getFileUri()) . '/текстовый файл.txt';
|
||||
$test_file = file_copy($test_file, $filename);
|
||||
|
||||
// Create a new node with the uploaded file.
|
||||
$nid = $this->uploadNodeFile($test_file, $field_name, $type_name);
|
||||
|
||||
// Load the node and the file.
|
||||
$node_storage->resetCache(array($nid));
|
||||
$node = $node_storage->load($nid);
|
||||
$file = file_load($node->{$field_name}->target_id);
|
||||
|
||||
// Generate and test sanitized tokens.
|
||||
$tests = array();
|
||||
$tests['[file:fid]'] = $file->id();
|
||||
$tests['[file:name]'] = SafeMarkup::checkPlain($file->getFilename());
|
||||
$tests['[file:path]'] = SafeMarkup::checkPlain($file->getFileUri());
|
||||
$tests['[file:mime]'] = SafeMarkup::checkPlain($file->getMimeType());
|
||||
$tests['[file:size]'] = format_size($file->getSize());
|
||||
$tests['[file:url]'] = SafeMarkup::checkPlain(file_create_url($file->getFileUri()));
|
||||
$tests['[file:created]'] = format_date($file->getCreatedTime(), 'medium', '', NULL, $language_interface->getId());
|
||||
$tests['[file:created:short]'] = format_date($file->getCreatedTime(), 'short', '', NULL, $language_interface->getId());
|
||||
$tests['[file:changed]'] = format_date($file->getChangedTime(), 'medium', '', NULL, $language_interface->getId());
|
||||
$tests['[file:changed:short]'] = format_date($file->getChangedTime(), 'short', '', NULL, $language_interface->getId());
|
||||
$tests['[file:owner]'] = SafeMarkup::checkPlain(user_format_name($this->adminUser));
|
||||
$tests['[file:owner:uid]'] = $file->getOwnerId();
|
||||
|
||||
// Test to make sure that we generated something for each token.
|
||||
$this->assertFalse(in_array(0, array_map('strlen', $tests)), 'No empty tokens generated.');
|
||||
|
||||
foreach ($tests as $input => $expected) {
|
||||
$output = $token_service->replace($input, array('file' => $file), array('langcode' => $language_interface->getId()));
|
||||
$this->assertEqual($output, $expected, format_string('Sanitized file token %token replaced.', array('%token' => $input)));
|
||||
}
|
||||
|
||||
// Generate and test unsanitized tokens.
|
||||
$tests['[file:name]'] = $file->getFilename();
|
||||
$tests['[file:path]'] = $file->getFileUri();
|
||||
$tests['[file:mime]'] = $file->getMimeType();
|
||||
$tests['[file:size]'] = format_size($file->getSize());
|
||||
|
||||
foreach ($tests as $input => $expected) {
|
||||
$output = $token_service->replace($input, array('file' => $file), array('langcode' => $language_interface->getId(), 'sanitize' => FALSE));
|
||||
$this->assertEqual($output, $expected, format_string('Unsanitized file token %token replaced.', array('%token' => $input)));
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,173 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains \Drupal\file\Tests\Formatter\FileEntityFormatterTest.
|
||||
*/
|
||||
|
||||
namespace Drupal\file\Tests\Formatter;
|
||||
|
||||
use Drupal\Core\Entity\Entity\EntityViewDisplay;
|
||||
use Drupal\Core\Url;
|
||||
use Drupal\file\Entity\File;
|
||||
use Drupal\simpletest\KernelTestBase;
|
||||
|
||||
/**
|
||||
* Tests the default file formatter.
|
||||
*
|
||||
* @group field
|
||||
*/
|
||||
class FileEntityFormatterTest extends KernelTestBase {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static $modules = ['file', 'user'];
|
||||
|
||||
/**
|
||||
* The files.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $files;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function setUp() {
|
||||
parent::setUp();
|
||||
|
||||
$this->installEntitySchema('file');
|
||||
|
||||
$this->files = [];
|
||||
file_put_contents('public://file.png', str_repeat('t', 10));
|
||||
$file = File::create([
|
||||
'uri' => 'public://file.png',
|
||||
'filename' => 'file.png',
|
||||
]);
|
||||
$file->save();
|
||||
$this->files[] = $file;
|
||||
|
||||
file_put_contents('public://file.tar', str_repeat('t', 200));
|
||||
$file = File::create([
|
||||
'uri' => 'public://file.tar',
|
||||
'filename' => 'file.tar',
|
||||
]);
|
||||
$file->save();
|
||||
$this->files[] = $file;
|
||||
|
||||
file_put_contents('public://file.tar.gz', str_repeat('t', 40000));
|
||||
$file = File::create([
|
||||
'uri' => 'public://file.tar.gz',
|
||||
'filename' => 'file.tar.gz',
|
||||
]);
|
||||
$file->save();
|
||||
$this->files[] = $file;
|
||||
|
||||
file_put_contents('public://file', str_repeat('t', 8000000));
|
||||
$file = File::create([
|
||||
'uri' => 'public://file',
|
||||
'filename' => 'file',
|
||||
]);
|
||||
$file->save();
|
||||
$this->files[] = $file;
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the file_link field formatter.
|
||||
*/
|
||||
public function testFormatterFileLink() {
|
||||
$entity_display = EntityViewDisplay::create([
|
||||
'targetEntityType' => 'file',
|
||||
'bundle' => 'file',
|
||||
]);
|
||||
$entity_display->setComponent('filename', ['type' => 'file_link']);
|
||||
|
||||
$build = $entity_display->buildMultiple($this->files)[0]['filename'][0];
|
||||
$this->assertEqual('file.png', $build['#title']);
|
||||
$this->assertEqual(Url::fromUri(file_create_url('public://file.png')), $build['#url']);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the file_link field formatter.
|
||||
*/
|
||||
public function testFormatterFileUri() {
|
||||
$entity_display = EntityViewDisplay::create([
|
||||
'targetEntityType' => 'file',
|
||||
'bundle' => 'file',
|
||||
]);
|
||||
$entity_display->setComponent('uri', ['type' => 'file_uri']);
|
||||
|
||||
$build = $entity_display->buildMultiple($this->files)[0]['uri'][0];
|
||||
$this->assertEqual('public://file.png', $build['#markup']);
|
||||
|
||||
$entity_display->setComponent('uri', ['type' => 'file_uri', 'settings' => ['file_download_path' => TRUE]]);
|
||||
$build = $entity_display->buildMultiple($this->files)[0]['uri'][0];
|
||||
$this->assertEqual(file_create_url('public://file.png'), $build['#markup']);
|
||||
|
||||
$entity_display->setComponent('uri', ['type' => 'file_uri', 'settings' => ['file_download_path' => TRUE, 'link_to_file' => TRUE]]);
|
||||
$build = $entity_display->buildMultiple($this->files)[0]['uri'][0];
|
||||
$this->assertEqual(file_create_url('public://file.png'), $build['#title']);
|
||||
$this->assertEqual(Url::fromUri(file_create_url('public://file.png')), $build['#url']);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the file_extension field formatter.
|
||||
*/
|
||||
public function testFormatterFileExtension() {
|
||||
$entity_display = EntityViewDisplay::create([
|
||||
'targetEntityType' => 'file',
|
||||
'bundle' => 'file',
|
||||
]);
|
||||
$entity_display->setComponent('filename', ['type' => 'file_extension']);
|
||||
|
||||
$expected = ['png', 'tar', 'gz', ''];
|
||||
foreach (array_values($this->files) as $i => $file) {
|
||||
$build = $entity_display->build($file);
|
||||
$this->assertEqual($expected[$i], $build['filename'][0]['#markup']);
|
||||
}
|
||||
|
||||
$entity_display->setComponent('filename', ['type' => 'file_extension', 'settings' => ['extension_detect_tar' => TRUE]]);
|
||||
|
||||
$expected = ['png', 'tar', 'tar.gz', ''];
|
||||
foreach (array_values($this->files) as $i => $file) {
|
||||
$build = $entity_display->build($file);
|
||||
$this->assertEqual($expected[$i], $build['filename'][0]['#markup']);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the file_extension field formatter.
|
||||
*/
|
||||
public function testFormatterFileMime() {
|
||||
$entity_display = EntityViewDisplay::create([
|
||||
'targetEntityType' => 'file',
|
||||
'bundle' => 'file',
|
||||
]);
|
||||
$entity_display->setComponent('filemime', ['type' => 'file_filemime', 'settings' => ['filemime_image' => TRUE]]);
|
||||
|
||||
foreach (array_values($this->files) as $i => $file) {
|
||||
$build = $entity_display->build($file);
|
||||
$this->assertEqual('image__file_icon', $build['filemime'][0]['#theme']);
|
||||
$this->assertEqual(spl_object_hash($file), spl_object_hash($build['filemime'][0]['#file']));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the file_size field formatter.
|
||||
*/
|
||||
public function testFormatterFileSize() {
|
||||
$entity_display = EntityViewDisplay::create([
|
||||
'targetEntityType' => 'file',
|
||||
'bundle' => 'file',
|
||||
]);
|
||||
$entity_display->setComponent('filesize', ['type' => 'file_size']);
|
||||
|
||||
$expected = ['10 bytes', '200 bytes', '39.06 KB', '7.63 MB'];
|
||||
foreach (array_values($this->files) as $i => $file) {
|
||||
$build = $entity_display->build($file);
|
||||
$this->assertEqual($expected[$i], $build['filesize'][0]['#markup']);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
104
core/modules/file/src/Tests/LoadTest.php
Normal file
104
core/modules/file/src/Tests/LoadTest.php
Normal file
|
@ -0,0 +1,104 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains \Drupal\file\Tests\LoadTest.
|
||||
*/
|
||||
|
||||
namespace Drupal\file\Tests;
|
||||
|
||||
/**
|
||||
* Tests the file_load() function.
|
||||
*
|
||||
* @group file
|
||||
*/
|
||||
class LoadTest extends FileManagedUnitTestBase {
|
||||
/**
|
||||
* Try to load a non-existent file by fid.
|
||||
*/
|
||||
function testLoadMissingFid() {
|
||||
$this->assertFalse(file_load(-1), 'Try to load an invalid fid fails.');
|
||||
$this->assertFileHooksCalled(array());
|
||||
}
|
||||
|
||||
/**
|
||||
* Try to load a non-existent file by URI.
|
||||
*/
|
||||
function testLoadMissingFilepath() {
|
||||
$files = entity_load_multiple_by_properties('file', array('uri' => 'foobar://misc/druplicon.png'));
|
||||
$this->assertFalse(reset($files), "Try to load a file that doesn't exist in the database fails.");
|
||||
$this->assertFileHooksCalled(array());
|
||||
}
|
||||
|
||||
/**
|
||||
* Try to load a non-existent file by status.
|
||||
*/
|
||||
function testLoadInvalidStatus() {
|
||||
$files = entity_load_multiple_by_properties('file', array('status' => -99));
|
||||
$this->assertFalse(reset($files), 'Trying to load a file with an invalid status fails.');
|
||||
$this->assertFileHooksCalled(array());
|
||||
}
|
||||
|
||||
/**
|
||||
* Load a single file and ensure that the correct values are returned.
|
||||
*/
|
||||
function testSingleValues() {
|
||||
// Create a new file entity from scratch so we know the values.
|
||||
$file = $this->createFile('druplicon.txt', NULL, 'public');
|
||||
|
||||
$by_fid_file = file_load($file->id());
|
||||
$this->assertFileHookCalled('load');
|
||||
$this->assertTrue(is_object($by_fid_file), 'file_load() returned an object.');
|
||||
$this->assertEqual($by_fid_file->id(), $file->id(), 'Loading by fid got the same fid.', 'File');
|
||||
$this->assertEqual($by_fid_file->getFileUri(), $file->getFileUri(), 'Loading by fid got the correct filepath.', 'File');
|
||||
$this->assertEqual($by_fid_file->getFilename(), $file->getFilename(), 'Loading by fid got the correct filename.', 'File');
|
||||
$this->assertEqual($by_fid_file->getMimeType(), $file->getMimeType(), 'Loading by fid got the correct MIME type.', 'File');
|
||||
$this->assertEqual($by_fid_file->isPermanent(), $file->isPermanent(), 'Loading by fid got the correct status.', 'File');
|
||||
$this->assertTrue($by_fid_file->file_test['loaded'], 'file_test_file_load() was able to modify the file during load.');
|
||||
}
|
||||
|
||||
/**
|
||||
* This will test loading file data from the database.
|
||||
*/
|
||||
function testMultiple() {
|
||||
// Create a new file entity.
|
||||
$file = $this->createFile('druplicon.txt', NULL, 'public');
|
||||
|
||||
// Load by path.
|
||||
file_test_reset();
|
||||
$by_path_files = entity_load_multiple_by_properties('file', array('uri' => $file->getFileUri()));
|
||||
$this->assertFileHookCalled('load');
|
||||
$this->assertEqual(1, count($by_path_files), 'file_load_multiple() returned an array of the correct size.');
|
||||
$by_path_file = reset($by_path_files);
|
||||
$this->assertTrue($by_path_file->file_test['loaded'], 'file_test_file_load() was able to modify the file during load.');
|
||||
$this->assertEqual($by_path_file->id(), $file->id(), 'Loading by filepath got the correct fid.', 'File');
|
||||
|
||||
// Load by fid.
|
||||
file_test_reset();
|
||||
$by_fid_files = file_load_multiple(array($file->id()));
|
||||
$this->assertFileHooksCalled(array());
|
||||
$this->assertEqual(1, count($by_fid_files), 'file_load_multiple() returned an array of the correct size.');
|
||||
$by_fid_file = reset($by_fid_files);
|
||||
$this->assertTrue($by_fid_file->file_test['loaded'], 'file_test_file_load() was able to modify the file during load.');
|
||||
$this->assertEqual($by_fid_file->getFileUri(), $file->getFileUri(), 'Loading by fid got the correct filepath.', 'File');
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads a single file and ensure that the correct values are returned.
|
||||
*/
|
||||
public function testUuidValues() {
|
||||
// Create a new file entity from scratch so we know the values.
|
||||
$file = $this->createFile('druplicon.txt', NULL, 'public');
|
||||
$file->save();
|
||||
file_test_reset();
|
||||
|
||||
$by_uuid_file = \Drupal::entityManager()->loadEntityByUuid('file', $file->uuid());
|
||||
$this->assertFileHookCalled('load');
|
||||
$this->assertTrue(is_object($by_uuid_file), '\Drupal::entityManager()->loadEntityByUuid() returned a file object.');
|
||||
if (is_object($by_uuid_file)) {
|
||||
$this->assertEqual($by_uuid_file->id(), $file->id(), 'Loading by UUID got the same fid.', 'File');
|
||||
$this->assertTrue($by_uuid_file->file_test['loaded'], 'file_test_file_load() was able to modify the file during load.');
|
||||
}
|
||||
}
|
||||
|
||||
}
|
162
core/modules/file/src/Tests/MoveTest.php
Normal file
162
core/modules/file/src/Tests/MoveTest.php
Normal file
|
@ -0,0 +1,162 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains \Drupal\file\Tests\MoveTest.
|
||||
*/
|
||||
|
||||
namespace Drupal\file\Tests;
|
||||
|
||||
/**
|
||||
* Tests the file move function.
|
||||
*
|
||||
* @group file
|
||||
*/
|
||||
class MoveTest extends FileManagedUnitTestBase {
|
||||
/**
|
||||
* Move a normal file.
|
||||
*/
|
||||
function testNormal() {
|
||||
$contents = $this->randomMachineName(10);
|
||||
$source = $this->createFile(NULL, $contents);
|
||||
$desired_filepath = 'public://' . $this->randomMachineName();
|
||||
|
||||
// Clone the object so we don't have to worry about the function changing
|
||||
// our reference copy.
|
||||
$result = file_move(clone $source, $desired_filepath, FILE_EXISTS_ERROR);
|
||||
|
||||
// Check the return status and that the contents changed.
|
||||
$this->assertTrue($result, 'File moved successfully.');
|
||||
$this->assertFalse(file_exists($source->getFileUri()));
|
||||
$this->assertEqual($contents, file_get_contents($result->getFileUri()), 'Contents of file correctly written.');
|
||||
|
||||
// Check that the correct hooks were called.
|
||||
$this->assertFileHooksCalled(array('move', 'load', 'update'));
|
||||
|
||||
// Make sure we got the same file back.
|
||||
$this->assertEqual($source->id(), $result->id(), format_string("Source file id's' %fid is unchanged after move.", array('%fid' => $source->id())));
|
||||
|
||||
// Reload the file from the database and check that the changes were
|
||||
// actually saved.
|
||||
$loaded_file = file_load($result->id(), TRUE);
|
||||
$this->assertTrue($loaded_file, 'File can be loaded from the database.');
|
||||
$this->assertFileUnchanged($result, $loaded_file);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test renaming when moving onto a file that already exists.
|
||||
*/
|
||||
function testExistingRename() {
|
||||
// Setup a file to overwrite.
|
||||
$contents = $this->randomMachineName(10);
|
||||
$source = $this->createFile(NULL, $contents);
|
||||
$target = $this->createFile();
|
||||
$this->assertDifferentFile($source, $target);
|
||||
|
||||
// Clone the object so we don't have to worry about the function changing
|
||||
// our reference copy.
|
||||
$result = file_move(clone $source, $target->getFileUri(), FILE_EXISTS_RENAME);
|
||||
|
||||
// Check the return status and that the contents changed.
|
||||
$this->assertTrue($result, 'File moved successfully.');
|
||||
$this->assertFalse(file_exists($source->getFileUri()));
|
||||
$this->assertEqual($contents, file_get_contents($result->getFileUri()), 'Contents of file correctly written.');
|
||||
|
||||
// Check that the correct hooks were called.
|
||||
$this->assertFileHooksCalled(array('move', 'load', 'update'));
|
||||
|
||||
// Compare the returned value to what made it into the database.
|
||||
$this->assertFileUnchanged($result, file_load($result->id(), TRUE));
|
||||
// The target file should not have been altered.
|
||||
$this->assertFileUnchanged($target, file_load($target->id(), TRUE));
|
||||
// Make sure we end up with two distinct files afterwards.
|
||||
$this->assertDifferentFile($target, $result);
|
||||
|
||||
// Compare the source and results.
|
||||
$loaded_source = file_load($source->id(), TRUE);
|
||||
$this->assertEqual($loaded_source->id(), $result->id(), "Returned file's id matches the source.");
|
||||
$this->assertNotEqual($loaded_source->getFileUri(), $source->getFileUri(), 'Returned file path has changed from the original.');
|
||||
}
|
||||
|
||||
/**
|
||||
* Test replacement when moving onto a file that already exists.
|
||||
*/
|
||||
function testExistingReplace() {
|
||||
// Setup a file to overwrite.
|
||||
$contents = $this->randomMachineName(10);
|
||||
$source = $this->createFile(NULL, $contents);
|
||||
$target = $this->createFile();
|
||||
$this->assertDifferentFile($source, $target);
|
||||
|
||||
// Clone the object so we don't have to worry about the function changing
|
||||
// our reference copy.
|
||||
$result = file_move(clone $source, $target->getFileUri(), FILE_EXISTS_REPLACE);
|
||||
|
||||
// Look at the results.
|
||||
$this->assertEqual($contents, file_get_contents($result->getFileUri()), 'Contents of file were overwritten.');
|
||||
$this->assertFalse(file_exists($source->getFileUri()));
|
||||
$this->assertTrue($result, 'File moved successfully.');
|
||||
|
||||
// Check that the correct hooks were called.
|
||||
$this->assertFileHooksCalled(array('move', 'update', 'delete', 'load'));
|
||||
|
||||
// Reload the file from the database and check that the changes were
|
||||
// actually saved.
|
||||
$loaded_result = file_load($result->id(), TRUE);
|
||||
$this->assertFileUnchanged($result, $loaded_result);
|
||||
// Check that target was re-used.
|
||||
$this->assertSameFile($target, $loaded_result);
|
||||
// Source and result should be totally different.
|
||||
$this->assertDifferentFile($source, $loaded_result);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test replacement when moving onto itself.
|
||||
*/
|
||||
function testExistingReplaceSelf() {
|
||||
// Setup a file to overwrite.
|
||||
$contents = $this->randomMachineName(10);
|
||||
$source = $this->createFile(NULL, $contents);
|
||||
|
||||
// Copy the file over itself. Clone the object so we don't have to worry
|
||||
// about the function changing our reference copy.
|
||||
$result = file_move(clone $source, $source->getFileUri(), FILE_EXISTS_REPLACE);
|
||||
$this->assertFalse($result, 'File move failed.');
|
||||
$this->assertEqual($contents, file_get_contents($source->getFileUri()), 'Contents of file were not altered.');
|
||||
|
||||
// Check that no hooks were called while failing.
|
||||
$this->assertFileHooksCalled(array());
|
||||
|
||||
// Load the file from the database and make sure it is identical to what
|
||||
// was returned.
|
||||
$this->assertFileUnchanged($source, file_load($source->id(), TRUE));
|
||||
}
|
||||
|
||||
/**
|
||||
* Test that moving onto an existing file fails when FILE_EXISTS_ERROR is
|
||||
* specified.
|
||||
*/
|
||||
function testExistingError() {
|
||||
$contents = $this->randomMachineName(10);
|
||||
$source = $this->createFile();
|
||||
$target = $this->createFile(NULL, $contents);
|
||||
$this->assertDifferentFile($source, $target);
|
||||
|
||||
// Clone the object so we don't have to worry about the function changing
|
||||
// our reference copy.
|
||||
$result = file_move(clone $source, $target->getFileUri(), FILE_EXISTS_ERROR);
|
||||
|
||||
// Check the return status and that the contents did not change.
|
||||
$this->assertFalse($result, 'File move failed.');
|
||||
$this->assertTrue(file_exists($source->getFileUri()));
|
||||
$this->assertEqual($contents, file_get_contents($target->getFileUri()), 'Contents of file were not altered.');
|
||||
|
||||
// Check that no hooks were called while failing.
|
||||
$this->assertFileHooksCalled(array());
|
||||
|
||||
// Load the file from the database and make sure it is identical to what
|
||||
// was returned.
|
||||
$this->assertFileUnchanged($source, file_load($source->id(), TRUE));
|
||||
$this->assertFileUnchanged($target, file_load($target->id(), TRUE));
|
||||
}
|
||||
}
|
|
@ -0,0 +1,130 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains \Drupal\file\Tests\PrivateFileOnTranslatedEntityTest.
|
||||
*/
|
||||
|
||||
namespace Drupal\file\Tests;
|
||||
|
||||
use Drupal\file\Entity\File;
|
||||
use Drupal\node\Entity\Node;
|
||||
|
||||
/**
|
||||
* Uploads private files to translated node and checks access.
|
||||
*
|
||||
* @group file
|
||||
*/
|
||||
class PrivateFileOnTranslatedEntityTest extends FileFieldTestBase {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static $modules = array('language', 'content_translation');
|
||||
|
||||
/**
|
||||
* The name of the file field used in the test.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $fieldName;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function setUp() {
|
||||
parent::setUp();
|
||||
|
||||
// Create the "Basic page" node type.
|
||||
$this->drupalCreateContentType(array('type' => 'page', 'name' => 'Basic page'));
|
||||
|
||||
// Create a file field on the "Basic page" node type.
|
||||
$this->fieldName = strtolower($this->randomMachineName());
|
||||
$this->createFileField($this->fieldName, 'node', 'page', array('uri_scheme' => 'private'));
|
||||
|
||||
// Create and login user.
|
||||
$permissions = array(
|
||||
'access administration pages',
|
||||
'administer content translation',
|
||||
'administer content types',
|
||||
'administer languages',
|
||||
'create content translations',
|
||||
'create page content',
|
||||
'edit any page content',
|
||||
'translate any entity',
|
||||
);
|
||||
$admin_user = $this->drupalCreateUser($permissions);
|
||||
$this->drupalLogin($admin_user);
|
||||
|
||||
// Add a second language.
|
||||
$edit = array();
|
||||
$edit['predefined_langcode'] = 'fr';
|
||||
$this->drupalPostForm('admin/config/regional/language/add', $edit, t('Add language'));
|
||||
|
||||
// Enable translation for "Basic page" nodes.
|
||||
$edit = array(
|
||||
'entity_types[node]' => 1,
|
||||
'settings[node][page][translatable]' => 1,
|
||||
"settings[node][page][fields][$this->fieldName]" => 1,
|
||||
);
|
||||
$this->drupalPostForm('admin/config/regional/content-language', $edit, t('Save configuration'));
|
||||
\Drupal::entityManager()->clearCachedDefinitions();
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests private file fields on translated nodes.
|
||||
*/
|
||||
public function testPrivateLanguageFile() {
|
||||
// Verify that the file field on the "Basic page" node type is translatable.
|
||||
$definitions = \Drupal::entityManager()->getFieldDefinitions('node', 'page');
|
||||
$this->assertTrue($definitions[$this->fieldName]->isTranslatable(), 'Node file field is translatable.');
|
||||
|
||||
// Create a default language node.
|
||||
$default_language_node = $this->drupalCreateNode(array('type' => 'page'));
|
||||
|
||||
// Edit the node to upload a file.
|
||||
$edit = array();
|
||||
$name = 'files[' . $this->fieldName . '_0]';
|
||||
$edit[$name] = drupal_realpath($this->drupalGetTestFiles('text')[0]->uri);
|
||||
$this->drupalPostForm('node/' . $default_language_node->id() . '/edit', $edit, t('Save'));
|
||||
$last_fid_prior = $this->getLastFileId();
|
||||
|
||||
// Languages are cached on many levels, and we need to clear those caches.
|
||||
$this->rebuildContainer();
|
||||
|
||||
// Ensure the file can be downloaded.
|
||||
\Drupal::entityManager()->getStorage('node')->resetCache(array($default_language_node->id()));
|
||||
$node = Node::load($default_language_node->id());
|
||||
$node_file = File::load($node->{$this->fieldName}->target_id);
|
||||
$this->drupalGet(file_create_url($node_file->getFileUri()));
|
||||
$this->assertResponse(200, 'Confirmed that the file attached to the English node can be downloaded.');
|
||||
|
||||
// Translate the node into French.
|
||||
$this->drupalGet('node/' . $default_language_node->id() . '/translations');
|
||||
$this->clickLink(t('Add'));
|
||||
|
||||
// Remove the existing file.
|
||||
$this->drupalPostForm(NULL, array(), t('Remove'));
|
||||
|
||||
// Upload a different file.
|
||||
$edit = array();
|
||||
$edit['title[0][value]'] = $this->randomMachineName();
|
||||
$name = 'files[' . $this->fieldName . '_0]';
|
||||
$edit[$name] = drupal_realpath($this->drupalGetTestFiles('text')[1]->uri);
|
||||
$this->drupalPostForm(NULL, $edit, t('Save (this translation)'));
|
||||
$last_fid = $this->getLastFileId();
|
||||
|
||||
// Verify the translation was created.
|
||||
\Drupal::entityManager()->getStorage('node')->resetCache(array($default_language_node->id()));
|
||||
$default_language_node = Node::load($default_language_node->id());
|
||||
$this->assertTrue($default_language_node->hasTranslation('fr'), 'Node found in database.');
|
||||
$this->assertTrue($last_fid > $last_fid_prior, 'New file got saved.');
|
||||
|
||||
// Ensure the file attached to the translated node can be downloaded.
|
||||
$french_node = $default_language_node->getTranslation('fr');
|
||||
$node_file = File::load($french_node->{$this->fieldName}->target_id);
|
||||
$this->drupalGet(file_create_url($node_file->getFileUri()));
|
||||
$this->assertResponse(200, 'Confirmed that the file attached to the French node can be downloaded.');
|
||||
}
|
||||
|
||||
}
|
28
core/modules/file/src/Tests/RemoteFileSaveUploadTest.php
Normal file
28
core/modules/file/src/Tests/RemoteFileSaveUploadTest.php
Normal file
|
@ -0,0 +1,28 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains \Drupal\file\Tests\RemoteFileSaveUploadTest.
|
||||
*/
|
||||
|
||||
namespace Drupal\file\Tests;
|
||||
|
||||
/**
|
||||
* Tests the file uploading functions.
|
||||
*
|
||||
* @group file
|
||||
*/
|
||||
class RemoteFileSaveUploadTest extends SaveUploadTest {
|
||||
|
||||
/**
|
||||
* Modules to enable.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public static $modules = array('file_test');
|
||||
|
||||
protected function setUp() {
|
||||
parent::setUp();
|
||||
$this->config('system.file')->set('default_scheme', 'dummy-remote')->save();
|
||||
}
|
||||
}
|
136
core/modules/file/src/Tests/SaveDataTest.php
Normal file
136
core/modules/file/src/Tests/SaveDataTest.php
Normal file
|
@ -0,0 +1,136 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains \Drupal\file\Tests\SaveDataTest.
|
||||
*/
|
||||
|
||||
namespace Drupal\file\Tests;
|
||||
|
||||
/**
|
||||
* Tests the file_save_data() function.
|
||||
*
|
||||
* @group file
|
||||
*/
|
||||
class SaveDataTest extends FileManagedUnitTestBase {
|
||||
/**
|
||||
* Test the file_save_data() function when no filename is provided.
|
||||
*/
|
||||
function testWithoutFilename() {
|
||||
$contents = $this->randomMachineName(8);
|
||||
|
||||
$result = file_save_data($contents);
|
||||
$this->assertTrue($result, 'Unnamed file saved correctly.');
|
||||
|
||||
$this->assertEqual(file_default_scheme(), file_uri_scheme($result->getFileUri()), "File was placed in Drupal's files directory.");
|
||||
$this->assertEqual($result->getFilename(), drupal_basename($result->getFileUri()), "Filename was set to the file's basename.");
|
||||
$this->assertEqual($contents, file_get_contents($result->getFileUri()), 'Contents of the file are correct.');
|
||||
$this->assertEqual($result->getMimeType(), 'application/octet-stream', 'A MIME type was set.');
|
||||
$this->assertTrue($result->isPermanent(), "The file's status was set to permanent.");
|
||||
|
||||
// Check that the correct hooks were called.
|
||||
$this->assertFileHooksCalled(array('insert'));
|
||||
|
||||
// Verify that what was returned is what's in the database.
|
||||
$this->assertFileUnchanged($result, file_load($result->id(), TRUE));
|
||||
}
|
||||
|
||||
/**
|
||||
* Test the file_save_data() function when a filename is provided.
|
||||
*/
|
||||
function testWithFilename() {
|
||||
$contents = $this->randomMachineName(8);
|
||||
|
||||
// Using filename with non-latin characters.
|
||||
$filename = 'Текстовый файл.txt';
|
||||
|
||||
$result = file_save_data($contents, 'public://' . $filename);
|
||||
$this->assertTrue($result, 'Unnamed file saved correctly.');
|
||||
|
||||
$this->assertEqual('public', file_uri_scheme($result->getFileUri()), "File was placed in Drupal's files directory.");
|
||||
$this->assertEqual($filename, drupal_basename($result->getFileUri()), 'File was named correctly.');
|
||||
$this->assertEqual($contents, file_get_contents($result->getFileUri()), 'Contents of the file are correct.');
|
||||
$this->assertEqual($result->getMimeType(), 'text/plain', 'A MIME type was set.');
|
||||
$this->assertTrue($result->isPermanent(), "The file's status was set to permanent.");
|
||||
|
||||
// Check that the correct hooks were called.
|
||||
$this->assertFileHooksCalled(array('insert'));
|
||||
|
||||
// Verify that what was returned is what's in the database.
|
||||
$this->assertFileUnchanged($result, file_load($result->id(), TRUE));
|
||||
}
|
||||
|
||||
/**
|
||||
* Test file_save_data() when renaming around an existing file.
|
||||
*/
|
||||
function testExistingRename() {
|
||||
// Setup a file to overwrite.
|
||||
$existing = $this->createFile();
|
||||
$contents = $this->randomMachineName(8);
|
||||
|
||||
$result = file_save_data($contents, $existing->getFileUri(), FILE_EXISTS_RENAME);
|
||||
$this->assertTrue($result, 'File saved successfully.');
|
||||
|
||||
$this->assertEqual('public', file_uri_scheme($result->getFileUri()), "File was placed in Drupal's files directory.");
|
||||
$this->assertEqual($result->getFilename(), $existing->getFilename(), 'Filename was set to the basename of the source, rather than that of the renamed file.');
|
||||
$this->assertEqual($contents, file_get_contents($result->getFileUri()), 'Contents of the file are correct.');
|
||||
$this->assertEqual($result->getMimeType(), 'application/octet-stream', 'A MIME type was set.');
|
||||
$this->assertTrue($result->isPermanent(), "The file's status was set to permanent.");
|
||||
|
||||
// Check that the correct hooks were called.
|
||||
$this->assertFileHooksCalled(array('insert'));
|
||||
|
||||
// Ensure that the existing file wasn't overwritten.
|
||||
$this->assertDifferentFile($existing, $result);
|
||||
$this->assertFileUnchanged($existing, file_load($existing->id(), TRUE));
|
||||
|
||||
// Verify that was returned is what's in the database.
|
||||
$this->assertFileUnchanged($result, file_load($result->id(), TRUE));
|
||||
}
|
||||
|
||||
/**
|
||||
* Test file_save_data() when replacing an existing file.
|
||||
*/
|
||||
function testExistingReplace() {
|
||||
// Setup a file to overwrite.
|
||||
$existing = $this->createFile();
|
||||
$contents = $this->randomMachineName(8);
|
||||
|
||||
$result = file_save_data($contents, $existing->getFileUri(), FILE_EXISTS_REPLACE);
|
||||
$this->assertTrue($result, 'File saved successfully.');
|
||||
|
||||
$this->assertEqual('public', file_uri_scheme($result->getFileUri()), "File was placed in Drupal's files directory.");
|
||||
$this->assertEqual($result->getFilename(), $existing->getFilename(), 'Filename was set to the basename of the existing file, rather than preserving the original name.');
|
||||
$this->assertEqual($contents, file_get_contents($result->getFileUri()), 'Contents of the file are correct.');
|
||||
$this->assertEqual($result->getMimeType(), 'application/octet-stream', 'A MIME type was set.');
|
||||
$this->assertTrue($result->isPermanent(), "The file's status was set to permanent.");
|
||||
|
||||
// Check that the correct hooks were called.
|
||||
$this->assertFileHooksCalled(array('load', 'update'));
|
||||
|
||||
// Verify that the existing file was re-used.
|
||||
$this->assertSameFile($existing, $result);
|
||||
|
||||
// Verify that what was returned is what's in the database.
|
||||
$this->assertFileUnchanged($result, file_load($result->id(), TRUE));
|
||||
}
|
||||
|
||||
/**
|
||||
* Test that file_save_data() fails overwriting an existing file.
|
||||
*/
|
||||
function testExistingError() {
|
||||
$contents = $this->randomMachineName(8);
|
||||
$existing = $this->createFile(NULL, $contents);
|
||||
|
||||
// Check the overwrite error.
|
||||
$result = file_save_data('asdf', $existing->getFileUri(), FILE_EXISTS_ERROR);
|
||||
$this->assertFalse($result, 'Overwriting a file fails when FILE_EXISTS_ERROR is specified.');
|
||||
$this->assertEqual($contents, file_get_contents($existing->getFileUri()), 'Contents of existing file were unchanged.');
|
||||
|
||||
// Check that no hooks were called while failing.
|
||||
$this->assertFileHooksCalled(array());
|
||||
|
||||
// Ensure that the existing file wasn't overwritten.
|
||||
$this->assertFileUnchanged($existing, file_load($existing->id(), TRUE));
|
||||
}
|
||||
}
|
93
core/modules/file/src/Tests/SaveTest.php
Normal file
93
core/modules/file/src/Tests/SaveTest.php
Normal file
|
@ -0,0 +1,93 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains \Drupal\file\Tests\SaveTest.
|
||||
*/
|
||||
|
||||
namespace Drupal\file\Tests;
|
||||
|
||||
use Drupal\file\Entity\File;
|
||||
use Drupal\Core\Entity\EntityStorageException;
|
||||
use Drupal\Core\Entity\EntityStorageInterface;
|
||||
use Drupal\Core\Entity\Sql\SqlEntityStorageInterface;
|
||||
|
||||
/**
|
||||
* File saving tests.
|
||||
*
|
||||
* @group file
|
||||
*/
|
||||
class SaveTest extends FileManagedUnitTestBase {
|
||||
function testFileSave() {
|
||||
// Create a new file entity.
|
||||
$file = File::create(array(
|
||||
'uid' => 1,
|
||||
'filename' => 'druplicon.txt',
|
||||
'uri' => 'public://druplicon.txt',
|
||||
'filemime' => 'text/plain',
|
||||
'status' => FILE_STATUS_PERMANENT,
|
||||
));
|
||||
file_put_contents($file->getFileUri(), 'hello world');
|
||||
|
||||
// Save it, inserting a new record.
|
||||
$file->save();
|
||||
|
||||
// Check that the correct hooks were called.
|
||||
$this->assertFileHooksCalled(array('insert'));
|
||||
|
||||
$this->assertTrue($file->id() > 0, 'A new file ID is set when saving a new file to the database.', 'File');
|
||||
$loaded_file = file_load($file->id());
|
||||
$this->assertNotNull($loaded_file, 'Record exists in the database.');
|
||||
$this->assertEqual($loaded_file->isPermanent(), $file->isPermanent(), 'Status was saved correctly.');
|
||||
$this->assertEqual($file->getSize(), filesize($file->getFileUri()), 'File size was set correctly.', 'File');
|
||||
$this->assertTrue($file->getChangedTime() > 1, 'File size was set correctly.', 'File');
|
||||
$this->assertEqual($loaded_file->langcode->value, 'en', 'Langcode was defaulted correctly.');
|
||||
|
||||
// Resave the file, updating the existing record.
|
||||
file_test_reset();
|
||||
$file->status->value = 7;
|
||||
$file->save();
|
||||
|
||||
// Check that the correct hooks were called.
|
||||
$this->assertFileHooksCalled(array('load', 'update'));
|
||||
|
||||
$this->assertEqual($file->id(), $file->id(), 'The file ID of an existing file is not changed when updating the database.', 'File');
|
||||
$this->assertTrue($file->getChangedTime() >= $file->getChangedTime(), "Timestamp didn't go backwards.", 'File');
|
||||
$loaded_file = file_load($file->id());
|
||||
$this->assertNotNull($loaded_file, 'Record still exists in the database.', 'File');
|
||||
$this->assertEqual($loaded_file->isPermanent(), $file->isPermanent(), 'Status was saved correctly.');
|
||||
$this->assertEqual($loaded_file->langcode->value, 'en', 'Langcode was saved correctly.');
|
||||
|
||||
// Try to insert a second file with the same name apart from case insensitivity
|
||||
// to ensure the 'uri' index allows for filenames with different cases.
|
||||
$uppercase_values = array(
|
||||
'uid' => 1,
|
||||
'filename' => 'DRUPLICON.txt',
|
||||
'uri' => 'public://DRUPLICON.txt',
|
||||
'filemime' => 'text/plain',
|
||||
'status' => FILE_STATUS_PERMANENT,
|
||||
);
|
||||
$uppercase_file = File::create($uppercase_values);
|
||||
file_put_contents($uppercase_file->getFileUri(), 'hello world');
|
||||
$violations = $uppercase_file->validate();
|
||||
$this->assertEqual(count($violations), 0, 'No violations when adding an URI with an existing filename in upper case.');
|
||||
$uppercase_file->save();
|
||||
|
||||
// Ensure the database URI uniqueness constraint is triggered.
|
||||
$uppercase_file_duplicate = File::create($uppercase_values);
|
||||
file_put_contents($uppercase_file_duplicate->getFileUri(), 'hello world');
|
||||
$violations = $uppercase_file_duplicate->validate();
|
||||
$this->assertEqual(count($violations), 1);
|
||||
$this->assertEqual($violations[0]->getMessage(), t('The file %value already exists. Enter a unique file URI.', [
|
||||
'%value' => $uppercase_file_duplicate->getFileUri(),
|
||||
]));
|
||||
// Ensure that file URI entity queries are case sensitive.
|
||||
$fids = \Drupal::entityQuery('file')
|
||||
->condition('uri', $uppercase_file->getFileUri())
|
||||
->execute();
|
||||
|
||||
$this->assertEqual(1, count($fids));
|
||||
$this->assertEqual(array($uppercase_file->id() => $uppercase_file->id()), $fids);
|
||||
|
||||
}
|
||||
}
|
364
core/modules/file/src/Tests/SaveUploadTest.php
Normal file
364
core/modules/file/src/Tests/SaveUploadTest.php
Normal file
|
@ -0,0 +1,364 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains \Drupal\file\Tests\SaveUploadTest.
|
||||
*/
|
||||
|
||||
namespace Drupal\file\Tests;
|
||||
|
||||
/**
|
||||
* Tests the file_save_upload() function.
|
||||
*
|
||||
* @group file
|
||||
*/
|
||||
class SaveUploadTest extends FileManagedTestBase {
|
||||
/**
|
||||
* Modules to enable.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public static $modules = array('dblog');
|
||||
|
||||
/**
|
||||
* An image file path for uploading.
|
||||
*
|
||||
* @var \Drupal\file\FileInterface
|
||||
*/
|
||||
protected $image;
|
||||
|
||||
/**
|
||||
* A PHP file path for upload security testing.
|
||||
*/
|
||||
protected $phpfile;
|
||||
|
||||
/**
|
||||
* The largest file id when the test starts.
|
||||
*/
|
||||
protected $maxFidBefore;
|
||||
|
||||
/**
|
||||
* Extension of the image filename.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $imageExtension;
|
||||
|
||||
protected function setUp() {
|
||||
parent::setUp();
|
||||
$account = $this->drupalCreateUser(array('access site reports'));
|
||||
$this->drupalLogin($account);
|
||||
|
||||
$image_files = $this->drupalGetTestFiles('image');
|
||||
$this->image = entity_create('file', (array) current($image_files));
|
||||
|
||||
list(, $this->imageExtension) = explode('.', $this->image->getFilename());
|
||||
$this->assertTrue(is_file($this->image->getFileUri()), "The image file we're going to upload exists.");
|
||||
|
||||
$this->phpfile = current($this->drupalGetTestFiles('php'));
|
||||
$this->assertTrue(is_file($this->phpfile->uri), 'The PHP file we are going to upload exists.');
|
||||
|
||||
$this->maxFidBefore = db_query('SELECT MAX(fid) AS fid FROM {file_managed}')->fetchField();
|
||||
|
||||
// Upload with replace to guarantee there's something there.
|
||||
$edit = array(
|
||||
'file_test_replace' => FILE_EXISTS_REPLACE,
|
||||
'files[file_test_upload]' => drupal_realpath($this->image->getFileUri()),
|
||||
);
|
||||
$this->drupalPostForm('file-test/upload', $edit, t('Submit'));
|
||||
$this->assertResponse(200, 'Received a 200 response for posted test file.');
|
||||
$this->assertRaw(t('You WIN!'), 'Found the success message.');
|
||||
|
||||
// Check that the correct hooks were called then clean out the hook
|
||||
// counters.
|
||||
$this->assertFileHooksCalled(array('validate', 'insert'));
|
||||
file_test_reset();
|
||||
}
|
||||
|
||||
/**
|
||||
* Test the file_save_upload() function.
|
||||
*/
|
||||
function testNormal() {
|
||||
$max_fid_after = db_query('SELECT MAX(fid) AS fid FROM {file_managed}')->fetchField();
|
||||
$this->assertTrue($max_fid_after > $this->maxFidBefore, 'A new file was created.');
|
||||
$file1 = file_load($max_fid_after);
|
||||
$this->assertTrue($file1, 'Loaded the file.');
|
||||
// MIME type of the uploaded image may be either image/jpeg or image/png.
|
||||
$this->assertEqual(substr($file1->getMimeType(), 0, 5), 'image', 'A MIME type was set.');
|
||||
|
||||
// Reset the hook counters to get rid of the 'load' we just called.
|
||||
file_test_reset();
|
||||
|
||||
// Upload a second file.
|
||||
$image2 = current($this->drupalGetTestFiles('image'));
|
||||
$edit = array('files[file_test_upload]' => drupal_realpath($image2->uri));
|
||||
$this->drupalPostForm('file-test/upload', $edit, t('Submit'));
|
||||
$this->assertResponse(200, 'Received a 200 response for posted test file.');
|
||||
$this->assertRaw(t('You WIN!'));
|
||||
$max_fid_after = db_query('SELECT MAX(fid) AS fid FROM {file_managed}')->fetchField();
|
||||
|
||||
// Check that the correct hooks were called.
|
||||
$this->assertFileHooksCalled(array('validate', 'insert'));
|
||||
|
||||
$file2 = file_load($max_fid_after);
|
||||
$this->assertTrue($file2, 'Loaded the file');
|
||||
// MIME type of the uploaded image may be either image/jpeg or image/png.
|
||||
$this->assertEqual(substr($file2->getMimeType(), 0, 5), 'image', 'A MIME type was set.');
|
||||
|
||||
// Load both files using file_load_multiple().
|
||||
$files = file_load_multiple(array($file1->id(), $file2->id()));
|
||||
$this->assertTrue(isset($files[$file1->id()]), 'File was loaded successfully');
|
||||
$this->assertTrue(isset($files[$file2->id()]), 'File was loaded successfully');
|
||||
|
||||
// Upload a third file to a subdirectory.
|
||||
$image3 = current($this->drupalGetTestFiles('image'));
|
||||
$image3_realpath = drupal_realpath($image3->uri);
|
||||
$dir = $this->randomMachineName();
|
||||
$edit = array(
|
||||
'files[file_test_upload]' => $image3_realpath,
|
||||
'file_subdir' => $dir,
|
||||
);
|
||||
$this->drupalPostForm('file-test/upload', $edit, t('Submit'));
|
||||
$this->assertResponse(200, 'Received a 200 response for posted test file.');
|
||||
$this->assertRaw(t('You WIN!'));
|
||||
$this->assertTrue(is_file('temporary://' . $dir . '/' . trim(drupal_basename($image3_realpath))));
|
||||
}
|
||||
|
||||
/**
|
||||
* Test extension handling.
|
||||
*/
|
||||
function testHandleExtension() {
|
||||
// The file being tested is a .gif which is in the default safe list
|
||||
// of extensions to allow when the extension validator isn't used. This is
|
||||
// implicitly tested at the testNormal() test. Here we tell
|
||||
// file_save_upload() to only allow ".foo".
|
||||
$extensions = 'foo';
|
||||
$edit = array(
|
||||
'file_test_replace' => FILE_EXISTS_REPLACE,
|
||||
'files[file_test_upload]' => drupal_realpath($this->image->getFileUri()),
|
||||
'extensions' => $extensions,
|
||||
);
|
||||
|
||||
$this->drupalPostForm('file-test/upload', $edit, t('Submit'));
|
||||
$this->assertResponse(200, 'Received a 200 response for posted test file.');
|
||||
$message = t('Only files with the following extensions are allowed:') . ' <em class="placeholder">' . $extensions . '</em>';
|
||||
$this->assertRaw($message, 'Cannot upload a disallowed extension');
|
||||
$this->assertRaw(t('Epic upload FAIL!'), 'Found the failure message.');
|
||||
|
||||
// Check that the correct hooks were called.
|
||||
$this->assertFileHooksCalled(array('validate'));
|
||||
|
||||
// Reset the hook counters.
|
||||
file_test_reset();
|
||||
|
||||
$extensions = 'foo ' . $this->imageExtension;
|
||||
// Now tell file_save_upload() to allow the extension of our test image.
|
||||
$edit = array(
|
||||
'file_test_replace' => FILE_EXISTS_REPLACE,
|
||||
'files[file_test_upload]' => drupal_realpath($this->image->getFileUri()),
|
||||
'extensions' => $extensions,
|
||||
);
|
||||
|
||||
$this->drupalPostForm('file-test/upload', $edit, t('Submit'));
|
||||
$this->assertResponse(200, 'Received a 200 response for posted test file.');
|
||||
$this->assertNoRaw(t('Only files with the following extensions are allowed:'), 'Can upload an allowed extension.');
|
||||
$this->assertRaw(t('You WIN!'), 'Found the success message.');
|
||||
|
||||
// Check that the correct hooks were called.
|
||||
$this->assertFileHooksCalled(array('validate', 'load', 'update'));
|
||||
|
||||
// Reset the hook counters.
|
||||
file_test_reset();
|
||||
|
||||
// Now tell file_save_upload() to allow any extension.
|
||||
$edit = array(
|
||||
'file_test_replace' => FILE_EXISTS_REPLACE,
|
||||
'files[file_test_upload]' => drupal_realpath($this->image->getFileUri()),
|
||||
'allow_all_extensions' => TRUE,
|
||||
);
|
||||
$this->drupalPostForm('file-test/upload', $edit, t('Submit'));
|
||||
$this->assertResponse(200, 'Received a 200 response for posted test file.');
|
||||
$this->assertNoRaw(t('Only files with the following extensions are allowed:'), 'Can upload any extension.');
|
||||
$this->assertRaw(t('You WIN!'), 'Found the success message.');
|
||||
|
||||
// Check that the correct hooks were called.
|
||||
$this->assertFileHooksCalled(array('validate', 'load', 'update'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Test dangerous file handling.
|
||||
*/
|
||||
function testHandleDangerousFile() {
|
||||
$config = $this->config('system.file');
|
||||
// Allow the .php extension and make sure it gets renamed to .txt for
|
||||
// safety. Also check to make sure its MIME type was changed.
|
||||
$edit = array(
|
||||
'file_test_replace' => FILE_EXISTS_REPLACE,
|
||||
'files[file_test_upload]' => drupal_realpath($this->phpfile->uri),
|
||||
'is_image_file' => FALSE,
|
||||
'extensions' => 'php',
|
||||
);
|
||||
|
||||
$this->drupalPostForm('file-test/upload', $edit, t('Submit'));
|
||||
$this->assertResponse(200, 'Received a 200 response for posted test file.');
|
||||
$message = t('For security reasons, your upload has been renamed to') . ' <em class="placeholder">' . $this->phpfile->filename . '.txt' . '</em>';
|
||||
$this->assertRaw($message, 'Dangerous file was renamed.');
|
||||
$this->assertRaw(t('File MIME type is text/plain.'), "Dangerous file's MIME type was changed.");
|
||||
$this->assertRaw(t('You WIN!'), 'Found the success message.');
|
||||
|
||||
// Check that the correct hooks were called.
|
||||
$this->assertFileHooksCalled(array('validate', 'insert'));
|
||||
|
||||
// Ensure dangerous files are not renamed when insecure uploads is TRUE.
|
||||
// Turn on insecure uploads.
|
||||
$config->set('allow_insecure_uploads', 1)->save();
|
||||
// Reset the hook counters.
|
||||
file_test_reset();
|
||||
|
||||
$this->drupalPostForm('file-test/upload', $edit, t('Submit'));
|
||||
$this->assertResponse(200, 'Received a 200 response for posted test file.');
|
||||
$this->assertNoRaw(t('For security reasons, your upload has been renamed'), 'Found no security message.');
|
||||
$this->assertRaw(t('File name is !filename', array('!filename' => $this->phpfile->filename)), 'Dangerous file was not renamed when insecure uploads is TRUE.');
|
||||
$this->assertRaw(t('You WIN!'), 'Found the success message.');
|
||||
|
||||
// Check that the correct hooks were called.
|
||||
$this->assertFileHooksCalled(array('validate', 'insert'));
|
||||
|
||||
// Turn off insecure uploads.
|
||||
$config->set('allow_insecure_uploads', 0)->save();
|
||||
}
|
||||
|
||||
/**
|
||||
* Test file munge handling.
|
||||
*/
|
||||
function testHandleFileMunge() {
|
||||
// Ensure insecure uploads are disabled for this test.
|
||||
$this->config('system.file')->set('allow_insecure_uploads', 0)->save();
|
||||
$this->image = file_move($this->image, $this->image->getFileUri() . '.foo.' . $this->imageExtension);
|
||||
|
||||
// Reset the hook counters to get rid of the 'move' we just called.
|
||||
file_test_reset();
|
||||
|
||||
$extensions = $this->imageExtension;
|
||||
$edit = array(
|
||||
'files[file_test_upload]' => drupal_realpath($this->image->getFileUri()),
|
||||
'extensions' => $extensions,
|
||||
);
|
||||
|
||||
$munged_filename = $this->image->getFilename();
|
||||
$munged_filename = substr($munged_filename, 0, strrpos($munged_filename, '.'));
|
||||
$munged_filename .= '_.' . $this->imageExtension;
|
||||
|
||||
$this->drupalPostForm('file-test/upload', $edit, t('Submit'));
|
||||
$this->assertResponse(200, 'Received a 200 response for posted test file.');
|
||||
$this->assertRaw(t('For security reasons, your upload has been renamed'), 'Found security message.');
|
||||
$this->assertRaw(t('File name is !filename', array('!filename' => $munged_filename)), 'File was successfully munged.');
|
||||
$this->assertRaw(t('You WIN!'), 'Found the success message.');
|
||||
|
||||
// Check that the correct hooks were called.
|
||||
$this->assertFileHooksCalled(array('validate', 'insert'));
|
||||
|
||||
// Ensure we don't munge files if we're allowing any extension.
|
||||
// Reset the hook counters.
|
||||
file_test_reset();
|
||||
|
||||
$edit = array(
|
||||
'files[file_test_upload]' => drupal_realpath($this->image->getFileUri()),
|
||||
'allow_all_extensions' => TRUE,
|
||||
);
|
||||
|
||||
$this->drupalPostForm('file-test/upload', $edit, t('Submit'));
|
||||
$this->assertResponse(200, 'Received a 200 response for posted test file.');
|
||||
$this->assertNoRaw(t('For security reasons, your upload has been renamed'), 'Found no security message.');
|
||||
$this->assertRaw(t('File name is !filename', array('!filename' => $this->image->getFilename())), 'File was not munged when allowing any extension.');
|
||||
$this->assertRaw(t('You WIN!'), 'Found the success message.');
|
||||
|
||||
// Check that the correct hooks were called.
|
||||
$this->assertFileHooksCalled(array('validate', 'insert'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Test renaming when uploading over a file that already exists.
|
||||
*/
|
||||
function testExistingRename() {
|
||||
$edit = array(
|
||||
'file_test_replace' => FILE_EXISTS_RENAME,
|
||||
'files[file_test_upload]' => drupal_realpath($this->image->getFileUri())
|
||||
);
|
||||
$this->drupalPostForm('file-test/upload', $edit, t('Submit'));
|
||||
$this->assertResponse(200, 'Received a 200 response for posted test file.');
|
||||
$this->assertRaw(t('You WIN!'), 'Found the success message.');
|
||||
|
||||
// Check that the correct hooks were called.
|
||||
$this->assertFileHooksCalled(array('validate', 'insert'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Test replacement when uploading over a file that already exists.
|
||||
*/
|
||||
function testExistingReplace() {
|
||||
$edit = array(
|
||||
'file_test_replace' => FILE_EXISTS_REPLACE,
|
||||
'files[file_test_upload]' => drupal_realpath($this->image->getFileUri())
|
||||
);
|
||||
$this->drupalPostForm('file-test/upload', $edit, t('Submit'));
|
||||
$this->assertResponse(200, 'Received a 200 response for posted test file.');
|
||||
$this->assertRaw(t('You WIN!'), 'Found the success message.');
|
||||
|
||||
// Check that the correct hooks were called.
|
||||
$this->assertFileHooksCalled(array('validate', 'load', 'update'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Test for failure when uploading over a file that already exists.
|
||||
*/
|
||||
function testExistingError() {
|
||||
$edit = array(
|
||||
'file_test_replace' => FILE_EXISTS_ERROR,
|
||||
'files[file_test_upload]' => drupal_realpath($this->image->getFileUri())
|
||||
);
|
||||
$this->drupalPostForm('file-test/upload', $edit, t('Submit'));
|
||||
$this->assertResponse(200, 'Received a 200 response for posted test file.');
|
||||
$this->assertRaw(t('Epic upload FAIL!'), 'Found the failure message.');
|
||||
|
||||
// Check that the no hooks were called while failing.
|
||||
$this->assertFileHooksCalled(array());
|
||||
}
|
||||
|
||||
/**
|
||||
* Test for no failures when not uploading a file.
|
||||
*/
|
||||
function testNoUpload() {
|
||||
$this->drupalPostForm('file-test/upload', array(), t('Submit'));
|
||||
$this->assertNoRaw(t('Epic upload FAIL!'), 'Failure message not found.');
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests for log entry on failing destination.
|
||||
*/
|
||||
function testDrupalMovingUploadedFileError() {
|
||||
// Create a directory and make it not writable.
|
||||
$test_directory = 'test_drupal_move_uploaded_file_fail';
|
||||
drupal_mkdir('temporary://' . $test_directory, 0000);
|
||||
$this->assertTrue(is_dir('temporary://' . $test_directory));
|
||||
|
||||
$edit = array(
|
||||
'file_subdir' => $test_directory,
|
||||
'files[file_test_upload]' => drupal_realpath($this->image->getFileUri())
|
||||
);
|
||||
|
||||
\Drupal::state()->set('file_test.disable_error_collection', TRUE);
|
||||
$this->drupalPostForm('file-test/upload', $edit, t('Submit'));
|
||||
$this->assertResponse(200, 'Received a 200 response for posted test file.');
|
||||
$this->assertRaw(t('File upload error. Could not move uploaded file.'), 'Found the failure message.');
|
||||
$this->assertRaw(t('Epic upload FAIL!'), 'Found the failure message.');
|
||||
|
||||
// Uploading failed. Now check the log.
|
||||
$this->drupalGet('admin/reports/dblog');
|
||||
$this->assertResponse(200);
|
||||
$this->assertRaw(t('Upload error. Could not move uploaded file @file to destination @destination.', array(
|
||||
'@file' => $this->image->getFilename(),
|
||||
'@destination' => 'temporary://' . $test_directory . '/' . $this->image->getFilename()
|
||||
)), 'Found upload error log entry.');
|
||||
}
|
||||
}
|
78
core/modules/file/src/Tests/SpaceUsedTest.php
Normal file
78
core/modules/file/src/Tests/SpaceUsedTest.php
Normal file
|
@ -0,0 +1,78 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains \Drupal\file\Tests\SpaceUsedTest.
|
||||
*/
|
||||
|
||||
namespace Drupal\file\Tests;
|
||||
|
||||
/**
|
||||
* Tests the spaceUsed() function.
|
||||
*
|
||||
* @group file
|
||||
*/
|
||||
class SpaceUsedTest extends FileManagedUnitTestBase {
|
||||
protected function setUp() {
|
||||
parent::setUp();
|
||||
|
||||
// Create records for a couple of users with different sizes.
|
||||
$this->createFileWithSize('public://example1.txt', 50, 2);
|
||||
$this->createFileWithSize('public://example2.txt', 20, 2);
|
||||
$this->createFileWithSize('public://example3.txt', 100, 3);
|
||||
$this->createFileWithSize('public://example4.txt', 200, 3);
|
||||
|
||||
// Now create some non-permanent files.
|
||||
$this->createFileWithSize('public://example5.txt', 1, 2, 0);
|
||||
$this->createFileWithSize('public://example6.txt', 3, 3, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a file with a given size.
|
||||
*
|
||||
* @param string $uri
|
||||
* URI of the file to create.
|
||||
* @param int $size
|
||||
* Size of the file.
|
||||
* @param int $uid
|
||||
* File owner ID.
|
||||
* @param int $status
|
||||
* Whether the file should be permanent or temporary.
|
||||
*
|
||||
* @return \Drupal\Core\Entity\EntityInterface
|
||||
* The file entity.
|
||||
*/
|
||||
protected function createFileWithSize($uri, $size, $uid, $status = FILE_STATUS_PERMANENT) {
|
||||
file_put_contents($uri, $this->randomMachineName($size));
|
||||
$file = entity_create('file', array(
|
||||
'uri' => $uri,
|
||||
'uid' => $uid,
|
||||
'status' => $status,
|
||||
));
|
||||
$file->save();
|
||||
return $file;
|
||||
}
|
||||
|
||||
/**
|
||||
* Test different users with the default status.
|
||||
*/
|
||||
function testFileSpaceUsed() {
|
||||
$file = $this->container->get('entity.manager')->getStorage('file');
|
||||
// Test different users with default status.
|
||||
$this->assertEqual($file->spaceUsed(2), 70);
|
||||
$this->assertEqual($file->spaceUsed(3), 300);
|
||||
$this->assertEqual($file->spaceUsed(), 370);
|
||||
|
||||
// Test the status fields
|
||||
$this->assertEqual($file->spaceUsed(NULL, 0), 4);
|
||||
$this->assertEqual($file->spaceUsed(NULL, FILE_STATUS_PERMANENT), 370);
|
||||
|
||||
// Test both the user and status.
|
||||
$this->assertEqual($file->spaceUsed(1, 0), 0);
|
||||
$this->assertEqual($file->spaceUsed(1, FILE_STATUS_PERMANENT), 0);
|
||||
$this->assertEqual($file->spaceUsed(2, 0), 1);
|
||||
$this->assertEqual($file->spaceUsed(2, FILE_STATUS_PERMANENT), 70);
|
||||
$this->assertEqual($file->spaceUsed(3, 0), 3);
|
||||
$this->assertEqual($file->spaceUsed(3, FILE_STATUS_PERMANENT), 300);
|
||||
}
|
||||
}
|
210
core/modules/file/src/Tests/UsageTest.php
Normal file
210
core/modules/file/src/Tests/UsageTest.php
Normal file
|
@ -0,0 +1,210 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains \Drupal\file\Tests\UsageTest.
|
||||
*/
|
||||
|
||||
namespace Drupal\file\Tests;
|
||||
|
||||
/**
|
||||
* Tests file usage functions.
|
||||
*
|
||||
* @group file
|
||||
*/
|
||||
class UsageTest extends FileManagedUnitTestBase {
|
||||
/**
|
||||
* Tests \Drupal\file\FileUsage\DatabaseFileUsageBackend::listUsage().
|
||||
*/
|
||||
function testGetUsage() {
|
||||
$file = $this->createFile();
|
||||
db_insert('file_usage')
|
||||
->fields(array(
|
||||
'fid' => $file->id(),
|
||||
'module' => 'testing',
|
||||
'type' => 'foo',
|
||||
'id' => 1,
|
||||
'count' => 1
|
||||
))
|
||||
->execute();
|
||||
db_insert('file_usage')
|
||||
->fields(array(
|
||||
'fid' => $file->id(),
|
||||
'module' => 'testing',
|
||||
'type' => 'bar',
|
||||
'id' => 2,
|
||||
'count' => 2
|
||||
))
|
||||
->execute();
|
||||
|
||||
$usage = $this->container->get('file.usage')->listUsage($file);
|
||||
|
||||
$this->assertEqual(count($usage['testing']), 2, 'Returned the correct number of items.');
|
||||
$this->assertTrue(isset($usage['testing']['foo'][1]), 'Returned the correct id.');
|
||||
$this->assertTrue(isset($usage['testing']['bar'][2]), 'Returned the correct id.');
|
||||
$this->assertEqual($usage['testing']['foo'][1], 1, 'Returned the correct count.');
|
||||
$this->assertEqual($usage['testing']['bar'][2], 2, 'Returned the correct count.');
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests \Drupal\file\FileUsage\DatabaseFileUsageBackend::add().
|
||||
*/
|
||||
function testAddUsage() {
|
||||
$file = $this->createFile();
|
||||
$file_usage = $this->container->get('file.usage');
|
||||
$file_usage->add($file, 'testing', 'foo', 1);
|
||||
// Add the file twice to ensure that the count is incremented rather than
|
||||
// creating additional records.
|
||||
$file_usage->add($file, 'testing', 'bar', 2);
|
||||
$file_usage->add($file, 'testing', 'bar', 2);
|
||||
|
||||
$usage = db_select('file_usage', 'f')
|
||||
->fields('f')
|
||||
->condition('f.fid', $file->id())
|
||||
->execute()
|
||||
->fetchAllAssoc('id');
|
||||
$this->assertEqual(count($usage), 2, 'Created two records');
|
||||
$this->assertEqual($usage[1]->module, 'testing', 'Correct module');
|
||||
$this->assertEqual($usage[2]->module, 'testing', 'Correct module');
|
||||
$this->assertEqual($usage[1]->type, 'foo', 'Correct type');
|
||||
$this->assertEqual($usage[2]->type, 'bar', 'Correct type');
|
||||
$this->assertEqual($usage[1]->count, 1, 'Correct count');
|
||||
$this->assertEqual($usage[2]->count, 2, 'Correct count');
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests \Drupal\file\FileUsage\DatabaseFileUsageBackend::delete().
|
||||
*/
|
||||
function testRemoveUsage() {
|
||||
$file = $this->createFile();
|
||||
$file_usage = $this->container->get('file.usage');
|
||||
db_insert('file_usage')
|
||||
->fields(array(
|
||||
'fid' => $file->id(),
|
||||
'module' => 'testing',
|
||||
'type' => 'bar',
|
||||
'id' => 2,
|
||||
'count' => 3,
|
||||
))
|
||||
->execute();
|
||||
|
||||
// Normal decrement.
|
||||
$file_usage->delete($file, 'testing', 'bar', 2);
|
||||
$count = db_select('file_usage', 'f')
|
||||
->fields('f', array('count'))
|
||||
->condition('f.fid', $file->id())
|
||||
->execute()
|
||||
->fetchField();
|
||||
$this->assertEqual(2, $count, 'The count was decremented correctly.');
|
||||
|
||||
// Multiple decrement and removal.
|
||||
$file_usage->delete($file, 'testing', 'bar', 2, 2);
|
||||
$count = db_select('file_usage', 'f')
|
||||
->fields('f', array('count'))
|
||||
->condition('f.fid', $file->id())
|
||||
->execute()
|
||||
->fetchField();
|
||||
$this->assertIdentical(FALSE, $count, 'The count was removed entirely when empty.');
|
||||
|
||||
// Non-existent decrement.
|
||||
$file_usage->delete($file, 'testing', 'bar', 2);
|
||||
$count = db_select('file_usage', 'f')
|
||||
->fields('f', array('count'))
|
||||
->condition('f.fid', $file->id())
|
||||
->execute()
|
||||
->fetchField();
|
||||
$this->assertIdentical(FALSE, $count, 'Decrementing non-exist record complete.');
|
||||
}
|
||||
|
||||
/**
|
||||
* Create files for all the possible combinations of age and status.
|
||||
*
|
||||
* We are using UPDATE statements because using the API would set the
|
||||
* timestamp.
|
||||
*/
|
||||
function createTempFiles() {
|
||||
// Temporary file that is old.
|
||||
$temp_old = file_save_data('');
|
||||
db_update('file_managed')
|
||||
->fields(array(
|
||||
'status' => 0,
|
||||
'changed' => REQUEST_TIME - $this->config('system.file')->get('temporary_maximum_age') - 1,
|
||||
))
|
||||
->condition('fid', $temp_old->id())
|
||||
->execute();
|
||||
$this->assertTrue(file_exists($temp_old->getFileUri()), 'Old temp file was created correctly.');
|
||||
|
||||
// Temporary file that is new.
|
||||
$temp_new = file_save_data('');
|
||||
db_update('file_managed')
|
||||
->fields(array('status' => 0))
|
||||
->condition('fid', $temp_new->id())
|
||||
->execute();
|
||||
$this->assertTrue(file_exists($temp_new->getFileUri()), 'New temp file was created correctly.');
|
||||
|
||||
// Permanent file that is old.
|
||||
$perm_old = file_save_data('');
|
||||
db_update('file_managed')
|
||||
->fields(array('changed' => REQUEST_TIME - $this->config('system.file')->get('temporary_maximum_age') - 1))
|
||||
->condition('fid', $temp_old->id())
|
||||
->execute();
|
||||
$this->assertTrue(file_exists($perm_old->getFileUri()), 'Old permanent file was created correctly.');
|
||||
|
||||
// Permanent file that is new.
|
||||
$perm_new = file_save_data('');
|
||||
$this->assertTrue(file_exists($perm_new->getFileUri()), 'New permanent file was created correctly.');
|
||||
return array($temp_old, $temp_new, $perm_old, $perm_new);
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensure that temporary files are removed by default.
|
||||
*/
|
||||
function testTempFileCleanupDefault() {
|
||||
list($temp_old, $temp_new, $perm_old, $perm_new) = $this->createTempFiles();
|
||||
|
||||
// Run cron and then ensure that only the old, temp file was deleted.
|
||||
$this->container->get('cron')->run();
|
||||
$this->assertFalse(file_exists($temp_old->getFileUri()), 'Old temp file was correctly removed.');
|
||||
$this->assertTrue(file_exists($temp_new->getFileUri()), 'New temp file was correctly ignored.');
|
||||
$this->assertTrue(file_exists($perm_old->getFileUri()), 'Old permanent file was correctly ignored.');
|
||||
$this->assertTrue(file_exists($perm_new->getFileUri()), 'New permanent file was correctly ignored.');
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensure that temporary files are kept as configured.
|
||||
*/
|
||||
function testTempFileNoCleanup() {
|
||||
list($temp_old, $temp_new, $perm_old, $perm_new) = $this->createTempFiles();
|
||||
|
||||
// Set the max age to 0, meaning no temporary files will be deleted.
|
||||
$this->config('system.file')
|
||||
->set('temporary_maximum_age', 0)
|
||||
->save();
|
||||
|
||||
// Run cron and then ensure that no file was deleted.
|
||||
$this->container->get('cron')->run();
|
||||
$this->assertTrue(file_exists($temp_old->getFileUri()), 'Old temp file was correctly ignored.');
|
||||
$this->assertTrue(file_exists($temp_new->getFileUri()), 'New temp file was correctly ignored.');
|
||||
$this->assertTrue(file_exists($perm_old->getFileUri()), 'Old permanent file was correctly ignored.');
|
||||
$this->assertTrue(file_exists($perm_new->getFileUri()), 'New permanent file was correctly ignored.');
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensure that temporary files are kept as configured.
|
||||
*/
|
||||
function testTempFileCustomCleanup() {
|
||||
list($temp_old, $temp_new, $perm_old, $perm_new) = $this->createTempFiles();
|
||||
|
||||
// Set the max age to older than default.
|
||||
$this->config('system.file')
|
||||
->set('temporary_maximum_age', 21600 + 2)
|
||||
->save();
|
||||
|
||||
// Run cron and then ensure that more files were deleted.
|
||||
$this->container->get('cron')->run();
|
||||
$this->assertTrue(file_exists($temp_old->getFileUri()), 'Old temp file was correctly ignored.');
|
||||
$this->assertTrue(file_exists($temp_new->getFileUri()), 'New temp file was correctly ignored.');
|
||||
$this->assertTrue(file_exists($perm_old->getFileUri()), 'Old permanent file was correctly ignored.');
|
||||
$this->assertTrue(file_exists($perm_new->getFileUri()), 'New permanent file was correctly ignored.');
|
||||
}
|
||||
}
|
41
core/modules/file/src/Tests/ValidateTest.php
Normal file
41
core/modules/file/src/Tests/ValidateTest.php
Normal file
|
@ -0,0 +1,41 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains \Drupal\file\Tests\ValidateTest.
|
||||
*/
|
||||
|
||||
namespace Drupal\file\Tests;
|
||||
|
||||
/**
|
||||
* Tests the file_validate() function.
|
||||
*
|
||||
* @group file
|
||||
*/
|
||||
class ValidateTest extends FileManagedUnitTestBase {
|
||||
/**
|
||||
* Test that the validators passed into are checked.
|
||||
*/
|
||||
function testCallerValidation() {
|
||||
$file = $this->createFile();
|
||||
|
||||
// Empty validators.
|
||||
$this->assertEqual(file_validate($file, array()), array(), 'Validating an empty array works successfully.');
|
||||
$this->assertFileHooksCalled(array('validate'));
|
||||
|
||||
// Use the file_test.module's test validator to ensure that passing tests
|
||||
// return correctly.
|
||||
file_test_reset();
|
||||
file_test_set_return('validate', array());
|
||||
$passing = array('file_test_validator' => array(array()));
|
||||
$this->assertEqual(file_validate($file, $passing), array(), 'Validating passes.');
|
||||
$this->assertFileHooksCalled(array('validate'));
|
||||
|
||||
// Now test for failures in validators passed in and by hook_validate.
|
||||
file_test_reset();
|
||||
file_test_set_return('validate', array('Epic fail'));
|
||||
$failing = array('file_test_validator' => array(array('Failed', 'Badly')));
|
||||
$this->assertEqual(file_validate($file, $failing), array('Failed', 'Badly', 'Epic fail'), 'Validating returns errors.');
|
||||
$this->assertFileHooksCalled(array('validate'));
|
||||
}
|
||||
}
|
158
core/modules/file/src/Tests/ValidatorTest.php
Normal file
158
core/modules/file/src/Tests/ValidatorTest.php
Normal file
|
@ -0,0 +1,158 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains \Drupal\file\Tests\ValidatorTest.
|
||||
*/
|
||||
|
||||
namespace Drupal\file\Tests;
|
||||
|
||||
/**
|
||||
* Tests the functions used to validate uploaded files.
|
||||
*
|
||||
* @group file
|
||||
*/
|
||||
class ValidatorTest extends FileManagedUnitTestBase {
|
||||
|
||||
/**
|
||||
* An image file.
|
||||
*
|
||||
* @var \Drupal\file\FileInterface
|
||||
*/
|
||||
protected $image;
|
||||
|
||||
/**
|
||||
* A file which is not an image.
|
||||
*
|
||||
* @var \Drupal\file\Entity\File
|
||||
*/
|
||||
protected $nonImage;
|
||||
|
||||
protected function setUp() {
|
||||
parent::setUp();
|
||||
|
||||
$this->image = entity_create('file');
|
||||
$this->image->setFileUri('core/misc/druplicon.png');
|
||||
$this->image->setFilename(drupal_basename($this->image->getFileUri()));
|
||||
|
||||
$this->nonImage = entity_create('file');
|
||||
$this->nonImage->setFileUri('core/assets/vendor/jquery/jquery.min.js');
|
||||
$this->nonImage->setFilename(drupal_basename($this->nonImage->getFileUri()));
|
||||
}
|
||||
|
||||
/**
|
||||
* Test the file_validate_extensions() function.
|
||||
*/
|
||||
function testFileValidateExtensions() {
|
||||
$file = entity_create('file', array('filename' => 'asdf.txt'));
|
||||
$errors = file_validate_extensions($file, 'asdf txt pork');
|
||||
$this->assertEqual(count($errors), 0, 'Valid extension accepted.', 'File');
|
||||
|
||||
$file->setFilename('asdf.txt');
|
||||
$errors = file_validate_extensions($file, 'exe png');
|
||||
$this->assertEqual(count($errors), 1, 'Invalid extension blocked.', 'File');
|
||||
}
|
||||
|
||||
/**
|
||||
* This ensures a specific file is actually an image.
|
||||
*/
|
||||
function testFileValidateIsImage() {
|
||||
$this->assertTrue(file_exists($this->image->getFileUri()), 'The image being tested exists.', 'File');
|
||||
$errors = file_validate_is_image($this->image);
|
||||
$this->assertEqual(count($errors), 0, 'No error reported for our image file.', 'File');
|
||||
|
||||
$this->assertTrue(file_exists($this->nonImage->getFileUri()), 'The non-image being tested exists.', 'File');
|
||||
$errors = file_validate_is_image($this->nonImage);
|
||||
$this->assertEqual(count($errors), 1, 'An error reported for our non-image file.', 'File');
|
||||
}
|
||||
|
||||
/**
|
||||
* This ensures the resolution of a specific file is within bounds.
|
||||
* The image will be resized if it's too large.
|
||||
*/
|
||||
function testFileValidateImageResolution() {
|
||||
// Non-images.
|
||||
$errors = file_validate_image_resolution($this->nonImage);
|
||||
$this->assertEqual(count($errors), 0, 'Should not get any errors for a non-image file.', 'File');
|
||||
$errors = file_validate_image_resolution($this->nonImage, '50x50', '100x100');
|
||||
$this->assertEqual(count($errors), 0, 'Do not check the resolution on non files.', 'File');
|
||||
|
||||
// Minimum size.
|
||||
$errors = file_validate_image_resolution($this->image);
|
||||
$this->assertEqual(count($errors), 0, 'No errors for an image when there is no minimum or maximum resolution.', 'File');
|
||||
$errors = file_validate_image_resolution($this->image, 0, '200x1');
|
||||
$this->assertEqual(count($errors), 1, 'Got an error for an image that was not wide enough.', 'File');
|
||||
$errors = file_validate_image_resolution($this->image, 0, '1x200');
|
||||
$this->assertEqual(count($errors), 1, 'Got an error for an image that was not tall enough.', 'File');
|
||||
$errors = file_validate_image_resolution($this->image, 0, '200x200');
|
||||
$this->assertEqual(count($errors), 1, 'Small images report an error.', 'File');
|
||||
|
||||
// Maximum size.
|
||||
if ($this->container->get('image.factory')->getToolkitId()) {
|
||||
// Copy the image so that the original doesn't get resized.
|
||||
copy('core/misc/druplicon.png', 'temporary://druplicon.png');
|
||||
$this->image->setFileUri('temporary://druplicon.png');
|
||||
|
||||
$errors = file_validate_image_resolution($this->image, '10x5');
|
||||
$this->assertEqual(count($errors), 0, 'No errors should be reported when an oversized image can be scaled down.', 'File');
|
||||
|
||||
$image = $this->container->get('image.factory')->get($this->image->getFileUri());
|
||||
$this->assertTrue($image->getWidth() <= 10, 'Image scaled to correct width.', 'File');
|
||||
$this->assertTrue($image->getHeight() <= 5, 'Image scaled to correct height.', 'File');
|
||||
|
||||
// Once again, now with negative width and height to force an error.
|
||||
copy('core/misc/druplicon.png', 'temporary://druplicon.png');
|
||||
$this->image->setFileUri('temporary://druplicon.png');
|
||||
$errors = file_validate_image_resolution($this->image, '-10x-5');
|
||||
$this->assertEqual(count($errors), 1, 'An error reported for an oversized image that can not be scaled down.', 'File');
|
||||
|
||||
drupal_unlink('temporary://druplicon.png');
|
||||
}
|
||||
else {
|
||||
// TODO: should check that the error is returned if no toolkit is available.
|
||||
$errors = file_validate_image_resolution($this->image, '5x10');
|
||||
$this->assertEqual(count($errors), 1, 'Oversize images that cannot be scaled get an error.', 'File');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This will ensure the filename length is valid.
|
||||
*/
|
||||
function testFileValidateNameLength() {
|
||||
// Create a new file entity.
|
||||
$file = entity_create('file');
|
||||
|
||||
// Add a filename with an allowed length and test it.
|
||||
$file->setFilename(str_repeat('x', 240));
|
||||
$this->assertEqual(strlen($file->getFilename()), 240);
|
||||
$errors = file_validate_name_length($file);
|
||||
$this->assertEqual(count($errors), 0, 'No errors reported for 240 length filename.', 'File');
|
||||
|
||||
// Add a filename with a length too long and test it.
|
||||
$file->setFilename(str_repeat('x', 241));
|
||||
$errors = file_validate_name_length($file);
|
||||
$this->assertEqual(count($errors), 1, 'An error reported for 241 length filename.', 'File');
|
||||
|
||||
// Add a filename with an empty string and test it.
|
||||
$file->setFilename('');
|
||||
$errors = file_validate_name_length($file);
|
||||
$this->assertEqual(count($errors), 1, 'An error reported for 0 length filename.', 'File');
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Test file_validate_size().
|
||||
*/
|
||||
function testFileValidateSize() {
|
||||
// Create a file with a size of 1000 bytes, and quotas of only 1 byte.
|
||||
$file = entity_create('file', array('filesize' => 1000));
|
||||
$errors = file_validate_size($file, 0, 0);
|
||||
$this->assertEqual(count($errors), 0, 'No limits means no errors.', 'File');
|
||||
$errors = file_validate_size($file, 1, 0);
|
||||
$this->assertEqual(count($errors), 1, 'Error for the file being over the limit.', 'File');
|
||||
$errors = file_validate_size($file, 0, 1);
|
||||
$this->assertEqual(count($errors), 1, 'Error for the user being over their limit.', 'File');
|
||||
$errors = file_validate_size($file, 1, 1);
|
||||
$this->assertEqual(count($errors), 2, 'Errors for both the file and their limit.', 'File');
|
||||
}
|
||||
}
|
|
@ -0,0 +1,96 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains \Drupal\file\Tests\Views\ExtensionViewsFieldTest.
|
||||
*/
|
||||
|
||||
namespace Drupal\file\Tests\Views;
|
||||
|
||||
use Drupal\file\Entity\File;
|
||||
use Drupal\views\Views;
|
||||
use Drupal\views\Tests\ViewUnitTestBase;
|
||||
use Drupal\views\Tests\ViewTestData;
|
||||
|
||||
/**
|
||||
* Tests the core Drupal\file\Plugin\views\field\Extension handler.
|
||||
*
|
||||
* @group file
|
||||
*/
|
||||
class ExtensionViewsFieldTest extends ViewUnitTestBase {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static $modules = array('file', 'file_test_views', 'user');
|
||||
|
||||
/**
|
||||
* Views used by this test.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public static $testViews = array('file_extension_view');
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function setUp() {
|
||||
parent::setUp();
|
||||
ViewTestData::createTestViews(get_class($this), array('file_test_views'));
|
||||
|
||||
$this->installEntitySchema('file');
|
||||
|
||||
file_put_contents('public://file.png', '');
|
||||
File::create([
|
||||
'uri' => 'public://file.png',
|
||||
'filename' => 'file.png',
|
||||
])->save();
|
||||
|
||||
file_put_contents('public://file.tar', '');
|
||||
File::create([
|
||||
'uri' => 'public://file.tar',
|
||||
'filename' => 'file.tar',
|
||||
])->save();
|
||||
|
||||
file_put_contents('public://file.tar.gz', '');
|
||||
File::create([
|
||||
'uri' => 'public://file.tar.gz',
|
||||
'filename' => 'file.tar.gz',
|
||||
])->save();
|
||||
|
||||
file_put_contents('public://file', '');
|
||||
File::create([
|
||||
'uri' => 'public://file',
|
||||
'filename' => 'file',
|
||||
])->save();
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests file extension views field handler extension_detect_tar option.
|
||||
*/
|
||||
public function testFileExtensionTarOption() {
|
||||
$view = Views::getView('file_extension_view');
|
||||
$view->setDisplay();
|
||||
$this->executeView($view);
|
||||
|
||||
// Test without the tar option.
|
||||
$this->assertEqual($view->field['extension']->advancedRender($view->result[0]), 'png');
|
||||
$this->assertEqual($view->field['extension']->advancedRender($view->result[1]), 'tar');
|
||||
$this->assertEqual($view->field['extension']->advancedRender($view->result[2]), 'gz');
|
||||
$this->assertEqual($view->field['extension']->advancedRender($view->result[3]), '');
|
||||
// Test with the tar option.
|
||||
|
||||
$view = Views::getView('file_extension_view');
|
||||
$view->setDisplay();
|
||||
$view->initHandlers();
|
||||
|
||||
$view->field['extension']->options['settings']['extension_detect_tar'] = TRUE;
|
||||
$this->executeView($view);
|
||||
|
||||
$this->assertEqual($view->field['extension']->advancedRender($view->result[0]), 'png');
|
||||
$this->assertEqual($view->field['extension']->advancedRender($view->result[1]), 'tar');
|
||||
$this->assertEqual($view->field['extension']->advancedRender($view->result[2]), 'tar.gz');
|
||||
$this->assertEqual($view->field['extension']->advancedRender($view->result[3]), '');
|
||||
}
|
||||
|
||||
}
|
97
core/modules/file/src/Tests/Views/FileViewsDataTest.php
Normal file
97
core/modules/file/src/Tests/Views/FileViewsDataTest.php
Normal file
|
@ -0,0 +1,97 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains \Drupal\file\Tests\Views\FileViewsDataTest.
|
||||
*/
|
||||
|
||||
namespace Drupal\file\Tests\Views;
|
||||
|
||||
use Drupal\field\Entity\FieldStorageConfig;
|
||||
use Drupal\field\Entity\FieldConfig;
|
||||
use Drupal\views\Tests\ViewUnitTestBase;
|
||||
use Drupal\views\Views;
|
||||
|
||||
/**
|
||||
* Tests file views data.
|
||||
*
|
||||
* @group file
|
||||
*/
|
||||
class FileViewsDataTest extends ViewUnitTestBase {
|
||||
|
||||
/**
|
||||
* Modules to install.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public static $modules = array('file', 'views', 'entity_test', 'user', 'field');
|
||||
|
||||
/**
|
||||
* Tests views data generated for file field relationship.
|
||||
*
|
||||
* @see file_field_views_data()
|
||||
* @see file_field_views_data_views_data_alter()
|
||||
*/
|
||||
public function testRelationshipViewsData() {
|
||||
// Create file field to entity_test.
|
||||
FieldStorageConfig::create(array(
|
||||
'entity_type' => 'entity_test',
|
||||
'field_name' => 'field_base_file',
|
||||
'type' => 'file',
|
||||
))->save();
|
||||
FieldConfig::create(array(
|
||||
'entity_type' => 'entity_test',
|
||||
'field_name' => 'field_base_file',
|
||||
'bundle' => 'entity_test',
|
||||
))->save();
|
||||
// Check the generated views data.
|
||||
$views_data = Views::viewsData()->get('entity_test__field_base_file');
|
||||
$relationship = $views_data['field_base_file_target_id']['relationship'];
|
||||
$this->assertEqual($relationship['id'], 'standard');
|
||||
$this->assertEqual($relationship['base'], 'file_managed');
|
||||
$this->assertEqual($relationship['base field'], 'fid');
|
||||
$this->assertEqual($relationship['entity type'], 'file');
|
||||
// Check the backwards reference.
|
||||
$views_data = Views::viewsData()->get('file_managed');
|
||||
$relationship = $views_data['reverse_field_base_file_entity_test']['relationship'];
|
||||
$this->assertEqual($relationship['id'], 'entity_reverse');
|
||||
$this->assertEqual($relationship['base'], 'entity_test');
|
||||
$this->assertEqual($relationship['base field'], 'id');
|
||||
$this->assertEqual($relationship['field table'], 'entity_test__field_base_file');
|
||||
$this->assertEqual($relationship['field field'], 'field_base_file_target_id');
|
||||
$this->assertEqual($relationship['field_name'], 'field_base_file');
|
||||
$this->assertEqual($relationship['entity_type'], 'entity_test');
|
||||
$this->assertEqual($relationship['join_extra'][0], ['field' => 'deleted', 'value' => 0, 'numeric' => TRUE]);
|
||||
|
||||
// Create file field to entity_test_mul.
|
||||
FieldStorageConfig::create(array(
|
||||
'entity_type' => 'entity_test_mul',
|
||||
'field_name' => 'field_data_file',
|
||||
'type' => 'file',
|
||||
))->save();
|
||||
FieldConfig::create(array(
|
||||
'entity_type' => 'entity_test_mul',
|
||||
'field_name' => 'field_data_file',
|
||||
'bundle' => 'entity_test_mul',
|
||||
))->save();
|
||||
// Check the generated views data.
|
||||
$views_data = Views::viewsData()->get('entity_test_mul__field_data_file');
|
||||
$relationship = $views_data['field_data_file_target_id']['relationship'];
|
||||
$this->assertEqual($relationship['id'], 'standard');
|
||||
$this->assertEqual($relationship['base'], 'file_managed');
|
||||
$this->assertEqual($relationship['base field'], 'fid');
|
||||
$this->assertEqual($relationship['entity type'], 'file');
|
||||
// Check the backwards reference.
|
||||
$views_data = Views::viewsData()->get('file_managed');
|
||||
$relationship = $views_data['reverse_field_data_file_entity_test_mul']['relationship'];
|
||||
$this->assertEqual($relationship['id'], 'entity_reverse');
|
||||
$this->assertEqual($relationship['base'], 'entity_test_mul_property_data');
|
||||
$this->assertEqual($relationship['base field'], 'id');
|
||||
$this->assertEqual($relationship['field table'], 'entity_test_mul__field_data_file');
|
||||
$this->assertEqual($relationship['field field'], 'field_data_file_target_id');
|
||||
$this->assertEqual($relationship['field_name'], 'field_data_file');
|
||||
$this->assertEqual($relationship['entity_type'], 'entity_test_mul');
|
||||
$this->assertEqual($relationship['join_extra'][0], ['field' => 'deleted', 'value' => 0, 'numeric' => TRUE]);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,75 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains \Drupal\file\Tests\Views\FileViewsFieldAccessTest.
|
||||
*/
|
||||
|
||||
namespace Drupal\file\Tests\Views;
|
||||
|
||||
use Drupal\file\Entity\File;
|
||||
use Drupal\language\Entity\ConfigurableLanguage;
|
||||
use Drupal\user\Entity\User;
|
||||
use Drupal\views\Tests\Handler\FieldFieldAccessTestBase;
|
||||
|
||||
/**
|
||||
* Tests base field access in Views for the file entity.
|
||||
*
|
||||
* @group File
|
||||
*/
|
||||
class FileViewsFieldAccessTest extends FieldFieldAccessTestBase {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static $modules = ['file', 'entity_test', 'language', 'user'];
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function setUp($import_test_views = TRUE) {
|
||||
parent::setUp($import_test_views);
|
||||
|
||||
$this->installEntitySchema('file');
|
||||
}
|
||||
|
||||
/**
|
||||
* Check access for file fields.
|
||||
*/
|
||||
public function testFileFields() {
|
||||
ConfigurableLanguage::create([
|
||||
'id' => 'fr',
|
||||
'name' => 'French',
|
||||
])->save();
|
||||
|
||||
$user = User::create([
|
||||
'name' => 'test user',
|
||||
]);
|
||||
$user->save();
|
||||
|
||||
file_put_contents('public://test.txt', 'test');
|
||||
$file = File::create([
|
||||
'filename' => 'test.txt',
|
||||
'uri' => 'public://test.txt',
|
||||
'status' => TRUE,
|
||||
'langcode' => 'fr',
|
||||
'uid' => $user->id()
|
||||
]);
|
||||
$file->save();
|
||||
|
||||
// @todo Expand the test coverage in https://www.drupal.org/node/2464635
|
||||
|
||||
$this->assertFieldAccess('file', 'fid', $file->id());
|
||||
$this->assertFieldAccess('file', 'uuid', $file->uuid());
|
||||
$this->assertFieldAccess('file', 'langcode', $file->language()->getName());
|
||||
$this->assertFieldAccess('file', 'uid', 'test user');
|
||||
$this->assertFieldAccess('file', 'filename', $file->getFilename());
|
||||
$this->assertFieldAccess('file', 'uri', $file->getFileUri());
|
||||
$this->assertFieldAccess('file', 'filemime', $file->filemime->value);
|
||||
$this->assertFieldAccess('file', 'filesize', '4 bytes');
|
||||
$this->assertFieldAccess('file', 'status', t('Permanent'));
|
||||
// $this->assertFieldAccess('file', 'created', \Drupal::service('date.formatter')->format(123456));
|
||||
// $this->assertFieldAccess('file', 'changed', \Drupal::service('date.formatter')->format(REQUEST_TIME));
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,98 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains \Drupal\file\Tests\Views\RelationshipUserFileDataTest.
|
||||
*/
|
||||
|
||||
namespace Drupal\file\Tests\Views;
|
||||
|
||||
use Drupal\views\Tests\ViewTestBase;
|
||||
use Drupal\views\Views;
|
||||
use Drupal\views\Tests\ViewTestData;
|
||||
|
||||
/**
|
||||
* Tests file on user relationship handler.
|
||||
*
|
||||
* @group file
|
||||
*/
|
||||
class RelationshipUserFileDataTest extends ViewTestBase {
|
||||
|
||||
/**
|
||||
* Modules to install.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public static $modules = array('file', 'file_test_views', 'user');
|
||||
|
||||
/**
|
||||
* Views used by this test.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public static $testViews = array('test_file_user_file_data');
|
||||
|
||||
protected function setUp() {
|
||||
parent::setUp();
|
||||
|
||||
// Create the user profile field and instance.
|
||||
entity_create('field_storage_config', array(
|
||||
'entity_type' => 'user',
|
||||
'field_name' => 'user_file',
|
||||
'type' => 'file',
|
||||
'translatable' => '0',
|
||||
))->save();
|
||||
entity_create('field_config', array(
|
||||
'label' => 'User File',
|
||||
'description' => '',
|
||||
'field_name' => 'user_file',
|
||||
'entity_type' => 'user',
|
||||
'bundle' => 'user',
|
||||
'required' => 0,
|
||||
))->save();
|
||||
|
||||
ViewTestData::createTestViews(get_class($this), array('file_test_views'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests using the views file relationship.
|
||||
*/
|
||||
public function testViewsHandlerRelationshipUserFileData() {
|
||||
$file = entity_create('file', array(
|
||||
'fid' => 2,
|
||||
'uid' => 2,
|
||||
'filename' => 'image-test.jpg',
|
||||
'uri' => "public://image-test.jpg",
|
||||
'filemime' => 'image/jpeg',
|
||||
'created' => 1,
|
||||
'changed' => 1,
|
||||
'status' => FILE_STATUS_PERMANENT,
|
||||
));
|
||||
$file->enforceIsNew();
|
||||
file_put_contents($file->getFileUri(), file_get_contents('core/modules/simpletest/files/image-1.png'));
|
||||
$file->save();
|
||||
|
||||
$account = $this->drupalCreateUser();
|
||||
$account->user_file->target_id = 2;
|
||||
$account->save();
|
||||
|
||||
$view = Views::getView('test_file_user_file_data');
|
||||
// Tests \Drupal\taxonomy\Plugin\views\relationship\NodeTermData::calculateDependencies().
|
||||
$expected = [
|
||||
'module' => [
|
||||
'file',
|
||||
'user',
|
||||
],
|
||||
];
|
||||
$this->assertIdentical($expected, $view->calculateDependencies());
|
||||
$this->executeView($view);
|
||||
$expected_result = array(
|
||||
array(
|
||||
'file_managed_user__user_file_fid' => '2',
|
||||
),
|
||||
);
|
||||
$column_map = array('file_managed_user__user_file_fid' => 'file_managed_user__user_file_fid');
|
||||
$this->assertIdenticalResultset($view, $expected_result, $column_map);
|
||||
}
|
||||
|
||||
}
|
Reference in a new issue