Update Composer, update everything
This commit is contained in:
parent
ea3e94409f
commit
dda5c284b6
19527 changed files with 1135420 additions and 351004 deletions
|
@ -7,6 +7,8 @@ use Drupal\Core\Form\FormStateInterface;
|
|||
|
||||
/**
|
||||
* Form controller for file_module_test module.
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
class FileModuleTestForm extends FormBase {
|
||||
|
||||
|
@ -83,7 +85,7 @@ class FileModuleTestForm extends FormBase {
|
|||
$fids[] = $fid;
|
||||
}
|
||||
|
||||
drupal_set_message($this->t('The file ids are %fids.', ['%fids' => implode(',', $fids)]));
|
||||
\Drupal::messenger()->addStatus($this->t('The file ids are %fids.', ['%fids' => implode(',', $fids)]));
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -4,3 +4,9 @@ file.test:
|
|||
_form: 'Drupal\file_test\Form\FileTestForm'
|
||||
requirements:
|
||||
_access: 'TRUE'
|
||||
file.save_upload_from_form_test:
|
||||
path: '/file-test/save_upload_from_form_test'
|
||||
defaults:
|
||||
_form: 'Drupal\file_test\Form\FileTestSaveUploadFromForm'
|
||||
requirements:
|
||||
_access: 'TRUE'
|
||||
|
|
|
@ -108,13 +108,13 @@ class FileTestForm implements FormInterface {
|
|||
$file = file_save_upload('file_test_upload', $validators, $destination, 0, $form_state->getValue('file_test_replace'));
|
||||
if ($file) {
|
||||
$form_state->setValue('file_test_upload', $file);
|
||||
drupal_set_message(t('File @filepath was uploaded.', ['@filepath' => $file->getFileUri()]));
|
||||
drupal_set_message(t('File name is @filename.', ['@filename' => $file->getFilename()]));
|
||||
drupal_set_message(t('File MIME type is @mimetype.', ['@mimetype' => $file->getMimeType()]));
|
||||
drupal_set_message(t('You WIN!'));
|
||||
\Drupal::messenger()->addStatus(t('File @filepath was uploaded.', ['@filepath' => $file->getFileUri()]));
|
||||
\Drupal::messenger()->addStatus(t('File name is @filename.', ['@filename' => $file->getFilename()]));
|
||||
\Drupal::messenger()->addStatus(t('File MIME type is @mimetype.', ['@mimetype' => $file->getMimeType()]));
|
||||
\Drupal::messenger()->addStatus(t('You WIN!'));
|
||||
}
|
||||
elseif ($file === FALSE) {
|
||||
drupal_set_message(t('Epic upload FAIL!'), 'error');
|
||||
\Drupal::messenger()->addError(t('Epic upload FAIL!'));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,179 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\file_test\Form;
|
||||
|
||||
use Drupal\Core\Form\FormBase;
|
||||
use Drupal\Core\Form\FormStateInterface;
|
||||
use Drupal\Core\Messenger\MessengerInterface;
|
||||
use Drupal\Core\State\StateInterface;
|
||||
use Symfony\Component\DependencyInjection\ContainerInterface;
|
||||
|
||||
/**
|
||||
* File test form class.
|
||||
*/
|
||||
class FileTestSaveUploadFromForm extends FormBase {
|
||||
|
||||
/**
|
||||
* Stores the state storage service.
|
||||
*
|
||||
* @var \Drupal\Core\State\StateInterface
|
||||
*/
|
||||
protected $state;
|
||||
|
||||
/**
|
||||
* The messenger.
|
||||
*
|
||||
* @var \Drupal\Core\Messenger\MessengerInterface
|
||||
*/
|
||||
protected $messenger;
|
||||
|
||||
/**
|
||||
* Constructs a FileTestSaveUploadFromForm object.
|
||||
*
|
||||
* @param \Drupal\Core\State\StateInterface $state
|
||||
* The state key value store.
|
||||
* @param \Drupal\Core\Messenger\MessengerInterface $messenger
|
||||
* The messenger.
|
||||
*/
|
||||
public function __construct(StateInterface $state, MessengerInterface $messenger) {
|
||||
$this->state = $state;
|
||||
$this->messenger = $messenger;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static function create(ContainerInterface $container) {
|
||||
return new static(
|
||||
$container->get('state'),
|
||||
$container->get('messenger')
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getFormId() {
|
||||
return '_file_test_save_upload_from_form';
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function buildForm(array $form, FormStateInterface $form_state) {
|
||||
$form['file_test_upload'] = [
|
||||
'#type' => 'file',
|
||||
'#multiple' => TRUE,
|
||||
'#title' => $this->t('Upload a file'),
|
||||
];
|
||||
$form['file_test_replace'] = [
|
||||
'#type' => 'select',
|
||||
'#title' => $this->t('Replace existing image'),
|
||||
'#options' => [
|
||||
FILE_EXISTS_RENAME => $this->t('Appends number until name is unique'),
|
||||
FILE_EXISTS_REPLACE => $this->t('Replace the existing file'),
|
||||
FILE_EXISTS_ERROR => $this->t('Fail with an error'),
|
||||
],
|
||||
'#default_value' => FILE_EXISTS_RENAME,
|
||||
];
|
||||
$form['file_subdir'] = [
|
||||
'#type' => 'textfield',
|
||||
'#title' => $this->t('Subdirectory for test file'),
|
||||
'#default_value' => '',
|
||||
];
|
||||
|
||||
$form['extensions'] = [
|
||||
'#type' => 'textfield',
|
||||
'#title' => $this->t('Allowed extensions.'),
|
||||
'#default_value' => '',
|
||||
];
|
||||
|
||||
$form['allow_all_extensions'] = [
|
||||
'#type' => 'checkbox',
|
||||
'#title' => $this->t('Allow all extensions?'),
|
||||
'#default_value' => FALSE,
|
||||
];
|
||||
|
||||
$form['is_image_file'] = [
|
||||
'#type' => 'checkbox',
|
||||
'#title' => $this->t('Is this an image file?'),
|
||||
'#default_value' => TRUE,
|
||||
];
|
||||
|
||||
$form['error_message'] = [
|
||||
'#type' => 'textfield',
|
||||
'#title' => $this->t('Custom error message.'),
|
||||
'#default_value' => '',
|
||||
];
|
||||
|
||||
$form['submit'] = [
|
||||
'#type' => 'submit',
|
||||
'#value' => $this->t('Submit'),
|
||||
];
|
||||
return $form;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function validateForm(array &$form, FormStateInterface $form_state) {
|
||||
// Process the upload and perform validation. Note: we're using the
|
||||
// form value for the $replace parameter.
|
||||
if (!$form_state->isValueEmpty('file_subdir')) {
|
||||
$destination = 'temporary://' . $form_state->getValue('file_subdir');
|
||||
file_prepare_directory($destination, FILE_CREATE_DIRECTORY);
|
||||
}
|
||||
else {
|
||||
$destination = FALSE;
|
||||
}
|
||||
|
||||
// Preset custom error message if requested.
|
||||
if ($form_state->getValue('error_message')) {
|
||||
$this->messenger->addError($form_state->getValue('error_message'));
|
||||
}
|
||||
|
||||
// Setup validators.
|
||||
$validators = [];
|
||||
if ($form_state->getValue('is_image_file')) {
|
||||
$validators['file_validate_is_image'] = [];
|
||||
}
|
||||
|
||||
if ($form_state->getValue('allow_all_extensions')) {
|
||||
$validators['file_validate_extensions'] = [];
|
||||
}
|
||||
elseif (!$form_state->isValueEmpty('extensions')) {
|
||||
$validators['file_validate_extensions'] = [$form_state->getValue('extensions')];
|
||||
}
|
||||
|
||||
// The test for drupal_move_uploaded_file() triggering a warning is
|
||||
// unavoidable. We're interested in what happens afterwards in
|
||||
// _file_save_upload_from_form().
|
||||
if ($this->state->get('file_test.disable_error_collection')) {
|
||||
define('SIMPLETEST_COLLECT_ERRORS', FALSE);
|
||||
}
|
||||
|
||||
$form['file_test_upload']['#upload_validators'] = $validators;
|
||||
$form['file_test_upload']['#upload_location'] = $destination;
|
||||
|
||||
$this->messenger->addStatus($this->t('Number of error messages before _file_save_upload_from_form(): @count.', ['@count' => count($this->messenger->messagesByType(MessengerInterface::TYPE_ERROR))]));
|
||||
$file = _file_save_upload_from_form($form['file_test_upload'], $form_state, 0, $form_state->getValue('file_test_replace'));
|
||||
$this->messenger->addStatus($this->t('Number of error messages after _file_save_upload_from_form(): @count.', ['@count' => count($this->messenger->messagesByType(MessengerInterface::TYPE_ERROR))]));
|
||||
|
||||
if ($file) {
|
||||
$form_state->setValue('file_test_upload', $file);
|
||||
$this->messenger->addStatus($this->t('File @filepath was uploaded.', ['@filepath' => $file->getFileUri()]));
|
||||
$this->messenger->addStatus($this->t('File name is @filename.', ['@filename' => $file->getFilename()]));
|
||||
$this->messenger->addStatus($this->t('File MIME type is @mimetype.', ['@mimetype' => $file->getMimeType()]));
|
||||
$this->messenger->addStatus($this->t('You WIN!'));
|
||||
}
|
||||
elseif ($file === FALSE) {
|
||||
$this->messenger->addError($this->t('Epic upload FAIL!'));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function submitForm(array &$form, FormStateInterface $form_state) {}
|
||||
|
||||
}
|
|
@ -0,0 +1,71 @@
|
|||
uuid: 9ca49b35-b49d-4014-9337-965cdf15b61e
|
||||
langcode: en
|
||||
status: true
|
||||
dependencies:
|
||||
config:
|
||||
- field.field.node.article.body
|
||||
- field.field.node.article.comment
|
||||
- field.field.node.article.field_file_generic_2677990
|
||||
- field.field.node.article.field_file_table_2677990
|
||||
- field.field.node.article.field_image
|
||||
- field.field.node.article.field_tags
|
||||
- image.style.large
|
||||
- node.type.article
|
||||
module:
|
||||
- comment
|
||||
- file
|
||||
- image
|
||||
- text
|
||||
- user
|
||||
_core:
|
||||
default_config_hash: JtAg_-waIt1quMtdDtHIaXJMxvTuSmxW7bWyO6Zd68E
|
||||
id: node.article.default
|
||||
targetEntityType: node
|
||||
bundle: article
|
||||
mode: default
|
||||
content:
|
||||
body:
|
||||
type: text_default
|
||||
weight: 0
|
||||
settings: { }
|
||||
third_party_settings: { }
|
||||
label: hidden
|
||||
comment:
|
||||
label: above
|
||||
type: comment_default
|
||||
weight: 20
|
||||
settings:
|
||||
pager_id: 0
|
||||
third_party_settings: { }
|
||||
field_file_generic_2677990:
|
||||
weight: 101
|
||||
label: above
|
||||
settings: { }
|
||||
third_party_settings: { }
|
||||
type: file_default
|
||||
field_file_table_2677990:
|
||||
weight: 102
|
||||
label: above
|
||||
settings: { }
|
||||
third_party_settings: { }
|
||||
type: file_table
|
||||
field_image:
|
||||
type: image
|
||||
weight: -1
|
||||
settings:
|
||||
image_style: large
|
||||
image_link: ''
|
||||
third_party_settings: { }
|
||||
label: hidden
|
||||
field_tags:
|
||||
type: entity_reference_label
|
||||
weight: 10
|
||||
label: above
|
||||
settings:
|
||||
link: true
|
||||
third_party_settings: { }
|
||||
links:
|
||||
weight: 100
|
||||
settings: { }
|
||||
third_party_settings: { }
|
||||
hidden: { }
|
88
web/core/modules/file/tests/fixtures/update/drupal-8.file_formatters_update_2677990.php
vendored
Normal file
88
web/core/modules/file/tests/fixtures/update/drupal-8.file_formatters_update_2677990.php
vendored
Normal file
|
@ -0,0 +1,88 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains database additions to drupal-8.bare.standard.php.gz for testing the
|
||||
* upgrade path of https://www.drupal.org/node/2677990.
|
||||
*/
|
||||
|
||||
use Drupal\Core\Database\Database;
|
||||
use Drupal\Component\Serialization\Yaml;
|
||||
use Drupal\field\Entity\FieldStorageConfig;
|
||||
|
||||
$connection = Database::getConnection();
|
||||
|
||||
// Configuration for a file field storage for generic display.
|
||||
$field_file_generic_2677990 = Yaml::decode(file_get_contents(__DIR__ . '/field.storage.node.field_file_generic_2677990.yml'));
|
||||
|
||||
// Configuration for a file field storage for table display.
|
||||
$field_file_table_2677990 = Yaml::decode(file_get_contents(__DIR__ . '/field.storage.node.field_file_table_2677990.yml'));
|
||||
|
||||
$connection->insert('config')
|
||||
->fields([
|
||||
'collection',
|
||||
'name',
|
||||
'data',
|
||||
])
|
||||
->values([
|
||||
'collection' => '',
|
||||
'name' => 'field.storage.' . $field_file_generic_2677990['id'],
|
||||
'data' => serialize($field_file_generic_2677990),
|
||||
])
|
||||
->values([
|
||||
'collection' => '',
|
||||
'name' => 'field.storage.' . $field_file_table_2677990['id'],
|
||||
'data' => serialize($field_file_table_2677990),
|
||||
])
|
||||
->execute();
|
||||
// We need to Update the registry of "last installed" field definitions.
|
||||
$installed = $connection->select('key_value')
|
||||
->fields('key_value', ['value'])
|
||||
->condition('collection', 'entity.definitions.installed')
|
||||
->condition('name', 'node.field_storage_definitions')
|
||||
->execute()
|
||||
->fetchField();
|
||||
$installed = unserialize($installed);
|
||||
$installed['field_file_generic_2677990'] = new FieldStorageConfig($field_file_generic_2677990);
|
||||
$installed['field_file_table_2677990'] = new FieldStorageConfig($field_file_table_2677990);
|
||||
$connection->update('key_value')
|
||||
->condition('collection', 'entity.definitions.installed')
|
||||
->condition('name', 'node.field_storage_definitions')
|
||||
->fields([
|
||||
'value' => serialize($installed),
|
||||
])
|
||||
->execute();
|
||||
|
||||
// Configuration for a file field storage for generic display.
|
||||
$field_file_generic_2677990 = Yaml::decode(file_get_contents(__DIR__ . '/field.field.node.article.field_file_generic_2677990.yml'));
|
||||
|
||||
// Configuration for a file field storage for table display.
|
||||
$field_file_table_2677990 = Yaml::decode(file_get_contents(__DIR__ . '/field.field.node.article.field_file_table_2677990.yml'));
|
||||
|
||||
$connection->insert('config')
|
||||
->fields([
|
||||
'collection',
|
||||
'name',
|
||||
'data',
|
||||
])
|
||||
->values([
|
||||
'collection' => '',
|
||||
'name' => 'field.field.' . $field_file_generic_2677990['id'],
|
||||
'data' => serialize($field_file_generic_2677990),
|
||||
])
|
||||
->values([
|
||||
'collection' => '',
|
||||
'name' => 'field.field.' . $field_file_table_2677990['id'],
|
||||
'data' => serialize($field_file_table_2677990),
|
||||
])
|
||||
->execute();
|
||||
|
||||
// Configuration of the view mode to set the proper formatters.
|
||||
$view_mode_2677990 = Yaml::decode(file_get_contents(__DIR__ . '/core.entity_view_display.node.article.default_2677990.yml'));
|
||||
|
||||
$connection->update('config')
|
||||
->fields([
|
||||
'data' => serialize($view_mode_2677990),
|
||||
])
|
||||
->condition('name', 'core.entity_view_display.' . $view_mode_2677990['id'])
|
||||
->execute();
|
|
@ -0,0 +1,27 @@
|
|||
uuid: d352a831-c267-4ecc-9b4e-7ae1896b2241
|
||||
langcode: en
|
||||
status: true
|
||||
dependencies:
|
||||
config:
|
||||
- field.storage.node.field_file_generic_2677990
|
||||
- node.type.article
|
||||
module:
|
||||
- file
|
||||
id: node.article.field_file_generic_2677990
|
||||
field_name: field_file_generic_2677990
|
||||
entity_type: node
|
||||
bundle: article
|
||||
label: 'File generic'
|
||||
description: ''
|
||||
required: false
|
||||
translatable: false
|
||||
default_value: { }
|
||||
default_value_callback: ''
|
||||
settings:
|
||||
file_directory: '[date:custom:Y]-[date:custom:m]'
|
||||
file_extensions: txt
|
||||
max_filesize: ''
|
||||
description_field: true
|
||||
handler: 'default:file'
|
||||
handler_settings: { }
|
||||
field_type: file
|
|
@ -0,0 +1,27 @@
|
|||
uuid: 44c7a590-ffcc-4534-b01c-b17b8d57ed48
|
||||
langcode: en
|
||||
status: true
|
||||
dependencies:
|
||||
config:
|
||||
- field.storage.node.field_file_table_2677990
|
||||
- node.type.article
|
||||
module:
|
||||
- file
|
||||
id: node.article.field_file_table_2677990
|
||||
field_name: field_file_table_2677990
|
||||
entity_type: node
|
||||
bundle: article
|
||||
label: 'File table'
|
||||
description: ''
|
||||
required: false
|
||||
translatable: false
|
||||
default_value: { }
|
||||
default_value_callback: ''
|
||||
settings:
|
||||
file_directory: '[date:custom:Y]-[date:custom:m]'
|
||||
file_extensions: txt
|
||||
max_filesize: ''
|
||||
description_field: true
|
||||
handler: 'default:file'
|
||||
handler_settings: { }
|
||||
field_type: file
|
23
web/core/modules/file/tests/fixtures/update/field.storage.node.field_file_generic_2677990.yml
vendored
Normal file
23
web/core/modules/file/tests/fixtures/update/field.storage.node.field_file_generic_2677990.yml
vendored
Normal file
|
@ -0,0 +1,23 @@
|
|||
uuid: a7eb470d-e538-4221-a8ac-57f989d92d8e
|
||||
langcode: en
|
||||
status: true
|
||||
dependencies:
|
||||
module:
|
||||
- file
|
||||
- node
|
||||
id: node.field_file_generic_2677990
|
||||
field_name: field_file_generic_2677990
|
||||
entity_type: node
|
||||
type: file
|
||||
settings:
|
||||
display_field: false
|
||||
display_default: false
|
||||
uri_scheme: public
|
||||
target_type: file
|
||||
module: file
|
||||
locked: false
|
||||
cardinality: 1
|
||||
translatable: true
|
||||
indexes: { }
|
||||
persist_with_no_fields: false
|
||||
custom_storage: false
|
23
web/core/modules/file/tests/fixtures/update/field.storage.node.field_file_table_2677990.yml
vendored
Normal file
23
web/core/modules/file/tests/fixtures/update/field.storage.node.field_file_table_2677990.yml
vendored
Normal file
|
@ -0,0 +1,23 @@
|
|||
uuid: 43113a5e-3e07-4234-b045-4aa4cd217dca
|
||||
langcode: en
|
||||
status: true
|
||||
dependencies:
|
||||
module:
|
||||
- file
|
||||
- node
|
||||
id: node.field_file_table_2677990
|
||||
field_name: field_file_table_2677990
|
||||
entity_type: node
|
||||
type: file
|
||||
settings:
|
||||
display_field: false
|
||||
display_default: false
|
||||
uri_scheme: public
|
||||
target_type: file
|
||||
module: file
|
||||
locked: false
|
||||
cardinality: 1
|
||||
translatable: true
|
||||
indexes: { }
|
||||
persist_with_no_fields: false
|
||||
custom_storage: false
|
|
@ -5,5 +5,5 @@ package: Testing
|
|||
version: VERSION
|
||||
core: 8.x
|
||||
dependencies:
|
||||
- file
|
||||
- views
|
||||
- drupal:file
|
||||
- drupal:views
|
||||
|
|
168
web/core/modules/file/tests/src/Functional/DownloadTest.php
Normal file
168
web/core/modules/file/tests/src/Functional/DownloadTest.php
Normal file
|
@ -0,0 +1,168 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\Tests\file\Functional;
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
public function testPublicFileTransfer() {
|
||||
// Test generating a 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'] . '/' . \Drupal::service('stream_wrapper_manager')->getViaScheme('public')->getDirectoryPath() . '/' . rawurlencode($file->getFilename());
|
||||
$this->assertEqual($filename, $url, 'Correctly generated a URL for a created file.');
|
||||
$http_client = $this->getHttpClient();
|
||||
$response = $http_client->head($url);
|
||||
$this->assertEquals(200, $response->getStatusCode(), 'Confirmed that the generated URL is correct by downloading the created file.');
|
||||
|
||||
// Test generating a 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.');
|
||||
$response = $http_client->head($url);
|
||||
$this->assertEquals(200, $response->getStatusCode(), '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', ['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->assertSame($contents, $this->getSession()->getPage()->getContent(), 'Contents of the file are correct.');
|
||||
$http_client = $this->getHttpClient();
|
||||
|
||||
// Deny access to all downloads via a -1 header.
|
||||
file_test_set_return('download', -1);
|
||||
$response = $http_client->head($url, ['http_errors' => FALSE]);
|
||||
$this->assertSame(403, $response->getStatusCode(), '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());
|
||||
$response = $http_client->head($url, ['http_errors' => FALSE]);
|
||||
$this->assertSame(404, $response->getStatusCode(), 'Correctly returned 404 response for a non-existent file.');
|
||||
}
|
||||
|
||||
/**
|
||||
* Test file_create_url().
|
||||
*/
|
||||
public 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://php.net/manual/function.rawurlencode.php#86506
|
||||
// "Special" ASCII characters.
|
||||
$basename = " -._!$'\"()*@[]?&+%#,;=:\n\x00" .
|
||||
// Characters that look like a percent-escaped string.
|
||||
"%23%25%26%2B%2F%3F" .
|
||||
// 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 = [
|
||||
'clean' => '',
|
||||
'unclean' => 'index.php/',
|
||||
];
|
||||
$public_directory_path = \Drupal::service('stream_wrapper_manager')->getViaScheme('public')->getDirectoryPath();
|
||||
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 . '/' . $public_directory_path . '/' . $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', ['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();
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,169 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\Tests\file\Functional;
|
||||
|
||||
use Drupal\node\Entity\Node;
|
||||
use Drupal\user\RoleInterface;
|
||||
use Drupal\file\Entity\File;
|
||||
|
||||
/**
|
||||
* Confirm that file field submissions work correctly for anonymous visitors.
|
||||
*
|
||||
* @group file
|
||||
*/
|
||||
class FileFieldAnonymousSubmissionTest extends FileFieldTestBase {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function setUp() {
|
||||
parent::setUp();
|
||||
// Set up permissions for anonymous attacker user.
|
||||
user_role_change_permissions(RoleInterface::ANONYMOUS_ID, [
|
||||
'create article content' => TRUE,
|
||||
'access content' => TRUE,
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the basic node submission for an anonymous visitor.
|
||||
*/
|
||||
public function testAnonymousNode() {
|
||||
$bundle_label = 'Article';
|
||||
$node_title = 'test page';
|
||||
|
||||
// Load the node form.
|
||||
$this->drupalLogout();
|
||||
$this->drupalGet('node/add/article');
|
||||
$this->assertResponse(200, 'Loaded the article node form.');
|
||||
$this->assertText(strip_tags(t('Create @name', ['@name' => $bundle_label])));
|
||||
|
||||
$edit = [
|
||||
'title[0][value]' => $node_title,
|
||||
'body[0][value]' => 'Test article',
|
||||
];
|
||||
$this->drupalPostForm(NULL, $edit, 'Save');
|
||||
$this->assertResponse(200);
|
||||
$t_args = ['@type' => $bundle_label, '%title' => $node_title];
|
||||
$this->assertText(strip_tags(t('@type %title has been created.', $t_args)), 'The node was created.');
|
||||
$matches = [];
|
||||
if (preg_match('@node/(\d+)$@', $this->getUrl(), $matches)) {
|
||||
$nid = end($matches);
|
||||
$this->assertNotEqual($nid, 0, 'The node ID was extracted from the URL.');
|
||||
$node = Node::load($nid);
|
||||
$this->assertNotEqual($node, NULL, 'The node was loaded successfully.');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests file submission for an anonymous visitor.
|
||||
*/
|
||||
public function testAnonymousNodeWithFile() {
|
||||
$bundle_label = 'Article';
|
||||
$node_title = 'Test page';
|
||||
$this->createFileField('field_image', 'node', 'article', [], ['file_extensions' => 'txt png']);
|
||||
|
||||
// Load the node form.
|
||||
$this->drupalLogout();
|
||||
$this->drupalGet('node/add/article');
|
||||
$this->assertResponse(200, 'Loaded the article node form.');
|
||||
$this->assertText(strip_tags(t('Create @name', ['@name' => $bundle_label])));
|
||||
|
||||
// Generate an image file.
|
||||
$image = $this->getTestFile('image');
|
||||
|
||||
// Submit the form.
|
||||
$edit = [
|
||||
'title[0][value]' => $node_title,
|
||||
'body[0][value]' => 'Test article',
|
||||
'files[field_image_0]' => $this->container->get('file_system')->realpath($image->getFileUri()),
|
||||
];
|
||||
$this->drupalPostForm(NULL, $edit, 'Save');
|
||||
$this->assertResponse(200);
|
||||
$t_args = ['@type' => $bundle_label, '%title' => $node_title];
|
||||
$this->assertText(strip_tags(t('@type %title has been created.', $t_args)), 'The node was created.');
|
||||
$matches = [];
|
||||
if (preg_match('@node/(\d+)$@', $this->getUrl(), $matches)) {
|
||||
$nid = end($matches);
|
||||
$this->assertNotEqual($nid, 0, 'The node ID was extracted from the URL.');
|
||||
$node = Node::load($nid);
|
||||
$this->assertNotEqual($node, NULL, 'The node was loaded successfully.');
|
||||
$this->assertFileExists(File::load($node->field_image->target_id), 'The image was uploaded successfully.');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests file submission for an anonymous visitor with a missing node title.
|
||||
*/
|
||||
public function testAnonymousNodeWithFileWithoutTitle() {
|
||||
$this->drupalLogout();
|
||||
$this->doTestNodeWithFileWithoutTitle();
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests file submission for an authenticated user with a missing node title.
|
||||
*/
|
||||
public function testAuthenticatedNodeWithFileWithoutTitle() {
|
||||
$admin_user = $this->drupalCreateUser([
|
||||
'bypass node access',
|
||||
'access content overview',
|
||||
'administer nodes',
|
||||
]);
|
||||
$this->drupalLogin($admin_user);
|
||||
$this->doTestNodeWithFileWithoutTitle();
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper method to test file submissions with missing node titles.
|
||||
*/
|
||||
protected function doTestNodeWithFileWithoutTitle() {
|
||||
$bundle_label = 'Article';
|
||||
$node_title = 'Test page';
|
||||
$this->createFileField('field_image', 'node', 'article', [], ['file_extensions' => 'txt png']);
|
||||
|
||||
// Load the node form.
|
||||
$this->drupalGet('node/add/article');
|
||||
$this->assertResponse(200, 'Loaded the article node form.');
|
||||
$this->assertText(strip_tags(t('Create @name', ['@name' => $bundle_label])));
|
||||
|
||||
// Generate an image file.
|
||||
$image = $this->getTestFile('image');
|
||||
|
||||
// Submit the form but exclude the title field.
|
||||
$edit = [
|
||||
'body[0][value]' => 'Test article',
|
||||
'files[field_image_0]' => $this->container->get('file_system')->realpath($image->getFileUri()),
|
||||
];
|
||||
if (!$this->loggedInUser) {
|
||||
$label = 'Save';
|
||||
}
|
||||
else {
|
||||
$label = 'Save';
|
||||
}
|
||||
$this->drupalPostForm(NULL, $edit, $label);
|
||||
$this->assertResponse(200);
|
||||
$t_args = ['@type' => $bundle_label, '%title' => $node_title];
|
||||
$this->assertNoText(strip_tags(t('@type %title has been created.', $t_args)), 'The node was created.');
|
||||
$this->assertText('Title field is required.');
|
||||
|
||||
// Submit the form again but this time with the missing title field. This
|
||||
// should still work.
|
||||
$edit = [
|
||||
'title[0][value]' => $node_title,
|
||||
];
|
||||
$this->drupalPostForm(NULL, $edit, $label);
|
||||
|
||||
// Confirm the final submission actually worked.
|
||||
$t_args = ['@type' => $bundle_label, '%title' => $node_title];
|
||||
$this->assertText(strip_tags(t('@type %title has been created.', $t_args)), 'The node was created.');
|
||||
$matches = [];
|
||||
if (preg_match('@node/(\d+)$@', $this->getUrl(), $matches)) {
|
||||
$nid = end($matches);
|
||||
$this->assertNotEqual($nid, 0, 'The node ID was extracted from the URL.');
|
||||
$node = Node::load($nid);
|
||||
$this->assertNotEqual($node, NULL, 'The node was loaded successfully.');
|
||||
$this->assertFileExists(File::load($node->field_image->target_id), 'The image was uploaded successfully.');
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,86 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\Tests\file\Functional;
|
||||
|
||||
use Drupal\field\Entity\FieldStorageConfig;
|
||||
use Drupal\field\Entity\FieldConfig;
|
||||
|
||||
/**
|
||||
* Provides methods for creating file fields.
|
||||
*/
|
||||
trait FileFieldCreationTrait {
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*
|
||||
* @return \Drupal\field\FieldStorageConfigInterface
|
||||
* The file field.
|
||||
*/
|
||||
public function createFileField($name, $entity_type, $bundle, $storage_settings = [], $field_settings = [], $widget_settings = []) {
|
||||
$field_storage = FieldStorageConfig::create([
|
||||
'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.
|
||||
*/
|
||||
public function attachFileField($name, $entity_type, $bundle, $field_settings = [], $widget_settings = []) {
|
||||
$field = [
|
||||
'field_name' => $name,
|
||||
'label' => $name,
|
||||
'entity_type' => $entity_type,
|
||||
'bundle' => $bundle,
|
||||
'required' => !empty($field_settings['required']),
|
||||
'settings' => $field_settings,
|
||||
];
|
||||
FieldConfig::create($field)->save();
|
||||
|
||||
entity_get_form_display($entity_type, $bundle, 'default')
|
||||
->setComponent($name, [
|
||||
'type' => 'file_generic',
|
||||
'settings' => $widget_settings,
|
||||
])
|
||||
->save();
|
||||
// Assign display settings.
|
||||
entity_get_display($entity_type, $bundle, 'default')
|
||||
->setComponent($name, [
|
||||
'label' => 'hidden',
|
||||
'type' => 'file_default',
|
||||
])
|
||||
->save();
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,223 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\Tests\file\Functional;
|
||||
|
||||
use Drupal\Core\Field\FieldStorageDefinitionInterface;
|
||||
use Drupal\file\Entity\File;
|
||||
use Drupal\node\Entity\Node;
|
||||
|
||||
/**
|
||||
* Tests the display of file fields in node and views.
|
||||
*
|
||||
* @group file
|
||||
*/
|
||||
class FileFieldDisplayTest extends FileFieldTestBase {
|
||||
|
||||
/**
|
||||
* Tests normal formatter display on node display.
|
||||
*/
|
||||
public function testNodeDisplay() {
|
||||
$field_name = strtolower($this->randomMachineName());
|
||||
$type_name = 'article';
|
||||
$field_storage_settings = [
|
||||
'display_field' => '1',
|
||||
'display_default' => '1',
|
||||
'cardinality' => FieldStorageDefinitionInterface::CARDINALITY_UNLIMITED,
|
||||
];
|
||||
$field_settings = [
|
||||
'description_field' => '1',
|
||||
];
|
||||
$widget_settings = [];
|
||||
$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(['type' => $type_name]);
|
||||
// Check file_default last as the assertions below assume that this is the
|
||||
// case.
|
||||
$file_formatters = ['file_table', 'file_url_plain', 'hidden', 'file_default'];
|
||||
foreach ($file_formatters as $formatter) {
|
||||
if ($formatter === 'hidden') {
|
||||
$edit = [
|
||||
"fields[$field_name][region]" => 'hidden',
|
||||
];
|
||||
}
|
||||
else {
|
||||
$edit = [
|
||||
"fields[$field_name][type]" => $formatter,
|
||||
"fields[$field_name][region]" => 'content',
|
||||
];
|
||||
}
|
||||
$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', ['%formatter' => $formatter]));
|
||||
}
|
||||
|
||||
$this->generateFile('escaped-&-text', 64, 10, 'text');
|
||||
$test_file = File::create([
|
||||
'uri' => 'public://escaped-&-text.txt',
|
||||
'name' => 'escaped-&-text',
|
||||
'filesize' => filesize('public://escaped-&-text.txt'),
|
||||
]);
|
||||
|
||||
// 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([$nid]);
|
||||
$node = $node_storage->load($nid);
|
||||
$node_file = File::load($node->{$field_name}->target_id);
|
||||
$file_link = [
|
||||
'#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 = [$field_name . '[0][display]' => FALSE];
|
||||
$this->drupalPostForm('node/' . $nid . '/edit', $edit, t('Save'));
|
||||
|
||||
$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 = [
|
||||
$field_name . '[0][description]' => $description,
|
||||
$field_name . '[0][display]' => TRUE,
|
||||
];
|
||||
$this->drupalPostForm('node/' . $nid . '/edit', $edit, t('Save'));
|
||||
$this->assertText($description);
|
||||
|
||||
// Ensure the filename in the link's title attribute is escaped.
|
||||
$this->assertRaw('title="escaped-&-text.txt"');
|
||||
|
||||
// Test that fields appear as expected after during the preview.
|
||||
// Add a second file.
|
||||
$name = 'files[' . $field_name . '_1][]';
|
||||
$edit_upload[$name] = \Drupal::service('file_system')->realpath($test_file->getFileUri());
|
||||
$this->drupalPostForm("node/$nid/edit", $edit_upload, t('Upload'));
|
||||
|
||||
// Uncheck the display checkboxes and go to the preview.
|
||||
$edit[$field_name . '[0][display]'] = FALSE;
|
||||
$edit[$field_name . '[1][display]'] = FALSE;
|
||||
$this->drupalPostForm(NULL, $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.');
|
||||
$this->assertSession()->responseContains($field_name . '[1][description]', 'Description of second file appears as expected.');
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests default display of File Field.
|
||||
*/
|
||||
public function testDefaultFileFieldDisplay() {
|
||||
$field_name = strtolower($this->randomMachineName());
|
||||
$type_name = 'article';
|
||||
$field_storage_settings = [
|
||||
'display_field' => '1',
|
||||
'display_default' => '0',
|
||||
'cardinality' => FieldStorageDefinitionInterface::CARDINALITY_UNLIMITED,
|
||||
];
|
||||
$field_settings = [
|
||||
'description_field' => '1',
|
||||
];
|
||||
$widget_settings = [];
|
||||
$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.
|
||||
*/
|
||||
public 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 = [
|
||||
'name' => $type_name,
|
||||
'type' => $type_name,
|
||||
];
|
||||
$this->drupalPostForm('admin/structure/types/add', $edit, t('Save and manage fields'));
|
||||
$edit = [
|
||||
'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, [], 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 = [
|
||||
'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 = [
|
||||
'title[0][value]' => $title,
|
||||
'files[field_' . $field_name . '_0]' => \Drupal::service('file_system')->realpath($file->uri),
|
||||
];
|
||||
$this->drupalPostForm('node/add/' . $type_name, $edit, t('Save'));
|
||||
$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.'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests description display of File Field.
|
||||
*/
|
||||
public function testDescriptionDefaultFileFieldDisplay() {
|
||||
$field_name = strtolower($this->randomMachineName());
|
||||
$type_name = 'article';
|
||||
$field_storage_settings = [
|
||||
'display_field' => '1',
|
||||
'display_default' => '1',
|
||||
'cardinality' => FieldStorageDefinitionInterface::CARDINALITY_UNLIMITED,
|
||||
];
|
||||
$field_settings = [
|
||||
'description_field' => '1',
|
||||
];
|
||||
$widget_settings = [];
|
||||
$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);
|
||||
|
||||
// Add file description.
|
||||
$description = 'This is the test file description';
|
||||
$this->drupalPostForm("node/$nid/edit", [$field_name . '[0][description]' => $description], t('Save'));
|
||||
|
||||
// Load uncached node.
|
||||
\Drupal::entityTypeManager()->getStorage('node')->resetCache([$nid]);
|
||||
$node = Node::load($nid);
|
||||
|
||||
// Test default formatter.
|
||||
$this->drupalGet('node/' . $nid);
|
||||
$this->assertFieldByXPath('//a[@href="' . $node->{$field_name}->entity->url() . '"]', $description);
|
||||
|
||||
// Change formatter to "Table of files".
|
||||
$display = \Drupal::entityTypeManager()->getStorage('entity_view_display')->load('node.' . $type_name . '.default');
|
||||
$display->setComponent($field_name, [
|
||||
'label' => 'hidden',
|
||||
'type' => 'file_table',
|
||||
])->save();
|
||||
|
||||
$this->drupalGet('node/' . $nid);
|
||||
$this->assertFieldByXPath('//a[@href="' . $node->{$field_name}->entity->url() . '"]', $description);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,33 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\Tests\file\Functional;
|
||||
|
||||
/**
|
||||
* 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));
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,94 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\Tests\file\Functional;
|
||||
|
||||
use Drupal\file\Entity\File;
|
||||
|
||||
/**
|
||||
* Tests that files are uploaded to proper locations.
|
||||
*
|
||||
* @group file
|
||||
*/
|
||||
class FileFieldPathTest extends FileFieldTestBase {
|
||||
|
||||
/**
|
||||
* Tests the normal formatter display on node display.
|
||||
*/
|
||||
public function testUploadPath() {
|
||||
/** @var \Drupal\node\NodeStorageInterface $node_storage */
|
||||
$node_storage = $this->container->get('entity.manager')->getStorage('node');
|
||||
$field_name = strtolower($this->randomMachineName());
|
||||
$type_name = 'article';
|
||||
$this->createFileField($field_name, 'node', $type_name);
|
||||
/** @var \Drupal\file\FileInterface $test_file */
|
||||
$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 correct location.
|
||||
$node_storage->resetCache([$nid]);
|
||||
$node = $node_storage->load($nid);
|
||||
/** @var \Drupal\file\FileInterface $node_file */
|
||||
$node_file = $node->{$field_name}->entity;
|
||||
$date_formatter = $this->container->get('date.formatter');
|
||||
$expected_filename =
|
||||
'public://' .
|
||||
$date_formatter->format(REQUEST_TIME, 'custom', 'Y') . '-' .
|
||||
$date_formatter->format(REQUEST_TIME, 'custom', 'm') . '/' .
|
||||
$test_file->getFilename();
|
||||
$this->assertPathMatch($expected_filename, $node_file->getFileUri(), format_string('The file %file was uploaded to the correct path.', ['%file' => $node_file->getFileUri()]));
|
||||
|
||||
// Change the path to contain multiple subdirectories.
|
||||
$this->updateFileField($field_name, $type_name, ['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([$nid]);
|
||||
$node = $node_storage->load($nid);
|
||||
$node_file = File::load($node->{$field_name}->target_id);
|
||||
$this->assertPathMatch('public://foo/bar/baz/' . $test_file->getFilename(), $node_file->getFileUri(), format_string('The file %file was uploaded to the correct path.', ['%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, ['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([$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 = ['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.', ['%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.
|
||||
*/
|
||||
public 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);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,71 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\Tests\file\Functional;
|
||||
|
||||
use Drupal\file\Entity\File;
|
||||
|
||||
/**
|
||||
* 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 = ['node', 'views'];
|
||||
|
||||
/**
|
||||
* Tests RSS enclosure formatter display for RSS feeds.
|
||||
*/
|
||||
public function testFileFieldRSSContent() {
|
||||
$node_storage = $this->container->get('entity.manager')->getStorage('node');
|
||||
$field_name = strtolower($this->randomMachineName());
|
||||
$type_name = 'article';
|
||||
|
||||
$this->createFileField($field_name, 'node', $type_name);
|
||||
|
||||
// RSS display must be added manually.
|
||||
$this->drupalGet("admin/structure/types/manage/$type_name/display");
|
||||
$edit = [
|
||||
"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 = [
|
||||
"fields[$field_name][type]" => 'file_rss_enclosure',
|
||||
"fields[$field_name][region]" => 'content',
|
||||
];
|
||||
$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(['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([$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());
|
||||
$selector = sprintf(
|
||||
'enclosure[@url="%s"][@length="%s"][@type="%s"]',
|
||||
file_create_url("public://$uploaded_filename", ['absolute' => TRUE]),
|
||||
$node_file->getSize(),
|
||||
$node_file->getMimeType()
|
||||
);
|
||||
$this->assertNotNull($this->getSession()->getDriver()->find('xpath', $selector), 'File field RSS enclosure is displayed when viewing the RSS feed.');
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,148 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\Tests\file\Functional;
|
||||
|
||||
use Drupal\file\Entity\File;
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
public function testRevisions() {
|
||||
// This test expects unused managed files to be marked as a temporary file
|
||||
// and then deleted up by file_cron().
|
||||
$this->config('file.settings')
|
||||
->set('make_unused_managed_files_temporary', TRUE)
|
||||
->save();
|
||||
$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([$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([$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', ['revision' => '1'], t('Save'));
|
||||
$node_storage->resetCache([$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', [], t('Revert'));
|
||||
$node_storage->resetCache([$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', [], 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', [], 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([
|
||||
'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', [], 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([
|
||||
'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.');
|
||||
}
|
||||
|
||||
}
|
|
@ -7,12 +7,18 @@ use Drupal\field\Entity\FieldConfig;
|
|||
use Drupal\file\FileInterface;
|
||||
use Drupal\Tests\BrowserTestBase;
|
||||
use Drupal\file\Entity\File;
|
||||
use Drupal\Tests\TestFileCreationTrait;
|
||||
|
||||
/**
|
||||
* Provides methods specifically for testing File module's field handling.
|
||||
*/
|
||||
abstract class FileFieldTestBase extends BrowserTestBase {
|
||||
|
||||
use FileFieldCreationTrait;
|
||||
use TestFileCreationTrait {
|
||||
getTestFiles as drupalGetTestFiles;
|
||||
}
|
||||
|
||||
/**
|
||||
* Modules to enable.
|
||||
*
|
||||
|
@ -57,76 +63,6 @@ abstract class FileFieldTestBase extends BrowserTestBase {
|
|||
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.
|
||||
*/
|
||||
public function createFileField($name, $entity_type, $bundle, $storage_settings = [], $field_settings = [], $widget_settings = []) {
|
||||
$field_storage = FieldStorageConfig::create([
|
||||
'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.
|
||||
*/
|
||||
public function attachFileField($name, $entity_type, $bundle, $field_settings = [], $widget_settings = []) {
|
||||
$field = [
|
||||
'field_name' => $name,
|
||||
'label' => $name,
|
||||
'entity_type' => $entity_type,
|
||||
'bundle' => $bundle,
|
||||
'required' => !empty($field_settings['required']),
|
||||
'settings' => $field_settings,
|
||||
];
|
||||
FieldConfig::create($field)->save();
|
||||
|
||||
entity_get_form_display($entity_type, $bundle, 'default')
|
||||
->setComponent($name, [
|
||||
'type' => 'file_generic',
|
||||
'settings' => $widget_settings,
|
||||
])
|
||||
->save();
|
||||
// Assign display settings.
|
||||
entity_get_display($entity_type, $bundle, 'default')
|
||||
->setComponent($name, [
|
||||
'label' => 'hidden',
|
||||
'type' => 'file_default',
|
||||
])
|
||||
->save();
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates an existing file field with new settings.
|
||||
*/
|
||||
|
@ -224,7 +160,7 @@ abstract class FileFieldTestBase extends BrowserTestBase {
|
|||
$edit[$name][] = $file_path;
|
||||
}
|
||||
}
|
||||
$this->drupalPostForm("node/$nid/edit", $edit, t('Save and keep published'));
|
||||
$this->drupalPostForm("node/$nid/edit", $edit, t('Save'));
|
||||
|
||||
return $nid;
|
||||
}
|
||||
|
@ -240,7 +176,7 @@ abstract class FileFieldTestBase extends BrowserTestBase {
|
|||
];
|
||||
|
||||
$this->drupalPostForm('node/' . $nid . '/edit', [], t('Remove'));
|
||||
$this->drupalPostForm(NULL, $edit, t('Save and keep published'));
|
||||
$this->drupalPostForm(NULL, $edit, t('Save'));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -248,18 +184,18 @@ abstract class FileFieldTestBase extends BrowserTestBase {
|
|||
*/
|
||||
public function replaceNodeFile($file, $field_name, $nid, $new_revision = TRUE) {
|
||||
$edit = [
|
||||
'files[' . $field_name . '_0]' => drupal_realpath($file->getFileUri()),
|
||||
'files[' . $field_name . '_0]' => \Drupal::service('file_system')->realpath($file->getFileUri()),
|
||||
'revision' => (string) (int) $new_revision,
|
||||
];
|
||||
|
||||
$this->drupalPostForm('node/' . $nid . '/edit', [], t('Remove'));
|
||||
$this->drupalPostForm(NULL, $edit, t('Save and keep published'));
|
||||
$this->drupalPostForm(NULL, $edit, t('Save'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Asserts that a file exists physically on disk.
|
||||
*
|
||||
* Overrides PHPUnit_Framework_Assert::assertFileExists() to also work with
|
||||
* Overrides PHPUnit\Framework\Assert::assertFileExists() to also work with
|
||||
* file entities.
|
||||
*
|
||||
* @param \Drupal\File\FileInterface|string $file
|
||||
|
@ -286,7 +222,7 @@ abstract class FileFieldTestBase extends BrowserTestBase {
|
|||
/**
|
||||
* Asserts that a file does not exist on disk.
|
||||
*
|
||||
* Overrides PHPUnit_Framework_Assert::assertFileExists() to also work with
|
||||
* Overrides PHPUnit\Framework\Assert::assertFileExists() to also work with
|
||||
* file entities.
|
||||
*
|
||||
* @param \Drupal\File\FileInterface|string $file
|
||||
|
|
|
@ -0,0 +1,190 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\Tests\file\Functional;
|
||||
|
||||
use Drupal\Core\Field\FieldStorageDefinitionInterface;
|
||||
use Drupal\field\Entity\FieldConfig;
|
||||
use Drupal\file\Entity\File;
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
public 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, [], ['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 = [];
|
||||
$edit['title[0][value]'] = $this->randomMachineName();
|
||||
$this->drupalPostForm('node/add/' . $type_name, $edit, t('Save'));
|
||||
$this->assertRaw(t('@title field is required.', ['@title' => $field->getLabel()]), 'Node save failed when required file field was empty.');
|
||||
|
||||
// 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', ['@test_file' => $test_file->getFileUri(), '@field_name' => $field_name, '@type_name' => $type_name]));
|
||||
|
||||
$node_storage->resetCache([$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, ['cardinality' => FieldStorageDefinitionInterface::CARDINALITY_UNLIMITED], ['required' => '1']);
|
||||
|
||||
// Try to post a new node without uploading a file in the multivalue field.
|
||||
$edit = [];
|
||||
$edit['title[0][value]'] = $this->randomMachineName();
|
||||
$this->drupalPostForm('node/add/' . $type_name, $edit, t('Save'));
|
||||
$this->assertRaw(t('@title field is required.', ['@title' => $field->getLabel()]), 'Node save failed when required multiple value file field was empty.');
|
||||
|
||||
// Create a new node with the uploaded file into the multivalue field.
|
||||
$nid = $this->uploadNodeFile($test_file, $field_name, $type_name);
|
||||
$node_storage->resetCache([$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.
|
||||
*/
|
||||
public 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, [], ['required' => '1']);
|
||||
|
||||
// 128KB.
|
||||
$small_file = $this->getTestFile('text', 131072);
|
||||
// 1.2MB
|
||||
$large_file = $this->getTestFile('text', 1310720);
|
||||
|
||||
// Test uploading both a large and small file with different increments.
|
||||
$sizes = [
|
||||
'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, ['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([$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).', ['%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).', ['%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.', ['%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).', ['%filesize' => format_size($large_file->getSize()), '%maxsize' => $max_filesize]));
|
||||
}
|
||||
|
||||
// Turn off the max filesize.
|
||||
$this->updateFileField($field_name, $type_name, ['max_filesize' => '']);
|
||||
|
||||
// Upload the big file successfully.
|
||||
$nid = $this->uploadNodeFile($large_file, $field_name, $type_name);
|
||||
$node_storage->resetCache([$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.', ['%filesize' => format_size($large_file->getSize())]));
|
||||
$this->assertFileEntryExists($node_file, format_string('File entry exists after uploading a file (%filesize) with no max limit.', ['%filesize' => format_size($large_file->getSize())]));
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests file extension checking.
|
||||
*/
|
||||
public 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, ['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([$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, ['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.', ['%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, ['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([$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.');
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks that a file can always be removed if it does not pass validation.
|
||||
*/
|
||||
public function testFileRemoval() {
|
||||
$node_storage = $this->container->get('entity.manager')->getStorage('node');
|
||||
$type_name = 'article';
|
||||
$field_name = 'file_test';
|
||||
$this->createFileField($field_name, 'node', $type_name);
|
||||
|
||||
$test_file = $this->getTestFile('image');
|
||||
|
||||
// Disable extension checking.
|
||||
$this->updateFileField($field_name, $type_name, ['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([$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, ['file_extensions' => 'txt']);
|
||||
|
||||
// Check that the file can still be removed.
|
||||
$this->removeNodeFile($nid);
|
||||
$this->assertNoText('Only files with the following extensions are allowed: txt.');
|
||||
$this->assertText('Article ' . $node->getTitle() . ' has been updated.');
|
||||
}
|
||||
|
||||
}
|
227
web/core/modules/file/tests/src/Functional/FileListingTest.php
Normal file
227
web/core/modules/file/tests/src/Functional/FileListingTest.php
Normal file
|
@ -0,0 +1,227 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\Tests\file\Functional;
|
||||
|
||||
use Drupal\node\Entity\Node;
|
||||
use Drupal\file\Entity\File;
|
||||
use Drupal\entity_test\Entity\EntityTestConstraints;
|
||||
|
||||
/**
|
||||
* Tests file listing page functionality.
|
||||
*
|
||||
* @group file
|
||||
*/
|
||||
class FileListingTest extends FileFieldTestBase {
|
||||
|
||||
/**
|
||||
* Modules to enable.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public static $modules = ['views', 'file', 'image', 'entity_test'];
|
||||
|
||||
/**
|
||||
* An authenticated user.
|
||||
*
|
||||
* @var \Drupal\user\UserInterface
|
||||
*/
|
||||
protected $baseUser;
|
||||
|
||||
protected function setUp() {
|
||||
parent::setUp();
|
||||
|
||||
// This test expects unused managed files to be marked as a temporary file.
|
||||
$this->config('file.settings')
|
||||
->set('make_unused_managed_files_temporary', TRUE)
|
||||
->save();
|
||||
|
||||
$this->adminUser = $this->drupalCreateUser(['access files overview', 'bypass node access']);
|
||||
$this->baseUser = $this->drupalCreateUser();
|
||||
$this->createFileField('file', 'node', 'article', [], ['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.
|
||||
*/
|
||||
public 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);
|
||||
|
||||
// Log in with user with right permissions and test listing.
|
||||
$this->drupalLogin($this->adminUser);
|
||||
|
||||
for ($i = 0; $i < 5; $i++) {
|
||||
$nodes[] = $this->drupalCreateNode(['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', ['@file' => $file->getFilename()]));
|
||||
|
||||
foreach ($nodes as &$node) {
|
||||
$this->drupalGet('node/' . $node->id() . '/edit');
|
||||
$file = $this->getTestFile('image');
|
||||
|
||||
$edit = [
|
||||
'files[file_0]' => \Drupal::service('file_system')->realpath($file->getFileUri()),
|
||||
];
|
||||
$this->drupalPostForm(NULL, $edit, t('Save'));
|
||||
$node = Node::load($node->id());
|
||||
}
|
||||
|
||||
$this->drupalGet('admin/content/files');
|
||||
|
||||
foreach ($nodes as $node) {
|
||||
$file = File::load($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->getSession()->getPage()->getContent()), '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 = File::load($orphaned_file);
|
||||
$usage = $this->sumUsages($file_usage->listUsage($file));
|
||||
$this->assertRaw('admin/content/files/usage/' . $file->id() . '">' . $usage);
|
||||
|
||||
$file = File::load($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)]", [':value' => 'Temporary']);
|
||||
$this->assertEqual(1, count($result), 'Unused file marked as temporary.');
|
||||
|
||||
// Test file usage page.
|
||||
foreach ($nodes as $node) {
|
||||
$file = File::load($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.');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests file listing usage page for entities with no canonical link template.
|
||||
*/
|
||||
public function testFileListingUsageNoLink() {
|
||||
// Login with user with right permissions and test listing.
|
||||
$this->drupalLogin($this->adminUser);
|
||||
|
||||
// Create a bundle and attach a File field to the bundle.
|
||||
$bundle = $this->randomMachineName();
|
||||
entity_test_create_bundle($bundle, NULL, 'entity_test_constraints');
|
||||
$this->createFileField('field_test_file', 'entity_test_constraints', $bundle, [], ['file_extensions' => 'txt png']);
|
||||
|
||||
// Create file to attach to entity.
|
||||
$file = File::create([
|
||||
'filename' => 'druplicon.txt',
|
||||
'uri' => 'public://druplicon.txt',
|
||||
'filemime' => 'text/plain',
|
||||
]);
|
||||
$file->setPermanent();
|
||||
file_put_contents($file->getFileUri(), 'hello world');
|
||||
$file->save();
|
||||
|
||||
// Create entity and attach the created file.
|
||||
$entity_name = $this->randomMachineName();
|
||||
$entity = EntityTestConstraints::create([
|
||||
'uid' => 1,
|
||||
'name' => $entity_name,
|
||||
'type' => $bundle,
|
||||
'field_test_file' => [
|
||||
'target_id' => $file->id(),
|
||||
],
|
||||
]);
|
||||
$entity->save();
|
||||
|
||||
// Create node entity and attach the created file.
|
||||
$node = $this->drupalCreateNode(['type' => 'article', 'file' => $file]);
|
||||
$node->save();
|
||||
|
||||
// Load the file usage page for the created and attached file.
|
||||
$this->drupalGet('admin/content/files/usage/' . $file->id());
|
||||
|
||||
$this->assertResponse(200);
|
||||
// Entity name should be displayed, but not linked if Entity::toUrl
|
||||
// throws an exception
|
||||
$this->assertText($entity_name, 'Entity name is added to file usage listing.');
|
||||
$this->assertNoLink($entity_name, 'Linked entity name not added to file usage listing.');
|
||||
$this->assertLink($node->getTitle());
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates and saves a test file.
|
||||
*
|
||||
* @return \Drupal\Core\Entity\EntityInterface
|
||||
* A file entity.
|
||||
*/
|
||||
protected function createFile() {
|
||||
// Create a new file entity.
|
||||
$file = File::create([
|
||||
'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;
|
||||
}
|
||||
|
||||
}
|
|
@ -3,6 +3,7 @@
|
|||
namespace Drupal\Tests\file\Functional;
|
||||
|
||||
use Drupal\file\Entity\File;
|
||||
use Drupal\user\Entity\Role;
|
||||
|
||||
/**
|
||||
* Tests access to managed files.
|
||||
|
@ -11,6 +12,19 @@ use Drupal\file\Entity\File;
|
|||
*/
|
||||
class FileManagedAccessTest extends FileManagedTestBase {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function setUp() {
|
||||
parent::setUp();
|
||||
|
||||
// Give anonymous users permission to access content, so they can view and
|
||||
// download public files.
|
||||
$anonymous_role = Role::load(Role::ANONYMOUS_ID);
|
||||
$anonymous_role->grantPermission('access content');
|
||||
$anonymous_role->save();
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests if public file is always accessible.
|
||||
*/
|
||||
|
@ -29,7 +43,7 @@ class FileManagedAccessTest extends FileManagedTestBase {
|
|||
$file->save();
|
||||
|
||||
// Create authenticated user to check file access.
|
||||
$account = $this->createUser(['access site reports']);
|
||||
$account = $this->createUser(['access site reports', 'access content']);
|
||||
|
||||
$this->assertTrue($file->access('view', $account), 'Public file is viewable to authenticated user');
|
||||
$this->assertTrue($file->access('download', $account), 'Public file is downloadable to authenticated user');
|
||||
|
@ -54,7 +68,7 @@ class FileManagedAccessTest extends FileManagedTestBase {
|
|||
$file->save();
|
||||
|
||||
// Create authenticated user to check file access.
|
||||
$account = $this->createUser(['access site reports']);
|
||||
$account = $this->createUser(['access site reports', 'access content']);
|
||||
|
||||
$this->assertFalse($file->access('view', $account), 'Private file is not viewable to authenticated user');
|
||||
$this->assertFalse($file->access('download', $account), 'Private file is not downloadable to authenticated user');
|
||||
|
|
|
@ -0,0 +1,228 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\Tests\file\Functional;
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
public 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 ([0, 1] as $tree) {
|
||||
foreach ([0, 1] as $extended) {
|
||||
foreach ([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, [], t('Save'));
|
||||
$this->assertRaw(t('The file ids are %fids.', ['%fids' => implode(',', [])]), 'Submitted without a file.');
|
||||
|
||||
// Submit with a file, but with an invalid form token. Ensure the file
|
||||
// was not saved.
|
||||
$last_fid_prior = $this->getLastFileId();
|
||||
$this->drupalGet($path);
|
||||
$form_token_field = $this->assertSession()->hiddenFieldExists('form_token');
|
||||
$form_token_field->setValue('invalid token');
|
||||
$edit = [
|
||||
$file_field_name => \Drupal::service('file_system')->realpath($test_file->getFileUri()),
|
||||
];
|
||||
$this->drupalPostForm(NULL, $edit, t('Save'));
|
||||
$this->assertText('The form has become outdated. Copy any unsaved work in the form below');
|
||||
$last_fid = $this->getLastFileId();
|
||||
$this->assertEqual($last_fid_prior, $last_fid, 'File was not saved when uploaded with an invalid form token.');
|
||||
|
||||
// Submit a new file, without using the Upload button.
|
||||
$last_fid_prior = $this->getLastFileId();
|
||||
$edit = [$file_field_name => \Drupal::service('file_system')->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.', ['%fids' => implode(',', [$last_fid])]), 'Submit handler has correct file info.');
|
||||
|
||||
// Submit no new input, but with a default file.
|
||||
$this->drupalPostForm($path . '/' . $last_fid, [], t('Save'));
|
||||
$this->assertRaw(t('The file ids are %fids.', ['%fids' => implode(',', [$last_fid])]), 'Empty submission did not change an existing file.');
|
||||
|
||||
// Upload, then Submit.
|
||||
$last_fid_prior = $this->getLastFileId();
|
||||
$this->drupalGet($path);
|
||||
$edit = [$file_field_name => \Drupal::service('file_system')->realpath($test_file->getFileUri())];
|
||||
$this->drupalPostForm(NULL, $edit, t('Upload'));
|
||||
$last_fid = $this->getLastFileId();
|
||||
$this->assertTrue($last_fid > $last_fid_prior, 'New file got uploaded.');
|
||||
$this->drupalPostForm(NULL, [], t('Save'));
|
||||
$this->assertRaw(t('The file ids are %fids.', ['%fids' => implode(',', [$last_fid])]), 'Submit handler has correct file info.');
|
||||
|
||||
// Remove, then Submit.
|
||||
$remove_button_title = $multiple ? t('Remove selected') : t('Remove');
|
||||
$remove_edit = [];
|
||||
if ($multiple) {
|
||||
$selected_checkbox = ($tree ? 'nested[file]' : 'file') . '[file_' . $last_fid . '][selected]';
|
||||
$remove_edit = [$selected_checkbox => '1'];
|
||||
}
|
||||
$this->drupalGet($path . '/' . $last_fid);
|
||||
$this->drupalPostForm(NULL, $remove_edit, $remove_button_title);
|
||||
$this->drupalPostForm(NULL, [], t('Save'));
|
||||
$this->assertRaw(t('The file ids are %fids.', ['%fids' => '']), 'Submission after file removal was successful.');
|
||||
|
||||
// Upload, then Remove, then Submit.
|
||||
$this->drupalGet($path);
|
||||
$edit = [$file_field_name => \Drupal::service('file_system')->realpath($test_file->getFileUri())];
|
||||
$this->drupalPostForm(NULL, $edit, t('Upload'));
|
||||
$remove_edit = [];
|
||||
if ($multiple) {
|
||||
$selected_checkbox = ($tree ? 'nested[file]' : 'file') . '[file_' . $this->getLastFileId() . '][selected]';
|
||||
$remove_edit = [$selected_checkbox => '1'];
|
||||
}
|
||||
$this->drupalPostForm(NULL, $remove_edit, $remove_button_title);
|
||||
|
||||
$this->drupalPostForm(NULL, [], t('Save'));
|
||||
$this->assertRaw(t('The file ids are %fids.', ['%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 = ['files[nested_file][]' => \Drupal::service('file_system')->realpath($test_file->getFileUri())];
|
||||
$fid_list = [];
|
||||
|
||||
$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, [], t('Save'));
|
||||
$this->assertRaw(t('The file ids are %fids.', ['%fids' => implode(',', $fid_list)]), 'Two files saved into a single multiple file element.');
|
||||
|
||||
// Delete only the first file.
|
||||
$edit = [
|
||||
'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.');
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensure that warning is shown if file on the field has been removed.
|
||||
*/
|
||||
public function testManagedFileRemoved() {
|
||||
$this->drupalGet('file/test/1/0/1');
|
||||
$test_file = $this->getTestFile('text');
|
||||
$file_field_name = 'files[nested_file][]';
|
||||
|
||||
$edit = [$file_field_name => \Drupal::service('file_system')->realpath($test_file->getFileUri())];
|
||||
$this->drupalPostForm(NULL, $edit, t('Upload'));
|
||||
|
||||
$fid = $this->getLastFileId();
|
||||
$file = \Drupal::entityManager()->getStorage('file')->load($fid);
|
||||
$file->delete();
|
||||
|
||||
$this->drupalPostForm(NULL, $edit, t('Upload'));
|
||||
// We expect the title 'Managed <em>file & butter</em>' which got escaped
|
||||
// via a t() call before.
|
||||
$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::service('file_system')->realpath($test_file->getFileUri())];
|
||||
$this->drupalPostForm(NULL, $edit, t('Upload'));
|
||||
$this->drupalPostForm(NULL, [], 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();
|
||||
}
|
||||
|
||||
/**
|
||||
* Verify that unused permanent files can be used.
|
||||
*/
|
||||
public function testUnusedPermanentFileValidation() {
|
||||
|
||||
// Create a permanent file without usages.
|
||||
$file = $this->getTestFile('image');
|
||||
$file->setPermanent();
|
||||
$file->save();
|
||||
|
||||
// By default, unused files are no longer marked temporary, and it must be
|
||||
// allowed to reference an unused file.
|
||||
$this->drupalGet('file/test/1/0/1/' . $file->id());
|
||||
$this->drupalPostForm(NULL, [], 'Save');
|
||||
$this->assertNoText('The file used in the Managed file & butter field may not be referenced.');
|
||||
$this->assertText('The file ids are ' . $file->id());
|
||||
|
||||
// Enable marking unused files as temporary, unused permanent files must not
|
||||
// be referenced now.
|
||||
$this->config('file.settings')
|
||||
->set('make_unused_managed_files_temporary', TRUE)
|
||||
->save();
|
||||
$this->drupalGet('file/test/1/0/1/' . $file->id());
|
||||
$this->drupalPostForm(NULL, [], 'Save');
|
||||
$this->assertText('The file used in the Managed file & butter field may not be referenced.');
|
||||
$this->assertNoText('The file ids are ' . $file->id());
|
||||
|
||||
// Make the file temporary, now using it is allowed.
|
||||
$file->setTemporary();
|
||||
$file->save();
|
||||
|
||||
$this->drupalGet('file/test/1/0/1/' . $file->id());
|
||||
$this->drupalPostForm(NULL, [], 'Save');
|
||||
$this->assertNoText('The file used in the Managed file & butter field may not be referenced.');
|
||||
$this->assertText('The file ids are ' . $file->id());
|
||||
|
||||
// Make the file permanent again and add a usage from itself, referencing is
|
||||
// still allowed.
|
||||
$file->setPermanent();
|
||||
$file->save();
|
||||
|
||||
/** @var \Drupal\file\FileUsage\FileUsageInterface $file_usage */
|
||||
$file_usage = \Drupal::service('file.usage');
|
||||
$file_usage->add($file, 'file', 'file', $file->id());
|
||||
|
||||
$this->drupalGet('file/test/1/0/1/' . $file->id());
|
||||
$this->drupalPostForm(NULL, [], 'Save');
|
||||
$this->assertNoText('The file used in the Managed file & butter field may not be referenced.');
|
||||
$this->assertText('The file ids are ' . $file->id());
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,205 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\Tests\file\Functional;
|
||||
|
||||
use Drupal\file\Entity\File;
|
||||
|
||||
/**
|
||||
* Uploads files to translated nodes.
|
||||
*
|
||||
* @group file
|
||||
*/
|
||||
class FileOnTranslatedEntityTest extends FileFieldTestBase {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static $modules = ['language', 'content_translation'];
|
||||
|
||||
/**
|
||||
* The name of the file field used in the test.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $fieldName;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function setUp() {
|
||||
parent::setUp();
|
||||
|
||||
// This test expects unused managed files to be marked as temporary a file.
|
||||
$this->config('file.settings')
|
||||
->set('make_unused_managed_files_temporary', TRUE)
|
||||
->save();
|
||||
|
||||
// Create the "Basic page" node type.
|
||||
// @todo Remove the disabling of new revision creation in
|
||||
// https://www.drupal.org/node/1239558.
|
||||
$this->drupalCreateContentType(['type' => 'page', 'name' => 'Basic page', 'new_revision' => FALSE]);
|
||||
|
||||
// Create a file field on the "Basic page" node type.
|
||||
$this->fieldName = strtolower($this->randomMachineName());
|
||||
$this->createFileField($this->fieldName, 'node', 'page');
|
||||
|
||||
// Create and log in user.
|
||||
$permissions = [
|
||||
'access administration pages',
|
||||
'administer content translation',
|
||||
'administer content types',
|
||||
'administer languages',
|
||||
'create content translations',
|
||||
'create page content',
|
||||
'edit any page content',
|
||||
'translate any entity',
|
||||
'delete any page content',
|
||||
];
|
||||
$admin_user = $this->drupalCreateUser($permissions);
|
||||
$this->drupalLogin($admin_user);
|
||||
|
||||
// Add a second and third language.
|
||||
$edit = [];
|
||||
$edit['predefined_langcode'] = 'fr';
|
||||
$this->drupalPostForm('admin/config/regional/language/add', $edit, t('Add language'));
|
||||
|
||||
$edit = [];
|
||||
$edit['predefined_langcode'] = 'nl';
|
||||
$this->drupalPostForm('admin/config/regional/language/add', $edit, t('Add language'));
|
||||
|
||||
// Enable translation for "Basic page" nodes.
|
||||
$edit = [
|
||||
'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 synced file fields on translated nodes.
|
||||
*/
|
||||
public function testSyncedFiles() {
|
||||
// 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(['type' => 'page', 'title' => 'Lost in translation']);
|
||||
|
||||
// Edit the node to upload a file.
|
||||
$edit = [];
|
||||
$name = 'files[' . $this->fieldName . '_0]';
|
||||
$edit[$name] = \Drupal::service('file_system')->realpath($this->drupalGetTestFiles('text')[0]->uri);
|
||||
$this->drupalPostForm('node/' . $default_language_node->id() . '/edit', $edit, t('Save'));
|
||||
$first_fid = $this->getLastFileId();
|
||||
|
||||
// Translate the node into French: remove the existing file.
|
||||
$this->drupalPostForm('node/' . $default_language_node->id() . '/translations/add/en/fr', [], t('Remove'));
|
||||
|
||||
// Upload a different file.
|
||||
$edit = [];
|
||||
$edit['title[0][value]'] = 'Bill Murray';
|
||||
$name = 'files[' . $this->fieldName . '_0]';
|
||||
$edit[$name] = \Drupal::service('file_system')->realpath($this->drupalGetTestFiles('text')[1]->uri);
|
||||
$this->drupalPostForm(NULL, $edit, t('Save (this translation)'));
|
||||
// This inspects the HTML after the post of the translation, the file
|
||||
// should be displayed on the original node.
|
||||
$this->assertRaw('file--mime-text-plain');
|
||||
$second_fid = $this->getLastFileId();
|
||||
|
||||
\Drupal::entityTypeManager()->getStorage('file')->resetCache();
|
||||
|
||||
/* @var $file \Drupal\file\FileInterface */
|
||||
|
||||
// Ensure the file status of the first file permanent.
|
||||
$file = File::load($first_fid);
|
||||
$this->assertTrue($file->isPermanent());
|
||||
|
||||
// Ensure the file status of the second file is permanent.
|
||||
$file = File::load($second_fid);
|
||||
$this->assertTrue($file->isPermanent());
|
||||
|
||||
// Translate the node into dutch: remove the existing file.
|
||||
$this->drupalPostForm('node/' . $default_language_node->id() . '/translations/add/en/nl', [], t('Remove'));
|
||||
|
||||
// Upload a different file.
|
||||
$edit = [];
|
||||
$edit['title[0][value]'] = 'Scarlett Johansson';
|
||||
$name = 'files[' . $this->fieldName . '_0]';
|
||||
$edit[$name] = \Drupal::service('file_system')->realpath($this->drupalGetTestFiles('text')[2]->uri);
|
||||
$this->drupalPostForm(NULL, $edit, t('Save (this translation)'));
|
||||
$third_fid = $this->getLastFileId();
|
||||
|
||||
\Drupal::entityTypeManager()->getStorage('file')->resetCache();
|
||||
|
||||
// Ensure the first file is untouched.
|
||||
$file = File::load($first_fid);
|
||||
$this->assertTrue($file->isPermanent(), 'First file still exists and is permanent.');
|
||||
// This inspects the HTML after the post of the translation, the file
|
||||
// should be displayed on the original node.
|
||||
$this->assertRaw('file--mime-text-plain');
|
||||
|
||||
// Ensure the file status of the second file is permanent.
|
||||
$file = File::load($second_fid);
|
||||
$this->assertTrue($file->isPermanent());
|
||||
|
||||
// Ensure the file status of the third file is permanent.
|
||||
$file = File::load($third_fid);
|
||||
$this->assertTrue($file->isPermanent());
|
||||
|
||||
// Edit the second translation: remove the existing file.
|
||||
$this->drupalPostForm('fr/node/' . $default_language_node->id() . '/edit', [], t('Remove'));
|
||||
|
||||
// Upload a different file.
|
||||
$edit = [];
|
||||
$edit['title[0][value]'] = 'David Bowie';
|
||||
$name = 'files[' . $this->fieldName . '_0]';
|
||||
$edit[$name] = \Drupal::service('file_system')->realpath($this->drupalGetTestFiles('text')[3]->uri);
|
||||
$this->drupalPostForm(NULL, $edit, t('Save (this translation)'));
|
||||
$replaced_second_fid = $this->getLastFileId();
|
||||
|
||||
\Drupal::entityTypeManager()->getStorage('file')->resetCache();
|
||||
|
||||
// Ensure the first and third files are untouched.
|
||||
$file = File::load($first_fid);
|
||||
$this->assertTrue($file->isPermanent(), 'First file still exists and is permanent.');
|
||||
|
||||
$file = File::load($third_fid);
|
||||
$this->assertTrue($file->isPermanent());
|
||||
|
||||
// Ensure the file status of the replaced second file is permanent.
|
||||
$file = File::load($replaced_second_fid);
|
||||
$this->assertTrue($file->isPermanent());
|
||||
|
||||
// Delete the third translation.
|
||||
$this->drupalPostForm('nl/node/' . $default_language_node->id() . '/delete', [], t('Delete Dutch translation'));
|
||||
|
||||
\Drupal::entityTypeManager()->getStorage('file')->resetCache();
|
||||
|
||||
// Ensure the first and replaced second files are untouched.
|
||||
$file = File::load($first_fid);
|
||||
$this->assertTrue($file->isPermanent(), 'First file still exists and is permanent.');
|
||||
|
||||
$file = File::load($replaced_second_fid);
|
||||
$this->assertTrue($file->isPermanent());
|
||||
|
||||
// Ensure the file status of the third file is now temporary.
|
||||
$file = File::load($third_fid);
|
||||
$this->assertTrue($file->isTemporary());
|
||||
|
||||
// Delete the all translations.
|
||||
$this->drupalPostForm('node/' . $default_language_node->id() . '/delete', [], t('Delete all translations'));
|
||||
|
||||
\Drupal::entityTypeManager()->getStorage('file')->resetCache();
|
||||
|
||||
// Ensure the file status of the all files are now temporary.
|
||||
$file = File::load($first_fid);
|
||||
$this->assertTrue($file->isTemporary(), 'First file still exists and is temporary.');
|
||||
|
||||
$file = File::load($replaced_second_fid);
|
||||
$this->assertTrue($file->isTemporary());
|
||||
}
|
||||
|
||||
}
|
232
web/core/modules/file/tests/src/Functional/FilePrivateTest.php
Normal file
232
web/core/modules/file/tests/src/Functional/FilePrivateTest.php
Normal file
|
@ -0,0 +1,232 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\Tests\file\Functional;
|
||||
|
||||
use Drupal\Core\Entity\Plugin\Validation\Constraint\ReferenceAccessConstraint;
|
||||
use Drupal\Component\Render\FormattableMarkup;
|
||||
use Drupal\file\Entity\File;
|
||||
use Drupal\node\Entity\NodeType;
|
||||
use Drupal\user\RoleInterface;
|
||||
|
||||
/**
|
||||
* Uploads a test to a private node and checks access.
|
||||
*
|
||||
* @group file
|
||||
*/
|
||||
class FilePrivateTest extends FileFieldTestBase {
|
||||
|
||||
/**
|
||||
* Modules to enable.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public static $modules = ['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);
|
||||
// This test expects unused managed files to be marked as a temporary file.
|
||||
$this->config('file.settings')
|
||||
->set('make_unused_managed_files_temporary', TRUE)
|
||||
->save();
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests file access for file uploaded to a private node.
|
||||
*/
|
||||
public function testPrivateFile() {
|
||||
$node_storage = $this->container->get('entity.manager')->getStorage('node');
|
||||
/** @var \Drupal\Core\File\FileSystemInterface $file_system */
|
||||
$file_system = \Drupal::service('file_system');
|
||||
$type_name = 'article';
|
||||
$field_name = strtolower($this->randomMachineName());
|
||||
$this->createFileField($field_name, 'node', $type_name, ['uri_scheme' => 'private']);
|
||||
|
||||
$test_file = $this->getTestFile('text');
|
||||
$nid = $this->uploadNodeFile($test_file, $field_name, $type_name, TRUE, ['private' => TRUE]);
|
||||
\Drupal::entityManager()->getStorage('node')->resetCache([$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, ['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, ['private' => TRUE]);
|
||||
\Drupal::entityManager()->getStorage('node')->resetCache([$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 = [];
|
||||
$edit['title[0][value]'] = $this->randomMachineName();
|
||||
$this->drupalPostForm('node/add/' . $type_name, $edit, t('Save'));
|
||||
$new_node = $this->drupalGetNodeByTitle($edit['title[0][value]']);
|
||||
|
||||
// Can't use drupalPostForm() to set hidden fields.
|
||||
$this->drupalGet('node/' . $new_node->id() . '/edit');
|
||||
$this->getSession()->getPage()->find('css', 'input[name="' . $field_name . '[0][fids]"]')->setValue($node_file->id());
|
||||
$this->getSession()->getPage()->pressButton(t('Save'));
|
||||
// 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(new FormattableMarkup($constraint->message, ['%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 = [];
|
||||
$edit['title[0][value]'] = $this->randomMachineName();
|
||||
// Can't use drupalPostForm() to set hidden fields.
|
||||
$this->drupalGet('node/add/' . $type_name);
|
||||
$this->getSession()->getPage()->find('css', 'input[name="title[0][value]"]')->setValue($edit['title[0][value]']);
|
||||
$this->getSession()->getPage()->find('css', 'input[name="' . $field_name . '[0][fids]"]')->setValue($node_file->id());
|
||||
$this->getSession()->getPage()->pressButton(t('Save'));
|
||||
$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(new FormattableMarkup($constraint->message, ['%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.');
|
||||
|
||||
// As an anonymous user, create a temporary file with no references and
|
||||
// confirm that only the session that uploaded it may view it.
|
||||
$this->drupalLogout();
|
||||
user_role_change_permissions(
|
||||
RoleInterface::ANONYMOUS_ID,
|
||||
[
|
||||
"create $type_name content" => TRUE,
|
||||
'access content' => TRUE,
|
||||
]
|
||||
);
|
||||
$test_file = $this->getTestFile('text');
|
||||
$this->drupalGet('node/add/' . $type_name);
|
||||
$edit = ['files[' . $field_name . '_0]' => $file_system->realpath($test_file->getFileUri())];
|
||||
$this->drupalPostForm(NULL, $edit, t('Upload'));
|
||||
/** @var \Drupal\file\FileStorageInterface $file_storage */
|
||||
$file_storage = $this->container->get('entity.manager')->getStorage('file');
|
||||
$files = $file_storage->loadByProperties(['uid' => 0]);
|
||||
$this->assertEqual(1, count($files), 'Loaded one anonymous file.');
|
||||
$file = end($files);
|
||||
$this->assertTrue($file->isTemporary(), 'File is temporary.');
|
||||
$usage = $this->container->get('file.usage')->listUsage($file);
|
||||
$this->assertFalse($usage, 'No file usage found.');
|
||||
$file_url = file_create_url($file->getFileUri());
|
||||
$this->drupalGet($file_url);
|
||||
$this->assertResponse(200, 'Confirmed that the anonymous uploader has access to the temporary file.');
|
||||
// Close the prior connection and remove the session cookie.
|
||||
$this->getSession()->reset();
|
||||
$this->drupalGet($file_url);
|
||||
$this->assertResponse(403, 'Confirmed that another anonymous user cannot access the temporary file.');
|
||||
|
||||
// As an anonymous user, create a permanent file, then remove all
|
||||
// references to the file (so that it becomes temporary again) and confirm
|
||||
// that only the session that uploaded it may view it.
|
||||
$test_file = $this->getTestFile('text');
|
||||
$this->drupalGet('node/add/' . $type_name);
|
||||
$edit = [];
|
||||
$edit['title[0][value]'] = $this->randomMachineName();
|
||||
$edit['files[' . $field_name . '_0]'] = $file_system->realpath($test_file->getFileUri());
|
||||
$this->drupalPostForm(NULL, $edit, t('Save'));
|
||||
$new_node = $this->drupalGetNodeByTitle($edit['title[0][value]']);
|
||||
$file_id = $new_node->{$field_name}->target_id;
|
||||
$file = File::load($file_id);
|
||||
$this->assertTrue($file->isPermanent(), 'File is permanent.');
|
||||
// Remove the reference to this file.
|
||||
$new_node->{$field_name} = [];
|
||||
$new_node->save();
|
||||
$file = File::load($file_id);
|
||||
$this->assertTrue($file->isTemporary(), 'File is temporary.');
|
||||
$usage = $this->container->get('file.usage')->listUsage($file);
|
||||
$this->assertFalse($usage, 'No file usage found.');
|
||||
$file_url = file_create_url($file->getFileUri());
|
||||
$this->drupalGet($file_url);
|
||||
$this->assertResponse(200, 'Confirmed that the anonymous uploader has access to the file whose references were removed.');
|
||||
// Close the prior connection and remove the session cookie.
|
||||
$this->getSession()->reset();
|
||||
$this->drupalGet($file_url);
|
||||
$this->assertResponse(403, 'Confirmed that another anonymous user cannot access the file whose references were removed.');
|
||||
|
||||
// As an anonymous user, create a permanent file that is referenced by a
|
||||
// published node and confirm that all anonymous users may view it.
|
||||
$test_file = $this->getTestFile('text');
|
||||
$this->drupalGet('node/add/' . $type_name);
|
||||
$edit = [];
|
||||
$edit['title[0][value]'] = $this->randomMachineName();
|
||||
$edit['files[' . $field_name . '_0]'] = $file_system->realpath($test_file->getFileUri());
|
||||
$this->drupalPostForm(NULL, $edit, t('Save'));
|
||||
$new_node = $this->drupalGetNodeByTitle($edit['title[0][value]']);
|
||||
$file = File::load($new_node->{$field_name}->target_id);
|
||||
$this->assertTrue($file->isPermanent(), 'File is permanent.');
|
||||
$usage = $this->container->get('file.usage')->listUsage($file);
|
||||
$this->assertTrue($usage, 'File usage found.');
|
||||
$file_url = file_create_url($file->getFileUri());
|
||||
$this->drupalGet($file_url);
|
||||
$this->assertResponse(200, 'Confirmed that the anonymous uploader has access to the permanent file that is referenced by a published node.');
|
||||
// Close the prior connection and remove the session cookie.
|
||||
$this->getSession()->reset();
|
||||
$this->drupalGet($file_url);
|
||||
$this->assertResponse(200, 'Confirmed that another anonymous user also has access to the permanent file that is referenced by a published node.');
|
||||
|
||||
// As an anonymous user, create a permanent file that is referenced by an
|
||||
// unpublished node and confirm that no anonymous users may view it (even
|
||||
// the session that uploaded the file) because they cannot view the
|
||||
// unpublished node.
|
||||
$test_file = $this->getTestFile('text');
|
||||
$this->drupalGet('node/add/' . $type_name);
|
||||
$edit = [];
|
||||
$edit['title[0][value]'] = $this->randomMachineName();
|
||||
$edit['files[' . $field_name . '_0]'] = $file_system->realpath($test_file->getFileUri());
|
||||
$this->drupalPostForm(NULL, $edit, t('Save'));
|
||||
$new_node = $this->drupalGetNodeByTitle($edit['title[0][value]']);
|
||||
$new_node->setUnpublished();
|
||||
$new_node->save();
|
||||
$file = File::load($new_node->{$field_name}->target_id);
|
||||
$this->assertTrue($file->isPermanent(), 'File is permanent.');
|
||||
$usage = $this->container->get('file.usage')->listUsage($file);
|
||||
$this->assertTrue($usage, 'File usage found.');
|
||||
$file_url = file_create_url($file->getFileUri());
|
||||
$this->drupalGet($file_url);
|
||||
$this->assertResponse(403, 'Confirmed that the anonymous uploader cannot access the permanent file when it is referenced by an unpublished node.');
|
||||
// Close the prior connection and remove the session cookie.
|
||||
$this->getSession()->reset();
|
||||
$this->drupalGet($file_url);
|
||||
$this->assertResponse(403, 'Confirmed that another anonymous user cannot access the permanent file when it is referenced by an unpublished node.');
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,98 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\Tests\file\Functional;
|
||||
|
||||
use Drupal\Component\Utility\Html;
|
||||
use Drupal\Core\Render\BubbleableMetadata;
|
||||
use Drupal\file\Entity\File;
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
public 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([$nid]);
|
||||
$node = $node_storage->load($nid);
|
||||
$file = File::load($node->{$field_name}->target_id);
|
||||
|
||||
// Generate and test sanitized tokens.
|
||||
$tests = [];
|
||||
$tests['[file:fid]'] = $file->id();
|
||||
$tests['[file:name]'] = Html::escape($file->getFilename());
|
||||
$tests['[file:path]'] = Html::escape($file->getFileUri());
|
||||
$tests['[file:mime]'] = Html::escape($file->getMimeType());
|
||||
$tests['[file:size]'] = format_size($file->getSize());
|
||||
$tests['[file:url]'] = Html::escape(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]'] = Html::escape($this->adminUser->getDisplayName());
|
||||
$tests['[file:owner:uid]'] = $file->getOwnerId();
|
||||
|
||||
$base_bubbleable_metadata = BubbleableMetadata::createFromObject($file);
|
||||
$metadata_tests = [];
|
||||
$metadata_tests['[file:fid]'] = $base_bubbleable_metadata;
|
||||
$metadata_tests['[file:name]'] = $base_bubbleable_metadata;
|
||||
$metadata_tests['[file:path]'] = $base_bubbleable_metadata;
|
||||
$metadata_tests['[file:mime]'] = $base_bubbleable_metadata;
|
||||
$metadata_tests['[file:size]'] = $base_bubbleable_metadata;
|
||||
$bubbleable_metadata = clone $base_bubbleable_metadata;
|
||||
$metadata_tests['[file:url]'] = $bubbleable_metadata->addCacheContexts(['url.site']);
|
||||
$bubbleable_metadata = clone $base_bubbleable_metadata;
|
||||
$metadata_tests['[file:created]'] = $bubbleable_metadata->addCacheTags(['rendered']);
|
||||
$metadata_tests['[file:created:short]'] = $bubbleable_metadata;
|
||||
$metadata_tests['[file:changed]'] = $bubbleable_metadata;
|
||||
$metadata_tests['[file:changed:short]'] = $bubbleable_metadata;
|
||||
$bubbleable_metadata = clone $base_bubbleable_metadata;
|
||||
$metadata_tests['[file:owner]'] = $bubbleable_metadata->addCacheTags(['user:2']);
|
||||
$metadata_tests['[file:owner:uid]'] = $bubbleable_metadata;
|
||||
|
||||
// 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) {
|
||||
$bubbleable_metadata = new BubbleableMetadata();
|
||||
$output = $token_service->replace($input, ['file' => $file], ['langcode' => $language_interface->getId()], $bubbleable_metadata);
|
||||
$this->assertEqual($output, $expected, format_string('Sanitized file token %token replaced.', ['%token' => $input]));
|
||||
$this->assertEqual($bubbleable_metadata, $metadata_tests[$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, ['file' => $file], ['langcode' => $language_interface->getId(), 'sanitize' => FALSE]);
|
||||
$this->assertEqual($output, $expected, format_string('Unsanitized file token %token replaced.', ['%token' => $input]));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,35 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\Tests\file\Functional;
|
||||
|
||||
use Drupal\Tests\rest\Functional\BasicAuthResourceTestTrait;
|
||||
use Drupal\Tests\rest\Functional\FileUploadResourceTestBase;
|
||||
|
||||
/**
|
||||
* @group file
|
||||
*/
|
||||
class FileUploadJsonBasicAuthTest extends FileUploadResourceTestBase {
|
||||
|
||||
use BasicAuthResourceTestTrait;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static $modules = ['basic_auth'];
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $format = 'json';
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $mimeType = 'application/json';
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $auth = 'basic_auth';
|
||||
|
||||
}
|
|
@ -0,0 +1,30 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\Tests\file\Functional;
|
||||
|
||||
use Drupal\Tests\rest\Functional\CookieResourceTestTrait;
|
||||
use Drupal\Tests\rest\Functional\FileUploadResourceTestBase;
|
||||
|
||||
/**
|
||||
* @group file
|
||||
*/
|
||||
class FileUploadJsonCookieTest extends FileUploadResourceTestBase {
|
||||
|
||||
use CookieResourceTestTrait;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $format = 'json';
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $mimeType = 'application/json';
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $auth = 'cookie';
|
||||
|
||||
}
|
|
@ -0,0 +1,58 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\Tests\file\Functional\Formatter;
|
||||
|
||||
use Drupal\entity_test\Entity\EntityTest;
|
||||
use Drupal\file\Entity\File;
|
||||
|
||||
/**
|
||||
* @coversDefaultClass \Drupal\file\Plugin\Field\FieldFormatter\FileAudioFormatter
|
||||
* @group file
|
||||
*/
|
||||
class FileAudioFormatterTest extends FileMediaFormatterTestBase {
|
||||
|
||||
/**
|
||||
* @covers ::viewElements
|
||||
*
|
||||
* @dataProvider dataProvider
|
||||
*/
|
||||
public function testRender($tag_count, $formatter_settings) {
|
||||
$field_config = $this->createMediaField('file_audio', 'mp3', $formatter_settings);
|
||||
|
||||
file_put_contents('public://file.mp3', str_repeat('t', 10));
|
||||
$file1 = File::create([
|
||||
'uri' => 'public://file.mp3',
|
||||
'filename' => 'file.mp3',
|
||||
]);
|
||||
$file1->save();
|
||||
|
||||
$file2 = File::create([
|
||||
'uri' => 'public://file.mp3',
|
||||
'filename' => 'file.mp3',
|
||||
]);
|
||||
$file2->save();
|
||||
|
||||
$entity = EntityTest::create([
|
||||
$field_config->getName() => [
|
||||
[
|
||||
'target_id' => $file1->id(),
|
||||
],
|
||||
[
|
||||
'target_id' => $file2->id(),
|
||||
],
|
||||
],
|
||||
]);
|
||||
$entity->save();
|
||||
|
||||
$this->drupalGet($entity->toUrl());
|
||||
|
||||
$file1_url = file_url_transform_relative(file_create_url($file1->getFileUri()));
|
||||
$file2_url = file_url_transform_relative(file_create_url($file2->getFileUri()));
|
||||
|
||||
$assert_session = $this->assertSession();
|
||||
$assert_session->elementsCount('css', 'audio[controls="controls"]', $tag_count);
|
||||
$assert_session->elementExists('css', "audio > source[src='$file1_url'][type='audio/mpeg']");
|
||||
$assert_session->elementExists('css', "audio > source[src='$file2_url'][type='audio/mpeg']");
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,92 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\Tests\file\Functional\Formatter;
|
||||
|
||||
use Drupal\Core\Field\FieldStorageDefinitionInterface;
|
||||
use Drupal\field\Entity\FieldConfig;
|
||||
use Drupal\field\Entity\FieldStorageConfig;
|
||||
use Drupal\Tests\BrowserTestBase;
|
||||
|
||||
/**
|
||||
* Provides methods specifically for testing File module's media formatter's.
|
||||
*/
|
||||
abstract class FileMediaFormatterTestBase extends BrowserTestBase {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $modules = [
|
||||
'entity_test',
|
||||
'field',
|
||||
'file',
|
||||
'user',
|
||||
'system',
|
||||
];
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function setUp() {
|
||||
parent::setUp();
|
||||
$this->drupalLogin($this->drupalCreateUser(['view test entity']));
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a file field and set's the correct formatter.
|
||||
*
|
||||
* @param string $formatter
|
||||
* The formatter ID.
|
||||
* @param string $file_extensions
|
||||
* The file extensions of the new field.
|
||||
* @param array $formatter_settings
|
||||
* Settings for the formatter.
|
||||
*
|
||||
* @return \Drupal\field\Entity\FieldConfig
|
||||
* Newly created file field.
|
||||
*/
|
||||
protected function createMediaField($formatter, $file_extensions, array $formatter_settings = []) {
|
||||
$entity_type = $bundle = 'entity_test';
|
||||
$field_name = mb_strtolower($this->randomMachineName());
|
||||
|
||||
FieldStorageConfig::create([
|
||||
'entity_type' => $entity_type,
|
||||
'field_name' => $field_name,
|
||||
'type' => 'file',
|
||||
'cardinality' => FieldStorageDefinitionInterface::CARDINALITY_UNLIMITED,
|
||||
])->save();
|
||||
$field_config = FieldConfig::create([
|
||||
'entity_type' => $entity_type,
|
||||
'field_name' => $field_name,
|
||||
'bundle' => $bundle,
|
||||
'settings' => [
|
||||
'file_extensions' => trim($file_extensions),
|
||||
],
|
||||
]);
|
||||
$field_config->save();
|
||||
|
||||
$display = entity_get_display('entity_test', 'entity_test', 'full');
|
||||
$display->setComponent($field_name, [
|
||||
'type' => $formatter,
|
||||
'settings' => $formatter_settings,
|
||||
])->save();
|
||||
|
||||
return $field_config;
|
||||
}
|
||||
|
||||
/**
|
||||
* Data provider for testRender.
|
||||
*
|
||||
* @return array
|
||||
* An array of data arrays.
|
||||
* The data array contains:
|
||||
* - The number of expected HTML tags.
|
||||
* - An array of settings for the field formatter.
|
||||
*/
|
||||
public function dataProvider() {
|
||||
return [
|
||||
[2, []],
|
||||
[1, ['multiple_file_display_type' => 'sources']],
|
||||
];
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,58 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\Tests\file\Functional\Formatter;
|
||||
|
||||
use Drupal\entity_test\Entity\EntityTest;
|
||||
use Drupal\file\Entity\File;
|
||||
|
||||
/**
|
||||
* @coversDefaultClass \Drupal\file\Plugin\Field\FieldFormatter\FileVideoFormatter
|
||||
* @group file
|
||||
*/
|
||||
class FileVideoFormatterTest extends FileMediaFormatterTestBase {
|
||||
|
||||
/**
|
||||
* @covers ::viewElements
|
||||
*
|
||||
* @dataProvider dataProvider
|
||||
*/
|
||||
public function testRender($tag_count, $formatter_settings) {
|
||||
$field_config = $this->createMediaField('file_video', 'mp4', $formatter_settings);
|
||||
|
||||
file_put_contents('public://file.mp4', str_repeat('t', 10));
|
||||
$file1 = File::create([
|
||||
'uri' => 'public://file.mp4',
|
||||
'filename' => 'file.mp4',
|
||||
]);
|
||||
$file1->save();
|
||||
|
||||
$file2 = File::create([
|
||||
'uri' => 'public://file.mp4',
|
||||
'filename' => 'file.mp4',
|
||||
]);
|
||||
$file2->save();
|
||||
|
||||
$entity = EntityTest::create([
|
||||
$field_config->getName() => [
|
||||
[
|
||||
'target_id' => $file1->id(),
|
||||
],
|
||||
[
|
||||
'target_id' => $file2->id(),
|
||||
],
|
||||
],
|
||||
]);
|
||||
$entity->save();
|
||||
|
||||
$this->drupalGet($entity->toUrl());
|
||||
|
||||
$file1_url = file_url_transform_relative(file_create_url($file1->getFileUri()));
|
||||
$file2_url = file_url_transform_relative(file_create_url($file2->getFileUri()));
|
||||
|
||||
$assert_session = $this->assertSession();
|
||||
$assert_session->elementsCount('css', 'video[controls="controls"]', $tag_count);
|
||||
$assert_session->elementExists('css', "video > source[src='$file1_url'][type='video/mp4']");
|
||||
$assert_session->elementExists('css', "video > source[src='$file2_url'][type='video/mp4']");
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,139 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\Tests\file\Functional\Hal;
|
||||
|
||||
use Drupal\Core\Cache\Cache;
|
||||
use Drupal\Tests\file\Functional\Rest\FileResourceTestBase;
|
||||
use Drupal\Tests\hal\Functional\EntityResource\HalEntityNormalizationTrait;
|
||||
use Drupal\Tests\rest\Functional\AnonResourceTestTrait;
|
||||
|
||||
/**
|
||||
* @group hal
|
||||
*/
|
||||
class FileHalJsonAnonTest extends FileResourceTestBase {
|
||||
|
||||
use HalEntityNormalizationTrait;
|
||||
use AnonResourceTestTrait;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static $modules = ['hal'];
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $format = 'hal_json';
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $mimeType = 'application/hal+json';
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function getExpectedNormalizedEntity() {
|
||||
$default_normalization = parent::getExpectedNormalizedEntity();
|
||||
|
||||
$normalization = $this->applyHalFieldNormalization($default_normalization);
|
||||
|
||||
$url = file_create_url($this->entity->getFileUri());
|
||||
// @see \Drupal\Tests\hal\Functional\EntityResource\File\FileHalJsonAnonTest::testGetBcUriField()
|
||||
if ($this->config('hal.settings')->get('bc_file_uri_as_url_normalizer')) {
|
||||
$normalization['uri'][0]['value'] = $url;
|
||||
}
|
||||
|
||||
$uid = $this->author->id();
|
||||
|
||||
return $normalization + [
|
||||
'_embedded' => [
|
||||
$this->baseUrl . '/rest/relation/file/file/uid' => [
|
||||
[
|
||||
'_links' => [
|
||||
'self' => [
|
||||
'href' => $this->baseUrl . "/user/$uid?_format=hal_json",
|
||||
],
|
||||
'type' => [
|
||||
'href' => $this->baseUrl . '/rest/type/user/user',
|
||||
],
|
||||
],
|
||||
'uuid' => [
|
||||
[
|
||||
'value' => $this->author->uuid(),
|
||||
],
|
||||
],
|
||||
],
|
||||
],
|
||||
],
|
||||
'_links' => [
|
||||
'self' => [
|
||||
'href' => $url,
|
||||
],
|
||||
'type' => [
|
||||
'href' => $this->baseUrl . '/rest/type/file/file',
|
||||
],
|
||||
$this->baseUrl . '/rest/relation/file/file/uid' => [
|
||||
[
|
||||
'href' => $this->baseUrl . "/user/$uid?_format=hal_json",
|
||||
],
|
||||
],
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function getNormalizedPostEntity() {
|
||||
return parent::getNormalizedPostEntity() + [
|
||||
'_links' => [
|
||||
'type' => [
|
||||
'href' => $this->baseUrl . '/rest/type/file/file',
|
||||
],
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function getExpectedCacheTags() {
|
||||
return Cache::mergeTags(parent::getExpectedCacheTags(), ['config:hal.settings']);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function getExpectedCacheContexts() {
|
||||
return [
|
||||
'url.site',
|
||||
'user.permissions',
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @see hal_update_8501()
|
||||
*/
|
||||
public function testGetBcUriField() {
|
||||
$this->config('hal.settings')->set('bc_file_uri_as_url_normalizer', TRUE)->save(TRUE);
|
||||
|
||||
$this->initAuthentication();
|
||||
$url = $this->getEntityResourceUrl();
|
||||
$url->setOption('query', ['_format' => static::$format]);
|
||||
$request_options = $this->getAuthenticationRequestOptions('GET');
|
||||
$this->provisionEntityResource();
|
||||
$this->setUpAuthorization('GET');
|
||||
$response = $this->request('GET', $url, $request_options);
|
||||
$expected = $this->getExpectedNormalizedEntity();
|
||||
static::recursiveKSort($expected);
|
||||
$actual = $this->serializer->decode((string) $response->getBody(), static::$format);
|
||||
static::recursiveKSort($actual);
|
||||
$this->assertSame($expected, $actual);
|
||||
|
||||
// Explicitly assert that $file->uri->value is an absolute file URL, unlike
|
||||
// the default normalization.
|
||||
$this->assertSame($this->baseUrl . '/' . $this->siteDirectory . '/files/drupal.txt', $actual['uri'][0]['value']);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,24 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\Tests\file\Functional\Hal;
|
||||
|
||||
use Drupal\Tests\rest\Functional\BasicAuthResourceTestTrait;
|
||||
|
||||
/**
|
||||
* @group hal
|
||||
*/
|
||||
class FileHalJsonBasicAuthTest extends FileHalJsonAnonTest {
|
||||
|
||||
use BasicAuthResourceTestTrait;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static $modules = ['basic_auth'];
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $auth = 'basic_auth';
|
||||
|
||||
}
|
|
@ -0,0 +1,19 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\Tests\file\Functional\Hal;
|
||||
|
||||
use Drupal\Tests\rest\Functional\CookieResourceTestTrait;
|
||||
|
||||
/**
|
||||
* @group hal
|
||||
*/
|
||||
class FileHalJsonCookieTest extends FileHalJsonAnonTest {
|
||||
|
||||
use CookieResourceTestTrait;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $auth = 'cookie';
|
||||
|
||||
}
|
|
@ -0,0 +1,24 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\Tests\file\Functional\Hal;
|
||||
|
||||
use Drupal\Tests\rest\Functional\BasicAuthResourceTestTrait;
|
||||
|
||||
/**
|
||||
* @group hal
|
||||
*/
|
||||
class FileUploadHalJsonBasicAuthTest extends FileUploadHalJsonTestBase {
|
||||
|
||||
use BasicAuthResourceTestTrait;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static $modules = ['basic_auth'];
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $auth = 'basic_auth';
|
||||
|
||||
}
|
|
@ -0,0 +1,19 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\Tests\file\Functional\Hal;
|
||||
|
||||
use Drupal\Tests\rest\Functional\CookieResourceTestTrait;
|
||||
|
||||
/**
|
||||
* @group hal
|
||||
*/
|
||||
class FileUploadHalJsonCookieTest extends FileUploadHalJsonTestBase {
|
||||
|
||||
use CookieResourceTestTrait;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $auth = 'cookie';
|
||||
|
||||
}
|
|
@ -0,0 +1,97 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\Tests\file\Functional\Hal;
|
||||
|
||||
use Drupal\Tests\rest\Functional\FileUploadResourceTestBase;
|
||||
use Drupal\Tests\hal\Functional\EntityResource\HalEntityNormalizationTrait;
|
||||
|
||||
/**
|
||||
* Tests binary data file upload route for HAL JSON.
|
||||
*/
|
||||
abstract class FileUploadHalJsonTestBase extends FileUploadResourceTestBase {
|
||||
|
||||
use HalEntityNormalizationTrait;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static $modules = ['hal'];
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $format = 'hal_json';
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $mimeType = 'application/hal+json';
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function getExpectedNormalizedEntity($fid = 1, $expected_filename = 'example.txt', $expected_as_filename = FALSE) {
|
||||
$normalization = parent::getExpectedNormalizedEntity($fid, $expected_filename, $expected_as_filename);
|
||||
|
||||
// Cannot use applyHalFieldNormalization() as it uses the $entity property
|
||||
// from the test class, which in the case of file upload tests, is the
|
||||
// parent entity test entity for the file that's created.
|
||||
|
||||
// The HAL normalization adds entity reference fields to '_links' and
|
||||
// '_embedded'.
|
||||
unset($normalization['uid']);
|
||||
|
||||
return $normalization + [
|
||||
'_links' => [
|
||||
'self' => [
|
||||
// @todo This can use a proper link once
|
||||
// https://www.drupal.org/project/drupal/issues/2907402 is complete.
|
||||
// This link matches what is generated from from File::url(), a
|
||||
// resource URL is currently not available.
|
||||
'href' => file_create_url($normalization['uri'][0]['value']),
|
||||
],
|
||||
'type' => [
|
||||
'href' => $this->baseUrl . '/rest/type/file/file',
|
||||
],
|
||||
$this->baseUrl . '/rest/relation/file/file/uid' => [
|
||||
['href' => $this->baseUrl . '/user/' . $this->account->id() . '?_format=hal_json'],
|
||||
],
|
||||
],
|
||||
'_embedded' => [
|
||||
$this->baseUrl . '/rest/relation/file/file/uid' => [
|
||||
[
|
||||
'_links' => [
|
||||
'self' => [
|
||||
'href' => $this->baseUrl . '/user/' . $this->account->id() . '?_format=hal_json',
|
||||
],
|
||||
'type' => [
|
||||
'href' => $this->baseUrl . '/rest/type/user/user',
|
||||
],
|
||||
],
|
||||
'uuid' => [
|
||||
[
|
||||
'value' => $this->account->uuid(),
|
||||
],
|
||||
],
|
||||
],
|
||||
],
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*
|
||||
* @see \Drupal\Tests\hal\Functional\EntityResource\EntityTest\EntityTestHalJsonAnonTest::getNormalizedPostEntity()
|
||||
*/
|
||||
protected function getNormalizedPostEntity() {
|
||||
return parent::getNormalizedPostEntity() + [
|
||||
'_links' => [
|
||||
'type' => [
|
||||
'href' => $this->baseUrl . '/rest/type/entity_test/entity_test',
|
||||
],
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,125 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\Tests\file\Functional;
|
||||
|
||||
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 = ['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(['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', ['uri_scheme' => 'private']);
|
||||
|
||||
// Create and log in user.
|
||||
$permissions = [
|
||||
'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 = [];
|
||||
$edit['predefined_langcode'] = 'fr';
|
||||
$this->drupalPostForm('admin/config/regional/language/add', $edit, t('Add language'));
|
||||
|
||||
// Enable translation for "Basic page" nodes.
|
||||
$edit = [
|
||||
'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(['type' => 'page']);
|
||||
|
||||
// Edit the node to upload a file.
|
||||
$edit = [];
|
||||
$name = 'files[' . $this->fieldName . '_0]';
|
||||
$edit[$name] = \Drupal::service('file_system')->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([$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, [], t('Remove'));
|
||||
|
||||
// Upload a different file.
|
||||
$edit = [];
|
||||
$edit['title[0][value]'] = $this->randomMachineName();
|
||||
$name = 'files[' . $this->fieldName . '_0]';
|
||||
$edit[$name] = \Drupal::service('file_system')->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([$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.');
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,24 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\Tests\file\Functional;
|
||||
|
||||
/**
|
||||
* Tests the file uploading functions.
|
||||
*
|
||||
* @group file
|
||||
*/
|
||||
class RemoteFileSaveUploadTest extends SaveUploadTest {
|
||||
|
||||
/**
|
||||
* Modules to enable.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public static $modules = ['file_test'];
|
||||
|
||||
protected function setUp() {
|
||||
parent::setUp();
|
||||
$this->config('system.file')->set('default_scheme', 'dummy-remote')->save();
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,24 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\Tests\file\Functional\Rest;
|
||||
|
||||
use Drupal\Tests\rest\Functional\AnonResourceTestTrait;
|
||||
|
||||
/**
|
||||
* @group rest
|
||||
*/
|
||||
class FileJsonAnonTest extends FileResourceTestBase {
|
||||
|
||||
use AnonResourceTestTrait;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $format = 'json';
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $mimeType = 'application/json';
|
||||
|
||||
}
|
|
@ -0,0 +1,34 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\Tests\file\Functional\Rest;
|
||||
|
||||
use Drupal\Tests\rest\Functional\BasicAuthResourceTestTrait;
|
||||
|
||||
/**
|
||||
* @group rest
|
||||
*/
|
||||
class FileJsonBasicAuthTest extends FileResourceTestBase {
|
||||
|
||||
use BasicAuthResourceTestTrait;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static $modules = ['basic_auth'];
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $format = 'json';
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $mimeType = 'application/json';
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $auth = 'basic_auth';
|
||||
|
||||
}
|
|
@ -0,0 +1,29 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\Tests\file\Functional\Rest;
|
||||
|
||||
use Drupal\Tests\rest\Functional\CookieResourceTestTrait;
|
||||
|
||||
/**
|
||||
* @group rest
|
||||
*/
|
||||
class FileJsonCookieTest extends FileResourceTestBase {
|
||||
|
||||
use CookieResourceTestTrait;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $format = 'json';
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $mimeType = 'application/json';
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $auth = 'cookie';
|
||||
|
||||
}
|
|
@ -0,0 +1,233 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\Tests\file\Functional\Rest;
|
||||
|
||||
use Drupal\file\Entity\File;
|
||||
use Drupal\Tests\rest\Functional\BcTimestampNormalizerUnixTestTrait;
|
||||
use Drupal\Tests\rest\Functional\EntityResource\EntityResourceTestBase;
|
||||
use Drupal\user\Entity\User;
|
||||
|
||||
abstract class FileResourceTestBase extends EntityResourceTestBase {
|
||||
|
||||
use BcTimestampNormalizerUnixTestTrait;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static $modules = ['file', 'user'];
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $entityTypeId = 'file';
|
||||
|
||||
/**
|
||||
* @var \Drupal\file\FileInterface
|
||||
*/
|
||||
protected $entity;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $patchProtectedFieldNames = [
|
||||
'uri' => NULL,
|
||||
'filemime' => NULL,
|
||||
'filesize' => NULL,
|
||||
'status' => NULL,
|
||||
'changed' => NULL,
|
||||
];
|
||||
|
||||
/**
|
||||
* @var \Drupal\user\UserInterface
|
||||
*/
|
||||
protected $author;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function setUpAuthorization($method) {
|
||||
switch ($method) {
|
||||
case 'GET':
|
||||
$this->grantPermissionsToTestedRole(['access content']);
|
||||
break;
|
||||
|
||||
case 'PATCH':
|
||||
case 'DELETE':
|
||||
// \Drupal\file\FileAccessControlHandler::checkAccess() grants 'update'
|
||||
// and 'delete' access only to the user that owns the file. So there is
|
||||
// no permission to grant: instead, the file owner must be changed from
|
||||
// its default (user 1) to the current user.
|
||||
$this->makeCurrentUserFileOwner();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function grantPermissionsToTestedRole(array $permissions) {
|
||||
// testPatch() and testDelete() test the 'bc_entity_resource_permissions' BC
|
||||
// layer; also call makeCurrentUserFileOwner() then.
|
||||
if ($permissions === ['restful patch entity:file'] || $permissions === ['restful delete entity:file']) {
|
||||
$this->makeCurrentUserFileOwner();
|
||||
}
|
||||
parent::grantPermissionsToTestedRole($permissions);
|
||||
}
|
||||
|
||||
/**
|
||||
* Makes the current user the file owner.
|
||||
*/
|
||||
protected function makeCurrentUserFileOwner() {
|
||||
$account = static::$auth ? User::load(2) : User::load(0);
|
||||
$this->entity->setOwnerId($account->id());
|
||||
$this->entity->setOwner($account);
|
||||
$this->entity->save();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function createEntity() {
|
||||
$this->author = User::load(1);
|
||||
|
||||
$file = File::create();
|
||||
$file->setOwnerId($this->author->id());
|
||||
$file->setFilename('drupal.txt');
|
||||
$file->setMimeType('text/plain');
|
||||
$file->setFileUri('public://drupal.txt');
|
||||
$file->set('status', FILE_STATUS_PERMANENT);
|
||||
$file->save();
|
||||
|
||||
file_put_contents($file->getFileUri(), 'Drupal');
|
||||
|
||||
return $file;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function getExpectedNormalizedEntity() {
|
||||
return [
|
||||
'changed' => [
|
||||
$this->formatExpectedTimestampItemValues($this->entity->getChangedTime()),
|
||||
],
|
||||
'created' => [
|
||||
$this->formatExpectedTimestampItemValues((int) $this->entity->getCreatedTime()),
|
||||
],
|
||||
'fid' => [
|
||||
[
|
||||
'value' => 1,
|
||||
],
|
||||
],
|
||||
'filemime' => [
|
||||
[
|
||||
'value' => 'text/plain',
|
||||
],
|
||||
],
|
||||
'filename' => [
|
||||
[
|
||||
'value' => 'drupal.txt',
|
||||
],
|
||||
],
|
||||
'filesize' => [
|
||||
[
|
||||
'value' => (int) $this->entity->getSize(),
|
||||
],
|
||||
],
|
||||
'langcode' => [
|
||||
[
|
||||
'value' => 'en',
|
||||
],
|
||||
],
|
||||
'status' => [
|
||||
[
|
||||
'value' => TRUE,
|
||||
],
|
||||
],
|
||||
'uid' => [
|
||||
[
|
||||
'target_id' => (int) $this->author->id(),
|
||||
'target_type' => 'user',
|
||||
'target_uuid' => $this->author->uuid(),
|
||||
'url' => base_path() . 'user/' . $this->author->id(),
|
||||
],
|
||||
],
|
||||
'uri' => [
|
||||
[
|
||||
'url' => base_path() . $this->siteDirectory . '/files/drupal.txt',
|
||||
'value' => 'public://drupal.txt',
|
||||
],
|
||||
],
|
||||
'uuid' => [
|
||||
[
|
||||
'value' => $this->entity->uuid(),
|
||||
],
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function getNormalizedPostEntity() {
|
||||
return [
|
||||
'uid' => [
|
||||
[
|
||||
'target_id' => $this->author->id(),
|
||||
],
|
||||
],
|
||||
'filename' => [
|
||||
[
|
||||
'value' => 'drupal.txt',
|
||||
],
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function getNormalizedPatchEntity() {
|
||||
return array_diff_key($this->getNormalizedPostEntity(), ['uid' => TRUE]);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function getExpectedCacheContexts() {
|
||||
return [
|
||||
'user.permissions',
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function testPost() {
|
||||
// Drupal 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 node's image field).
|
||||
// For that purpose, there is the "file_upload" REST resource plugin.
|
||||
// @see \Drupal\file\FileAccessControlHandler::checkCreateAccess()
|
||||
// @see \Drupal\file\Plugin\rest\resource\FileUploadResource
|
||||
$this->markTestSkipped();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function getExpectedUnauthorizedAccessMessage($method) {
|
||||
if ($this->config('rest.settings')->get('bc_entity_resource_permissions')) {
|
||||
return parent::getExpectedUnauthorizedAccessMessage($method);
|
||||
}
|
||||
|
||||
if ($method === 'GET') {
|
||||
return "The 'access content' permission is required.";
|
||||
}
|
||||
if ($method === 'PATCH' || $method === 'DELETE') {
|
||||
return 'Only the file owner can update or delete the file entity.';
|
||||
}
|
||||
return parent::getExpectedUnauthorizedAccessMessage($method);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,26 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\Tests\file\Functional\Rest;
|
||||
|
||||
use Drupal\Tests\rest\Functional\AnonResourceTestTrait;
|
||||
use Drupal\Tests\rest\Functional\EntityResource\XmlEntityNormalizationQuirksTrait;
|
||||
|
||||
/**
|
||||
* @group rest
|
||||
*/
|
||||
class FileXmlAnonTest extends FileResourceTestBase {
|
||||
|
||||
use AnonResourceTestTrait;
|
||||
use XmlEntityNormalizationQuirksTrait;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $format = 'xml';
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $mimeType = 'text/xml; charset=UTF-8';
|
||||
|
||||
}
|
|
@ -0,0 +1,36 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\Tests\file\Functional\Rest;
|
||||
|
||||
use Drupal\Tests\rest\Functional\BasicAuthResourceTestTrait;
|
||||
use Drupal\Tests\rest\Functional\EntityResource\XmlEntityNormalizationQuirksTrait;
|
||||
|
||||
/**
|
||||
* @group rest
|
||||
*/
|
||||
class FileXmlBasicAuthTest extends FileResourceTestBase {
|
||||
|
||||
use BasicAuthResourceTestTrait;
|
||||
use XmlEntityNormalizationQuirksTrait;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static $modules = ['basic_auth'];
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $format = 'xml';
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $mimeType = 'text/xml; charset=UTF-8';
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $auth = 'basic_auth';
|
||||
|
||||
}
|
|
@ -0,0 +1,31 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\Tests\file\Functional\Rest;
|
||||
|
||||
use Drupal\Tests\rest\Functional\CookieResourceTestTrait;
|
||||
use Drupal\Tests\rest\Functional\EntityResource\XmlEntityNormalizationQuirksTrait;
|
||||
|
||||
/**
|
||||
* @group rest
|
||||
*/
|
||||
class FileXmlCookieTest extends FileResourceTestBase {
|
||||
|
||||
use CookieResourceTestTrait;
|
||||
use XmlEntityNormalizationQuirksTrait;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $format = 'xml';
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $mimeType = 'text/xml; charset=UTF-8';
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $auth = 'cookie';
|
||||
|
||||
}
|
|
@ -0,0 +1,494 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\Tests\file\Functional;
|
||||
|
||||
use Drupal\file\Entity\File;
|
||||
use Drupal\Tests\TestFileCreationTrait;
|
||||
|
||||
/**
|
||||
* Tests the _file_save_upload_from_form() function.
|
||||
*
|
||||
* @group file
|
||||
*
|
||||
* @see _file_save_upload_from_form()
|
||||
*/
|
||||
class SaveUploadFormTest extends FileManagedTestBase {
|
||||
|
||||
use TestFileCreationTrait {
|
||||
getTestFiles as drupalGetTestFiles;
|
||||
}
|
||||
|
||||
/**
|
||||
* Modules to enable.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public static $modules = ['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;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function setUp() {
|
||||
parent::setUp();
|
||||
$account = $this->drupalCreateUser(['access site reports']);
|
||||
$this->drupalLogin($account);
|
||||
|
||||
$image_files = $this->drupalGetTestFiles('image');
|
||||
$this->image = File::create((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();
|
||||
|
||||
/** @var \Drupal\Core\File\FileSystemInterface $file_system */
|
||||
$file_system = \Drupal::service('file_system');
|
||||
// Upload with replace to guarantee there's something there.
|
||||
$edit = [
|
||||
'file_test_replace' => FILE_EXISTS_REPLACE,
|
||||
'files[file_test_upload][]' => $file_system->realpath($this->image->getFileUri()),
|
||||
];
|
||||
$this->drupalPostForm('file-test/save_upload_from_form_test', $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(['validate', 'insert']);
|
||||
file_test_reset();
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the _file_save_upload_from_form() function.
|
||||
*/
|
||||
public 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'));
|
||||
/** @var \Drupal\Core\File\FileSystemInterface $file_system */
|
||||
$file_system = \Drupal::service('file_system');
|
||||
$edit = ['files[file_test_upload][]' => $file_system->realpath($image2->uri)];
|
||||
$this->drupalPostForm('file-test/save_upload_from_form_test', $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(['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::loadMultiple().
|
||||
$files = File::loadMultiple([$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 = $file_system->realpath($image3->uri);
|
||||
$dir = $this->randomMachineName();
|
||||
$edit = [
|
||||
'files[file_test_upload][]' => $image3_realpath,
|
||||
'file_subdir' => $dir,
|
||||
];
|
||||
$this->drupalPostForm('file-test/save_upload_from_form_test', $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))));
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests extension handling.
|
||||
*/
|
||||
public function testHandleExtension() {
|
||||
/** @var \Drupal\Core\File\FileSystemInterface $file_system */
|
||||
$file_system = \Drupal::service('file_system');
|
||||
// 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_from_form() to only allow ".foo".
|
||||
$extensions = 'foo';
|
||||
$edit = [
|
||||
'file_test_replace' => FILE_EXISTS_REPLACE,
|
||||
'files[file_test_upload][]' => $file_system->realpath($this->image->getFileUri()),
|
||||
'extensions' => $extensions,
|
||||
];
|
||||
|
||||
$this->drupalPostForm('file-test/save_upload_from_form_test', $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(['validate']);
|
||||
|
||||
// Reset the hook counters.
|
||||
file_test_reset();
|
||||
|
||||
$extensions = 'foo ' . $this->imageExtension;
|
||||
// Now tell _file_save_upload_from_form() to allow the extension of our test image.
|
||||
$edit = [
|
||||
'file_test_replace' => FILE_EXISTS_REPLACE,
|
||||
'files[file_test_upload][]' => $file_system->realpath($this->image->getFileUri()),
|
||||
'extensions' => $extensions,
|
||||
];
|
||||
|
||||
$this->drupalPostForm('file-test/save_upload_from_form_test', $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(['validate', 'load', 'update']);
|
||||
|
||||
// Reset the hook counters.
|
||||
file_test_reset();
|
||||
|
||||
// Now tell _file_save_upload_from_form() to allow any extension.
|
||||
$edit = [
|
||||
'file_test_replace' => FILE_EXISTS_REPLACE,
|
||||
'files[file_test_upload][]' => $file_system->realpath($this->image->getFileUri()),
|
||||
'allow_all_extensions' => TRUE,
|
||||
];
|
||||
$this->drupalPostForm('file-test/save_upload_from_form_test', $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(['validate', 'load', 'update']);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests dangerous file handling.
|
||||
*/
|
||||
public function testHandleDangerousFile() {
|
||||
$config = $this->config('system.file');
|
||||
/** @var \Drupal\Core\File\FileSystemInterface $file_system */
|
||||
$file_system = \Drupal::service('file_system');
|
||||
// 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 = [
|
||||
'file_test_replace' => FILE_EXISTS_REPLACE,
|
||||
'files[file_test_upload][]' => $file_system->realpath($this->phpfile->uri),
|
||||
'is_image_file' => FALSE,
|
||||
'extensions' => 'php',
|
||||
];
|
||||
|
||||
$this->drupalPostForm('file-test/save_upload_from_form_test', $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(['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/save_upload_from_form_test', $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', ['@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(['validate', 'insert']);
|
||||
|
||||
// Turn off insecure uploads.
|
||||
$config->set('allow_insecure_uploads', 0)->save();
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests file munge handling.
|
||||
*/
|
||||
public function testHandleFileMunge() {
|
||||
/** @var \Drupal\Core\File\FileSystemInterface $file_system */
|
||||
$file_system = \Drupal::service('file_system');
|
||||
// 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 = [
|
||||
'files[file_test_upload][]' => $file_system->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/save_upload_from_form_test', $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', ['@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(['validate', 'insert']);
|
||||
|
||||
// Ensure we don't munge files if we're allowing any extension.
|
||||
// Reset the hook counters.
|
||||
file_test_reset();
|
||||
|
||||
$edit = [
|
||||
'files[file_test_upload][]' => $file_system->realpath($this->image->getFileUri()),
|
||||
'allow_all_extensions' => TRUE,
|
||||
];
|
||||
|
||||
$this->drupalPostForm('file-test/save_upload_from_form_test', $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', ['@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(['validate', 'insert']);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests renaming when uploading over a file that already exists.
|
||||
*/
|
||||
public function testExistingRename() {
|
||||
/** @var \Drupal\Core\File\FileSystemInterface $file_system */
|
||||
$file_system = \Drupal::service('file_system');
|
||||
$edit = [
|
||||
'file_test_replace' => FILE_EXISTS_RENAME,
|
||||
'files[file_test_upload][]' => $file_system->realpath($this->image->getFileUri()),
|
||||
];
|
||||
$this->drupalPostForm('file-test/save_upload_from_form_test', $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(['validate', 'insert']);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests replacement when uploading over a file that already exists.
|
||||
*/
|
||||
public function testExistingReplace() {
|
||||
/** @var \Drupal\Core\File\FileSystemInterface $file_system */
|
||||
$file_system = \Drupal::service('file_system');
|
||||
$edit = [
|
||||
'file_test_replace' => FILE_EXISTS_REPLACE,
|
||||
'files[file_test_upload][]' => $file_system->realpath($this->image->getFileUri()),
|
||||
];
|
||||
$this->drupalPostForm('file-test/save_upload_from_form_test', $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(['validate', 'load', 'update']);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests for failure when uploading over a file that already exists.
|
||||
*/
|
||||
public function testExistingError() {
|
||||
/** @var \Drupal\Core\File\FileSystemInterface $file_system */
|
||||
$file_system = \Drupal::service('file_system');
|
||||
$edit = [
|
||||
'file_test_replace' => FILE_EXISTS_ERROR,
|
||||
'files[file_test_upload][]' => $file_system->realpath($this->image->getFileUri()),
|
||||
];
|
||||
$this->drupalPostForm('file-test/save_upload_from_form_test', $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([]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests for no failures when not uploading a file.
|
||||
*/
|
||||
public function testNoUpload() {
|
||||
$this->drupalPostForm('file-test/save_upload_from_form_test', [], t('Submit'));
|
||||
$this->assertNoRaw(t('Epic upload FAIL!'), 'Failure message not found.');
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests for log entry on failing destination.
|
||||
*/
|
||||
public 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));
|
||||
|
||||
/** @var \Drupal\Core\File\FileSystemInterface $file_system */
|
||||
$file_system = \Drupal::service('file_system');
|
||||
$edit = [
|
||||
'file_subdir' => $test_directory,
|
||||
'files[file_test_upload][]' => $file_system->realpath($this->image->getFileUri()),
|
||||
];
|
||||
|
||||
\Drupal::state()->set('file_test.disable_error_collection', TRUE);
|
||||
$this->drupalPostForm('file-test/save_upload_from_form_test', $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.', [
|
||||
'@file' => $this->image->getFilename(),
|
||||
'@destination' => 'temporary://' . $test_directory . '/' . $this->image->getFilename(),
|
||||
]), 'Found upload error log entry.');
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests that form validation does not change error messages.
|
||||
*/
|
||||
public function testErrorMessagesAreNotChanged() {
|
||||
$error = 'An error message set before _file_save_upload_from_form()';
|
||||
|
||||
/** @var \Drupal\Core\File\FileSystemInterface $file_system */
|
||||
$file_system = \Drupal::service('file_system');
|
||||
$edit = [
|
||||
'files[file_test_upload][]' => $file_system->realpath($this->image->getFileUri()),
|
||||
'error_message' => $error,
|
||||
];
|
||||
$this->drupalPostForm('file-test/save_upload_from_form_test', $edit, t('Submit'));
|
||||
$this->assertResponse(200, 'Received a 200 response for posted test file.');
|
||||
$this->assertRaw(t('You WIN!'), 'Found the success message.');
|
||||
|
||||
// Ensure the expected error message is present and the counts before and
|
||||
// after calling _file_save_upload_from_form() are correct.
|
||||
$this->assertText($error);
|
||||
$this->assertRaw('Number of error messages before _file_save_upload_from_form(): 1');
|
||||
$this->assertRaw('Number of error messages after _file_save_upload_from_form(): 1');
|
||||
|
||||
// Test that error messages are preserved when an error occurs.
|
||||
$edit = [
|
||||
'files[file_test_upload][]' => $file_system->realpath($this->image->getFileUri()),
|
||||
'error_message' => $error,
|
||||
'extensions' => 'foo',
|
||||
];
|
||||
$this->drupalPostForm('file-test/save_upload_from_form_test', $edit, t('Submit'));
|
||||
$this->assertResponse(200, 'Received a 200 response for posted test file.');
|
||||
$this->assertRaw(t('Epic upload FAIL!'), 'Found the failure message.');
|
||||
|
||||
// Ensure the expected error message is present and the counts before and
|
||||
// after calling _file_save_upload_from_form() are correct.
|
||||
$this->assertText($error);
|
||||
$this->assertRaw('Number of error messages before _file_save_upload_from_form(): 1');
|
||||
$this->assertRaw('Number of error messages after _file_save_upload_from_form(): 1');
|
||||
|
||||
// Test a successful upload with no messages.
|
||||
$edit = [
|
||||
'files[file_test_upload][]' => $file_system->realpath($this->image->getFileUri()),
|
||||
];
|
||||
$this->drupalPostForm('file-test/save_upload_from_form_test', $edit, t('Submit'));
|
||||
$this->assertResponse(200, 'Received a 200 response for posted test file.');
|
||||
$this->assertRaw(t('You WIN!'), 'Found the success message.');
|
||||
|
||||
// Ensure the error message is not present and the counts before and after
|
||||
// calling _file_save_upload_from_form() are correct.
|
||||
$this->assertNoText($error);
|
||||
$this->assertRaw('Number of error messages before _file_save_upload_from_form(): 0');
|
||||
$this->assertRaw('Number of error messages after _file_save_upload_from_form(): 0');
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests that multiple validation errors are combined in one message.
|
||||
*/
|
||||
public function testCombinedErrorMessages() {
|
||||
$textfile = current($this->drupalGetTestFiles('text'));
|
||||
$this->assertTrue(is_file($textfile->uri), 'The text file we are going to upload exists.');
|
||||
|
||||
/** @var \Drupal\Core\File\FileSystemInterface $file_system */
|
||||
$file_system = \Drupal::service('file_system');
|
||||
|
||||
// Can't use drupalPostForm() for set nonexistent fields.
|
||||
$this->drupalGet('file-test/save_upload_from_form_test');
|
||||
$client = $this->getSession()->getDriver()->getClient();
|
||||
$submit_xpath = $this->assertSession()->buttonExists('Submit')->getXpath();
|
||||
$form = $client->getCrawler()->filterXPath($submit_xpath)->form();
|
||||
$edit = [
|
||||
'allow_all_extensions' => FALSE,
|
||||
'is_image_file' => TRUE,
|
||||
'extensions' => 'jpeg',
|
||||
];
|
||||
$edit += $form->getPhpValues();
|
||||
$files['files']['file_test_upload'][0] = $file_system->realpath($this->phpfile->uri);
|
||||
$files['files']['file_test_upload'][1] = $file_system->realpath($textfile->uri);
|
||||
$client->request($form->getMethod(), $form->getUri(), $edit, $files);
|
||||
|
||||
$this->assertResponse(200, 'Received a 200 response for posted test file.');
|
||||
$this->assertRaw(t('Epic upload FAIL!'), 'Found the failure message.');
|
||||
|
||||
// Search for combined error message followed by a formatted list of messages.
|
||||
$this->assertRaw(t('One or more files could not be uploaded.') . '<div class="item-list">', 'Error message contains combined list of validation errors.');
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests highlighting of file upload field when it has an error.
|
||||
*/
|
||||
public function testUploadFieldIsHighlighted() {
|
||||
$this->assertEqual(0, count($this->cssSelect('input[name="files[file_test_upload][]"].error')), 'Successful file upload has no error.');
|
||||
|
||||
/** @var \Drupal\Core\File\FileSystemInterface $file_system */
|
||||
$file_system = \Drupal::service('file_system');
|
||||
$edit = [
|
||||
'files[file_test_upload][]' => $file_system->realpath($this->image->getFileUri()),
|
||||
'extensions' => 'foo',
|
||||
];
|
||||
$this->drupalPostForm('file-test/save_upload_from_form_test', $edit, t('Submit'));
|
||||
$this->assertResponse(200, 'Received a 200 response for posted test file.');
|
||||
$this->assertRaw(t('Epic upload FAIL!'), 'Found the failure message.');
|
||||
$this->assertEqual(1, count($this->cssSelect('input[name="files[file_test_upload][]"].error')), 'File upload field has error.');
|
||||
}
|
||||
|
||||
}
|
368
web/core/modules/file/tests/src/Functional/SaveUploadTest.php
Normal file
368
web/core/modules/file/tests/src/Functional/SaveUploadTest.php
Normal file
|
@ -0,0 +1,368 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\Tests\file\Functional;
|
||||
|
||||
use Drupal\file\Entity\File;
|
||||
use Drupal\Tests\TestFileCreationTrait;
|
||||
|
||||
/**
|
||||
* Tests the file_save_upload() function.
|
||||
*
|
||||
* @group file
|
||||
*/
|
||||
class SaveUploadTest extends FileManagedTestBase {
|
||||
|
||||
use TestFileCreationTrait {
|
||||
getTestFiles as drupalGetTestFiles;
|
||||
}
|
||||
|
||||
/**
|
||||
* Modules to enable.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public static $modules = ['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(['access site reports']);
|
||||
$this->drupalLogin($account);
|
||||
|
||||
$image_files = $this->drupalGetTestFiles('image');
|
||||
$this->image = File::create((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 = [
|
||||
'file_test_replace' => FILE_EXISTS_REPLACE,
|
||||
'files[file_test_upload]' => \Drupal::service('file_system')->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(['validate', 'insert']);
|
||||
file_test_reset();
|
||||
}
|
||||
|
||||
/**
|
||||
* Test the file_save_upload() function.
|
||||
*/
|
||||
public 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 = ['files[file_test_upload]' => \Drupal::service('file_system')->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(['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::loadMultiple().
|
||||
$files = File::loadMultiple([$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::service('file_system')->realpath($image3->uri);
|
||||
$dir = $this->randomMachineName();
|
||||
$edit = [
|
||||
'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.
|
||||
*/
|
||||
public 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 = [
|
||||
'file_test_replace' => FILE_EXISTS_REPLACE,
|
||||
'files[file_test_upload]' => \Drupal::service('file_system')->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(['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 = [
|
||||
'file_test_replace' => FILE_EXISTS_REPLACE,
|
||||
'files[file_test_upload]' => \Drupal::service('file_system')->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(['validate', 'load', 'update']);
|
||||
|
||||
// Reset the hook counters.
|
||||
file_test_reset();
|
||||
|
||||
// Now tell file_save_upload() to allow any extension.
|
||||
$edit = [
|
||||
'file_test_replace' => FILE_EXISTS_REPLACE,
|
||||
'files[file_test_upload]' => \Drupal::service('file_system')->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(['validate', 'load', 'update']);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test dangerous file handling.
|
||||
*/
|
||||
public 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 = [
|
||||
'file_test_replace' => FILE_EXISTS_REPLACE,
|
||||
'files[file_test_upload]' => \Drupal::service('file_system')->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(['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', ['@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(['validate', 'insert']);
|
||||
|
||||
// Turn off insecure uploads.
|
||||
$config->set('allow_insecure_uploads', 0)->save();
|
||||
}
|
||||
|
||||
/**
|
||||
* Test file munge handling.
|
||||
*/
|
||||
public 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 = [
|
||||
'files[file_test_upload]' => \Drupal::service('file_system')->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', ['@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(['validate', 'insert']);
|
||||
|
||||
// Ensure we don't munge files if we're allowing any extension.
|
||||
// Reset the hook counters.
|
||||
file_test_reset();
|
||||
|
||||
$edit = [
|
||||
'files[file_test_upload]' => \Drupal::service('file_system')->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', ['@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(['validate', 'insert']);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test renaming when uploading over a file that already exists.
|
||||
*/
|
||||
public function testExistingRename() {
|
||||
$edit = [
|
||||
'file_test_replace' => FILE_EXISTS_RENAME,
|
||||
'files[file_test_upload]' => \Drupal::service('file_system')->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(['validate', 'insert']);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test replacement when uploading over a file that already exists.
|
||||
*/
|
||||
public function testExistingReplace() {
|
||||
$edit = [
|
||||
'file_test_replace' => FILE_EXISTS_REPLACE,
|
||||
'files[file_test_upload]' => \Drupal::service('file_system')->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(['validate', 'load', 'update']);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test for failure when uploading over a file that already exists.
|
||||
*/
|
||||
public function testExistingError() {
|
||||
$edit = [
|
||||
'file_test_replace' => FILE_EXISTS_ERROR,
|
||||
'files[file_test_upload]' => \Drupal::service('file_system')->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([]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test for no failures when not uploading a file.
|
||||
*/
|
||||
public function testNoUpload() {
|
||||
$this->drupalPostForm('file-test/upload', [], t('Submit'));
|
||||
$this->assertNoRaw(t('Epic upload FAIL!'), 'Failure message not found.');
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests for log entry on failing destination.
|
||||
*/
|
||||
public 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 = [
|
||||
'file_subdir' => $test_directory,
|
||||
'files[file_test_upload]' => \Drupal::service('file_system')->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.', [
|
||||
'@file' => $this->image->getFilename(),
|
||||
'@destination' => 'temporary://' . $test_directory . '/' . $this->image->getFilename(),
|
||||
]), 'Found upload error log entry.');
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,59 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\Tests\file\Functional\Update;
|
||||
|
||||
use Drupal\FunctionalTests\Update\UpdatePathTestBase;
|
||||
|
||||
/**
|
||||
* Tests File update path.
|
||||
*
|
||||
* @group legacy
|
||||
*/
|
||||
class FileUpdateTest extends UpdatePathTestBase {
|
||||
|
||||
/**
|
||||
* Modules to enable after the database is loaded.
|
||||
*/
|
||||
protected static $modules = ['file'];
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function setDatabaseDumpFiles() {
|
||||
$this->databaseDumpFiles = [
|
||||
__DIR__ . '/../../../../../system/tests/fixtures/update/drupal-8.bare.standard.php.gz',
|
||||
__DIR__ . '/../../../../tests/fixtures/update/drupal-8.file_formatters_update_2677990.php',
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests file_update_8001().
|
||||
*/
|
||||
public function testPostUpdate8001() {
|
||||
$view = 'core.entity_view_display.node.article.default';
|
||||
|
||||
// Check that field_file_generic formatter has no
|
||||
// use_description_as_link_text setting.
|
||||
$formatter_settings = $this->config($view)->get('content.field_file_generic_2677990.settings');
|
||||
$this->assertTrue(!isset($formatter_settings['use_description_as_link_text']));
|
||||
|
||||
// Check that field_file_table formatter has no use_description_as_link_text
|
||||
// setting.
|
||||
$formatter_settings = $this->config($view)->get('content.field_file_table_2677990.settings');
|
||||
$this->assertTrue(!isset($formatter_settings['use_description_as_link_text']));
|
||||
|
||||
// Run updates.
|
||||
$this->runUpdates();
|
||||
|
||||
// Check that field_file_generic formatter has a
|
||||
// use_description_as_link_text setting which value is TRUE.
|
||||
$formatter_settings = $this->config($view)->get('content.field_file_generic_2677990.settings');
|
||||
$this->assertEqual($formatter_settings, ['use_description_as_link_text' => TRUE]);
|
||||
|
||||
// Check that field_file_table formatter has a use_description_as_link_text
|
||||
// setting which value is FALSE.
|
||||
$formatter_settings = $this->config($view)->get('content.field_file_table_2677990.settings');
|
||||
$this->assertEqual($formatter_settings, ['use_description_as_link_text' => FALSE]);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,43 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\Tests\file\Functional\Update;
|
||||
|
||||
use Drupal\FunctionalTests\Update\UpdatePathTestBase;
|
||||
|
||||
/**
|
||||
* Tests the upgrade path for setting the file usage deletion configuration.
|
||||
*
|
||||
* @see https://www.drupal.org/node/2801777
|
||||
*
|
||||
* @group Update
|
||||
* @group legacy
|
||||
*/
|
||||
class FileUsageTemporaryDeletionConfigurationUpdateTest extends UpdatePathTestBase {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $modules = ['file'];
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function setDatabaseDumpFiles() {
|
||||
$this->databaseDumpFiles = [
|
||||
__DIR__ . '/../../../../../system/tests/fixtures/update/drupal-8.bare.standard.php.gz',
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests that make_unused_managed_files_temporary conditions are correct.
|
||||
*
|
||||
* Verify that the before and after conditions for the variable are correct.
|
||||
*/
|
||||
public function testUpdateHookN() {
|
||||
$this->assertIdentical($this->config('file.settings')->get('make_unused_managed_files_temporary'), NULL);
|
||||
$this->runUpdates();
|
||||
$this->assertIdentical($this->config('file.settings')->get('make_unused_managed_files_temporary'), FALSE);
|
||||
$this->assertResponse('200');
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,96 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\Tests\file\Functional\Views;
|
||||
|
||||
use Drupal\field\Entity\FieldConfig;
|
||||
use Drupal\file\Entity\File;
|
||||
use Drupal\Tests\views\Functional\ViewTestBase;
|
||||
use Drupal\views\Views;
|
||||
use Drupal\views\Tests\ViewTestData;
|
||||
use Drupal\field\Entity\FieldStorageConfig;
|
||||
|
||||
/**
|
||||
* Tests file on user relationship handler.
|
||||
*
|
||||
* @group file
|
||||
*/
|
||||
class RelationshipUserFileDataTest extends ViewTestBase {
|
||||
|
||||
/**
|
||||
* Modules to install.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public static $modules = ['file', 'file_test_views', 'user'];
|
||||
|
||||
/**
|
||||
* Views used by this test.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public static $testViews = ['test_file_user_file_data'];
|
||||
|
||||
protected function setUp($import_test_views = TRUE) {
|
||||
parent::setUp($import_test_views);
|
||||
|
||||
// Create the user profile field and instance.
|
||||
FieldStorageConfig::create([
|
||||
'entity_type' => 'user',
|
||||
'field_name' => 'user_file',
|
||||
'type' => 'file',
|
||||
'translatable' => '0',
|
||||
])->save();
|
||||
FieldConfig::create([
|
||||
'label' => 'User File',
|
||||
'description' => '',
|
||||
'field_name' => 'user_file',
|
||||
'entity_type' => 'user',
|
||||
'bundle' => 'user',
|
||||
'required' => 0,
|
||||
])->save();
|
||||
|
||||
ViewTestData::createTestViews(get_class($this), ['file_test_views']);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests using the views file relationship.
|
||||
*/
|
||||
public function testViewsHandlerRelationshipUserFileData() {
|
||||
$file = File::create([
|
||||
'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->getDependencies());
|
||||
$this->executeView($view);
|
||||
$expected_result = [
|
||||
[
|
||||
'file_managed_user__user_file_fid' => '2',
|
||||
],
|
||||
];
|
||||
$column_map = ['file_managed_user__user_file_fid' => 'file_managed_user__user_file_fid'];
|
||||
$this->assertIdenticalResultset($view, $expected_result, $column_map);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,49 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\Tests\file\FunctionalJavascript;
|
||||
|
||||
use Drupal\FunctionalJavascriptTests\WebDriverTestBase;
|
||||
use Drupal\Tests\file\Functional\FileFieldCreationTrait;
|
||||
use Drupal\Tests\TestFileCreationTrait;
|
||||
|
||||
/**
|
||||
* Tests validation functions such as file type, max file size, max size per
|
||||
* node, and required.
|
||||
*
|
||||
* @group file
|
||||
*/
|
||||
class FileFieldValidateTest extends WebDriverTestBase {
|
||||
|
||||
use FileFieldCreationTrait;
|
||||
use TestFileCreationTrait;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static $modules = ['node', 'file'];
|
||||
|
||||
/**
|
||||
* Test the validation message is displayed only once for ajax uploads.
|
||||
*/
|
||||
public function testAjaxValidationMessage() {
|
||||
$field_name = strtolower($this->randomMachineName());
|
||||
$this->drupalCreateContentType(['type' => 'article', 'name' => 'Article']);
|
||||
$this->createFileField($field_name, 'node', 'article', [], ['file_extensions' => 'txt']);
|
||||
|
||||
$this->drupalLogin($this->drupalCreateUser([
|
||||
'access content',
|
||||
'create article content',
|
||||
]));
|
||||
|
||||
$page = $this->getSession()->getPage();
|
||||
$this->drupalGet('node/add/article');
|
||||
$image_file = current($this->getTestFiles('image'));
|
||||
$image_path = $this->container->get('file_system')->realpath($image_file->uri);
|
||||
$page->attachFileToField('files[' . $field_name . '_0]', $image_path);
|
||||
$elements = $page->waitFor(10, function () use ($page) {
|
||||
return $page->findAll('css', '.messages--error');
|
||||
});
|
||||
$this->assertCount(1, $elements, 'Ajax validation messages are displayed once.');
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,101 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\Tests\file\FunctionalJavascript;
|
||||
|
||||
use Drupal\Core\Database\Database;
|
||||
use Drupal\FunctionalJavascriptTests\WebDriverTestBase;
|
||||
|
||||
/**
|
||||
* Tests the 'managed_file' element type.
|
||||
*
|
||||
* @group file
|
||||
*/
|
||||
class FileManagedFileElementTest extends WebDriverTestBase {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $modules = ['node', 'file', 'file_module_test', 'field_ui'];
|
||||
|
||||
/**
|
||||
* A user with administration permissions.
|
||||
*
|
||||
* @var \Drupal\user\UserInterface
|
||||
*/
|
||||
protected $adminUser;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function setUp() {
|
||||
parent::setUp();
|
||||
$this->adminUser = $this->drupalCreateUser(['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(['type' => 'article', 'name' => 'Article']);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the managed_file element type.
|
||||
*/
|
||||
public function testManagedFile() {
|
||||
// Perform the tests with all permutations of $form['#tree'],
|
||||
// $element['#extended'], and $element['#multiple'].
|
||||
$filename = \Drupal::service('file_system')->tempnam('temporary://', "testManagedFile") . '.txt';
|
||||
file_put_contents($filename, $this->randomString(128));
|
||||
foreach ([0, 1] as $tree) {
|
||||
foreach ([0, 1] as $extended) {
|
||||
foreach ([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 . ']';
|
||||
|
||||
// Now, test the Upload and Remove buttons, with Ajax.
|
||||
// Upload, then Submit.
|
||||
$last_fid_prior = $this->getLastFileId();
|
||||
$this->drupalGet($path);
|
||||
$this->getSession()->getPage()->attachFileToField($file_field_name, $this->container->get('file_system')->realpath($filename));
|
||||
$uploaded_file = $this->assertSession()->waitForElement('css', '.file--mime-text-plain');
|
||||
$this->assertNotEmpty($uploaded_file);
|
||||
$last_fid = $this->getLastFileId();
|
||||
$this->assertGreaterThan($last_fid_prior, $last_fid, 'New file got uploaded.');
|
||||
$this->drupalPostForm(NULL, [], t('Save'));
|
||||
|
||||
// Remove, then Submit.
|
||||
$remove_button_title = $multiple ? t('Remove selected') : t('Remove');
|
||||
$this->drupalGet($path . '/' . $last_fid);
|
||||
if ($multiple) {
|
||||
$selected_checkbox = ($tree ? 'nested[file]' : 'file') . '[file_' . $last_fid . '][selected]';
|
||||
$this->getSession()->getPage()->checkField($selected_checkbox);
|
||||
}
|
||||
$this->getSession()->getPage()->pressButton($remove_button_title);
|
||||
$this->assertSession()->assertWaitOnAjaxRequest();
|
||||
$this->drupalPostForm(NULL, [], t('Save'));
|
||||
$this->assertSession()->responseContains(t('The file ids are %fids.', ['%fids' => '']));
|
||||
|
||||
// Upload, then Remove, then Submit.
|
||||
$this->drupalGet($path);
|
||||
$this->getSession()->getPage()->attachFileToField($file_field_name, $this->container->get('file_system')->realpath($filename));
|
||||
$uploaded_file = $this->assertSession()->waitForElement('css', '.file--mime-text-plain');
|
||||
$this->assertNotEmpty($uploaded_file);
|
||||
if ($multiple) {
|
||||
$selected_checkbox = ($tree ? 'nested[file]' : 'file') . '[file_' . $this->getLastFileId() . '][selected]';
|
||||
$this->getSession()->getPage()->checkField($selected_checkbox);
|
||||
}
|
||||
$this->getSession()->getPage()->pressButton($remove_button_title);
|
||||
$this->assertSession()->assertWaitOnAjaxRequest();
|
||||
|
||||
$this->drupalPostForm(NULL, [], t('Save'));
|
||||
$this->assertSession()->responseContains(t('The file ids are %fids.', ['%fids' => '']));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the fid of the last inserted file.
|
||||
*/
|
||||
protected function getLastFileId() {
|
||||
return (int) Database::getConnection()->query('SELECT MAX(fid) FROM {file_managed}')->fetchField();
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,119 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\Tests\file\FunctionalJavascript;
|
||||
|
||||
use Drupal\Component\Utility\Bytes;
|
||||
use Drupal\FunctionalJavascriptTests\WebDriverTestBase;
|
||||
use Drupal\Tests\TestFileCreationTrait;
|
||||
use Drupal\Tests\file\Functional\FileFieldCreationTrait;
|
||||
|
||||
/**
|
||||
* Tests uploading a file that exceeds the maximum file size.
|
||||
*
|
||||
* @group file
|
||||
*/
|
||||
class MaximumFileSizeExceededUploadTest extends WebDriverTestBase {
|
||||
|
||||
use FileFieldCreationTrait;
|
||||
use TestFileCreationTrait;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static $modules = ['node', 'file'];
|
||||
|
||||
/**
|
||||
* The file system service.
|
||||
*
|
||||
* @var \Drupal\Core\File\FileSystemInterface
|
||||
*/
|
||||
protected $fileSystem;
|
||||
|
||||
/**
|
||||
* A test user.
|
||||
*
|
||||
* @var \Drupal\user\UserInterface
|
||||
*/
|
||||
protected $user;
|
||||
|
||||
/**
|
||||
* The original value of the 'display_errors' PHP configuration option.
|
||||
*
|
||||
* @todo Remove this when issue #2905597 is fixed.
|
||||
* @see https://www.drupal.org/node/2905597
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $originalDisplayErrorsValue;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function setUp() {
|
||||
parent::setUp();
|
||||
|
||||
$this->fileSystem = $this->container->get('file_system');
|
||||
|
||||
// Create the Article node type.
|
||||
$this->drupalCreateContentType(['type' => 'article', 'name' => 'Article']);
|
||||
|
||||
// Attach a file field to the node type.
|
||||
$field_settings = ['file_extensions' => 'txt'];
|
||||
$this->createFileField('field_file', 'node', 'article', [], $field_settings);
|
||||
|
||||
// Log in as a content author who can create Articles.
|
||||
$this->user = $this->drupalCreateUser([
|
||||
'access content',
|
||||
'create article content',
|
||||
]);
|
||||
$this->drupalLogin($this->user);
|
||||
|
||||
// Disable the displaying of errors, so that the AJAX responses are not
|
||||
// contaminated with error messages about exceeding the maximum POST size.
|
||||
// @todo Remove this when issue #2905597 is fixed.
|
||||
// @see https://www.drupal.org/node/2905597
|
||||
$this->originalDisplayErrorsValue = ini_set('display_errors', '0');
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function tearDown() {
|
||||
// Restore the displaying of errors to the original value.
|
||||
// @todo Remove this when issue #2905597 is fixed.
|
||||
// @see https://www.drupal.org/node/2905597
|
||||
ini_set('display_errors', $this->originalDisplayErrorsValue);
|
||||
|
||||
parent::tearDown();
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests that uploading files exceeding maximum size are handled correctly.
|
||||
*/
|
||||
public function testUploadFileExceedingMaximumFileSize() {
|
||||
$session = $this->getSession();
|
||||
|
||||
// Create a test file that exceeds the maximum POST size with 1 kilobyte.
|
||||
$post_max_size = Bytes::toInt(ini_get('post_max_size'));
|
||||
$invalid_file = $this->generateFile('exceeding_post_max_size', ceil(($post_max_size + 1024) / 1024), 1024);
|
||||
|
||||
// Go to the node creation form and try to upload the test file.
|
||||
$this->drupalGet('node/add/article');
|
||||
$page = $session->getPage();
|
||||
$page->attachFileToField("files[field_file_0]", $this->fileSystem->realpath($invalid_file));
|
||||
|
||||
// An error message should appear informing the user that the file exceeded
|
||||
// the maximum file size.
|
||||
$this->assertSession()->waitForElement('css', '.messages--error');
|
||||
// The error message includes the actual file size limit which depends on
|
||||
// the current environment, so we check for a part of the message.
|
||||
$this->assertSession()->pageTextContains('An unrecoverable error occurred. The uploaded file likely exceeded the maximum file size');
|
||||
|
||||
// Now upload a valid file and check that the error message disappears.
|
||||
$valid_file = $this->generateFile('not_exceeding_post_max_size', 8, 8);
|
||||
$page->attachFileToField("files[field_file_0]", $this->fileSystem->realpath($valid_file));
|
||||
$this->assertSession()->waitForElement('named', ['id_or_name', 'field_file_0_remove_button']);
|
||||
$this->assertSession()->elementNotExists('css', '.messages--error');
|
||||
}
|
||||
|
||||
}
|
|
@ -93,7 +93,7 @@ class AccessTest extends KernelTestBase {
|
|||
\Drupal::currentUser()->setAccount($this->user1);
|
||||
/** @var \Drupal\file\FileInterface $file */
|
||||
$file = File::create([
|
||||
'uri' => 'public://test.png'
|
||||
'uri' => 'public://test.png',
|
||||
]);
|
||||
// While creating a file entity access will be allowed for create-only
|
||||
// fields.
|
||||
|
@ -123,4 +123,28 @@ class AccessTest extends KernelTestBase {
|
|||
$this->assertFalse($this->file->access('create'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests cacheability metadata.
|
||||
*/
|
||||
public function testFileCacheability() {
|
||||
$file = File::create([
|
||||
'filename' => 'green-scarf',
|
||||
'uri' => 'private://green-scarf',
|
||||
'filemime' => 'text/plain',
|
||||
'status' => FILE_STATUS_PERMANENT,
|
||||
]);
|
||||
$file->save();
|
||||
\Drupal::service('session')->set('anonymous_allowed_file_ids', [$file->id() => $file->id()]);
|
||||
|
||||
$account = User::getAnonymousUser();
|
||||
$file->setOwnerId($account->id())->save();
|
||||
$this->assertSame(['session', 'user'], $file->access('view', $account, TRUE)->getCacheContexts());
|
||||
$this->assertSame(['session', 'user'], $file->access('download', $account, TRUE)->getCacheContexts());
|
||||
|
||||
$account = $this->user1;
|
||||
$file->setOwnerId($account->id())->save();
|
||||
$this->assertSame(['user'], $file->access('view', $account, TRUE)->getCacheContexts());
|
||||
$this->assertSame(['user'], $file->access('download', $account, TRUE)->getCacheContexts());
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -0,0 +1,91 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\Tests\file\Kernel;
|
||||
|
||||
use Drupal\Core\Field\FieldItemInterface;
|
||||
use Drupal\Core\TypedData\DataDefinitionInterface;
|
||||
use Drupal\file\FileInterface;
|
||||
use Drupal\file\ComputedFileUrl;
|
||||
use Drupal\KernelTests\KernelTestBase;
|
||||
|
||||
/**
|
||||
* @coversDefaultClass \Drupal\file\ComputedFileUrl
|
||||
*
|
||||
* @group file
|
||||
*/
|
||||
class ComputedFileUrlTest extends KernelTestBase {
|
||||
|
||||
/**
|
||||
* The test URL to use.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $testUrl = 'public://druplicon.txt';
|
||||
|
||||
/**
|
||||
* @covers ::getValue
|
||||
*/
|
||||
public function testGetValue() {
|
||||
$entity = $this->prophesize(FileInterface::class);
|
||||
$entity->getFileUri()
|
||||
->willReturn($this->testUrl);
|
||||
|
||||
$parent = $this->prophesize(FieldItemInterface::class);
|
||||
$parent->getEntity()
|
||||
->shouldBeCalledTimes(2)
|
||||
->willReturn($entity->reveal());
|
||||
|
||||
$definition = $this->prophesize(DataDefinitionInterface::class);
|
||||
|
||||
$typed_data = new ComputedFileUrl($definition->reveal(), $this->randomMachineName(), $parent->reveal());
|
||||
|
||||
$expected = base_path() . $this->siteDirectory . '/files/druplicon.txt';
|
||||
|
||||
$this->assertSame($expected, $typed_data->getValue());
|
||||
// Do this a second time to confirm the same value is returned but the value
|
||||
// isn't retrieved from the parent entity again.
|
||||
$this->assertSame($expected, $typed_data->getValue());
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers ::setValue
|
||||
*/
|
||||
public function testSetValue() {
|
||||
$name = $this->randomMachineName();
|
||||
$parent = $this->prophesize(FieldItemInterface::class);
|
||||
$parent->onChange($name)
|
||||
->shouldBeCalled();
|
||||
|
||||
$definition = $this->prophesize(DataDefinitionInterface::class);
|
||||
$typed_data = new ComputedFileUrl($definition->reveal(), $name, $parent->reveal());
|
||||
|
||||
// Setting the value explicitly should mean the parent entity is never
|
||||
// called into.
|
||||
$typed_data->setValue($this->testUrl);
|
||||
|
||||
$this->assertSame($this->testUrl, $typed_data->getValue());
|
||||
// Do this a second time to confirm the same value is returned but the value
|
||||
// isn't retrieved from the parent entity again.
|
||||
$this->assertSame($this->testUrl, $typed_data->getValue());
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers ::setValue
|
||||
*/
|
||||
public function testSetValueNoNotify() {
|
||||
$name = $this->randomMachineName();
|
||||
$parent = $this->prophesize(FieldItemInterface::class);
|
||||
$parent->onChange($name)
|
||||
->shouldNotBeCalled();
|
||||
|
||||
$definition = $this->prophesize(DataDefinitionInterface::class);
|
||||
$typed_data = new ComputedFileUrl($definition->reveal(), $name, $parent->reveal());
|
||||
|
||||
// Setting the value should explicitly should mean the parent entity is
|
||||
// never called into.
|
||||
$typed_data->setValue($this->testUrl, FALSE);
|
||||
|
||||
$this->assertSame($this->testUrl, $typed_data->getValue());
|
||||
}
|
||||
|
||||
}
|
|
@ -10,6 +10,7 @@ use Drupal\file\Entity\File;
|
|||
* @group file
|
||||
*/
|
||||
class CopyTest extends FileManagedUnitTestBase {
|
||||
|
||||
/**
|
||||
* Test file copying in the normal, base case.
|
||||
*/
|
||||
|
|
|
@ -10,6 +10,7 @@ use Drupal\file\Entity\File;
|
|||
* @group file
|
||||
*/
|
||||
class DeleteTest extends FileManagedUnitTestBase {
|
||||
|
||||
/**
|
||||
* Tries deleting a normal file (as opposed to a directory, symlink, etc).
|
||||
*/
|
||||
|
@ -28,6 +29,11 @@ class DeleteTest extends FileManagedUnitTestBase {
|
|||
* Tries deleting a file that is in use.
|
||||
*/
|
||||
public function testInUse() {
|
||||
// This test expects unused managed files to be marked as a temporary file
|
||||
// and then deleted up by file_cron().
|
||||
$this->config('file.settings')
|
||||
->set('make_unused_managed_files_temporary', TRUE)
|
||||
->save();
|
||||
$file = $this->createFile();
|
||||
$file_usage = $this->container->get('file.usage');
|
||||
$file_usage->add($file, 'testing', 'test', 1);
|
||||
|
|
|
@ -10,6 +10,7 @@ use Drupal\field\Entity\FieldConfig;
|
|||
use Drupal\Tests\field\Kernel\FieldKernelTestBase;
|
||||
use Drupal\field\Entity\FieldStorageConfig;
|
||||
use Drupal\file\Entity\File;
|
||||
use Drupal\user\Entity\Role;
|
||||
|
||||
/**
|
||||
* Tests using entity fields of the file field type.
|
||||
|
@ -42,6 +43,14 @@ class FileItemTest extends FieldKernelTestBase {
|
|||
protected function setUp() {
|
||||
parent::setUp();
|
||||
|
||||
$this->installEntitySchema('user');
|
||||
$this->installConfig(['user']);
|
||||
// Give anonymous users permission to access content, so they can view and
|
||||
// download public files.
|
||||
$anonymous_role = Role::load(Role::ANONYMOUS_ID);
|
||||
$anonymous_role->grantPermission('access content');
|
||||
$anonymous_role->save();
|
||||
|
||||
$this->installEntitySchema('file');
|
||||
$this->installSchema('file', ['file_usage']);
|
||||
|
||||
|
|
|
@ -78,9 +78,9 @@ class FileItemValidationTest extends KernelTestBase {
|
|||
'default' => [
|
||||
'files' => [
|
||||
'test.txt' => str_repeat('a', 3000),
|
||||
]
|
||||
]
|
||||
]
|
||||
],
|
||||
],
|
||||
],
|
||||
]);
|
||||
|
||||
// Test for max filesize.
|
||||
|
@ -95,7 +95,7 @@ class FileItemValidationTest extends KernelTestBase {
|
|||
'uid' => $this->user->id(),
|
||||
'field_test_file' => [
|
||||
'target_id' => $file->id(),
|
||||
]
|
||||
],
|
||||
]);
|
||||
$result = $entity_test->validate();
|
||||
$this->assertCount(2, $result);
|
||||
|
@ -104,6 +104,18 @@ class FileItemValidationTest extends KernelTestBase {
|
|||
$this->assertEquals('The file is <em class="placeholder">2.93 KB</em> exceeding the maximum file size of <em class="placeholder">2 KB</em>.', (string) $result->get(0)->getMessage());
|
||||
$this->assertEquals('field_test_file.0', $result->get(1)->getPropertyPath());
|
||||
$this->assertEquals('Only files with the following extensions are allowed: <em class="placeholder">jpg|png</em>.', (string) $result->get(1)->getMessage());
|
||||
|
||||
// Refer to a file that does not exist.
|
||||
$entity_test = EntityTest::create([
|
||||
'uid' => $this->user->id(),
|
||||
'field_test_file' => [
|
||||
'target_id' => 2,
|
||||
],
|
||||
]);
|
||||
$result = $entity_test->validate();
|
||||
$this->assertCount(1, $result);
|
||||
$this->assertEquals('field_test_file.0.target_id', $result->get(0)->getPropertyPath());
|
||||
$this->assertEquals('The referenced entity (<em class="placeholder">file</em>: <em class="placeholder">2</em>) does not exist.', (string) $result->get(0)->getMessage());
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
40
web/core/modules/file/tests/src/Kernel/FileUriItemTest.php
Normal file
40
web/core/modules/file/tests/src/Kernel/FileUriItemTest.php
Normal file
|
@ -0,0 +1,40 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\Tests\file\Kernel;
|
||||
|
||||
use Drupal\file\Entity\File;
|
||||
|
||||
/**
|
||||
* File URI field item test.
|
||||
*
|
||||
* @group file
|
||||
*
|
||||
* @see \Drupal\file\Plugin\Field\FieldType\FileUriItem
|
||||
* @see \Drupal\file\FileUrl
|
||||
*/
|
||||
class FileUriItemTest extends FileManagedUnitTestBase {
|
||||
|
||||
/**
|
||||
* Tests the file entity override of the URI field.
|
||||
*/
|
||||
public function testCustomFileUriField() {
|
||||
$uri = 'public://druplicon.txt';
|
||||
|
||||
// Create a new file entity.
|
||||
$file = File::create([
|
||||
'uid' => 1,
|
||||
'filename' => 'druplicon.txt',
|
||||
'uri' => $uri,
|
||||
'filemime' => 'text/plain',
|
||||
'status' => FILE_STATUS_PERMANENT,
|
||||
]);
|
||||
file_put_contents($file->getFileUri(), 'hello world');
|
||||
|
||||
$file->save();
|
||||
|
||||
$this->assertSame($uri, $file->uri->value);
|
||||
$expected_url = base_path() . $this->siteDirectory . '/files/druplicon.txt';
|
||||
$this->assertSame($expected_url, $file->uri->url);
|
||||
}
|
||||
|
||||
}
|
27
web/core/modules/file/tests/src/Kernel/FileUrlTest.php
Normal file
27
web/core/modules/file/tests/src/Kernel/FileUrlTest.php
Normal file
|
@ -0,0 +1,27 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\Tests\file\Kernel;
|
||||
|
||||
/**
|
||||
* Tests the file url.
|
||||
*
|
||||
* @group file
|
||||
*/
|
||||
class FileUrlTest extends FileManagedUnitTestBase {
|
||||
|
||||
/**
|
||||
* Test public files with a different host name from settings.
|
||||
*/
|
||||
public function testFilesUrlWithDifferentHostName() {
|
||||
$test_base_url = 'http://www.example.com/cdn';
|
||||
$this->setSetting('file_public_base_url', $test_base_url);
|
||||
$filepath = file_create_filename('test.txt', '');
|
||||
$directory_uri = 'public://' . dirname($filepath);
|
||||
file_prepare_directory($directory_uri, FILE_CREATE_DIRECTORY);
|
||||
$file = $this->createFile($filepath, NULL, 'public');
|
||||
$url = file_create_url($file->getFileUri());
|
||||
$expected_url = $test_base_url . '/' . basename($filepath);
|
||||
$this->assertSame($url, $expected_url);
|
||||
}
|
||||
|
||||
}
|
|
@ -10,6 +10,7 @@ use Drupal\file\Entity\File;
|
|||
* @group file
|
||||
*/
|
||||
class LoadTest extends FileManagedUnitTestBase {
|
||||
|
||||
/**
|
||||
* Try to load a non-existent file by fid.
|
||||
*/
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\Tests\file\Kernel\Migrate\d6;
|
||||
|
||||
use Drupal\migrate\Plugin\MigrationInterface;
|
||||
|
||||
/**
|
||||
|
@ -29,7 +30,7 @@ trait FileMigrationTestTrait {
|
|||
// Make sure we have a single trailing slash.
|
||||
$source = $migration->getSourceConfiguration();
|
||||
$source['site_path'] = 'core/modules/simpletest';
|
||||
$source['constants']['source_base_path'] = \Drupal::root() . '/';
|
||||
$source['constants']['source_base_path'] = $this->root . '/';
|
||||
$migration->set('source', $source);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,7 +2,6 @@
|
|||
|
||||
namespace Drupal\Tests\file\Kernel\Migrate\d6;
|
||||
|
||||
use Drupal\Component\Utility\Random;
|
||||
use Drupal\file\Entity\File;
|
||||
use Drupal\file\FileInterface;
|
||||
use Drupal\KernelTests\KernelTestBase;
|
||||
|
@ -11,7 +10,7 @@ use Drupal\Tests\migrate\Kernel\MigrateDumpAlterInterface;
|
|||
use Drupal\Tests\migrate_drupal\Kernel\d6\MigrateDrupal6TestBase;
|
||||
|
||||
/**
|
||||
* file migration.
|
||||
* Test file migration.
|
||||
*
|
||||
* @group migrate_drupal_6
|
||||
*/
|
||||
|
@ -68,8 +67,10 @@ class MigrateFileTest extends MigrateDrupal6TestBase implements MigrateDumpAlter
|
|||
public function testFiles() {
|
||||
$this->assertEntity(1, 'Image1.png', '39325', 'public://image-1.png', 'image/png', '1');
|
||||
$this->assertEntity(2, 'Image2.jpg', '1831', 'public://image-2.jpg', 'image/jpeg', '1');
|
||||
$this->assertEntity(3, 'Image-test.gif', '183', 'public://image-test.gif', 'image/jpeg', '1');
|
||||
$this->assertEntity(3, 'image-3.jpg', '1831', 'public://image-3.jpg', 'image/jpeg', '1');
|
||||
$this->assertEntity(4, 'html-1.txt', '24', 'public://html-1.txt', 'text/plain', '1');
|
||||
// Ensure temporary file was not migrated.
|
||||
$this->assertNull(File::load(6));
|
||||
|
||||
$map_table = $this->getMigration('d6_file')->getIdMap()->mapTableName();
|
||||
$map = \Drupal::database()
|
||||
|
@ -81,10 +82,9 @@ class MigrateFileTest extends MigrateDrupal6TestBase implements MigrateDumpAlter
|
|||
// The 4 files from the fixture.
|
||||
1 => '1',
|
||||
2 => '2',
|
||||
// The file updated in migrateDumpAlter().
|
||||
3 => '3',
|
||||
5 => '4',
|
||||
// The file updated in migrateDumpAlter().
|
||||
6 => NULL,
|
||||
// The file created in migrateDumpAlter().
|
||||
7 => '4',
|
||||
];
|
||||
|
@ -124,10 +124,9 @@ class MigrateFileTest extends MigrateDrupal6TestBase implements MigrateDumpAlter
|
|||
// The 4 files from the fixture.
|
||||
1 => '5',
|
||||
2 => '6',
|
||||
// The file updated in migrateDumpAlter().
|
||||
3 => '7',
|
||||
5 => '8',
|
||||
// The file updated in migrateDumpAlter().
|
||||
6 => NULL,
|
||||
// The files created in migrateDumpAlter().
|
||||
7 => '8',
|
||||
8 => '8',
|
||||
|
@ -142,33 +141,17 @@ class MigrateFileTest extends MigrateDrupal6TestBase implements MigrateDumpAlter
|
|||
$this->assertEquals(8, count(File::loadMultiple()));
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
* A filename based upon the test.
|
||||
*/
|
||||
public static function getUniqueFilename() {
|
||||
return static::$tempFilename;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static function migrateDumpAlter(KernelTestBase $test) {
|
||||
// Creates a random filename and updates the source database.
|
||||
$random = new Random();
|
||||
$temp_directory = file_directory_temp();
|
||||
file_prepare_directory($temp_directory, FILE_CREATE_DIRECTORY);
|
||||
static::$tempFilename = $test->getDatabasePrefix() . $random->name() . '.jpg';
|
||||
$file_path = $temp_directory . '/' . static::$tempFilename;
|
||||
file_put_contents($file_path, '');
|
||||
|
||||
$db = Database::getConnection('default', 'migrate');
|
||||
|
||||
$db->update('files')
|
||||
->condition('fid', 6)
|
||||
->condition('fid', 3)
|
||||
->fields([
|
||||
'filename' => static::$tempFilename,
|
||||
'filepath' => $file_path,
|
||||
'filename' => 'image-3.jpg',
|
||||
'filepath' => 'core/modules/simpletest/files/image-3.jpg',
|
||||
])
|
||||
->execute();
|
||||
|
||||
|
|
|
@ -44,7 +44,7 @@ class MigrateUploadEntityDisplayTest extends MigrateDrupal6TestBase {
|
|||
$component = $display->getComponent('upload');
|
||||
$this->assertTrue(is_null($component));
|
||||
|
||||
$this->assertIdentical(['node', 'page', 'default', 'upload'], $this->getMigration('d6_upload_entity_display')->getIdMap()->lookupDestinationID(['page']));
|
||||
$this->assertIdentical(['node', 'page', 'default', 'upload'], $this->getMigration('d6_upload_entity_display')->getIdMap()->lookupDestinationId(['page']));
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -44,7 +44,7 @@ class MigrateUploadEntityFormDisplayTest extends MigrateDrupal6TestBase {
|
|||
$component = $display->getComponent('upload');
|
||||
$this->assertTrue(is_null($component));
|
||||
|
||||
$this->assertIdentical(['node', 'page', 'default', 'upload'], $this->getMigration('d6_upload_entity_form_display')->getIdMap()->lookupDestinationID(['page']));
|
||||
$this->assertIdentical(['node', 'page', 'default', 'upload'], $this->getMigration('d6_upload_entity_form_display')->getIdMap()->lookupDestinationId(['page']));
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -31,7 +31,7 @@ class MigrateUploadFieldTest extends MigrateDrupal6TestBase {
|
|||
public function testUpload() {
|
||||
$field_storage = FieldStorageConfig::load('node.upload');
|
||||
$this->assertIdentical('node.upload', $field_storage->id());
|
||||
$this->assertIdentical(['node', 'upload'], $this->getMigration('d6_upload_field')->getIdMap()->lookupDestinationID(['']));
|
||||
$this->assertIdentical(['node', 'upload'], $this->getMigration('d6_upload_field')->getIdMap()->lookupDestinationId(['']));
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -43,7 +43,7 @@ class MigrateUploadInstanceTest extends MigrateDrupal6TestBase {
|
|||
$field = FieldConfig::load('node.article.upload');
|
||||
$this->assertTrue(is_null($field));
|
||||
|
||||
$this->assertIdentical(['node', 'page', 'upload'], $this->getMigration('d6_upload_field_instance')->getIdMap()->lookupDestinationID(['page']));
|
||||
$this->assertIdentical(['node', 'page', 'upload'], $this->getMigration('d6_upload_field_instance')->getIdMap()->lookupDestinationId(['page']));
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -16,7 +16,7 @@ class MigrateUploadTest extends MigrateDrupal6TestBase {
|
|||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static $modules = ['menu_ui'];
|
||||
public static $modules = ['language', 'menu_ui'];
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
|
@ -51,7 +51,7 @@ class MigrateUploadTest extends MigrateDrupal6TestBase {
|
|||
}
|
||||
$this->prepareMigrations($id_mappings);
|
||||
|
||||
$this->migrateContent();
|
||||
$this->migrateContent(['translations']);
|
||||
// Since we are only testing a subset of the file migration, do not check
|
||||
// that the full file migration has been run.
|
||||
$migration = $this->getMigration('d6_upload');
|
||||
|
@ -65,16 +65,18 @@ class MigrateUploadTest extends MigrateDrupal6TestBase {
|
|||
public function testUpload() {
|
||||
$this->container->get('entity.manager')
|
||||
->getStorage('node')
|
||||
->resetCache([1, 2]);
|
||||
->resetCache([1, 2, 12]);
|
||||
|
||||
$nodes = Node::loadMultiple([1, 2]);
|
||||
$nodes = Node::loadMultiple([1, 2, 12]);
|
||||
$node = $nodes[1];
|
||||
$this->assertEquals('en', $node->langcode->value);
|
||||
$this->assertIdentical(1, count($node->upload));
|
||||
$this->assertIdentical('1', $node->upload[0]->target_id);
|
||||
$this->assertIdentical('file 1-1-1', $node->upload[0]->description);
|
||||
$this->assertIdentical(FALSE, $node->upload[0]->isDisplayed());
|
||||
|
||||
$node = $nodes[2];
|
||||
$this->assertEquals('en', $node->langcode->value);
|
||||
$this->assertIdentical(2, count($node->upload));
|
||||
$this->assertIdentical('3', $node->upload[0]->target_id);
|
||||
$this->assertIdentical('file 2-3-3', $node->upload[0]->description);
|
||||
|
@ -82,6 +84,13 @@ class MigrateUploadTest extends MigrateDrupal6TestBase {
|
|||
$this->assertIdentical('2', $node->upload[1]->target_id);
|
||||
$this->assertIdentical(TRUE, $node->upload[1]->isDisplayed());
|
||||
$this->assertIdentical('file 2-3-2', $node->upload[1]->description);
|
||||
|
||||
$node = $nodes[12];
|
||||
$this->assertEquals('zu', $node->langcode->value);
|
||||
$this->assertEquals(1, count($node->upload));
|
||||
$this->assertEquals('3', $node->upload[0]->target_id);
|
||||
$this->assertEquals('file 12-15-3', $node->upload[0]->description);
|
||||
$this->assertEquals(FALSE, $node->upload[0]->isDisplayed());
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -0,0 +1,81 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\Tests\file\Kernel\Migrate\d7;
|
||||
|
||||
use Drupal\file\Entity\File;
|
||||
use Drupal\file\FileInterface;
|
||||
|
||||
/**
|
||||
* A trait to setup the file migration.
|
||||
*/
|
||||
trait FileMigrationSetupTrait {
|
||||
|
||||
/**
|
||||
* Returns information about the file to be migrated.
|
||||
*
|
||||
* @return array
|
||||
* Array with keys 'path', 'size', 'base_path', and 'plugin_id'.
|
||||
*/
|
||||
abstract protected function getFileMigrationInfo();
|
||||
|
||||
/**
|
||||
* Prepare the file migration for running.
|
||||
*/
|
||||
protected function fileMigrationSetup() {
|
||||
$this->installEntitySchema('file');
|
||||
$this->installSchema('file', ['file_usage']);
|
||||
|
||||
$info = $this->getFileMigrationInfo();
|
||||
$fs = $this->container->get('file_system');
|
||||
// Ensure that the files directory exists.
|
||||
$fs->mkdir(dirname($info['path']), NULL, TRUE);
|
||||
// Put test file in the source directory.
|
||||
file_put_contents($info['path'], str_repeat('*', $info['size']));
|
||||
|
||||
/** @var \Drupal\migrate\Plugin\Migration $migration */
|
||||
$migration = $this->getMigration($info['plugin_id']);
|
||||
// Set the source plugin's source_base_path configuration value, which
|
||||
// would normally be set by the user running the migration.
|
||||
$source = $migration->getSourceConfiguration();
|
||||
$source['constants']['source_base_path'] = $fs->realpath($info['base_path']);
|
||||
$migration->set('source', $source);
|
||||
$this->executeMigration($migration);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests a single file entity.
|
||||
*
|
||||
* @param int $id
|
||||
* The file ID.
|
||||
* @param string $name
|
||||
* The expected file name.
|
||||
* @param string $uri
|
||||
* The expected URI.
|
||||
* @param string $mime
|
||||
* The expected MIME type.
|
||||
* @param string $size
|
||||
* The expected file size.
|
||||
* @param string $created
|
||||
* The expected creation time.
|
||||
* @param string $changed
|
||||
* The expected modification time.
|
||||
* @param string $uid
|
||||
* The expected owner ID.
|
||||
*/
|
||||
protected function assertEntity($id, $name, $uri, $mime, $size, $created, $changed, $uid) {
|
||||
/** @var \Drupal\file\FileInterface $file */
|
||||
$file = File::load($id);
|
||||
$this->assertInstanceOf(FileInterface::class, $file);
|
||||
$this->assertSame($name, $file->getFilename());
|
||||
$this->assertSame($uri, $file->getFileUri());
|
||||
$this->assertFileExists($uri);
|
||||
$this->assertSame($mime, $file->getMimeType());
|
||||
$this->assertSame($size, $file->getSize());
|
||||
// isPermanent(), isTemporary(), etc. are determined by the status column.
|
||||
$this->assertTrue($file->isPermanent());
|
||||
$this->assertSame($created, $file->getCreatedTime());
|
||||
$this->assertSame($changed, $file->getChangedTime());
|
||||
$this->assertSame($uid, $file->getOwnerId());
|
||||
}
|
||||
|
||||
}
|
|
@ -2,9 +2,7 @@
|
|||
|
||||
namespace Drupal\Tests\file\Kernel\Migrate\d7;
|
||||
|
||||
use Drupal\Core\StreamWrapper\StreamWrapperInterface;
|
||||
use Drupal\file\Entity\File;
|
||||
use Drupal\file\FileInterface;
|
||||
use Drupal\Tests\migrate_drupal\Kernel\d7\MigrateDrupal7TestBase;
|
||||
|
||||
/**
|
||||
|
@ -14,6 +12,11 @@ use Drupal\Tests\migrate_drupal\Kernel\d7\MigrateDrupal7TestBase;
|
|||
*/
|
||||
class MigrateFileTest extends MigrateDrupal7TestBase {
|
||||
|
||||
use FileMigrationSetupTrait;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static $modules = ['file'];
|
||||
|
||||
/**
|
||||
|
@ -21,60 +24,19 @@ class MigrateFileTest extends MigrateDrupal7TestBase {
|
|||
*/
|
||||
protected function setUp() {
|
||||
parent::setUp();
|
||||
|
||||
$this->installEntitySchema('file');
|
||||
$this->container->get('stream_wrapper_manager')->registerWrapper('public', 'Drupal\Core\StreamWrapper\PublicStream', StreamWrapperInterface::NORMAL);
|
||||
|
||||
$fs = \Drupal::service('file_system');
|
||||
// The public file directory active during the test will serve as the
|
||||
// root of the fictional Drupal 7 site we're migrating.
|
||||
$fs->mkdir('public://sites/default/files', NULL, TRUE);
|
||||
file_put_contents('public://sites/default/files/cube.jpeg', str_repeat('*', 3620));
|
||||
|
||||
/** @var \Drupal\migrate\Plugin\Migration $migration */
|
||||
$migration = $this->getMigration('d7_file');
|
||||
// Set the source plugin's source_base_path configuration value, which
|
||||
// would normally be set by the user running the migration.
|
||||
$source = $migration->getSourceConfiguration();
|
||||
$source['constants']['source_base_path'] = $fs->realpath('public://');
|
||||
$migration->set('source', $source);
|
||||
$this->executeMigration($migration);
|
||||
$this->fileMigrationSetup();
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests a single file entity.
|
||||
*
|
||||
* @param int $id
|
||||
* The file ID.
|
||||
* @param string $name
|
||||
* The expected file name.
|
||||
* @param string $uri
|
||||
* The expected URI.
|
||||
* @param string $mime
|
||||
* The expected MIME type.
|
||||
* @param int $size
|
||||
* The expected file size.
|
||||
* @param int $created
|
||||
* The expected creation time.
|
||||
* @param int $changed
|
||||
* The expected modification time.
|
||||
* @param int $uid
|
||||
* The expected owner ID.
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function assertEntity($id, $name, $uri, $mime, $size, $created, $changed, $uid) {
|
||||
/** @var \Drupal\file\FileInterface $file */
|
||||
$file = File::load($id);
|
||||
$this->assertTrue($file instanceof FileInterface);
|
||||
$this->assertIdentical($name, $file->getFilename());
|
||||
$this->assertIdentical($uri, $file->getFileUri());
|
||||
$this->assertTrue(file_exists($uri));
|
||||
$this->assertIdentical($mime, $file->getMimeType());
|
||||
$this->assertIdentical($size, $file->getSize());
|
||||
// isPermanent(), isTemporary(), etc. are determined by the status column.
|
||||
$this->assertTrue($file->isPermanent());
|
||||
$this->assertIdentical($created, $file->getCreatedTime());
|
||||
$this->assertIdentical($changed, $file->getChangedTime());
|
||||
$this->assertIdentical($uid, $file->getOwnerId());
|
||||
protected function getFileMigrationInfo() {
|
||||
return [
|
||||
'path' => 'public://sites/default/files/cube.jpeg',
|
||||
'size' => '3620',
|
||||
'base_path' => 'public://',
|
||||
'plugin_id' => 'd7_file',
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -82,6 +44,8 @@ class MigrateFileTest extends MigrateDrupal7TestBase {
|
|||
*/
|
||||
public function testFileMigration() {
|
||||
$this->assertEntity(1, 'cube.jpeg', 'public://cube.jpeg', 'image/jpeg', '3620', '1421727515', '1421727515', '1');
|
||||
// Ensure temporary file was not migrated.
|
||||
$this->assertNull(File::load(4));
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -0,0 +1,59 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\Tests\file\Kernel\Migrate\d7;
|
||||
|
||||
use Drupal\Core\DependencyInjection\ContainerBuilder;
|
||||
use Drupal\Tests\migrate_drupal\Kernel\d7\MigrateDrupal7TestBase;
|
||||
|
||||
/**
|
||||
* Tests private files migration.
|
||||
*
|
||||
* @group file
|
||||
*/
|
||||
class MigratePrivateFileTest extends MigrateDrupal7TestBase {
|
||||
|
||||
use FileMigrationSetupTrait;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static $modules = ['file'];
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function setUp() {
|
||||
parent::setUp();
|
||||
$this->setSetting('file_private_path', $this->container->get('site.path') . '/private');
|
||||
$this->fileMigrationSetup();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function getFileMigrationInfo() {
|
||||
return [
|
||||
'path' => 'private://sites/default/private/Babylon5.txt',
|
||||
'size' => '3',
|
||||
'base_path' => 'private://',
|
||||
'plugin_id' => 'd7_file_private',
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function register(ContainerBuilder $container) {
|
||||
parent::register($container);
|
||||
$container->register('stream_wrapper.private', 'Drupal\Core\StreamWrapper\PrivateStream')
|
||||
->addTag('stream_wrapper', ['scheme' => 'private']);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests that all expected files are migrated.
|
||||
*/
|
||||
public function testFileMigration() {
|
||||
$this->assertEntity(3, 'Babylon5.txt', 'private://Babylon5.txt', 'text/plain', '3', '1486104045', '1486104045', '1');
|
||||
}
|
||||
|
||||
}
|
|
@ -12,6 +12,7 @@ use Drupal\Tests\migrate_drupal\Kernel\MigrateDrupalTestBase;
|
|||
* @coversDefaultClass \Drupal\file\Plugin\migrate\process\d6\CckFile
|
||||
*
|
||||
* @group file
|
||||
* @group legacy
|
||||
*/
|
||||
class CckFileTest extends MigrateDrupalTestBase {
|
||||
|
||||
|
@ -19,6 +20,7 @@ class CckFileTest extends MigrateDrupalTestBase {
|
|||
* Tests configurability of file migration name.
|
||||
*
|
||||
* @covers ::__construct
|
||||
* @expectedDeprecation CckFile is deprecated in Drupal 8.3.x and will be be removed before Drupal 9.0.x. Use \Drupal\file\Plugin\migrate\process\d6\FieldFile instead.
|
||||
*/
|
||||
public function testConfigurableFileMigration() {
|
||||
$migration = Migration::create($this->container, [], 'custom_migration', []);
|
||||
|
|
|
@ -10,6 +10,7 @@ use Drupal\file\Entity\File;
|
|||
* @group file
|
||||
*/
|
||||
class MoveTest extends FileManagedUnitTestBase {
|
||||
|
||||
/**
|
||||
* Move a normal file.
|
||||
*/
|
||||
|
|
|
@ -46,11 +46,42 @@ class FileTest extends MigrateSqlSourceTestBase {
|
|||
'status' => 1,
|
||||
'timestamp' => 1382255662,
|
||||
],
|
||||
[
|
||||
'fid' => 3,
|
||||
'uid' => 1,
|
||||
'filename' => 'migrate-test-file-3.pdf',
|
||||
'filepath' => '/tmp/migrate-test-file-3.pdf',
|
||||
'filemime' => 'application/pdf',
|
||||
'filesize' => 304124,
|
||||
'status' => 1,
|
||||
'timestamp' => 1382277662,
|
||||
],
|
||||
];
|
||||
|
||||
// The expected results are identical to the source data.
|
||||
$tests[0]['expected_data'] = $tests[0]['source_data']['files'];
|
||||
|
||||
// The expected results are the same as the source data but excluding
|
||||
// the temporary file.
|
||||
$tests[0]['expected_data'] = [
|
||||
[
|
||||
'fid' => 1,
|
||||
'uid' => 1,
|
||||
'filename' => 'migrate-test-file-1.pdf',
|
||||
'filepath' => 'sites/default/files/migrate-test-file-1.pdf',
|
||||
'filemime' => 'application/pdf',
|
||||
'filesize' => 890404,
|
||||
'status' => 1,
|
||||
'timestamp' => 1382255613,
|
||||
],
|
||||
[
|
||||
'fid' => 2,
|
||||
'uid' => 1,
|
||||
'filename' => 'migrate-test-file-2.pdf',
|
||||
'filepath' => 'sites/default/files/migrate-test-file-2.pdf',
|
||||
'filemime' => 'application/pdf',
|
||||
'filesize' => 204124,
|
||||
'status' => 1,
|
||||
'timestamp' => 1382255662,
|
||||
],
|
||||
];
|
||||
return $tests;
|
||||
}
|
||||
|
||||
|
|
|
@ -34,6 +34,14 @@ class UploadTest extends MigrateSqlSourceTestBase {
|
|||
'list' => '0',
|
||||
'weight' => '-1',
|
||||
],
|
||||
[
|
||||
'fid' => '3',
|
||||
'nid' => '12',
|
||||
'vid' => '15',
|
||||
'description' => 'file 12-15-3',
|
||||
'list' => '0',
|
||||
'weight' => '0',
|
||||
],
|
||||
];
|
||||
|
||||
$tests[0]['source_data']['node'] = [
|
||||
|
@ -54,6 +62,23 @@ class UploadTest extends MigrateSqlSourceTestBase {
|
|||
'tnid' => '0',
|
||||
'translate' => '0',
|
||||
],
|
||||
[
|
||||
'nid' => '12',
|
||||
'vid' => '15',
|
||||
'type' => 'page',
|
||||
'language' => 'zu',
|
||||
'title' => 'Abantu zulu',
|
||||
'uid' => '1',
|
||||
'status' => '1',
|
||||
'created' => '1444238800',
|
||||
'changed' => '1444238808',
|
||||
'comment' => '0',
|
||||
'promote' => '0',
|
||||
'moderate' => '0',
|
||||
'sticky' => '0',
|
||||
'tnid' => '12',
|
||||
'translate' => '0',
|
||||
],
|
||||
];
|
||||
|
||||
// The expected results.
|
||||
|
@ -66,10 +91,24 @@ class UploadTest extends MigrateSqlSourceTestBase {
|
|||
'list' => '0',
|
||||
],
|
||||
],
|
||||
'language' => '',
|
||||
'nid' => '1',
|
||||
'vid' => '1',
|
||||
'type' => 'story',
|
||||
],
|
||||
[
|
||||
'upload' => [
|
||||
[
|
||||
'fid' => '3',
|
||||
'description' => 'file 12-15-3',
|
||||
'list' => '0',
|
||||
],
|
||||
],
|
||||
'language' => 'zu',
|
||||
'nid' => '12',
|
||||
'vid' => '15',
|
||||
'type' => 'page',
|
||||
],
|
||||
];
|
||||
|
||||
return $tests;
|
||||
|
|
|
@ -84,15 +84,14 @@ class FileTest extends MigrateSqlSourceTestBase {
|
|||
],
|
||||
];
|
||||
|
||||
// The expected results will include only the first three files, since we
|
||||
// are configuring the plugin to filter out the file with the null URI
|
||||
// scheme.
|
||||
$tests[0]['expected_data'] = array_slice($tests[0]['source_data']['file_managed'], 0, 3);
|
||||
// The expected results will include only the first two files, since the
|
||||
// plugin will filter out files with either the null URI scheme or the
|
||||
// temporary scheme.
|
||||
$tests[0]['expected_data'] = array_slice($tests[0]['source_data']['file_managed'], 0, 2);
|
||||
|
||||
// The filepath property will vary by URI scheme.
|
||||
$tests[0]['expected_data'][0]['filepath'] = 'sites/default/files/cube.jpeg';
|
||||
$tests[0]['expected_data'][1]['filepath'] = '/path/to/private/files/cube.jpeg';
|
||||
$tests[0]['expected_data'][2]['filepath'] = '/tmp/cube.jpeg';
|
||||
|
||||
// Do an automatic count.
|
||||
$tests[0]['expected_count'] = NULL;
|
||||
|
@ -102,10 +101,61 @@ class FileTest extends MigrateSqlSourceTestBase {
|
|||
'constants' => [
|
||||
'source_base_path' => '/path/to/files',
|
||||
],
|
||||
// Only return files which use one of these URI schemes.
|
||||
'scheme' => ['public', 'private', 'temporary'],
|
||||
];
|
||||
|
||||
// Test getting only public files.
|
||||
$tests[1]['source_data'] = $tests[0]['source_data'];
|
||||
|
||||
$tests[1]['expected_data'] = [
|
||||
[
|
||||
'fid' => '1',
|
||||
'uid' => '1',
|
||||
'filename' => 'cube.jpeg',
|
||||
'uri' => 'public://cube.jpeg',
|
||||
'filemime' => 'image/jpeg',
|
||||
'filesize' => '3620',
|
||||
'status' => '1',
|
||||
'timestamp' => '1421727515',
|
||||
],
|
||||
];
|
||||
// Do an automatic count.
|
||||
$tests[1]['expected_count'] = NULL;
|
||||
|
||||
// Set up plugin configuration.
|
||||
$tests[1]['configuration'] = [
|
||||
'constants' => [
|
||||
'source_base_path' => '/path/to/files',
|
||||
],
|
||||
'scheme' => ['public'],
|
||||
];
|
||||
|
||||
// Test getting only public files when configuration scheme is not an array.
|
||||
$tests[2]['source_data'] = $tests[0]['source_data'];
|
||||
|
||||
$tests[2]['expected_data'] = [
|
||||
[
|
||||
'fid' => '1',
|
||||
'uid' => '1',
|
||||
'filename' => 'cube.jpeg',
|
||||
'uri' => 'public://cube.jpeg',
|
||||
'filemime' => 'image/jpeg',
|
||||
'filesize' => '3620',
|
||||
'status' => '1',
|
||||
'timestamp' => '1421727515',
|
||||
],
|
||||
];
|
||||
// Do an automatic count.
|
||||
$tests[2]['expected_count'] = NULL;
|
||||
|
||||
// Set up plugin configuration.
|
||||
$tests[2]['configuration'] = [
|
||||
'constants' => [
|
||||
'source_base_path' => '/path/to/files',
|
||||
],
|
||||
'scheme' => 'public',
|
||||
];
|
||||
|
||||
return $tests;
|
||||
}
|
||||
|
||||
|
|
|
@ -10,6 +10,7 @@ use Drupal\file\Entity\File;
|
|||
* @group file
|
||||
*/
|
||||
class SaveDataTest extends FileManagedUnitTestBase {
|
||||
|
||||
/**
|
||||
* Test the file_save_data() function when no filename is provided.
|
||||
*/
|
||||
|
|
|
@ -10,6 +10,7 @@ use Drupal\file\Entity\File;
|
|||
* @group file
|
||||
*/
|
||||
class SaveTest extends FileManagedUnitTestBase {
|
||||
|
||||
public function testFileSave() {
|
||||
// Create a new file entity.
|
||||
$file = File::create([
|
||||
|
@ -81,6 +82,22 @@ class SaveTest extends FileManagedUnitTestBase {
|
|||
$this->assertEqual(1, count($fids));
|
||||
$this->assertEqual([$uppercase_file->id() => $uppercase_file->id()], $fids);
|
||||
|
||||
// Save a file with zero bytes.
|
||||
$file = File::create([
|
||||
'uid' => 1,
|
||||
'filename' => 'no-druplicon.txt',
|
||||
'uri' => 'public://no-druplicon.txt',
|
||||
'filemime' => 'text/plain',
|
||||
'status' => FILE_STATUS_PERMANENT,
|
||||
]);
|
||||
|
||||
file_put_contents($file->getFileUri(), '');
|
||||
|
||||
// Save it, inserting a new record.
|
||||
$file->save();
|
||||
|
||||
// Check the file size was set to zero.
|
||||
$this->assertSame(0, $file->getSize());
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\Tests\file\Kernel;
|
||||
|
||||
use Drupal\file\Entity\File;
|
||||
|
||||
/**
|
||||
|
@ -9,6 +10,7 @@ use Drupal\file\Entity\File;
|
|||
* @group file
|
||||
*/
|
||||
class SpaceUsedTest extends FileManagedUnitTestBase {
|
||||
|
||||
protected function setUp() {
|
||||
parent::setUp();
|
||||
|
||||
|
|
|
@ -15,6 +15,7 @@ use Drupal\node\Entity\NodeType;
|
|||
* @group file
|
||||
*/
|
||||
class UsageTest extends FileManagedUnitTestBase {
|
||||
|
||||
/**
|
||||
* Tests \Drupal\file\FileUsage\DatabaseFileUsageBackend::listUsage().
|
||||
*/
|
||||
|
@ -26,7 +27,7 @@ class UsageTest extends FileManagedUnitTestBase {
|
|||
'module' => 'testing',
|
||||
'type' => 'foo',
|
||||
'id' => 1,
|
||||
'count' => 1
|
||||
'count' => 1,
|
||||
])
|
||||
->execute();
|
||||
db_insert('file_usage')
|
||||
|
@ -35,7 +36,7 @@ class UsageTest extends FileManagedUnitTestBase {
|
|||
'module' => 'testing',
|
||||
'type' => 'bar',
|
||||
'id' => 2,
|
||||
'count' => 2
|
||||
'count' => 2,
|
||||
])
|
||||
->execute();
|
||||
|
||||
|
@ -74,11 +75,34 @@ class UsageTest extends FileManagedUnitTestBase {
|
|||
$this->assertEqual($usage[2]->count, 2, 'Correct count');
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests file usage deletion when files are made temporary.
|
||||
*/
|
||||
public function testRemoveUsageTemporary() {
|
||||
$this->config('file.settings')
|
||||
->set('make_unused_managed_files_temporary', TRUE)
|
||||
->save();
|
||||
$file = $this->doTestRemoveUsage();
|
||||
$this->assertTrue($file->isTemporary());
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests file usage deletion when files are made temporary.
|
||||
*/
|
||||
public function testRemoveUsageNonTemporary() {
|
||||
$this->config('file.settings')
|
||||
->set('make_unused_managed_files_temporary', FALSE)
|
||||
->save();
|
||||
$file = $this->doTestRemoveUsage();
|
||||
$this->assertFalse($file->isTemporary());
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests \Drupal\file\FileUsage\DatabaseFileUsageBackend::delete().
|
||||
*/
|
||||
public function testRemoveUsage() {
|
||||
public function doTestRemoveUsage() {
|
||||
$file = $this->createFile();
|
||||
$file->setPermanent();
|
||||
$file_usage = $this->container->get('file.usage');
|
||||
db_insert('file_usage')
|
||||
->fields([
|
||||
|
@ -116,6 +140,7 @@ class UsageTest extends FileManagedUnitTestBase {
|
|||
->execute()
|
||||
->fetchField();
|
||||
$this->assertIdentical(FALSE, $count, 'Decrementing non-exist record complete.');
|
||||
return $file;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -2,13 +2,13 @@
|
|||
|
||||
namespace Drupal\Tests\file\Kernel;
|
||||
|
||||
|
||||
/**
|
||||
* Tests the file_validate() function.
|
||||
*
|
||||
* @group file
|
||||
*/
|
||||
class ValidateTest extends FileManagedUnitTestBase {
|
||||
|
||||
/**
|
||||
* Test that the validators passed into are checked.
|
||||
*/
|
||||
|
|
|
@ -137,7 +137,6 @@ class ValidatorTest extends FileManagedUnitTestBase {
|
|||
$this->assertEqual(count($errors), 1, 'An error reported for 0 length filename.', 'File');
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Test file_validate_size().
|
||||
*/
|
||||
|
|
|
@ -48,7 +48,7 @@ class FileViewsFieldAccessTest extends FieldFieldAccessTestBase {
|
|||
'uri' => 'public://test.txt',
|
||||
'status' => TRUE,
|
||||
'langcode' => 'fr',
|
||||
'uid' => $user->id()
|
||||
'uid' => $user->id(),
|
||||
]);
|
||||
$file->save();
|
||||
|
||||
|
|
|
@ -0,0 +1,82 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\Tests\file\Unit\Plugin\migrate\cckfield\d6;
|
||||
|
||||
use Drupal\migrate\Plugin\MigrationInterface;
|
||||
use Drupal\migrate\Row;
|
||||
use Drupal\Tests\UnitTestCase;
|
||||
use Drupal\file\Plugin\migrate\cckfield\d6\FileField;
|
||||
use Prophecy\Argument;
|
||||
|
||||
/**
|
||||
* @coversDefaultClass \Drupal\file\Plugin\migrate\cckfield\d6\FileField
|
||||
* @group file
|
||||
* @group legacy
|
||||
*/
|
||||
class FileCckTest extends UnitTestCase {
|
||||
|
||||
/**
|
||||
* @var \Drupal\migrate_drupal\Plugin\MigrateCckFieldInterface
|
||||
*/
|
||||
protected $plugin;
|
||||
|
||||
/**
|
||||
* @var \Drupal\migrate\Plugin\MigrationInterface
|
||||
*/
|
||||
protected $migration;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function setUp() {
|
||||
$this->plugin = new FileField([], 'file', []);
|
||||
|
||||
$migration = $this->prophesize(MigrationInterface::class);
|
||||
|
||||
// The plugin's defineValueProcessPipeline() method will call
|
||||
// mergeProcessOfProperty() and return nothing. So, in order to examine the
|
||||
// process pipeline created by the plugin, we need to ensure that
|
||||
// getProcess() always returns the last input to mergeProcessOfProperty().
|
||||
$migration->mergeProcessOfProperty(Argument::type('string'), Argument::type('array'))
|
||||
->will(function ($arguments) use ($migration) {
|
||||
$migration->getProcess()->willReturn($arguments[1]);
|
||||
});
|
||||
$this->migration = $migration->reveal();
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers ::processCckFieldValues
|
||||
*/
|
||||
public function testProcessCckFieldValues() {
|
||||
$this->plugin->processCckFieldValues($this->migration, 'somefieldname', []);
|
||||
|
||||
$expected = [
|
||||
'plugin' => 'd6_cck_file',
|
||||
'source' => 'somefieldname',
|
||||
];
|
||||
$this->assertSame($expected, $this->migration->getProcess());
|
||||
}
|
||||
|
||||
/**
|
||||
* Data provider for testGetFieldType().
|
||||
*/
|
||||
public function getFieldTypeProvider() {
|
||||
return [
|
||||
['image', 'imagefield_widget'],
|
||||
['file', 'filefield_widget'],
|
||||
['file', 'x_widget'],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers ::getFieldType
|
||||
* @dataProvider getFieldTypeProvider
|
||||
*/
|
||||
public function testGetFieldType($expected_type, $widget_type, array $settings = []) {
|
||||
$row = new Row();
|
||||
$row->setSourceProperty('widget_type', $widget_type);
|
||||
$row->setSourceProperty('global_settings', $settings);
|
||||
$this->assertSame($expected_type, $this->plugin->getFieldType($row));
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,87 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\Tests\file\Unit\Plugin\migrate\cckfield\d7;
|
||||
|
||||
use Drupal\migrate\Plugin\MigrationInterface;
|
||||
use Drupal\migrate\Row;
|
||||
use Drupal\Tests\UnitTestCase;
|
||||
use Drupal\file\Plugin\migrate\cckfield\d7\FileField;
|
||||
use Prophecy\Argument;
|
||||
|
||||
/**
|
||||
* @coversDefaultClass \Drupal\file\Plugin\migrate\cckfield\d7\FileField
|
||||
* @group file
|
||||
* @group legacy
|
||||
*/
|
||||
class FileCckTest extends UnitTestCase {
|
||||
|
||||
/**
|
||||
* @var \Drupal\migrate_drupal\Plugin\MigrateCckFieldInterface
|
||||
*/
|
||||
protected $plugin;
|
||||
|
||||
/**
|
||||
* @var \Drupal\migrate\Plugin\MigrationInterface
|
||||
*/
|
||||
protected $migration;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function setUp() {
|
||||
$this->plugin = new FileField([], 'file', []);
|
||||
|
||||
$migration = $this->prophesize(MigrationInterface::class);
|
||||
|
||||
// The plugin's defineValueProcessPipeline() method will call
|
||||
// mergeProcessOfProperty() and return nothing. So, in order to examine the
|
||||
// process pipeline created by the plugin, we need to ensure that
|
||||
// getProcess() always returns the last input to mergeProcessOfProperty().
|
||||
$migration->mergeProcessOfProperty(Argument::type('string'), Argument::type('array'))
|
||||
->will(function ($arguments) use ($migration) {
|
||||
$migration->getProcess()->willReturn($arguments[1]);
|
||||
});
|
||||
$this->migration = $migration->reveal();
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers ::processCckFieldValues
|
||||
*/
|
||||
public function testProcessCckFieldValues() {
|
||||
$this->plugin->processCckFieldValues($this->migration, 'somefieldname', []);
|
||||
|
||||
$expected = [
|
||||
'plugin' => 'sub_process',
|
||||
'source' => 'somefieldname',
|
||||
'process' => [
|
||||
'target_id' => 'fid',
|
||||
'display' => 'display',
|
||||
'description' => 'description',
|
||||
],
|
||||
];
|
||||
$this->assertSame($expected, $this->migration->getProcess());
|
||||
}
|
||||
|
||||
/**
|
||||
* Data provider for testGetFieldType().
|
||||
*/
|
||||
public function getFieldTypeProvider() {
|
||||
return [
|
||||
['image', 'imagefield_widget'],
|
||||
['file', 'filefield_widget'],
|
||||
['file', 'x_widget'],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers ::getFieldType
|
||||
* @dataProvider getFieldTypeProvider
|
||||
*/
|
||||
public function testGetFieldType($expected_type, $widget_type, array $settings = []) {
|
||||
$row = new Row();
|
||||
$row->setSourceProperty('widget_type', $widget_type);
|
||||
$row->setSourceProperty('global_settings', $settings);
|
||||
$this->assertSame($expected_type, $this->plugin->getFieldType($row));
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,66 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\Tests\file\Unit\Plugin\migrate\cckfield\d7;
|
||||
|
||||
use Drupal\migrate\Plugin\MigrationInterface;
|
||||
use Drupal\Tests\UnitTestCase;
|
||||
use Drupal\file\Plugin\migrate\cckfield\d7\ImageField;
|
||||
use Prophecy\Argument;
|
||||
|
||||
/**
|
||||
* @coversDefaultClass \Drupal\file\Plugin\migrate\cckfield\d7\ImageField
|
||||
* @group file
|
||||
* @group legacy
|
||||
*/
|
||||
class ImageCckTest extends UnitTestCase {
|
||||
|
||||
/**
|
||||
* @var \Drupal\migrate_drupal\Plugin\MigrateCckFieldInterface
|
||||
*/
|
||||
protected $plugin;
|
||||
|
||||
/**
|
||||
* @var \Drupal\migrate\Plugin\MigrationInterface
|
||||
*/
|
||||
protected $migration;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function setUp() {
|
||||
$this->plugin = new ImageField([], 'image', []);
|
||||
|
||||
$migration = $this->prophesize(MigrationInterface::class);
|
||||
|
||||
// The plugin's defineValueProcessPipeline() method will call
|
||||
// mergeProcessOfProperty() and return nothing. So, in order to examine the
|
||||
// process pipeline created by the plugin, we need to ensure that
|
||||
// getProcess() always returns the last input to mergeProcessOfProperty().
|
||||
$migration->mergeProcessOfProperty(Argument::type('string'), Argument::type('array'))
|
||||
->will(function ($arguments) use ($migration) {
|
||||
$migration->getProcess()->willReturn($arguments[1]);
|
||||
});
|
||||
$this->migration = $migration->reveal();
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers ::processCckFieldValues
|
||||
*/
|
||||
public function testProcessCckFieldValues() {
|
||||
$this->plugin->processCckFieldValues($this->migration, 'somefieldname', []);
|
||||
|
||||
$expected = [
|
||||
'plugin' => 'sub_process',
|
||||
'source' => 'somefieldname',
|
||||
'process' => [
|
||||
'target_id' => 'fid',
|
||||
'alt' => 'alt',
|
||||
'title' => 'title',
|
||||
'width' => 'width',
|
||||
'height' => 'height',
|
||||
],
|
||||
];
|
||||
$this->assertSame($expected, $this->migration->getProcess());
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,19 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\Tests\file\Unit\Plugin\migrate\field\d6;
|
||||
|
||||
/**
|
||||
* @coversDefaultClass \Drupal\file\Plugin\migrate\field\d6\FileField
|
||||
* @group legacy
|
||||
* @group file
|
||||
*/
|
||||
class FileFieldLegacyTest extends FileFieldTest {
|
||||
|
||||
/**
|
||||
* @expectedDeprecation Deprecated in Drupal 8.6.0, to be removed before Drupal 9.0.0. Use defineValueProcessPipeline() instead. See https://www.drupal.org/node/2944598.
|
||||
*/
|
||||
public function testDefineValueProcessPipeline($method = 'processFieldValues') {
|
||||
parent::testDefineValueProcessPipeline($method);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,81 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\Tests\file\Unit\Plugin\migrate\field\d6;
|
||||
|
||||
use Drupal\migrate\Plugin\MigrationInterface;
|
||||
use Drupal\migrate\Row;
|
||||
use Drupal\Tests\UnitTestCase;
|
||||
use Drupal\file\Plugin\migrate\field\d6\FileField;
|
||||
use Prophecy\Argument;
|
||||
|
||||
/**
|
||||
* @coversDefaultClass \Drupal\file\Plugin\migrate\field\d6\FileField
|
||||
* @group file
|
||||
*/
|
||||
class FileFieldTest extends UnitTestCase {
|
||||
|
||||
/**
|
||||
* @var \Drupal\migrate_drupal\Plugin\MigrateFieldInterface
|
||||
*/
|
||||
protected $plugin;
|
||||
|
||||
/**
|
||||
* @var \Drupal\migrate\Plugin\MigrationInterface
|
||||
*/
|
||||
protected $migration;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function setUp() {
|
||||
$this->plugin = new FileField([], 'file', []);
|
||||
|
||||
$migration = $this->prophesize(MigrationInterface::class);
|
||||
|
||||
// The plugin's defineValueProcessPipeline() method will call
|
||||
// mergeProcessOfProperty() and return nothing. So, in order to examine the
|
||||
// process pipeline created by the plugin, we need to ensure that
|
||||
// getProcess() always returns the last input to mergeProcessOfProperty().
|
||||
$migration->mergeProcessOfProperty(Argument::type('string'), Argument::type('array'))
|
||||
->will(function ($arguments) use ($migration) {
|
||||
$migration->getProcess()->willReturn($arguments[1]);
|
||||
});
|
||||
$this->migration = $migration->reveal();
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers ::defineValueProcessPipeline
|
||||
*/
|
||||
public function testDefineValueProcessPipeline($method = 'defineValueProcessPipeline') {
|
||||
$this->plugin->$method($this->migration, 'somefieldname', []);
|
||||
|
||||
$expected = [
|
||||
'plugin' => 'd6_field_file',
|
||||
'source' => 'somefieldname',
|
||||
];
|
||||
$this->assertSame($expected, $this->migration->getProcess());
|
||||
}
|
||||
|
||||
/**
|
||||
* Data provider for testGetFieldType().
|
||||
*/
|
||||
public function getFieldTypeProvider() {
|
||||
return [
|
||||
['image', 'imagefield_widget'],
|
||||
['file', 'filefield_widget'],
|
||||
['file', 'x_widget'],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers ::getFieldType
|
||||
* @dataProvider getFieldTypeProvider
|
||||
*/
|
||||
public function testGetFieldType($expected_type, $widget_type, array $settings = []) {
|
||||
$row = new Row();
|
||||
$row->setSourceProperty('widget_type', $widget_type);
|
||||
$row->setSourceProperty('global_settings', $settings);
|
||||
$this->assertSame($expected_type, $this->plugin->getFieldType($row));
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,60 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\Tests\file\Unit\Plugin\migrate\field\d6;
|
||||
|
||||
use Drupal\migrate\Plugin\MigrationInterface;
|
||||
use Drupal\Tests\UnitTestCase;
|
||||
use Drupal\file\Plugin\migrate\field\d6\ImageField;
|
||||
use Prophecy\Argument;
|
||||
|
||||
/**
|
||||
* @coversDefaultClass \Drupal\file\Plugin\migrate\field\d6\ImageField
|
||||
* @group file
|
||||
* @group legacy
|
||||
*/
|
||||
class ImageFieldTest extends UnitTestCase {
|
||||
|
||||
/**
|
||||
* @var \Drupal\migrate_drupal\Plugin\MigrateFieldInterface
|
||||
*/
|
||||
protected $plugin;
|
||||
|
||||
/**
|
||||
* @var \Drupal\migrate\Plugin\MigrationInterface
|
||||
*/
|
||||
protected $migration;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function setUp() {
|
||||
$this->plugin = new ImageField([], 'image', []);
|
||||
|
||||
$migration = $this->prophesize(MigrationInterface::class);
|
||||
|
||||
// The plugin's processFieldValues() method will call
|
||||
// mergeProcessOfProperty() and return nothing. So, in order to examine the
|
||||
// process pipeline created by the plugin, we need to ensure that
|
||||
// getProcess() always returns the last input to mergeProcessOfProperty().
|
||||
$migration->mergeProcessOfProperty(Argument::type('string'), Argument::type('array'))
|
||||
->will(function ($arguments) use ($migration) {
|
||||
$migration->getProcess()->willReturn($arguments[1]);
|
||||
});
|
||||
$this->migration = $migration->reveal();
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers ::processFieldValues
|
||||
* @expectedDeprecation ImageField is deprecated in Drupal 8.5.x and will be removed before Drupal 9.0.x. Use \Drupal\image\Plugin\migrate\field\d6\ImageField instead. See https://www.drupal.org/node/2936061.
|
||||
*/
|
||||
public function testProcessFieldValues() {
|
||||
$this->plugin->processFieldValues($this->migration, 'somefieldname', []);
|
||||
|
||||
$expected = [
|
||||
'plugin' => 'd6_field_file',
|
||||
'source' => 'somefieldname',
|
||||
];
|
||||
$this->assertSame($expected, $this->migration->getProcess());
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,19 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\Tests\file\Unit\Plugin\migrate\field\d7;
|
||||
|
||||
/**
|
||||
* @coversDefaultClass \Drupal\file\Plugin\migrate\field\d7\FileField
|
||||
* @group legacy
|
||||
* @group file
|
||||
*/
|
||||
class FileFieldLegacyTest extends FileFieldTest {
|
||||
|
||||
/**
|
||||
* @expectedDeprecation Deprecated in Drupal 8.6.0, to be removed before Drupal 9.0.0. Use defineValueProcessPipeline() instead. See https://www.drupal.org/node/2944598.
|
||||
*/
|
||||
public function testDefineValueProcessPipeline($method = 'processFieldValues') {
|
||||
parent::testDefineValueProcessPipeline($method);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,86 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\Tests\file\Unit\Plugin\migrate\field\d7;
|
||||
|
||||
use Drupal\migrate\Plugin\MigrationInterface;
|
||||
use Drupal\migrate\Row;
|
||||
use Drupal\Tests\UnitTestCase;
|
||||
use Drupal\file\Plugin\migrate\field\d7\FileField;
|
||||
use Prophecy\Argument;
|
||||
|
||||
/**
|
||||
* @coversDefaultClass \Drupal\file\Plugin\migrate\field\d7\FileField
|
||||
* @group file
|
||||
*/
|
||||
class FileFieldTest extends UnitTestCase {
|
||||
|
||||
/**
|
||||
* @var \Drupal\migrate_drupal\Plugin\MigrateFieldInterface
|
||||
*/
|
||||
protected $plugin;
|
||||
|
||||
/**
|
||||
* @var \Drupal\migrate\Plugin\MigrationInterface
|
||||
*/
|
||||
protected $migration;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function setUp() {
|
||||
$this->plugin = new FileField([], 'file', []);
|
||||
|
||||
$migration = $this->prophesize(MigrationInterface::class);
|
||||
|
||||
// The plugin's defineValueProcessPipeline() method will call
|
||||
// mergeProcessOfProperty() and return nothing. So, in order to examine the
|
||||
// process pipeline created by the plugin, we need to ensure that
|
||||
// getProcess() always returns the last input to mergeProcessOfProperty().
|
||||
$migration->mergeProcessOfProperty(Argument::type('string'), Argument::type('array'))
|
||||
->will(function ($arguments) use ($migration) {
|
||||
$migration->getProcess()->willReturn($arguments[1]);
|
||||
});
|
||||
$this->migration = $migration->reveal();
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers ::defineValueProcessPipeline
|
||||
*/
|
||||
public function testDefineValueProcessPipeline($method = 'defineValueProcessPipeline') {
|
||||
$this->plugin->$method($this->migration, 'somefieldname', []);
|
||||
|
||||
$expected = [
|
||||
'plugin' => 'sub_process',
|
||||
'source' => 'somefieldname',
|
||||
'process' => [
|
||||
'target_id' => 'fid',
|
||||
'display' => 'display',
|
||||
'description' => 'description',
|
||||
],
|
||||
];
|
||||
$this->assertSame($expected, $this->migration->getProcess());
|
||||
}
|
||||
|
||||
/**
|
||||
* Data provider for testGetFieldType().
|
||||
*/
|
||||
public function getFieldTypeProvider() {
|
||||
return [
|
||||
['image', 'imagefield_widget'],
|
||||
['file', 'filefield_widget'],
|
||||
['file', 'x_widget'],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers ::getFieldType
|
||||
* @dataProvider getFieldTypeProvider
|
||||
*/
|
||||
public function testGetFieldType($expected_type, $widget_type, array $settings = []) {
|
||||
$row = new Row();
|
||||
$row->setSourceProperty('widget_type', $widget_type);
|
||||
$row->setSourceProperty('global_settings', $settings);
|
||||
$this->assertSame($expected_type, $this->plugin->getFieldType($row));
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,18 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\Tests\file\Unit\Plugin\migrate\field\d7;
|
||||
|
||||
/**
|
||||
* @group legacy
|
||||
* @group file
|
||||
*/
|
||||
class ImageFieldLegacyTest extends ImageFieldTest {
|
||||
|
||||
/**
|
||||
* @expectedDeprecation Deprecated in Drupal 8.6.0, to be removed before Drupal 9.0.0. Use defineValueProcessPipeline() instead. See https://www.drupal.org/node/2944598.
|
||||
*/
|
||||
public function testDefineValueProcessPipeline($method = 'processFieldValues') {
|
||||
parent::testDefineValueProcessPipeline($method);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,68 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\Tests\file\Unit\Plugin\migrate\field\d7;
|
||||
|
||||
use Drupal\migrate\Plugin\MigrationInterface;
|
||||
use Drupal\Tests\UnitTestCase;
|
||||
use Drupal\file\Plugin\migrate\field\d7\ImageField;
|
||||
use Prophecy\Argument;
|
||||
|
||||
/**
|
||||
* @coversDefaultClass \Drupal\file\Plugin\migrate\field\d7\ImageField
|
||||
* @group file
|
||||
* @group legacy
|
||||
*/
|
||||
class ImageFieldTest extends UnitTestCase {
|
||||
|
||||
/**
|
||||
* @var \Drupal\migrate_drupal\Plugin\MigrateFieldInterface
|
||||
*/
|
||||
protected $plugin;
|
||||
|
||||
/**
|
||||
* @var \Drupal\migrate\Plugin\MigrationInterface
|
||||
*/
|
||||
protected $migration;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function setUp() {
|
||||
$this->plugin = new ImageField([], 'image', []);
|
||||
|
||||
$migration = $this->prophesize(MigrationInterface::class);
|
||||
|
||||
// The plugin's defineValueProcessPipeline() method will call
|
||||
// mergeProcessOfProperty() and return nothing. So, in order to examine the
|
||||
// process pipeline created by the plugin, we need to ensure that
|
||||
// getProcess() always returns the last input to mergeProcessOfProperty().
|
||||
$migration->mergeProcessOfProperty(Argument::type('string'), Argument::type('array'))
|
||||
->will(function ($arguments) use ($migration) {
|
||||
$migration->getProcess()->willReturn($arguments[1]);
|
||||
});
|
||||
$this->migration = $migration->reveal();
|
||||
}
|
||||
|
||||
/**
|
||||
* @runInSeparateProcess
|
||||
* @covers ::defineValueProcessPipeline
|
||||
* @expectedDeprecation ImageField is deprecated in Drupal 8.5.x and will be removed before Drupal 9.0.x. Use \Drupal\image\Plugin\migrate\field\d7\ImageField instead. See https://www.drupal.org/node/2936061.
|
||||
*/
|
||||
public function testDefineValueProcessPipeline($method = 'defineValueProcessPipeline') {
|
||||
$this->plugin->$method($this->migration, 'somefieldname', []);
|
||||
|
||||
$expected = [
|
||||
'plugin' => 'sub_process',
|
||||
'source' => 'somefieldname',
|
||||
'process' => [
|
||||
'target_id' => 'fid',
|
||||
'alt' => 'alt',
|
||||
'title' => 'title',
|
||||
'width' => 'width',
|
||||
'height' => 'height',
|
||||
],
|
||||
];
|
||||
$this->assertSame($expected, $this->migration->getProcess());
|
||||
}
|
||||
|
||||
}
|
|
@ -11,11 +11,14 @@ use Drupal\Tests\UnitTestCase;
|
|||
|
||||
/**
|
||||
* @group file
|
||||
* @group legacy
|
||||
*/
|
||||
class CckFileTest extends UnitTestCase {
|
||||
|
||||
/**
|
||||
* Tests that alt and title attributes are included in transformed values.
|
||||
*
|
||||
* @expectedDeprecation CckFile is deprecated in Drupal 8.3.x and will be be removed before Drupal 9.0.x. Use \Drupal\file\Plugin\migrate\process\d6\FieldFile instead.
|
||||
*/
|
||||
public function testTransformAltTitle() {
|
||||
$executable = $this->prophesize(MigrateExecutableInterface::class)->reveal();
|
||||
|
|
|
@ -0,0 +1,51 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\Tests\file\Unit\Plugin\migrate\process\d6;
|
||||
|
||||
use Drupal\file\Plugin\migrate\process\d6\FieldFile;
|
||||
use Drupal\migrate\Plugin\MigrationInterface;
|
||||
use Drupal\migrate\MigrateExecutableInterface;
|
||||
use Drupal\migrate\Plugin\MigrateProcessInterface;
|
||||
use Drupal\migrate\Row;
|
||||
use Drupal\Tests\UnitTestCase;
|
||||
|
||||
/**
|
||||
* @group file
|
||||
*/
|
||||
class FieldFileTest extends UnitTestCase {
|
||||
|
||||
/**
|
||||
* Tests that alt and title attributes are included in transformed values.
|
||||
*/
|
||||
public function testTransformAltTitle() {
|
||||
$executable = $this->prophesize(MigrateExecutableInterface::class)->reveal();
|
||||
$row = $this->prophesize(Row::class)->reveal();
|
||||
$migration = $this->prophesize(MigrationInterface::class)->reveal();
|
||||
|
||||
$migration_plugin = $this->prophesize(MigrateProcessInterface::class);
|
||||
$migration_plugin->transform(1, $executable, $row, 'foo')->willReturn(1);
|
||||
|
||||
$plugin = new FieldFile([], 'd6_file', [], $migration, $migration_plugin->reveal());
|
||||
|
||||
$options = [
|
||||
'alt' => 'Foobaz',
|
||||
'title' => 'Wambooli',
|
||||
];
|
||||
$value = [
|
||||
'fid' => 1,
|
||||
'list' => TRUE,
|
||||
'data' => serialize($options),
|
||||
];
|
||||
|
||||
$transformed = $plugin->transform($value, $executable, $row, 'foo');
|
||||
$expected = [
|
||||
'target_id' => 1,
|
||||
'display' => TRUE,
|
||||
'description' => '',
|
||||
'alt' => 'Foobaz',
|
||||
'title' => 'Wambooli',
|
||||
];
|
||||
$this->assertSame($expected, $transformed);
|
||||
}
|
||||
|
||||
}
|
|
@ -4,7 +4,6 @@ namespace Drupal\Tests\file\Unit\Plugin\migrate\process\d6;
|
|||
|
||||
use Drupal\file\Plugin\migrate\process\d6\FileUri;
|
||||
use Drupal\migrate\MigrateExecutable;
|
||||
use Drupal\migrate\MigrateMessage;
|
||||
use Drupal\migrate\Row;
|
||||
use Drupal\Tests\migrate\Unit\MigrateTestCase;
|
||||
|
||||
|
@ -69,7 +68,7 @@ class FileUriTest extends MigrateTestCase {
|
|||
}
|
||||
|
||||
protected function doTransform(array $value) {
|
||||
$executable = new MigrateExecutable($this->getMigration(), new MigrateMessage());
|
||||
$executable = new MigrateExecutable($this->getMigration());
|
||||
$row = new Row();
|
||||
|
||||
return (new FileUri([], 'file_uri', []))
|
||||
|
|
Reference in a new issue