Update to Drupal 8.1.2. For more information, see https://www.drupal.org/project/drupal/releases/8.1.2
This commit is contained in:
parent
9eae24d844
commit
28556d630e
1322 changed files with 6699 additions and 2064 deletions
|
@ -709,11 +709,12 @@ function file_save_upload($form_field_name, $validators = array(), $destination
|
|||
$user = \Drupal::currentUser();
|
||||
static $upload_cache;
|
||||
|
||||
$file_upload = \Drupal::request()->files->get("files[$form_field_name]", NULL, TRUE);
|
||||
$all_files = \Drupal::request()->files->get('files', array());
|
||||
// Make sure there's an upload to process.
|
||||
if (empty($file_upload)) {
|
||||
if (empty($all_files[$form_field_name])) {
|
||||
return NULL;
|
||||
}
|
||||
$file_upload = $all_files[$form_field_name];
|
||||
|
||||
// Return cached objects without processing since the file will have
|
||||
// already been processed and the paths in $_FILES will be invalid.
|
||||
|
@ -1168,10 +1169,11 @@ function file_managed_file_submit($form, FormStateInterface $form_state) {
|
|||
*/
|
||||
function file_managed_file_save_upload($element, FormStateInterface $form_state) {
|
||||
$upload_name = implode('_', $element['#parents']);
|
||||
$file_upload = \Drupal::request()->files->get("files[$upload_name]", NULL, TRUE);
|
||||
if (empty($file_upload)) {
|
||||
$all_files = \Drupal::request()->files->get('files', array());
|
||||
if (empty($all_files[$upload_name])) {
|
||||
return FALSE;
|
||||
}
|
||||
$file_upload = $all_files[$upload_name];
|
||||
|
||||
$destination = isset($element['#upload_location']) ? $element['#upload_location'] : NULL;
|
||||
if (isset($destination) && !file_prepare_directory($destination, FILE_CREATE_DIRECTORY)) {
|
||||
|
|
|
@ -97,7 +97,7 @@ class ManagedFile extends FormElement {
|
|||
// Temporary files that belong to other users should never be
|
||||
// allowed.
|
||||
if ($file->isTemporary()) {
|
||||
if ($file->getOwnerId() != \Drupal::currentUser()->id()) {
|
||||
if ($file->getOwnerId() != \Drupal::currentUser()->id()) {
|
||||
$force_default = TRUE;
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -13,6 +13,8 @@ use Drupal\user\UserInterface;
|
|||
/**
|
||||
* Defines the file entity class.
|
||||
*
|
||||
* @ingroup file
|
||||
*
|
||||
* @ContentEntityType(
|
||||
* id = "file",
|
||||
* label = @Translation("File"),
|
||||
|
@ -186,7 +188,11 @@ class File extends ContentEntityBase implements FileInterface {
|
|||
public function preSave(EntityStorageInterface $storage) {
|
||||
parent::preSave($storage);
|
||||
|
||||
$this->setSize(filesize($this->getFileUri()));
|
||||
// The file itself might not exist or be available right now.
|
||||
$uri = $this->getFileUri();
|
||||
if ($size = @filesize($uri)) {
|
||||
$this->setSize($size);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -6,6 +6,8 @@ use Drupal\Core\Access\AccessResult;
|
|||
use Drupal\Core\Entity\EntityAccessControlHandler;
|
||||
use Drupal\Core\Entity\EntityInterface;
|
||||
use Drupal\Core\Entity\EntityStorageInterface;
|
||||
use Drupal\Core\Field\FieldDefinitionInterface;
|
||||
use Drupal\Core\Field\FieldItemListInterface;
|
||||
use Drupal\Core\Session\AccountInterface;
|
||||
|
||||
/**
|
||||
|
@ -43,6 +45,16 @@ class FileAccessControlHandler extends EntityAccessControlHandler {
|
|||
}
|
||||
}
|
||||
|
||||
if ($operation == 'delete' || $operation == 'update') {
|
||||
$account = $this->prepareUser($account);
|
||||
$file_uid = $entity->get('uid')->getValue();
|
||||
// Only the file owner can delete and update the file entity.
|
||||
if ($account->id() == $file_uid[0]['target_id']) {
|
||||
return AccessResult::allowed();
|
||||
}
|
||||
return AccessResult::forbidden();
|
||||
}
|
||||
|
||||
// No opinion.
|
||||
return AccessResult::neutral();
|
||||
}
|
||||
|
@ -63,4 +75,30 @@ class FileAccessControlHandler extends EntityAccessControlHandler {
|
|||
return file_get_file_references($file, NULL, EntityStorageInterface::FIELD_LOAD_REVISION, NULL);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function checkFieldAccess($operation, FieldDefinitionInterface $field_definition, AccountInterface $account, FieldItemListInterface $items = NULL) {
|
||||
// No user can edit the status of a file. Prevents saving a new file as
|
||||
// persistent before even validating it.
|
||||
if ($field_definition->getName() === 'status' && $operation === 'edit') {
|
||||
return AccessResult::forbidden();
|
||||
}
|
||||
return parent::checkFieldAccess($operation, $field_definition, $account, $items);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function checkCreateAccess(AccountInterface $account, array $context, $entity_bundle = NULL) {
|
||||
// The file entity has no "create" permission because by default Drupal core
|
||||
// does not allow creating file entities independently. It allows you to
|
||||
// create file entities that are referenced from another entity
|
||||
// (e.g. an image for a article). A contributed module is free to alter
|
||||
// this to allow file entities to be created directly.
|
||||
// @todo Update comment to mention REST module when
|
||||
// https://www.drupal.org/node/1927648 is fixed.
|
||||
return AccessResult::neutral();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -8,6 +8,8 @@ use Drupal\Core\Entity\EntityChangedInterface;
|
|||
|
||||
/**
|
||||
* Defines getter and setter methods for file entity base fields.
|
||||
*
|
||||
* @ingroup file
|
||||
*/
|
||||
interface FileInterface extends ContentEntityInterface, EntityChangedInterface, EntityOwnerInterface {
|
||||
|
||||
|
@ -113,4 +115,5 @@ interface FileInterface extends ContentEntityInterface, EntityChangedInterface,
|
|||
* Creation timestamp of the file entity.
|
||||
*/
|
||||
public function getCreatedTime();
|
||||
|
||||
}
|
||||
|
|
|
@ -23,4 +23,5 @@ interface FileStorageInterface extends ContentEntityStorageInterface {
|
|||
* An integer containing the number of bytes used.
|
||||
*/
|
||||
public function spaceUsed($uid = NULL, $status = FILE_STATUS_PERMANENT);
|
||||
|
||||
}
|
||||
|
|
|
@ -107,4 +107,5 @@ class DatabaseFileUsageBackend extends FileUsageBase {
|
|||
}
|
||||
return $references;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -32,4 +32,5 @@ abstract class FileUsageBase implements FileUsageInterface {
|
|||
$file->save();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -64,7 +64,7 @@ interface FileUsageInterface {
|
|||
* A nested array with usage data. The first level is keyed by module name,
|
||||
* the second by object type and the third by the object id. The value of
|
||||
* the third level contains the usage count.
|
||||
*
|
||||
*/
|
||||
public function listUsage(FileInterface $file);
|
||||
|
||||
}
|
||||
|
|
|
@ -372,7 +372,8 @@ class FileWidget extends WidgetBase implements ContainerFactoryPluginInterface {
|
|||
);
|
||||
if (isset($item['display'])) {
|
||||
$element['display']['#value'] = $item['display'] ? '1' : '';
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
$element['display']['#value'] = $element['#display_default'];
|
||||
}
|
||||
}
|
||||
|
|
|
@ -168,4 +168,5 @@ class DownloadTest extends FileManagedTestBase {
|
|||
|
||||
$file->delete();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -89,4 +89,5 @@ class FileFieldPathTest extends FileFieldTestBase {
|
|||
$result = preg_match('/' . preg_quote($base_path, '/') . '(_[0-9]+)?\.' . preg_quote($extension, '/') . '/', $actual_path);
|
||||
$this->assertTrue($result, $message);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -64,4 +64,5 @@ class FileFieldRSSContentTest extends FileFieldTestBase {
|
|||
);
|
||||
$this->assertRaw($test_element, 'File field RSS enclosure is displayed when viewing the RSS feed.');
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -138,4 +138,5 @@ class FileFieldRevisionTest extends FileFieldTestBase {
|
|||
$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.');
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -191,7 +191,7 @@ class FileFieldWidgetTest extends FileFieldTestBase {
|
|||
$check_field_name = $field_name;
|
||||
}
|
||||
|
||||
$this->assertIdentical((string) $button['name'], $check_field_name . '_' . $key. '_remove_button');
|
||||
$this->assertIdentical((string) $button['name'], $check_field_name . '_' . $key . '_remove_button');
|
||||
}
|
||||
|
||||
// "Click" the remove button (emulating either a nojs or js submission).
|
||||
|
|
|
@ -65,4 +65,5 @@ class FileManagedAccessTest extends FileManagedTestBase {
|
|||
$this->assertFalse($file->access('view', $account), 'Private file is not viewable to anonymous user');
|
||||
$this->assertFalse($file->access('download', $account), 'Private file is not downloadable to anonymous user');
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -171,4 +171,27 @@ class FileManagedFileElementTest extends FileFieldTestBase {
|
|||
$this->assertRaw('The file referenced by the Managed <em>file & butter</em> field does not exist.');
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensure a file entity can be saved when the file does not exist on disk.
|
||||
*/
|
||||
public function testFileRemovedFromDisk() {
|
||||
$this->drupalGet('file/test/1/0/1');
|
||||
$test_file = $this->getTestFile('text');
|
||||
$file_field_name = 'files[nested_file][]';
|
||||
|
||||
$edit = [$file_field_name => drupal_realpath($test_file->getFileUri())];
|
||||
$this->drupalPostForm(NULL, $edit, t('Upload'));
|
||||
$this->drupalPostForm(NULL, array(), t('Save'));
|
||||
|
||||
$fid = $this->getLastFileId();
|
||||
/** @var $file \Drupal\file\FileInterface */
|
||||
$file = $this->container->get('entity_type.manager')->getStorage('file')->load($fid);
|
||||
$file->setPermanent();
|
||||
$file->save();
|
||||
$this->assertTrue(file_unmanaged_delete($file->getFileUri()));
|
||||
$file->save();
|
||||
$this->assertTrue($file->isPermanent());
|
||||
$file->delete();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -75,9 +75,9 @@ class FilePrivateTest extends FileFieldTestBase {
|
|||
$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'));
|
||||
$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');
|
||||
$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())));
|
||||
|
@ -111,4 +111,5 @@ class FilePrivateTest extends FileFieldTestBase {
|
|||
$this->drupalGet($file_url);
|
||||
$this->assertResponse(403, 'Confirmed that access is denied for another user to the temporary file.');
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -93,4 +93,5 @@ class FileTokenReplaceTest extends FileFieldTestBase {
|
|||
$this->assertEqual($output, $expected, format_string('Unsanitized file token %token replaced.', array('%token' => $input)));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -20,4 +20,5 @@ class RemoteFileSaveUploadTest extends SaveUploadTest {
|
|||
parent::setUp();
|
||||
$this->config('system.file')->set('default_scheme', 'dummy-remote')->save();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -358,4 +358,5 @@ class SaveUploadTest extends FileManagedTestBase {
|
|||
'@destination' => 'temporary://' . $test_directory . '/' . $this->image->getFilename()
|
||||
)), 'Found upload error log entry.');
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -117,4 +117,5 @@ class FileTestForm implements FormInterface {
|
|||
drupal_set_message(t('Epic upload FAIL!'), 'error');
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -46,4 +46,5 @@ class DummyReadOnlyStreamWrapper extends LocalReadOnlyStream {
|
|||
function getExternalUrl() {
|
||||
return '/dummy/example.txt';
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -30,4 +30,5 @@ class DummyRemoteStreamWrapper extends PublicStream {
|
|||
function realpath() {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -46,4 +46,5 @@ class DummyStreamWrapper extends LocalStream {
|
|||
function getExternalUrl() {
|
||||
return '/dummy/example.txt';
|
||||
}
|
||||
|
||||
}
|
||||
|
|
107
core/modules/file/tests/src/Kernel/AccessTest.php
Normal file
107
core/modules/file/tests/src/Kernel/AccessTest.php
Normal file
|
@ -0,0 +1,107 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\Tests\file\Kernel;
|
||||
|
||||
use Drupal\file\Entity\File;
|
||||
use Drupal\KernelTests\KernelTestBase;
|
||||
use Drupal\user\Entity\User;
|
||||
|
||||
/**
|
||||
* Tests for the File access control.
|
||||
*
|
||||
* @group file
|
||||
*/
|
||||
class AccessTest extends KernelTestBase {
|
||||
|
||||
/**
|
||||
* Modules to enable.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public static $modules = ['file', 'system', 'user'];
|
||||
|
||||
/**
|
||||
* An authenticated user.
|
||||
*
|
||||
* @var \Drupal\user\UserInterface
|
||||
*/
|
||||
protected $user1;
|
||||
|
||||
/**
|
||||
* An authenticated user.
|
||||
*
|
||||
* @var \Drupal\user\UserInterface
|
||||
*/
|
||||
protected $user2;
|
||||
|
||||
/**
|
||||
* The file object used in the test.
|
||||
*
|
||||
* @var \Drupal\file\FileInterface
|
||||
*/
|
||||
protected $file;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function setUp() {
|
||||
parent::setUp();
|
||||
|
||||
$this->installEntitySchema('file');
|
||||
$this->installEntitySchema('user');
|
||||
$this->installSchema('file', array('file_usage'));
|
||||
$this->installSchema('system', 'sequences');
|
||||
|
||||
$this->user1 = User::create([
|
||||
'name' => 'user1',
|
||||
'status' => 1,
|
||||
]);
|
||||
$this->user1->save();
|
||||
|
||||
$this->user2 = User::create([
|
||||
'name' => 'user2',
|
||||
'status' => 1,
|
||||
]);
|
||||
$this->user2->save();
|
||||
|
||||
$this->file = File::create(array(
|
||||
'uid' => $this->user1->id(),
|
||||
'filename' => 'druplicon.txt',
|
||||
'filemime' => 'text/plain',
|
||||
));
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests that only the file owner can delete or update a file.
|
||||
*/
|
||||
public function testOnlyOwnerCanDeleteUpdateFile() {
|
||||
\Drupal::currentUser()->setAccount($this->user2);
|
||||
$this->assertFalse($this->file->access('delete'));
|
||||
$this->assertFalse($this->file->access('update'));
|
||||
|
||||
\Drupal::currentUser()->setAccount($this->user1);
|
||||
$this->assertTrue($this->file->access('delete'));
|
||||
$this->assertTrue($this->file->access('update'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests that the status field is not editable.
|
||||
*/
|
||||
public function testStatusFieldIsNotEditable() {
|
||||
\Drupal::currentUser()->setAccount($this->user1);
|
||||
$this->assertFalse($this->file->get('status')->access('edit'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests create access checks.
|
||||
*/
|
||||
public function testCreateAccess() {
|
||||
// Anonymous users can create a file by default.
|
||||
$this->assertFalse($this->file->access('create'));
|
||||
|
||||
// Authenticated users can create a file by default.
|
||||
\Drupal::currentUser()->setAccount($this->user1);
|
||||
$this->assertFalse($this->file->access('create'));
|
||||
}
|
||||
|
||||
}
|
|
@ -141,4 +141,5 @@ class CopyTest extends FileManagedUnitTestBase {
|
|||
$this->assertFileUnchanged($source, File::load($source->id()));
|
||||
$this->assertFileUnchanged($target, File::load($target->id()));
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -68,4 +68,5 @@ class DeleteTest extends FileManagedUnitTestBase {
|
|||
$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.');
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -14,7 +14,7 @@ use Drupal\Tests\migrate_drupal\Kernel\d7\MigrateDrupal7TestBase;
|
|||
*/
|
||||
class MigrateFileTest extends MigrateDrupal7TestBase {
|
||||
|
||||
static $modules = ['file'];
|
||||
public static $modules = ['file'];
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
|
|
|
@ -156,4 +156,5 @@ class MoveTest extends FileManagedUnitTestBase {
|
|||
$this->assertFileUnchanged($source, File::load($source->id()));
|
||||
$this->assertFileUnchanged($target, File::load($target->id()));
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -130,4 +130,5 @@ class SaveDataTest extends FileManagedUnitTestBase {
|
|||
// Ensure that the existing file wasn't overwritten.
|
||||
$this->assertFileUnchanged($existing, File::load($existing->id()));
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -82,4 +82,5 @@ class SaveTest extends FileManagedUnitTestBase {
|
|||
$this->assertEqual(array($uppercase_file->id() => $uppercase_file->id()), $fids);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -71,4 +71,5 @@ class SpaceUsedTest extends FileManagedUnitTestBase {
|
|||
$this->assertEqual($file->spaceUsed(3, 0), 3);
|
||||
$this->assertEqual($file->spaceUsed(3, FILE_STATUS_PERMANENT), 300);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -202,4 +202,5 @@ class UsageTest extends FileManagedUnitTestBase {
|
|||
$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.');
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -34,4 +34,5 @@ class ValidateTest extends FileManagedUnitTestBase {
|
|||
$this->assertEqual(file_validate($file, $failing), array('Failed', 'Badly', 'Epic fail'), 'Validating returns errors.');
|
||||
$this->assertFileHooksCalled(array('validate'));
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -51,7 +51,7 @@ class ValidatorTest extends FileManagedUnitTestBase {
|
|||
}
|
||||
|
||||
/**
|
||||
* This ensures a specific file is actually an image.
|
||||
* This ensures a specific file is actually an image.
|
||||
*/
|
||||
function testFileValidateIsImage() {
|
||||
$this->assertTrue(file_exists($this->image->getFileUri()), 'The image being tested exists.', 'File');
|
||||
|
@ -64,8 +64,9 @@ class ValidatorTest extends FileManagedUnitTestBase {
|
|||
}
|
||||
|
||||
/**
|
||||
* This ensures the resolution of a specific file is within bounds.
|
||||
* The image will be resized if it's too large.
|
||||
* 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.
|
||||
|
@ -113,7 +114,7 @@ class ValidatorTest extends FileManagedUnitTestBase {
|
|||
}
|
||||
|
||||
/**
|
||||
* This will ensure the filename length is valid.
|
||||
* This will ensure the filename length is valid.
|
||||
*/
|
||||
function testFileValidateNameLength() {
|
||||
// Create a new file entity.
|
||||
|
@ -152,4 +153,5 @@ class ValidatorTest extends FileManagedUnitTestBase {
|
|||
$errors = file_validate_size($file, 1, 1);
|
||||
$this->assertEqual(count($errors), 2, 'Errors for both the file and their limit.', 'File');
|
||||
}
|
||||
|
||||
}
|
||||
|
|
Reference in a new issue