updated core to 8.6.1 via composer
This commit is contained in:
@@ -7,7 +7,7 @@
|
||||
* prevents separate file fields from accidentally uploading files).
|
||||
*/
|
||||
|
||||
(function ($, Drupal) {
|
||||
(function($, Drupal) {
|
||||
/**
|
||||
* Attach behaviors to the file fields passed in the settings.
|
||||
*
|
||||
@@ -24,9 +24,14 @@
|
||||
let elements;
|
||||
|
||||
function initFileValidation(selector) {
|
||||
$context.find(selector)
|
||||
$context
|
||||
.find(selector)
|
||||
.once('fileValidate')
|
||||
.on('change.fileValidate', { extensions: elements[selector] }, Drupal.file.validateExtension);
|
||||
.on(
|
||||
'change.fileValidate',
|
||||
{ extensions: elements[selector] },
|
||||
Drupal.file.validateExtension,
|
||||
);
|
||||
}
|
||||
|
||||
if (settings.file && settings.file.elements) {
|
||||
@@ -39,7 +44,8 @@
|
||||
let elements;
|
||||
|
||||
function removeFileValidation(selector) {
|
||||
$context.find(selector)
|
||||
$context
|
||||
.find(selector)
|
||||
.removeOnce('fileValidate')
|
||||
.off('change.fileValidate', Drupal.file.validateExtension);
|
||||
}
|
||||
@@ -63,11 +69,17 @@
|
||||
*/
|
||||
Drupal.behaviors.fileAutoUpload = {
|
||||
attach(context) {
|
||||
$(context).find('input[type="file"]').once('auto-file-upload').on('change.autoFileUpload', Drupal.file.triggerUploadButton);
|
||||
$(context)
|
||||
.find('input[type="file"]')
|
||||
.once('auto-file-upload')
|
||||
.on('change.autoFileUpload', Drupal.file.triggerUploadButton);
|
||||
},
|
||||
detach(context, setting, trigger) {
|
||||
detach(context, settings, trigger) {
|
||||
if (trigger === 'unload') {
|
||||
$(context).find('input[type="file"]').removeOnce('auto-file-upload').off('.autoFileUpload');
|
||||
$(context)
|
||||
.find('input[type="file"]')
|
||||
.removeOnce('auto-file-upload')
|
||||
.off('.autoFileUpload');
|
||||
}
|
||||
},
|
||||
};
|
||||
@@ -85,13 +97,23 @@
|
||||
Drupal.behaviors.fileButtons = {
|
||||
attach(context) {
|
||||
const $context = $(context);
|
||||
$context.find('.js-form-submit').on('mousedown', Drupal.file.disableFields);
|
||||
$context.find('.js-form-managed-file .js-form-submit').on('mousedown', Drupal.file.progressBar);
|
||||
$context
|
||||
.find('.js-form-submit')
|
||||
.on('mousedown', Drupal.file.disableFields);
|
||||
$context
|
||||
.find('.js-form-managed-file .js-form-submit')
|
||||
.on('mousedown', Drupal.file.progressBar);
|
||||
},
|
||||
detach(context) {
|
||||
const $context = $(context);
|
||||
$context.find('.js-form-submit').off('mousedown', Drupal.file.disableFields);
|
||||
$context.find('.js-form-managed-file .js-form-submit').off('mousedown', Drupal.file.progressBar);
|
||||
detach(context, settings, trigger) {
|
||||
if (trigger === 'unload') {
|
||||
const $context = $(context);
|
||||
$context
|
||||
.find('.js-form-submit')
|
||||
.off('mousedown', Drupal.file.disableFields);
|
||||
$context
|
||||
.find('.js-form-managed-file .js-form-submit')
|
||||
.off('mousedown', Drupal.file.progressBar);
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
@@ -107,10 +129,14 @@
|
||||
*/
|
||||
Drupal.behaviors.filePreviewLinks = {
|
||||
attach(context) {
|
||||
$(context).find('div.js-form-managed-file .file a').on('click', Drupal.file.openInNewWindow);
|
||||
$(context)
|
||||
.find('div.js-form-managed-file .file a')
|
||||
.on('click', Drupal.file.openInNewWindow);
|
||||
},
|
||||
detach(context) {
|
||||
$(context).find('div.js-form-managed-file .file a').off('click', Drupal.file.openInNewWindow);
|
||||
$(context)
|
||||
.find('div.js-form-managed-file .file a')
|
||||
.off('click', Drupal.file.openInNewWindow);
|
||||
},
|
||||
};
|
||||
|
||||
@@ -120,7 +146,6 @@
|
||||
* @namespace
|
||||
*/
|
||||
Drupal.file = Drupal.file || {
|
||||
|
||||
/**
|
||||
* Client-side file input validation of file extensions.
|
||||
*
|
||||
@@ -139,18 +164,25 @@
|
||||
if (extensionPattern.length > 1 && this.value.length > 0) {
|
||||
const acceptableMatch = new RegExp(`\\.(${extensionPattern})$`, 'gi');
|
||||
if (!acceptableMatch.test(this.value)) {
|
||||
const error = Drupal.t('The selected file %filename cannot be uploaded. Only files with the following extensions are allowed: %extensions.', {
|
||||
// According to the specifications of HTML5, a file upload control
|
||||
// should not reveal the real local path to the file that a user
|
||||
// has selected. Some web browsers implement this restriction by
|
||||
// replacing the local path with "C:\fakepath\", which can cause
|
||||
// confusion by leaving the user thinking perhaps Drupal could not
|
||||
// find the file because it messed up the file path. To avoid this
|
||||
// confusion, therefore, we strip out the bogus fakepath string.
|
||||
'%filename': this.value.replace('C:\\fakepath\\', ''),
|
||||
'%extensions': extensionPattern.replace(/\|/g, ', '),
|
||||
});
|
||||
$(this).closest('div.js-form-managed-file').prepend(`<div class="messages messages--error file-upload-js-error" aria-live="polite">${error}</div>`);
|
||||
const error = Drupal.t(
|
||||
'The selected file %filename cannot be uploaded. Only files with the following extensions are allowed: %extensions.',
|
||||
{
|
||||
// According to the specifications of HTML5, a file upload control
|
||||
// should not reveal the real local path to the file that a user
|
||||
// has selected. Some web browsers implement this restriction by
|
||||
// replacing the local path with "C:\fakepath\", which can cause
|
||||
// confusion by leaving the user thinking perhaps Drupal could not
|
||||
// find the file because it messed up the file path. To avoid this
|
||||
// confusion, therefore, we strip out the bogus fakepath string.
|
||||
'%filename': this.value.replace('C:\\fakepath\\', ''),
|
||||
'%extensions': extensionPattern.replace(/\|/g, ', '),
|
||||
},
|
||||
);
|
||||
$(this)
|
||||
.closest('div.js-form-managed-file')
|
||||
.prepend(
|
||||
`<div class="messages messages--error file-upload-js-error" aria-live="polite">${error}</div>`,
|
||||
);
|
||||
this.value = '';
|
||||
// Cancel all other change event handlers.
|
||||
event.stopImmediatePropagation();
|
||||
@@ -167,7 +199,10 @@
|
||||
* The event triggered. For example `change.autoFileUpload`.
|
||||
*/
|
||||
triggerUploadButton(event) {
|
||||
$(event.target).closest('.js-form-managed-file').find('.js-form-submit').trigger('mousedown');
|
||||
$(event.target)
|
||||
.closest('.js-form-managed-file')
|
||||
.find('.js-form-submit')
|
||||
.trigger('mousedown');
|
||||
},
|
||||
|
||||
/**
|
||||
@@ -179,17 +214,14 @@
|
||||
* The event triggered, most likely a `mousedown` event.
|
||||
*/
|
||||
disableFields(event) {
|
||||
const $clickedButton = $(this).findOnce('ajax');
|
||||
|
||||
// Only disable upload fields for Ajax buttons.
|
||||
if (!$clickedButton.length) {
|
||||
return;
|
||||
}
|
||||
const $clickedButton = $(this);
|
||||
|
||||
// Check if we're working with an "Upload" button.
|
||||
let $enabledFields = [];
|
||||
if ($clickedButton.closest('div.js-form-managed-file').length > 0) {
|
||||
$enabledFields = $clickedButton.closest('div.js-form-managed-file').find('input.js-form-file');
|
||||
$enabledFields = $clickedButton
|
||||
.closest('div.js-form-managed-file')
|
||||
.find('input.js-form-file');
|
||||
}
|
||||
|
||||
// Temporarily disable upload fields other than the one we're currently
|
||||
@@ -201,7 +233,11 @@
|
||||
// functions are called, so we don't have to worry about the fields being
|
||||
// re-enabled too soon. @todo If the previous sentence is true, why not
|
||||
// set the timeout to 0?
|
||||
const $fieldsToTemporarilyDisable = $('div.js-form-managed-file input.js-form-file').not($enabledFields).not(':disabled');
|
||||
const $fieldsToTemporarilyDisable = $(
|
||||
'div.js-form-managed-file input.js-form-file',
|
||||
)
|
||||
.not($enabledFields)
|
||||
.not(':disabled');
|
||||
$fieldsToTemporarilyDisable.prop('disabled', true);
|
||||
setTimeout(() => {
|
||||
$fieldsToTemporarilyDisable.prop('disabled', false);
|
||||
@@ -218,12 +254,17 @@
|
||||
*/
|
||||
progressBar(event) {
|
||||
const $clickedButton = $(this);
|
||||
const $progressId = $clickedButton.closest('div.js-form-managed-file').find('input.file-progress');
|
||||
const $progressId = $clickedButton
|
||||
.closest('div.js-form-managed-file')
|
||||
.find('input.file-progress');
|
||||
if ($progressId.length) {
|
||||
const originalName = $progressId.attr('name');
|
||||
|
||||
// Replace the name with the required identifier.
|
||||
$progressId.attr('name', originalName.match(/APC_UPLOAD_PROGRESS|UPLOAD_IDENTIFIER/)[0]);
|
||||
$progressId.attr(
|
||||
'name',
|
||||
originalName.match(/APC_UPLOAD_PROGRESS|UPLOAD_IDENTIFIER/)[0],
|
||||
);
|
||||
|
||||
// Restore the original name after the upload begins.
|
||||
setTimeout(() => {
|
||||
@@ -232,8 +273,12 @@
|
||||
}
|
||||
// Show the progress bar if the upload takes longer than half a second.
|
||||
setTimeout(() => {
|
||||
$clickedButton.closest('div.js-form-managed-file').find('div.ajax-progress-bar').slideDown();
|
||||
$clickedButton
|
||||
.closest('div.js-form-managed-file')
|
||||
.find('div.ajax-progress-bar')
|
||||
.slideDown();
|
||||
}, 500);
|
||||
$clickedButton.trigger('fileUpload');
|
||||
},
|
||||
|
||||
/**
|
||||
@@ -247,7 +292,11 @@
|
||||
openInNewWindow(event) {
|
||||
event.preventDefault();
|
||||
$(this).attr('target', '_blank');
|
||||
window.open(this.href, 'filePreview', 'toolbar=0,scrollbars=1,location=1,statusbar=1,menubar=0,resizable=1,width=500,height=550');
|
||||
window.open(
|
||||
this.href,
|
||||
'filePreview',
|
||||
'toolbar=0,scrollbars=1,location=1,statusbar=1,menubar=0,resizable=1,width=500,height=550',
|
||||
);
|
||||
},
|
||||
};
|
||||
}(jQuery, Drupal));
|
||||
})(jQuery, Drupal);
|
||||
|
||||
@@ -5,4 +5,4 @@ package: Field types
|
||||
version: VERSION
|
||||
core: 8.x
|
||||
dependencies:
|
||||
- field
|
||||
- drupal:field
|
||||
|
||||
@@ -39,7 +39,7 @@
|
||||
attach: function attach(context) {
|
||||
$(context).find('input[type="file"]').once('auto-file-upload').on('change.autoFileUpload', Drupal.file.triggerUploadButton);
|
||||
},
|
||||
detach: function detach(context, setting, trigger) {
|
||||
detach: function detach(context, settings, trigger) {
|
||||
if (trigger === 'unload') {
|
||||
$(context).find('input[type="file"]').removeOnce('auto-file-upload').off('.autoFileUpload');
|
||||
}
|
||||
@@ -52,10 +52,12 @@
|
||||
$context.find('.js-form-submit').on('mousedown', Drupal.file.disableFields);
|
||||
$context.find('.js-form-managed-file .js-form-submit').on('mousedown', Drupal.file.progressBar);
|
||||
},
|
||||
detach: function detach(context) {
|
||||
var $context = $(context);
|
||||
$context.find('.js-form-submit').off('mousedown', Drupal.file.disableFields);
|
||||
$context.find('.js-form-managed-file .js-form-submit').off('mousedown', Drupal.file.progressBar);
|
||||
detach: function detach(context, settings, trigger) {
|
||||
if (trigger === 'unload') {
|
||||
var $context = $(context);
|
||||
$context.find('.js-form-submit').off('mousedown', Drupal.file.disableFields);
|
||||
$context.find('.js-form-managed-file .js-form-submit').off('mousedown', Drupal.file.progressBar);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@@ -93,11 +95,7 @@
|
||||
$(event.target).closest('.js-form-managed-file').find('.js-form-submit').trigger('mousedown');
|
||||
},
|
||||
disableFields: function disableFields(event) {
|
||||
var $clickedButton = $(this).findOnce('ajax');
|
||||
|
||||
if (!$clickedButton.length) {
|
||||
return;
|
||||
}
|
||||
var $clickedButton = $(this);
|
||||
|
||||
var $enabledFields = [];
|
||||
if ($clickedButton.closest('div.js-form-managed-file').length > 0) {
|
||||
@@ -126,6 +124,7 @@
|
||||
setTimeout(function () {
|
||||
$clickedButton.closest('div.js-form-managed-file').find('div.ajax-progress-bar').slideDown();
|
||||
}, 500);
|
||||
$clickedButton.trigger('fileUpload');
|
||||
},
|
||||
openInNewWindow: function openInNewWindow(event) {
|
||||
event.preventDefault();
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
use Drupal\Core\Datetime\Entity\DateFormat;
|
||||
use Drupal\Core\Field\FieldDefinitionInterface;
|
||||
use Drupal\Core\Form\FormStateInterface;
|
||||
use Drupal\Core\Messenger\MessengerInterface;
|
||||
use Drupal\Core\Render\BubbleableMetadata;
|
||||
use Drupal\Core\Render\Element;
|
||||
use Drupal\Core\Routing\RouteMatchInterface;
|
||||
@@ -19,6 +20,11 @@ use Drupal\Component\Utility\Unicode;
|
||||
use Drupal\Core\Entity\EntityStorageInterface;
|
||||
use Drupal\Core\Template\Attribute;
|
||||
|
||||
/**
|
||||
* The regex pattern used when checking for insecure file types.
|
||||
*/
|
||||
define('FILE_INSECURE_EXTENSION_REGEX', '/\.(php|pl|py|cgi|asp|js)(\.|$)/i');
|
||||
|
||||
// Load all Field module hooks for File.
|
||||
require_once __DIR__ . '/file.field.inc';
|
||||
|
||||
@@ -156,7 +162,7 @@ function file_copy(FileInterface $source, $destination = NULL, $replace = FILE_E
|
||||
else {
|
||||
\Drupal::logger('file')->notice('File %file could not be copied because the destination %destination is invalid. This is often caused by improper use of file_copy() or a missing stream wrapper.', ['%file' => $source->getFileUri(), '%destination' => $destination]);
|
||||
}
|
||||
drupal_set_message(t('The specified file %file could not be copied because the destination is invalid. More information is available in the system log.', ['%file' => $source->getFileUri()]), 'error');
|
||||
\Drupal::messenger()->addError(t('The specified file %file could not be copied because the destination is invalid. More information is available in the system log.', ['%file' => $source->getFileUri()]));
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
@@ -231,7 +237,7 @@ function file_move(FileInterface $source, $destination = NULL, $replace = FILE_E
|
||||
else {
|
||||
\Drupal::logger('file')->notice('File %file could not be moved because the destination %destination is invalid. This may be caused by improper use of file_move() or a missing stream wrapper.', ['%file' => $source->getFileUri(), '%destination' => $destination]);
|
||||
}
|
||||
drupal_set_message(t('The specified file %file could not be moved because the destination is invalid. More information is available in the system log.', ['%file' => $source->getFileUri()]), 'error');
|
||||
\Drupal::messenger()->addError(t('The specified file %file could not be moved because the destination is invalid. More information is available in the system log.', ['%file' => $source->getFileUri()]));
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
@@ -479,7 +485,7 @@ function file_validate_image_resolution(FileInterface $file, $maximum_dimensions
|
||||
'%new_height' => $image->getHeight(),
|
||||
]);
|
||||
}
|
||||
drupal_set_message($message);
|
||||
\Drupal::messenger()->addStatus($message);
|
||||
}
|
||||
else {
|
||||
$errors[] = t('The image exceeds the maximum allowed dimensions and an attempt to resize it failed.');
|
||||
@@ -547,7 +553,7 @@ function file_save_data($data, $destination = NULL, $replace = FILE_EXISTS_RENAM
|
||||
}
|
||||
if (!file_valid_uri($destination)) {
|
||||
\Drupal::logger('file')->notice('The data could not be saved because the destination %destination is invalid. This may be caused by improper use of file_save_data() or a missing stream wrapper.', ['%destination' => $destination]);
|
||||
drupal_set_message(t('The data could not be saved because the destination is invalid. More information is available in the system log.'), 'error');
|
||||
\Drupal::messenger()->addError(t('The data could not be saved because the destination is invalid. More information is available in the system log.'));
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
@@ -761,7 +767,7 @@ function file_cron() {
|
||||
function _file_save_upload_from_form(array $element, FormStateInterface $form_state, $delta = NULL, $replace = FILE_EXISTS_RENAME) {
|
||||
// Get all errors set before calling this method. This will also clear them
|
||||
// from $_SESSION.
|
||||
$errors_before = drupal_get_messages('error');
|
||||
$errors_before = \Drupal::messenger()->deleteByType(MessengerInterface::TYPE_ERROR);
|
||||
|
||||
$upload_location = isset($element['#upload_location']) ? $element['#upload_location'] : FALSE;
|
||||
$upload_name = implode('_', $element['#parents']);
|
||||
@@ -771,9 +777,8 @@ function _file_save_upload_from_form(array $element, FormStateInterface $form_st
|
||||
|
||||
// Get new errors that are generated while trying to save the upload. This
|
||||
// will also clear them from $_SESSION.
|
||||
$errors_new = drupal_get_messages('error');
|
||||
if (!empty($errors_new['error'])) {
|
||||
$errors_new = $errors_new['error'];
|
||||
$errors_new = \Drupal::messenger()->deleteByType(MessengerInterface::TYPE_ERROR);
|
||||
if (!empty($errors_new)) {
|
||||
|
||||
if (count($errors_new) > 1) {
|
||||
// Render multiple errors into a single message.
|
||||
@@ -798,9 +803,9 @@ function _file_save_upload_from_form(array $element, FormStateInterface $form_st
|
||||
|
||||
// Ensure that errors set prior to calling this method are still shown to the
|
||||
// user.
|
||||
if (!empty($errors_before['error'])) {
|
||||
foreach ($errors_before['error'] as $error) {
|
||||
drupal_set_message($error, 'error');
|
||||
if (!empty($errors_before)) {
|
||||
foreach ($errors_before as $error) {
|
||||
\Drupal::messenger()->addError($error);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -888,13 +893,13 @@ function file_save_upload($form_field_name, $validators = [], $destination = FAL
|
||||
switch ($file_info->getError()) {
|
||||
case UPLOAD_ERR_INI_SIZE:
|
||||
case UPLOAD_ERR_FORM_SIZE:
|
||||
drupal_set_message(t('The file %file could not be saved because it exceeds %maxsize, the maximum allowed size for uploads.', ['%file' => $file_info->getFilename(), '%maxsize' => format_size(file_upload_max_size())]), 'error');
|
||||
\Drupal::messenger()->addError(t('The file %file could not be saved because it exceeds %maxsize, the maximum allowed size for uploads.', ['%file' => $file_info->getFilename(), '%maxsize' => format_size(file_upload_max_size())]));
|
||||
$files[$i] = FALSE;
|
||||
continue;
|
||||
|
||||
case UPLOAD_ERR_PARTIAL:
|
||||
case UPLOAD_ERR_NO_FILE:
|
||||
drupal_set_message(t('The file %file could not be saved because the upload did not complete.', ['%file' => $file_info->getFilename()]), 'error');
|
||||
\Drupal::messenger()->addError(t('The file %file could not be saved because the upload did not complete.', ['%file' => $file_info->getFilename()]));
|
||||
$files[$i] = FALSE;
|
||||
continue;
|
||||
|
||||
@@ -907,7 +912,7 @@ function file_save_upload($form_field_name, $validators = [], $destination = FAL
|
||||
|
||||
// Unknown error
|
||||
default:
|
||||
drupal_set_message(t('The file %file could not be saved. An unknown error has occurred.', ['%file' => $file_info->getFilename()]), 'error');
|
||||
\Drupal::messenger()->addError(t('The file %file could not be saved. An unknown error has occurred.', ['%file' => $file_info->getFilename()]));
|
||||
$files[$i] = FALSE;
|
||||
continue;
|
||||
|
||||
@@ -954,7 +959,7 @@ function file_save_upload($form_field_name, $validators = [], $destination = FAL
|
||||
// rename filename.php.foo and filename.php to filename.php.foo.txt and
|
||||
// filename.php.txt, respectively). Don't rename if 'allow_insecure_uploads'
|
||||
// evaluates to TRUE.
|
||||
if (!\Drupal::config('system.file')->get('allow_insecure_uploads') && preg_match('/\.(php|pl|py|cgi|asp|js)(\.|$)/i', $file->getFilename()) && (substr($file->getFilename(), -4) != '.txt')) {
|
||||
if (!\Drupal::config('system.file')->get('allow_insecure_uploads') && preg_match(FILE_INSECURE_EXTENSION_REGEX, $file->getFilename()) && (substr($file->getFilename(), -4) != '.txt')) {
|
||||
$file->setMimeType('text/plain');
|
||||
// The destination filename will also later be used to create the URI.
|
||||
$file->setFilename($file->getFilename() . '.txt');
|
||||
@@ -962,7 +967,7 @@ function file_save_upload($form_field_name, $validators = [], $destination = FAL
|
||||
// to add it here or else the file upload will fail.
|
||||
if (!empty($extensions)) {
|
||||
$validators['file_validate_extensions'][0] .= ' txt';
|
||||
drupal_set_message(t('For security reasons, your upload has been renamed to %filename.', ['%filename' => $file->getFilename()]));
|
||||
\Drupal::messenger()->addStatus(t('For security reasons, your upload has been renamed to %filename.', ['%filename' => $file->getFilename()]));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -974,7 +979,7 @@ function file_save_upload($form_field_name, $validators = [], $destination = FAL
|
||||
// Assert that the destination contains a valid stream.
|
||||
$destination_scheme = file_uri_scheme($destination);
|
||||
if (!file_stream_wrapper_valid_scheme($destination_scheme)) {
|
||||
drupal_set_message(t('The file could not be uploaded because the destination %destination is invalid.', ['%destination' => $destination]), 'error');
|
||||
\Drupal::messenger()->addError(t('The file could not be uploaded because the destination %destination is invalid.', ['%destination' => $destination]));
|
||||
$files[$i] = FALSE;
|
||||
continue;
|
||||
}
|
||||
@@ -988,7 +993,7 @@ function file_save_upload($form_field_name, $validators = [], $destination = FAL
|
||||
// If file_destination() returns FALSE then $replace === FILE_EXISTS_ERROR and
|
||||
// there's an existing file so we need to bail.
|
||||
if ($file->destination === FALSE) {
|
||||
drupal_set_message(t('The file %source could not be uploaded because a file by that name already exists in the destination %directory.', ['%source' => $form_field_name, '%directory' => $destination]), 'error');
|
||||
\Drupal::messenger()->addError(t('The file %source could not be uploaded because a file by that name already exists in the destination %directory.', ['%source' => $form_field_name, '%directory' => $destination]));
|
||||
$files[$i] = FALSE;
|
||||
continue;
|
||||
}
|
||||
@@ -1010,19 +1015,17 @@ function file_save_upload($form_field_name, $validators = [], $destination = FAL
|
||||
'#items' => $errors,
|
||||
],
|
||||
];
|
||||
// @todo Add support for render arrays in drupal_set_message()? See
|
||||
// https://www.drupal.org/node/2505497.
|
||||
drupal_set_message(\Drupal::service('renderer')->renderPlain($message), 'error');
|
||||
// @todo Add support for render arrays in
|
||||
// \Drupal\Core\Messenger\MessengerInterface::addMessage()?
|
||||
// @see https://www.drupal.org/node/2505497.
|
||||
\Drupal::messenger()->addError(\Drupal::service('renderer')->renderPlain($message));
|
||||
$files[$i] = FALSE;
|
||||
continue;
|
||||
}
|
||||
|
||||
// Move uploaded files from PHP's upload_tmp_dir to Drupal's temporary
|
||||
// directory. This overcomes open_basedir restrictions for future file
|
||||
// operations.
|
||||
$file->setFileUri($file->destination);
|
||||
if (!drupal_move_uploaded_file($file_info->getRealPath(), $file->getFileUri())) {
|
||||
drupal_set_message(t('File upload error. Could not move uploaded file.'), 'error');
|
||||
\Drupal::messenger()->addError(t('File upload error. Could not move uploaded file.'));
|
||||
\Drupal::logger('file')->notice('Upload error. Could not move uploaded file %file to destination %destination.', ['%file' => $file->getFilename(), '%destination' => $file->getFileUri()]);
|
||||
$files[$i] = FALSE;
|
||||
continue;
|
||||
|
||||
@@ -299,6 +299,10 @@ class ManagedFile extends FormElement {
|
||||
|
||||
// Add the upload progress callback.
|
||||
$element['upload_button']['#ajax']['progress']['url'] = Url::fromRoute('file.ajax_progress', ['key' => $upload_progress_key]);
|
||||
|
||||
// Set a custom submit event so we can modify the upload progress
|
||||
// identifier element before the form gets submitted.
|
||||
$element['upload_button']['#ajax']['event'] = 'fileUpload';
|
||||
}
|
||||
|
||||
// The file upload field itself.
|
||||
|
||||
@@ -18,6 +18,13 @@ use Drupal\user\UserInterface;
|
||||
* @ContentEntityType(
|
||||
* id = "file",
|
||||
* label = @Translation("File"),
|
||||
* label_collection = @Translation("Files"),
|
||||
* label_singular = @Translation("file"),
|
||||
* label_plural = @Translation("files"),
|
||||
* label_count = @PluralTranslation(
|
||||
* singular = "@count file",
|
||||
* plural = "@count files",
|
||||
* ),
|
||||
* handlers = {
|
||||
* "storage" = "Drupal\file\FileStorage",
|
||||
* "storage_schema" = "Drupal\file\FileStorageSchema",
|
||||
|
||||
@@ -52,11 +52,11 @@ class FileAccessControlHandler extends EntityAccessControlHandler {
|
||||
// services can be more properly injected.
|
||||
$allowed_fids = \Drupal::service('session')->get('anonymous_allowed_file_ids', []);
|
||||
if (!empty($allowed_fids[$entity->id()])) {
|
||||
return AccessResult::allowed();
|
||||
return AccessResult::allowed()->addCacheContexts(['session', 'user']);
|
||||
}
|
||||
}
|
||||
else {
|
||||
return AccessResult::allowed();
|
||||
return AccessResult::allowed()->addCacheContexts(['user']);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -64,11 +64,11 @@ class FileAccessControlHandler extends EntityAccessControlHandler {
|
||||
if ($operation == 'delete' || $operation == 'update') {
|
||||
$account = $this->prepareUser($account);
|
||||
$file_uid = $entity->get('uid')->getValue();
|
||||
// Only the file owner can delete and update the file entity.
|
||||
// Only the file owner can update or delete the file entity.
|
||||
if ($account->id() == $file_uid[0]['target_id']) {
|
||||
return AccessResult::allowed();
|
||||
}
|
||||
return AccessResult::forbidden();
|
||||
return AccessResult::forbidden('Only the file owner can update or delete the file entity.');
|
||||
}
|
||||
|
||||
// No opinion.
|
||||
@@ -127,8 +127,6 @@ class FileAccessControlHandler extends EntityAccessControlHandler {
|
||||
// create file entities that are referenced from another entity
|
||||
// (e.g. an image for a article). A contributed module is free to alter
|
||||
// this to allow file entities to be created directly.
|
||||
// @todo Update comment to mention REST module when
|
||||
// https://www.drupal.org/node/1927648 is fixed.
|
||||
return AccessResult::neutral();
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\file;
|
||||
|
||||
use Drupal\Core\DependencyInjection\ContainerBuilder;
|
||||
use Drupal\Core\DependencyInjection\ServiceModifierInterface;
|
||||
use Drupal\Core\StackMiddleware\NegotiationMiddleware;
|
||||
|
||||
/**
|
||||
* Adds 'application/octet-stream' as a known (bin) format.
|
||||
*/
|
||||
class FileServiceProvider implements ServiceModifierInterface {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function alter(ContainerBuilder $container) {
|
||||
if ($container->has('http_middleware.negotiation') && is_a($container->getDefinition('http_middleware.negotiation')->getClass(), NegotiationMiddleware::class, TRUE)) {
|
||||
$container->getDefinition('http_middleware.negotiation')->addMethodCall('registerFormat', ['bin', ['application/octet-stream']]);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -17,7 +17,7 @@ class FileStorageSchema extends SqlContentEntityStorageSchema {
|
||||
$schema = parent::getSharedTableFieldSchema($storage_definition, $table_name, $column_mapping);
|
||||
$field_name = $storage_definition->getName();
|
||||
|
||||
if ($table_name == 'file_managed') {
|
||||
if ($table_name == $this->storage->getBaseTable()) {
|
||||
switch ($field_name) {
|
||||
case 'status':
|
||||
case 'changed':
|
||||
|
||||
@@ -65,7 +65,7 @@ class FileViewsData extends EntityViewsData {
|
||||
$data['file_managed']['uid']['relationship']['title'] = $this->t('User who uploaded');
|
||||
$data['file_managed']['uid']['relationship']['label'] = $this->t('User who uploaded');
|
||||
|
||||
$data['file_usage']['table']['group'] = $this->t('File Usage');
|
||||
$data['file_usage']['table']['group'] = $this->t('File Usage');
|
||||
|
||||
// Provide field-type-things to several base tables; on the core files table
|
||||
// ("file_managed") so that we can create relationships from files to
|
||||
|
||||
@@ -365,7 +365,7 @@ class FileWidget extends WidgetBase implements ContainerFactoryPluginInterface {
|
||||
'%list' => implode(', ', $removed_names),
|
||||
];
|
||||
$message = t('Field %field can only hold @max values but there were @count uploaded. The following files have been omitted as a result: %list.', $args);
|
||||
drupal_set_message($message, 'warning');
|
||||
\Drupal::messenger()->addWarning($message);
|
||||
$values['fids'] = array_slice($values['fids'], 0, $keep);
|
||||
NestedArray::setValue($form_state->getValues(), $element['#parents'], $values);
|
||||
}
|
||||
|
||||
+6
-1
@@ -15,7 +15,12 @@ class FileValidationConstraintValidator extends ConstraintValidator {
|
||||
*/
|
||||
public function validate($value, Constraint $constraint) {
|
||||
// Get the file to execute validators.
|
||||
$file = $value->get('entity')->getTarget()->getValue();
|
||||
$target = $value->get('entity')->getTarget();
|
||||
if (!$target) {
|
||||
return;
|
||||
}
|
||||
|
||||
$file = $target->getValue();
|
||||
// Get the validators.
|
||||
$validators = $value->getUploadValidators();
|
||||
// Checks that a file meets the criteria specified by the validators.
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
|
||||
namespace Drupal\file\Plugin\migrate\destination;
|
||||
|
||||
use Drupal\Component\Utility\Unicode;
|
||||
use Drupal\Core\Field\Plugin\Field\FieldType\UriItem;
|
||||
use Drupal\migrate\Row;
|
||||
use Drupal\migrate\MigrateException;
|
||||
@@ -58,7 +57,7 @@ class EntityFile extends EntityContentBase {
|
||||
// Make it into a proper public file uri, stripping off the existing
|
||||
// scheme if present.
|
||||
$value = 'public://' . preg_replace('|^[a-z]+://|i', '', $value);
|
||||
$value = Unicode::substr($value, 0, $field_definitions['uri']->getSetting('max_length'));
|
||||
$value = mb_substr($value, 0, $field_definitions['uri']->getSetting('max_length'));
|
||||
// Create a real file, so File::preSave() can do filesize() on it.
|
||||
touch($value);
|
||||
$row->setDestinationProperty('uri', $value);
|
||||
|
||||
@@ -42,7 +42,7 @@ class FileField extends FieldPluginBase {
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function processFieldValues(MigrationInterface $migration, $field_name, $data) {
|
||||
public function defineValueProcessPipeline(MigrationInterface $migration, $field_name, $data) {
|
||||
$process = [
|
||||
'plugin' => 'd6_field_file',
|
||||
'source' => $field_name,
|
||||
|
||||
@@ -18,7 +18,7 @@ class FileField extends D6FileField {
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function processFieldValues(MigrationInterface $migration, $field_name, $data) {
|
||||
public function defineValueProcessPipeline(MigrationInterface $migration, $field_name, $data) {
|
||||
$process = [
|
||||
'plugin' => 'sub_process',
|
||||
'source' => $field_name,
|
||||
|
||||
@@ -42,6 +42,7 @@ class File extends DrupalSqlBase {
|
||||
public function query() {
|
||||
return $this->select('files', 'f')
|
||||
->fields('f')
|
||||
->condition('filepath', '/tmp%', 'NOT LIKE')
|
||||
->orderBy('timestamp')
|
||||
// If two or more files have the same timestamp, they'll end up in a
|
||||
// non-deterministic order. Ordering by fid (or any other unique field)
|
||||
@@ -88,6 +89,7 @@ class File extends DrupalSqlBase {
|
||||
'is_public' => $this->t('TRUE if the files directory is public otherwise FALSE.'),
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
|
||||
@@ -43,18 +43,21 @@ class File extends DrupalSqlBase {
|
||||
public function query() {
|
||||
$query = $this->select('file_managed', 'f')
|
||||
->fields('f')
|
||||
->condition('uri', 'temporary://%', 'NOT LIKE')
|
||||
->orderBy('f.timestamp');
|
||||
|
||||
// Filter by scheme(s), if configured.
|
||||
if (isset($this->configuration['scheme'])) {
|
||||
$schemes = [];
|
||||
// Remove 'temporary' scheme.
|
||||
$valid_schemes = array_diff((array) $this->configuration['scheme'], ['temporary']);
|
||||
// Accept either a single scheme, or a list.
|
||||
foreach ((array) $this->configuration['scheme'] as $scheme) {
|
||||
foreach ((array) $valid_schemes as $scheme) {
|
||||
$schemes[] = rtrim($scheme) . '://';
|
||||
}
|
||||
$schemes = array_map([$this->getDatabase(), 'escapeLike'], $schemes);
|
||||
|
||||
// uri LIKE 'public://%' OR uri LIKE 'private://%'
|
||||
// Add conditions, uri LIKE 'public://%' OR uri LIKE 'private://%'.
|
||||
$conditions = new Condition('OR');
|
||||
foreach ($schemes as $scheme) {
|
||||
$conditions->condition('uri', $scheme . '%', 'LIKE');
|
||||
|
||||
@@ -0,0 +1,586 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\file\Plugin\rest\resource;
|
||||
|
||||
use Drupal\Component\Utility\Bytes;
|
||||
use Drupal\Component\Utility\Crypt;
|
||||
use Drupal\Core\Config\Config;
|
||||
use Drupal\Core\Entity\EntityTypeManagerInterface;
|
||||
use Drupal\Core\Field\FieldDefinitionInterface;
|
||||
use Drupal\Core\File\FileSystemInterface;
|
||||
use Drupal\Core\Lock\LockBackendInterface;
|
||||
use Drupal\Core\Session\AccountInterface;
|
||||
use Drupal\Core\Utility\Token;
|
||||
use Drupal\file\FileInterface;
|
||||
use Drupal\rest\ModifiedResourceResponse;
|
||||
use Drupal\rest\Plugin\ResourceBase;
|
||||
use Drupal\Component\Render\PlainTextOutput;
|
||||
use Drupal\Core\Entity\EntityFieldManagerInterface;
|
||||
use Drupal\file\Entity\File;
|
||||
use Drupal\rest\Plugin\rest\resource\EntityResourceValidationTrait;
|
||||
use Drupal\rest\RequestHandler;
|
||||
use Psr\Log\LoggerInterface;
|
||||
use Symfony\Component\DependencyInjection\ContainerInterface;
|
||||
use Symfony\Component\HttpFoundation\File\MimeType\MimeTypeGuesserInterface;
|
||||
use Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException;
|
||||
use Symfony\Component\HttpKernel\Exception\BadRequestHttpException;
|
||||
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
|
||||
use Symfony\Component\HttpKernel\Exception\UnprocessableEntityHttpException;
|
||||
use Symfony\Component\Routing\Route;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\HttpKernel\Exception\HttpException;
|
||||
|
||||
/**
|
||||
* File upload resource.
|
||||
*
|
||||
* This is implemented as a field-level resource for the following reasons:
|
||||
* - Validation for uploaded files is tied to fields (allowed extensions, max
|
||||
* size, etc..).
|
||||
* - The actual files do not need to be stored in another temporary location,
|
||||
* to be later moved when they are referenced from a file field.
|
||||
* - Permission to upload a file can be determined by a users field level
|
||||
* create access to the file field.
|
||||
*
|
||||
* @RestResource(
|
||||
* id = "file:upload",
|
||||
* label = @Translation("File Upload"),
|
||||
* serialization_class = "Drupal\file\Entity\File",
|
||||
* uri_paths = {
|
||||
* "https://www.drupal.org/link-relations/create" = "/file/upload/{entity_type_id}/{bundle}/{field_name}"
|
||||
* }
|
||||
* )
|
||||
*/
|
||||
class FileUploadResource extends ResourceBase {
|
||||
|
||||
use EntityResourceValidationTrait {
|
||||
validate as resourceValidate;
|
||||
}
|
||||
|
||||
/**
|
||||
* The regex used to extract the filename from the content disposition header.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
const REQUEST_HEADER_FILENAME_REGEX = '@\bfilename(?<star>\*?)=\"(?<filename>.+)\"@';
|
||||
|
||||
/**
|
||||
* The amount of bytes to read in each iteration when streaming file data.
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
const BYTES_TO_READ = 8192;
|
||||
|
||||
/**
|
||||
* The file system service.
|
||||
*
|
||||
* @var \Drupal\Core\File\FileSystemInterface
|
||||
*/
|
||||
protected $fileSystem;
|
||||
|
||||
/**
|
||||
* The entity type manager.
|
||||
*
|
||||
* @var \Drupal\Core\Entity\EntityTypeManagerInterface
|
||||
*/
|
||||
protected $entityTypeManager;
|
||||
|
||||
/**
|
||||
* The entity field manager.
|
||||
*
|
||||
* @var \Drupal\Core\Entity\EntityFieldManagerInterface
|
||||
*/
|
||||
protected $entityFieldManager;
|
||||
|
||||
/**
|
||||
* The currently authenticated user.
|
||||
*
|
||||
* @var \Drupal\Core\Session\AccountInterface
|
||||
*/
|
||||
protected $currentUser;
|
||||
|
||||
/**
|
||||
* The MIME type guesser.
|
||||
*
|
||||
* @var \Symfony\Component\HttpFoundation\File\MimeType\MimeTypeGuesserInterface
|
||||
*/
|
||||
protected $mimeTypeGuesser;
|
||||
|
||||
/**
|
||||
* The token replacement instance.
|
||||
*
|
||||
* @var \Drupal\Core\Utility\Token
|
||||
*/
|
||||
protected $token;
|
||||
|
||||
/**
|
||||
* The lock service.
|
||||
*
|
||||
* @var \Drupal\Core\Lock\LockBackendInterface
|
||||
*/
|
||||
protected $lock;
|
||||
|
||||
/**
|
||||
* @var \Drupal\Core\Config\ImmutableConfig
|
||||
*/
|
||||
protected $systemFileConfig;
|
||||
|
||||
/**
|
||||
* Constructs a FileUploadResource instance.
|
||||
*
|
||||
* @param array $configuration
|
||||
* A configuration array containing information about the plugin instance.
|
||||
* @param string $plugin_id
|
||||
* The plugin_id for the plugin instance.
|
||||
* @param mixed $plugin_definition
|
||||
* The plugin implementation definition.
|
||||
* @param array $serializer_formats
|
||||
* The available serialization formats.
|
||||
* @param \Psr\Log\LoggerInterface $logger
|
||||
* A logger instance.
|
||||
* @param \Drupal\Core\File\FileSystemInterface $file_system
|
||||
* The file system service.
|
||||
* @param \Drupal\Core\Entity\EntityTypeManagerInterface $entity_type_manager
|
||||
* The entity type manager.
|
||||
* @param \Drupal\Core\Entity\EntityFieldManagerInterface $entity_field_manager
|
||||
* The entity field manager.
|
||||
* @param \Drupal\Core\Session\AccountInterface $current_user
|
||||
* The currently authenticated user.
|
||||
* @param \Symfony\Component\HttpFoundation\File\MimeType\MimeTypeGuesserInterface $mime_type_guesser
|
||||
* The MIME type guesser.
|
||||
* @param \Drupal\Core\Utility\Token $token
|
||||
* The token replacement instance.
|
||||
* @param \Drupal\Core\Lock\LockBackendInterface $lock
|
||||
* The lock service.
|
||||
* @param \Drupal\Core\Config\Config $system_file_config
|
||||
* The system file configuration.
|
||||
*/
|
||||
public function __construct(array $configuration, $plugin_id, $plugin_definition, $serializer_formats, LoggerInterface $logger, FileSystemInterface $file_system, EntityTypeManagerInterface $entity_type_manager, EntityFieldManagerInterface $entity_field_manager, AccountInterface $current_user, MimeTypeGuesserInterface $mime_type_guesser, Token $token, LockBackendInterface $lock, Config $system_file_config) {
|
||||
parent::__construct($configuration, $plugin_id, $plugin_definition, $serializer_formats, $logger);
|
||||
$this->fileSystem = $file_system;
|
||||
$this->entityTypeManager = $entity_type_manager;
|
||||
$this->entityFieldManager = $entity_field_manager;
|
||||
$this->currentUser = $current_user;
|
||||
$this->mimeTypeGuesser = $mime_type_guesser;
|
||||
$this->token = $token;
|
||||
$this->lock = $lock;
|
||||
$this->systemFileConfig = $system_file_config;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) {
|
||||
return new static(
|
||||
$configuration,
|
||||
$plugin_id,
|
||||
$plugin_definition,
|
||||
$container->getParameter('serializer.formats'),
|
||||
$container->get('logger.factory')->get('rest'),
|
||||
$container->get('file_system'),
|
||||
$container->get('entity_type.manager'),
|
||||
$container->get('entity_field.manager'),
|
||||
$container->get('current_user'),
|
||||
$container->get('file.mime_type.guesser'),
|
||||
$container->get('token'),
|
||||
$container->get('lock'),
|
||||
$container->get('config.factory')->get('system.file')
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function permissions() {
|
||||
// Access to this resource depends on field-level access so no explicit
|
||||
// permissions are required.
|
||||
// @see \Drupal\file\Plugin\rest\resource\FileUploadResource::validateAndLoadFieldDefinition()
|
||||
// @see \Drupal\rest\Plugin\rest\resource\EntityResource::permissions()
|
||||
return [];
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a file from an endpoint.
|
||||
*
|
||||
* @param \Symfony\Component\HttpFoundation\Request $request
|
||||
* The current request.
|
||||
* @param string $entity_type_id
|
||||
* The entity type ID.
|
||||
* @param string $bundle
|
||||
* The entity bundle. This will be the same as $entity_type_id for entity
|
||||
* types that don't support bundles.
|
||||
* @param string $field_name
|
||||
* The field name.
|
||||
*
|
||||
* @return \Drupal\rest\ModifiedResourceResponse
|
||||
* A 201 response, on success.
|
||||
*
|
||||
* @throws \Symfony\Component\HttpKernel\Exception\HttpException
|
||||
* Thrown when temporary files cannot be written, a lock cannot be acquired,
|
||||
* or when temporary files cannot be moved to their new location.
|
||||
*/
|
||||
public function post(Request $request, $entity_type_id, $bundle, $field_name) {
|
||||
$filename = $this->validateAndParseContentDispositionHeader($request);
|
||||
|
||||
$field_definition = $this->validateAndLoadFieldDefinition($entity_type_id, $bundle, $field_name);
|
||||
|
||||
$destination = $this->getUploadLocation($field_definition->getSettings());
|
||||
|
||||
// Check the destination file path is writable.
|
||||
if (!file_prepare_directory($destination, FILE_CREATE_DIRECTORY)) {
|
||||
throw new HttpException(500, 'Destination file path is not writable');
|
||||
}
|
||||
|
||||
$validators = $this->getUploadValidators($field_definition);
|
||||
|
||||
$prepared_filename = $this->prepareFilename($filename, $validators);
|
||||
|
||||
// Create the file.
|
||||
$file_uri = "{$destination}/{$prepared_filename}";
|
||||
|
||||
$temp_file_path = $this->streamUploadData();
|
||||
|
||||
// This will take care of altering $file_uri if a file already exists.
|
||||
file_unmanaged_prepare($temp_file_path, $file_uri);
|
||||
|
||||
// Lock based on the prepared file URI.
|
||||
$lock_id = $this->generateLockIdFromFileUri($file_uri);
|
||||
|
||||
if (!$this->lock->acquire($lock_id)) {
|
||||
throw new HttpException(503, sprintf('File "%s" is already locked for writing'), NULL, ['Retry-After' => 1]);
|
||||
}
|
||||
|
||||
// Begin building file entity.
|
||||
$file = File::create([]);
|
||||
$file->setOwnerId($this->currentUser->id());
|
||||
$file->setFilename($prepared_filename);
|
||||
$file->setMimeType($this->mimeTypeGuesser->guess($prepared_filename));
|
||||
$file->setFileUri($file_uri);
|
||||
// Set the size. This is done in File::preSave() but we validate the file
|
||||
// before it is saved.
|
||||
$file->setSize(@filesize($temp_file_path));
|
||||
|
||||
// Validate the file entity against entity-level validation and field-level
|
||||
// validators.
|
||||
$this->validate($file, $validators);
|
||||
|
||||
// Move the file to the correct location after validation. Use
|
||||
// FILE_EXISTS_ERROR as the file location has already been determined above
|
||||
// in file_unmanaged_prepare().
|
||||
if (!file_unmanaged_move($temp_file_path, $file_uri, FILE_EXISTS_ERROR)) {
|
||||
throw new HttpException(500, 'Temporary file could not be moved to file location');
|
||||
}
|
||||
|
||||
$file->save();
|
||||
|
||||
$this->lock->release($lock_id);
|
||||
|
||||
// 201 Created responses return the newly created entity in the response
|
||||
// body. These responses are not cacheable, so we add no cacheability
|
||||
// metadata here.
|
||||
return new ModifiedResourceResponse($file, 201);
|
||||
}
|
||||
|
||||
/**
|
||||
* Streams file upload data to temporary file and moves to file destination.
|
||||
*
|
||||
* @return string
|
||||
* The temp file path.
|
||||
*
|
||||
* @throws \Symfony\Component\HttpKernel\Exception\HttpException
|
||||
* Thrown when input data cannot be read, the temporary file cannot be
|
||||
* opened, or the temporary file cannot be written.
|
||||
*/
|
||||
protected function streamUploadData() {
|
||||
// 'rb' is needed so reading works correctly on Windows environments too.
|
||||
$file_data = fopen('php://input', 'rb');
|
||||
|
||||
$temp_file_path = $this->fileSystem->tempnam('temporary://', 'file');
|
||||
$temp_file = fopen($temp_file_path, 'wb');
|
||||
|
||||
if ($temp_file) {
|
||||
while (!feof($file_data)) {
|
||||
$read = fread($file_data, static::BYTES_TO_READ);
|
||||
|
||||
if ($read === FALSE) {
|
||||
// Close the file streams.
|
||||
fclose($temp_file);
|
||||
fclose($file_data);
|
||||
$this->logger->error('Input data could not be read');
|
||||
throw new HttpException(500, 'Input file data could not be read');
|
||||
}
|
||||
|
||||
if (fwrite($temp_file, $read) === FALSE) {
|
||||
// Close the file streams.
|
||||
fclose($temp_file);
|
||||
fclose($file_data);
|
||||
$this->logger->error('Temporary file data for "%path" could not be written', ['%path' => $temp_file_path]);
|
||||
throw new HttpException(500, 'Temporary file data could not be written');
|
||||
}
|
||||
}
|
||||
|
||||
// Close the temp file stream.
|
||||
fclose($temp_file);
|
||||
}
|
||||
else {
|
||||
// Close the file streams.
|
||||
fclose($temp_file);
|
||||
fclose($file_data);
|
||||
$this->logger->error('Temporary file "%path" could not be opened for file upload', ['%path' => $temp_file_path]);
|
||||
throw new HttpException(500, 'Temporary file could not be opened');
|
||||
}
|
||||
|
||||
// Close the input stream.
|
||||
fclose($file_data);
|
||||
|
||||
return $temp_file_path;
|
||||
}
|
||||
|
||||
/**
|
||||
* Validates and extracts the filename from the Content-Disposition header.
|
||||
*
|
||||
* @param \Symfony\Component\HttpFoundation\Request $request
|
||||
* The request object.
|
||||
*
|
||||
* @return string
|
||||
* The filename extracted from the header.
|
||||
*
|
||||
* @throws \Symfony\Component\HttpKernel\Exception\BadRequestHttpException
|
||||
* Thrown when the 'Content-Disposition' request header is invalid.
|
||||
*/
|
||||
protected function validateAndParseContentDispositionHeader(Request $request) {
|
||||
// Firstly, check the header exists.
|
||||
if (!$request->headers->has('content-disposition')) {
|
||||
throw new BadRequestHttpException('"Content-Disposition" header is required. A file name in the format "filename=FILENAME" must be provided');
|
||||
}
|
||||
|
||||
$content_disposition = $request->headers->get('content-disposition');
|
||||
|
||||
// Parse the header value. This regex does not allow an empty filename.
|
||||
// i.e. 'filename=""'. This also matches on a word boundary so other keys
|
||||
// like 'not_a_filename' don't work.
|
||||
if (!preg_match(static::REQUEST_HEADER_FILENAME_REGEX, $content_disposition, $matches)) {
|
||||
throw new BadRequestHttpException('No filename found in "Content-Disposition" header. A file name in the format "filename=FILENAME" must be provided');
|
||||
}
|
||||
|
||||
// Check for the "filename*" format. This is currently unsupported.
|
||||
if (!empty($matches['star'])) {
|
||||
throw new BadRequestHttpException('The extended "filename*" format is currently not supported in the "Content-Disposition" header');
|
||||
}
|
||||
|
||||
// Don't validate the actual filename here, that will be done by the upload
|
||||
// validators in validate().
|
||||
// @see \Drupal\file\Plugin\rest\resource\FileUploadResource::validate()
|
||||
$filename = $matches['filename'];
|
||||
|
||||
// Make sure only the filename component is returned. Path information is
|
||||
// stripped as per https://tools.ietf.org/html/rfc6266#section-4.3.
|
||||
return basename($filename);
|
||||
}
|
||||
|
||||
/**
|
||||
* Validates and loads a field definition instance.
|
||||
*
|
||||
* @param string $entity_type_id
|
||||
* The entity type ID the field is attached to.
|
||||
* @param string $bundle
|
||||
* The bundle the field is attached to.
|
||||
* @param string $field_name
|
||||
* The field name.
|
||||
*
|
||||
* @return \Drupal\Core\Field\FieldDefinitionInterface
|
||||
* The field definition.
|
||||
*
|
||||
* @throws \Symfony\Component\HttpKernel\Exception\BadRequestHttpException
|
||||
* Thrown when the field does not exist.
|
||||
* @throws \Symfony\Component\HttpFoundation\File\Exception\AccessDeniedException
|
||||
* Thrown when the target type of the field is not a file, or the current
|
||||
* user does not have 'edit' access for the field.
|
||||
*/
|
||||
protected function validateAndLoadFieldDefinition($entity_type_id, $bundle, $field_name) {
|
||||
$field_definitions = $this->entityFieldManager->getFieldDefinitions($entity_type_id, $bundle);
|
||||
if (!isset($field_definitions[$field_name])) {
|
||||
throw new NotFoundHttpException(sprintf('Field "%s" does not exist', $field_name));
|
||||
}
|
||||
|
||||
/** @var \Drupal\Core\Field\FieldDefinitionInterface $field_definition */
|
||||
$field_definition = $field_definitions[$field_name];
|
||||
if ($field_definition->getSetting('target_type') !== 'file') {
|
||||
throw new AccessDeniedHttpException(sprintf('"%s" is not a file field', $field_name));
|
||||
}
|
||||
|
||||
$entity_access_control_handler = $this->entityTypeManager->getAccessControlHandler($entity_type_id);
|
||||
$bundle = $this->entityTypeManager->getDefinition($entity_type_id)->hasKey('bundle') ? $bundle : NULL;
|
||||
$access_result = $entity_access_control_handler->createAccess($bundle, NULL, [], TRUE)
|
||||
->andIf($entity_access_control_handler->fieldAccess('edit', $field_definition, NULL, NULL, TRUE));
|
||||
if (!$access_result->isAllowed()) {
|
||||
throw new AccessDeniedHttpException($access_result->getReason());
|
||||
}
|
||||
|
||||
return $field_definition;
|
||||
}
|
||||
|
||||
/**
|
||||
* Validates the file.
|
||||
*
|
||||
* @param \Drupal\file\FileInterface $file
|
||||
* The file entity to validate.
|
||||
* @param array $validators
|
||||
* An array of upload validators to pass to file_validate().
|
||||
*
|
||||
* @throws \Symfony\Component\HttpKernel\Exception\UnprocessableEntityHttpException
|
||||
* Thrown when there are file validation errors.
|
||||
*/
|
||||
protected function validate(FileInterface $file, array $validators) {
|
||||
$this->resourceValidate($file);
|
||||
|
||||
// Validate the file based on the field definition configuration.
|
||||
$errors = file_validate($file, $validators);
|
||||
|
||||
if (!empty($errors)) {
|
||||
$message = "Unprocessable Entity: file validation failed.\n";
|
||||
$message .= implode("\n", array_map(function ($error) {
|
||||
return PlainTextOutput::renderFromHtml($error);
|
||||
}, $errors));
|
||||
|
||||
throw new UnprocessableEntityHttpException($message);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepares the filename to strip out any malicious extensions.
|
||||
*
|
||||
* @param string $filename
|
||||
* The file name.
|
||||
* @param array $validators
|
||||
* The array of upload validators.
|
||||
*
|
||||
* @return string
|
||||
* The prepared/munged filename.
|
||||
*/
|
||||
protected function prepareFilename($filename, array &$validators) {
|
||||
if (!empty($validators['file_validate_extensions'][0])) {
|
||||
// If there is a file_validate_extensions validator and a list of
|
||||
// valid extensions, munge the filename to protect against possible
|
||||
// malicious extension hiding within an unknown file type. For example,
|
||||
// "filename.html.foo".
|
||||
$filename = file_munge_filename($filename, $validators['file_validate_extensions'][0]);
|
||||
}
|
||||
|
||||
// Rename potentially executable files, to help prevent exploits (i.e. will
|
||||
// rename filename.php.foo and filename.php to filename.php.foo.txt and
|
||||
// filename.php.txt, respectively). Don't rename if 'allow_insecure_uploads'
|
||||
// evaluates to TRUE.
|
||||
if (!$this->systemFileConfig->get('allow_insecure_uploads') && preg_match(FILE_INSECURE_EXTENSION_REGEX, $filename) && (substr($filename, -4) != '.txt')) {
|
||||
// The destination filename will also later be used to create the URI.
|
||||
$filename .= '.txt';
|
||||
|
||||
// The .txt extension may not be in the allowed list of extensions. We
|
||||
// have to add it here or else the file upload will fail.
|
||||
if (!empty($validators['file_validate_extensions'][0])) {
|
||||
$validators['file_validate_extensions'][0] .= ' txt';
|
||||
}
|
||||
}
|
||||
|
||||
return $filename;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines the URI for a file field.
|
||||
*
|
||||
* @param array $settings
|
||||
* The array of field settings.
|
||||
*
|
||||
* @return string
|
||||
* An un-sanitized file directory URI with tokens replaced. The result of
|
||||
* the token replacement is then converted to plain text and returned.
|
||||
*/
|
||||
protected function getUploadLocation(array $settings) {
|
||||
$destination = trim($settings['file_directory'], '/');
|
||||
|
||||
// Replace tokens. As the tokens might contain HTML we convert it to plain
|
||||
// text.
|
||||
$destination = PlainTextOutput::renderFromHtml($this->token->replace($destination, []));
|
||||
return $settings['uri_scheme'] . '://' . $destination;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the upload validators for a field definition.
|
||||
*
|
||||
* This is copied from \Drupal\file\Plugin\Field\FieldType\FileItem as there
|
||||
* is no entity instance available here that that a FileItem would exist for.
|
||||
*
|
||||
* @param \Drupal\Core\Field\FieldDefinitionInterface $field_definition
|
||||
* The field definition for which to get validators.
|
||||
*
|
||||
* @return array
|
||||
* An array suitable for passing to file_save_upload() or the file field
|
||||
* element's '#upload_validators' property.
|
||||
*/
|
||||
protected function getUploadValidators(FieldDefinitionInterface $field_definition) {
|
||||
$validators = [
|
||||
// Add in our check of the file name length.
|
||||
'file_validate_name_length' => [],
|
||||
];
|
||||
$settings = $field_definition->getSettings();
|
||||
|
||||
// Cap the upload size according to the PHP limit.
|
||||
$max_filesize = Bytes::toInt(file_upload_max_size());
|
||||
if (!empty($settings['max_filesize'])) {
|
||||
$max_filesize = min($max_filesize, Bytes::toInt($settings['max_filesize']));
|
||||
}
|
||||
|
||||
// There is always a file size limit due to the PHP server limit.
|
||||
$validators['file_validate_size'] = [$max_filesize];
|
||||
|
||||
// Add the extension check if necessary.
|
||||
if (!empty($settings['file_extensions'])) {
|
||||
$validators['file_validate_extensions'] = [$settings['file_extensions']];
|
||||
}
|
||||
|
||||
return $validators;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function getBaseRoute($canonical_path, $method) {
|
||||
return new Route($canonical_path, [
|
||||
'_controller' => RequestHandler::class . '::handleRaw',
|
||||
],
|
||||
$this->getBaseRouteRequirements($method),
|
||||
[],
|
||||
'',
|
||||
[],
|
||||
// The HTTP method is a requirement for this route.
|
||||
[$method]
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function getBaseRouteRequirements($method) {
|
||||
$requirements = parent::getBaseRouteRequirements($method);
|
||||
|
||||
// Add the content type format access check. This will enforce that all
|
||||
// incoming requests can only use the 'application/octet-stream'
|
||||
// Content-Type header.
|
||||
$requirements['_content_type_format'] = 'bin';
|
||||
|
||||
return $requirements;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates a lock ID based on the file URI.
|
||||
*
|
||||
* @param $file_uri
|
||||
* The file URI.
|
||||
*
|
||||
* @return string
|
||||
* The generated lock ID.
|
||||
*/
|
||||
protected static function generateLockIdFromFileUri($file_uri) {
|
||||
return 'file:rest:' . Crypt::hashBase64($file_uri);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -2,6 +2,8 @@
|
||||
|
||||
namespace Drupal\file\Tests;
|
||||
|
||||
@trigger_error('The ' . __NAMESPACE__ . '\FileFieldTestBase is deprecated in Drupal 8.5.x and will be removed before Drupal 9.0.0. Instead, use \Drupal\Tests\file\Functional\FileFieldTestBase. See https://www.drupal.org/node/2969361.', E_USER_DEPRECATED);
|
||||
|
||||
use Drupal\field\Entity\FieldStorageConfig;
|
||||
use Drupal\field\Entity\FieldConfig;
|
||||
use Drupal\file\FileInterface;
|
||||
|
||||
@@ -4,7 +4,6 @@ namespace Drupal\file\Tests;
|
||||
|
||||
use Drupal\comment\Entity\Comment;
|
||||
use Drupal\comment\Tests\CommentTestTrait;
|
||||
use Drupal\Component\Utility\Unicode;
|
||||
use Drupal\Core\Url;
|
||||
use Drupal\field\Entity\FieldConfig;
|
||||
use Drupal\field\Entity\FieldStorageConfig;
|
||||
@@ -270,7 +269,7 @@ class FileFieldWidgetTest extends FileFieldTestBase {
|
||||
// Try to upload exactly the allowed number of files on revision. Create an
|
||||
// empty node first, to fill it in its first revision.
|
||||
$node = $this->drupalCreateNode([
|
||||
'type' => $type_name
|
||||
'type' => $type_name,
|
||||
]);
|
||||
$this->uploadNodeFile($test_file, $field_name, $node->id(), 1);
|
||||
$node_storage->resetCache([$nid]);
|
||||
@@ -461,7 +460,7 @@ class FileFieldWidgetTest extends FileFieldTestBase {
|
||||
* Tests file widget element.
|
||||
*/
|
||||
public function testWidgetElement() {
|
||||
$field_name = Unicode::strtolower($this->randomMachineName());
|
||||
$field_name = mb_strtolower($this->randomMachineName());
|
||||
$html_name = str_replace('_', '-', $field_name);
|
||||
$this->createFileField($field_name, 'node', 'article', ['cardinality' => FieldStorageConfig::CARDINALITY_UNLIMITED]);
|
||||
$file = $this->getTestFile('text');
|
||||
|
||||
@@ -10,6 +10,7 @@ namespace Drupal\file\Tests;
|
||||
* that aren't related to fields into it.
|
||||
*/
|
||||
class FileManagedFileElementTest extends FileFieldTestBase {
|
||||
|
||||
/**
|
||||
* Tests the managed_file element type.
|
||||
*/
|
||||
|
||||
@@ -2,6 +2,8 @@
|
||||
|
||||
namespace Drupal\file\Tests;
|
||||
|
||||
@trigger_error('The ' . __NAMESPACE__ . '\FileManagedTestBase is deprecated in Drupal 8.5.x and will be removed before Drupal 9.0.0. Instead, use \Drupal\Tests\file\Functional\FileManagedTestBase. See https://www.drupal.org/node/2969361.', E_USER_DEPRECATED);
|
||||
|
||||
use Drupal\file\Entity\File;
|
||||
use Drupal\file\FileInterface;
|
||||
use Drupal\simpletest\WebTestBase;
|
||||
|
||||
@@ -85,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)]));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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!'));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -49,7 +49,7 @@ $connection->update('key_value')
|
||||
->condition('collection', 'entity.definitions.installed')
|
||||
->condition('name', 'node.field_storage_definitions')
|
||||
->fields([
|
||||
'value' => serialize($installed)
|
||||
'value' => serialize($installed),
|
||||
])
|
||||
->execute();
|
||||
|
||||
|
||||
@@ -5,5 +5,5 @@ package: Testing
|
||||
version: VERSION
|
||||
core: 8.x
|
||||
dependencies:
|
||||
- file
|
||||
- views
|
||||
- drupal:file
|
||||
- drupal:views
|
||||
|
||||
+14
-11
@@ -1,6 +1,6 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\file\Tests;
|
||||
namespace Drupal\Tests\file\Functional;
|
||||
|
||||
/**
|
||||
* Tests for download/file transfer functions.
|
||||
@@ -8,6 +8,7 @@ namespace Drupal\file\Tests;
|
||||
* @group file
|
||||
*/
|
||||
class DownloadTest extends FileManagedTestBase {
|
||||
|
||||
protected function setUp() {
|
||||
parent::setUp();
|
||||
// Clear out any hook calls.
|
||||
@@ -25,16 +26,17 @@ class DownloadTest extends FileManagedTestBase {
|
||||
// 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.');
|
||||
$this->drupalHead($url);
|
||||
$this->assertResponse(200, 'Confirmed that the generated URL is correct by downloading the 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.');
|
||||
$this->drupalHead($url);
|
||||
$this->assertResponse(200, 'Confirmed that the generated URL is correct by downloading the shipped file.');
|
||||
$response = $http_client->head($url);
|
||||
$this->assertEquals(200, $response->getStatusCode(), 'Confirmed that the generated URL is correct by downloading the shipped file.');
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -60,7 +62,7 @@ class DownloadTest extends FileManagedTestBase {
|
||||
$file->setPermanent();
|
||||
$file->save();
|
||||
|
||||
$url = file_create_url($file->getFileUri());
|
||||
$url = file_create_url($file->getFileUri());
|
||||
|
||||
// Set file_test access header to allow the download.
|
||||
file_test_set_return('download', ['x-foo' => 'Bar']);
|
||||
@@ -70,17 +72,18 @@ class DownloadTest extends FileManagedTestBase {
|
||||
$this->assertResponse(200, 'Correctly allowed access to a file when file_test provides headers.');
|
||||
|
||||
// Test that the file transferred correctly.
|
||||
$this->assertEqual($contents, $this->content, 'Contents of the file are correct.');
|
||||
$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);
|
||||
$this->drupalHead($url);
|
||||
$this->assertResponse(403, 'Correctly denied access to a file when file_test sets the header to -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());
|
||||
$this->drupalHead($url);
|
||||
$this->assertResponse(404, 'Correctly returned 404 response for a non-existent file.');
|
||||
$response = $http_client->head($url, ['http_errors' => FALSE]);
|
||||
$this->assertSame(404, $response->getStatusCode(), 'Correctly returned 404 response for a non-existent file.');
|
||||
}
|
||||
|
||||
/**
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\file\Tests;
|
||||
namespace Drupal\Tests\file\Functional;
|
||||
|
||||
use Drupal\node\Entity\Node;
|
||||
use Drupal\user\RoleInterface;
|
||||
+6
-5
@@ -1,6 +1,6 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\file\Tests;
|
||||
namespace Drupal\Tests\file\Functional;
|
||||
|
||||
use Drupal\Core\Field\FieldStorageDefinitionInterface;
|
||||
use Drupal\file\Entity\File;
|
||||
@@ -53,8 +53,7 @@ class FileFieldDisplayTest extends FileFieldTestBase {
|
||||
$this->assertNoText($field_name, format_string('Field label is hidden when no file attached for formatter %formatter', ['%formatter' => $formatter]));
|
||||
}
|
||||
|
||||
$test_file = $this->getTestFile('text');
|
||||
simpletest_generate_file('escaped-&-text', 64, 10, 'text');
|
||||
$this->generateFile('escaped-&-text', 64, 10, 'text');
|
||||
$test_file = File::create([
|
||||
'uri' => 'public://escaped-&-text.txt',
|
||||
'name' => 'escaped-&-text',
|
||||
@@ -97,15 +96,17 @@ class FileFieldDisplayTest extends FileFieldTestBase {
|
||||
// Test that fields appear as expected after during the preview.
|
||||
// Add a second file.
|
||||
$name = 'files[' . $field_name . '_1][]';
|
||||
$edit[$name] = \Drupal::service('file_system')->realpath($test_file->getFileUri());
|
||||
$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("node/$nid/edit", $edit, t('Preview'));
|
||||
$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.');
|
||||
}
|
||||
|
||||
/**
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\file\Tests;
|
||||
namespace Drupal\Tests\file\Functional;
|
||||
|
||||
/**
|
||||
* Tests file formatter access.
|
||||
+2
-1
@@ -1,6 +1,6 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\file\Tests;
|
||||
namespace Drupal\Tests\file\Functional;
|
||||
|
||||
use Drupal\file\Entity\File;
|
||||
|
||||
@@ -10,6 +10,7 @@ use Drupal\file\Entity\File;
|
||||
* @group file
|
||||
*/
|
||||
class FileFieldPathTest extends FileFieldTestBase {
|
||||
|
||||
/**
|
||||
* Tests the normal formatter display on node display.
|
||||
*/
|
||||
+3
-3
@@ -1,6 +1,6 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\file\Tests;
|
||||
namespace Drupal\Tests\file\Functional;
|
||||
|
||||
use Drupal\file\Entity\File;
|
||||
|
||||
@@ -60,12 +60,12 @@ class FileFieldRSSContentTest extends FileFieldTestBase {
|
||||
$this->drupalGet('rss.xml');
|
||||
$uploaded_filename = str_replace('public://', '', $node_file->getFileUri());
|
||||
$selector = sprintf(
|
||||
'enclosure[url="%s"][length="%s"][type="%s"]',
|
||||
'enclosure[@url="%s"][@length="%s"][@type="%s"]',
|
||||
file_create_url("public://$uploaded_filename", ['absolute' => TRUE]),
|
||||
$node_file->getSize(),
|
||||
$node_file->getMimeType()
|
||||
);
|
||||
$this->assertTrue(!empty($this->cssSelect($selector)), 'File field RSS enclosure is displayed when viewing the RSS feed.');
|
||||
$this->assertNotNull($this->getSession()->getDriver()->find('xpath', $selector), 'File field RSS enclosure is displayed when viewing the RSS feed.');
|
||||
}
|
||||
|
||||
}
|
||||
+2
-1
@@ -1,6 +1,6 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\file\Tests;
|
||||
namespace Drupal\Tests\file\Functional;
|
||||
|
||||
use Drupal\file\Entity\File;
|
||||
|
||||
@@ -10,6 +10,7 @@ use Drupal\file\Entity\File;
|
||||
* @group file
|
||||
*/
|
||||
class FileFieldRevisionTest extends FileFieldTestBase {
|
||||
|
||||
/**
|
||||
* Tests creating multiple revisions of a node and managing attached files.
|
||||
*
|
||||
@@ -7,6 +7,7 @@ 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.
|
||||
@@ -14,6 +15,9 @@ use Drupal\file\Entity\File;
|
||||
abstract class FileFieldTestBase extends BrowserTestBase {
|
||||
|
||||
use FileFieldCreationTrait;
|
||||
use TestFileCreationTrait {
|
||||
getTestFiles as drupalGetTestFiles;
|
||||
}
|
||||
|
||||
/**
|
||||
* Modules to enable.
|
||||
@@ -156,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;
|
||||
}
|
||||
@@ -172,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'));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -185,7 +189,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'));
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
+1
-22
@@ -1,6 +1,6 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\file\Tests;
|
||||
namespace Drupal\Tests\file\Functional;
|
||||
|
||||
use Drupal\Core\Field\FieldStorageDefinitionInterface;
|
||||
use Drupal\field\Entity\FieldConfig;
|
||||
@@ -187,25 +187,4 @@ class FileFieldValidateTest extends FileFieldTestBase {
|
||||
$this->assertText('Article ' . $node->getTitle() . ' has been updated.');
|
||||
}
|
||||
|
||||
/**
|
||||
* Test the validation message is displayed only once for ajax uploads.
|
||||
*/
|
||||
public function testAJAXValidationMessage() {
|
||||
$field_name = strtolower($this->randomMachineName());
|
||||
$this->createFileField($field_name, 'node', 'article');
|
||||
|
||||
$this->drupalGet('node/add/article');
|
||||
/** @var \Drupal\file\FileInterface $image_file */
|
||||
$image_file = $this->getTestFile('image');
|
||||
$edit = [
|
||||
'files[' . $field_name . '_0]' => $this->container->get('file_system')->realpath($image_file->getFileUri()),
|
||||
'title[0][value]' => $this->randomMachineName(),
|
||||
];
|
||||
$this->drupalPostAjaxForm(NULL, $edit, $field_name . '_0_upload_button');
|
||||
$elements = $this->xpath('//div[contains(@class, :class)]', [
|
||||
':class' => 'messages--error',
|
||||
]);
|
||||
$this->assertEqual(count($elements), 1, 'Ajax validation messages are displayed once.');
|
||||
}
|
||||
|
||||
}
|
||||
+3
-3
@@ -1,6 +1,6 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\file\Tests;
|
||||
namespace Drupal\Tests\file\Functional;
|
||||
|
||||
use Drupal\node\Entity\Node;
|
||||
use Drupal\file\Entity\File;
|
||||
@@ -110,7 +110,7 @@ class FileListingTest extends FileFieldTestBase {
|
||||
$this->assertLinkByHref(file_create_url($file->getFileUri()));
|
||||
$this->assertLinkByHref('admin/content/files/usage/' . $file->id());
|
||||
}
|
||||
$this->assertFalse(preg_match('/views-field-status priority-low\">\s*' . t('Temporary') . '/', $this->getRawContent()), 'All files are stored as permanent.');
|
||||
$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;
|
||||
@@ -127,7 +127,7 @@ class FileListingTest extends FileFieldTestBase {
|
||||
$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' => t('Temporary')]);
|
||||
$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.
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\file\Tests;
|
||||
namespace Drupal\Tests\file\Functional;
|
||||
|
||||
use Drupal\file\Entity\File;
|
||||
|
||||
+19
-21
@@ -1,9 +1,9 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\file\Tests;
|
||||
namespace Drupal\Tests\file\Functional;
|
||||
|
||||
use Drupal\Core\Entity\Plugin\Validation\Constraint\ReferenceAccessConstraint;
|
||||
use Drupal\Component\Utility\SafeMarkup;
|
||||
use Drupal\Component\Render\FormattableMarkup;
|
||||
use Drupal\file\Entity\File;
|
||||
use Drupal\node\Entity\NodeType;
|
||||
use Drupal\user\RoleInterface;
|
||||
@@ -81,23 +81,29 @@ class FilePrivateTest extends FileFieldTestBase {
|
||||
$edit['title[0][value]'] = $this->randomMachineName();
|
||||
$this->drupalPostForm('node/add/' . $type_name, $edit, t('Save'));
|
||||
$new_node = $this->drupalGetNodeByTitle($edit['title[0][value]']);
|
||||
$edit[$field_name . '[0][fids]'] = $node_file->id();
|
||||
$this->drupalPostForm('node/' . $new_node->id() . '/edit', $edit, t('Save'));
|
||||
|
||||
// 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(SafeMarkup::format($constraint->message, ['%type' => 'file', '%id' => $node_file->id()]));
|
||||
$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();
|
||||
$edit[$field_name . '[0][fids]'] = $node_file->id();
|
||||
$this->drupalPostForm('node/add/' . $type_name, $edit, t('Save'));
|
||||
// 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(SafeMarkup::format($constraint->message, ['%type' => 'file', '%id' => $node_file->id()]));
|
||||
$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);
|
||||
@@ -144,9 +150,7 @@ class FilePrivateTest extends FileFieldTestBase {
|
||||
$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->curlClose();
|
||||
$this->curlCookies = [];
|
||||
$this->cookies = [];
|
||||
$this->getSession()->reset();
|
||||
$this->drupalGet($file_url);
|
||||
$this->assertResponse(403, 'Confirmed that another anonymous user cannot access the temporary file.');
|
||||
|
||||
@@ -174,9 +178,7 @@ class FilePrivateTest extends FileFieldTestBase {
|
||||
$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->curlClose();
|
||||
$this->curlCookies = [];
|
||||
$this->cookies = [];
|
||||
$this->getSession()->reset();
|
||||
$this->drupalGet($file_url);
|
||||
$this->assertResponse(403, 'Confirmed that another anonymous user cannot access the file whose references were removed.');
|
||||
|
||||
@@ -197,9 +199,7 @@ class FilePrivateTest extends FileFieldTestBase {
|
||||
$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->curlClose();
|
||||
$this->curlCookies = [];
|
||||
$this->cookies = [];
|
||||
$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.');
|
||||
|
||||
@@ -214,7 +214,7 @@ class FilePrivateTest extends FileFieldTestBase {
|
||||
$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->setPublished(FALSE);
|
||||
$new_node->setUnpublished();
|
||||
$new_node->save();
|
||||
$file = File::load($new_node->{$field_name}->target_id);
|
||||
$this->assertTrue($file->isPermanent(), 'File is permanent.');
|
||||
@@ -224,9 +224,7 @@ class FilePrivateTest extends FileFieldTestBase {
|
||||
$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->curlClose();
|
||||
$this->curlCookies = [];
|
||||
$this->cookies = [];
|
||||
$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.');
|
||||
}
|
||||
+2
-1
@@ -1,6 +1,6 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\file\Tests;
|
||||
namespace Drupal\Tests\file\Functional;
|
||||
|
||||
use Drupal\Component\Utility\Html;
|
||||
use Drupal\Core\Render\BubbleableMetadata;
|
||||
@@ -13,6 +13,7 @@ use Drupal\file\Entity\File;
|
||||
* @group file
|
||||
*/
|
||||
class FileTokenReplaceTest extends FileFieldTestBase {
|
||||
|
||||
/**
|
||||
* Creates a file, then tests the tokens generated from it.
|
||||
*/
|
||||
@@ -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';
|
||||
|
||||
}
|
||||
@@ -2,7 +2,6 @@
|
||||
|
||||
namespace Drupal\Tests\file\Functional\Formatter;
|
||||
|
||||
use Drupal\Component\Utility\Unicode;
|
||||
use Drupal\Core\Field\FieldStorageDefinitionInterface;
|
||||
use Drupal\field\Entity\FieldConfig;
|
||||
use Drupal\field\Entity\FieldStorageConfig;
|
||||
@@ -47,7 +46,7 @@ abstract class FileMediaFormatterTestBase extends BrowserTestBase {
|
||||
*/
|
||||
protected function createMediaField($formatter, $file_extensions, array $formatter_settings = []) {
|
||||
$entity_type = $bundle = 'entity_test';
|
||||
$field_name = Unicode::strtolower($this->randomMachineName());
|
||||
$field_name = mb_strtolower($this->randomMachineName());
|
||||
|
||||
FieldStorageConfig::create([
|
||||
'entity_type' => $entity_type,
|
||||
|
||||
@@ -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',
|
||||
],
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
}
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\file\Tests;
|
||||
namespace Drupal\Tests\file\Functional;
|
||||
|
||||
use Drupal\file\Entity\File;
|
||||
use Drupal\node\Entity\Node;
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\file\Tests;
|
||||
namespace Drupal\Tests\file\Functional;
|
||||
|
||||
/**
|
||||
* Tests the file uploading functions.
|
||||
@@ -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';
|
||||
|
||||
}
|
||||
+24
-14
@@ -1,8 +1,9 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\file\Tests;
|
||||
namespace Drupal\Tests\file\Functional;
|
||||
|
||||
use Drupal\file\Entity\File;
|
||||
use Drupal\Tests\TestFileCreationTrait;
|
||||
|
||||
/**
|
||||
* Tests the _file_save_upload_from_form() function.
|
||||
@@ -13,6 +14,10 @@ use Drupal\file\Entity\File;
|
||||
*/
|
||||
class SaveUploadFormTest extends FileManagedTestBase {
|
||||
|
||||
use TestFileCreationTrait {
|
||||
getTestFiles as drupalGetTestFiles;
|
||||
}
|
||||
|
||||
/**
|
||||
* Modules to enable.
|
||||
*
|
||||
@@ -298,7 +303,7 @@ class SaveUploadFormTest extends FileManagedTestBase {
|
||||
$file_system = \Drupal::service('file_system');
|
||||
$edit = [
|
||||
'file_test_replace' => FILE_EXISTS_RENAME,
|
||||
'files[file_test_upload][]' => $file_system->realpath($this->image->getFileUri())
|
||||
'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.');
|
||||
@@ -316,7 +321,7 @@ class SaveUploadFormTest extends FileManagedTestBase {
|
||||
$file_system = \Drupal::service('file_system');
|
||||
$edit = [
|
||||
'file_test_replace' => FILE_EXISTS_REPLACE,
|
||||
'files[file_test_upload][]' => $file_system->realpath($this->image->getFileUri())
|
||||
'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.');
|
||||
@@ -334,7 +339,7 @@ class SaveUploadFormTest extends FileManagedTestBase {
|
||||
$file_system = \Drupal::service('file_system');
|
||||
$edit = [
|
||||
'file_test_replace' => FILE_EXISTS_ERROR,
|
||||
'files[file_test_upload][]' => $file_system->realpath($this->image->getFileUri())
|
||||
'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.');
|
||||
@@ -365,7 +370,7 @@ class SaveUploadFormTest extends FileManagedTestBase {
|
||||
$file_system = \Drupal::service('file_system');
|
||||
$edit = [
|
||||
'file_subdir' => $test_directory,
|
||||
'files[file_test_upload][]' => $file_system->realpath($this->image->getFileUri())
|
||||
'files[file_test_upload][]' => $file_system->realpath($this->image->getFileUri()),
|
||||
];
|
||||
|
||||
\Drupal::state()->set('file_test.disable_error_collection', TRUE);
|
||||
@@ -379,7 +384,7 @@ class SaveUploadFormTest extends FileManagedTestBase {
|
||||
$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()
|
||||
'@destination' => 'temporary://' . $test_directory . '/' . $this->image->getFilename(),
|
||||
]), 'Found upload error log entry.');
|
||||
}
|
||||
|
||||
@@ -409,7 +414,7 @@ class SaveUploadFormTest extends FileManagedTestBase {
|
||||
$edit = [
|
||||
'files[file_test_upload][]' => $file_system->realpath($this->image->getFileUri()),
|
||||
'error_message' => $error,
|
||||
'extensions' => 'foo'
|
||||
'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.');
|
||||
@@ -419,7 +424,7 @@ class SaveUploadFormTest extends FileManagedTestBase {
|
||||
// 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(): 2');
|
||||
$this->assertRaw('Number of error messages after _file_save_upload_from_form(): 1');
|
||||
|
||||
// Test a successful upload with no messages.
|
||||
$edit = [
|
||||
@@ -445,17 +450,22 @@ class SaveUploadFormTest extends FileManagedTestBase {
|
||||
|
||||
/** @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 = [
|
||||
'files[file_test_upload][]' => [
|
||||
$file_system->realpath($this->phpfile->uri),
|
||||
$file_system->realpath($textfile->uri),
|
||||
],
|
||||
'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->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.');
|
||||
|
||||
@@ -473,7 +483,7 @@ class SaveUploadFormTest extends FileManagedTestBase {
|
||||
$file_system = \Drupal::service('file_system');
|
||||
$edit = [
|
||||
'files[file_test_upload][]' => $file_system->realpath($this->image->getFileUri()),
|
||||
'extensions' => 'foo'
|
||||
'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.');
|
||||
+12
-6
@@ -1,8 +1,9 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\file\Tests;
|
||||
namespace Drupal\Tests\file\Functional;
|
||||
|
||||
use Drupal\file\Entity\File;
|
||||
use Drupal\Tests\TestFileCreationTrait;
|
||||
|
||||
/**
|
||||
* Tests the file_save_upload() function.
|
||||
@@ -10,6 +11,11 @@ use Drupal\file\Entity\File;
|
||||
* @group file
|
||||
*/
|
||||
class SaveUploadTest extends FileManagedTestBase {
|
||||
|
||||
use TestFileCreationTrait {
|
||||
getTestFiles as drupalGetTestFiles;
|
||||
}
|
||||
|
||||
/**
|
||||
* Modules to enable.
|
||||
*
|
||||
@@ -280,7 +286,7 @@ class SaveUploadTest extends FileManagedTestBase {
|
||||
public function testExistingRename() {
|
||||
$edit = [
|
||||
'file_test_replace' => FILE_EXISTS_RENAME,
|
||||
'files[file_test_upload]' => \Drupal::service('file_system')->realpath($this->image->getFileUri())
|
||||
'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.');
|
||||
@@ -296,7 +302,7 @@ class SaveUploadTest extends FileManagedTestBase {
|
||||
public function testExistingReplace() {
|
||||
$edit = [
|
||||
'file_test_replace' => FILE_EXISTS_REPLACE,
|
||||
'files[file_test_upload]' => \Drupal::service('file_system')->realpath($this->image->getFileUri())
|
||||
'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.');
|
||||
@@ -312,7 +318,7 @@ class SaveUploadTest extends FileManagedTestBase {
|
||||
public function testExistingError() {
|
||||
$edit = [
|
||||
'file_test_replace' => FILE_EXISTS_ERROR,
|
||||
'files[file_test_upload]' => \Drupal::service('file_system')->realpath($this->image->getFileUri())
|
||||
'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.');
|
||||
@@ -341,7 +347,7 @@ class SaveUploadTest extends FileManagedTestBase {
|
||||
|
||||
$edit = [
|
||||
'file_subdir' => $test_directory,
|
||||
'files[file_test_upload]' => \Drupal::service('file_system')->realpath($this->image->getFileUri())
|
||||
'files[file_test_upload]' => \Drupal::service('file_system')->realpath($this->image->getFileUri()),
|
||||
];
|
||||
|
||||
\Drupal::state()->set('file_test.disable_error_collection', TRUE);
|
||||
@@ -355,7 +361,7 @@ class SaveUploadTest extends FileManagedTestBase {
|
||||
$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()
|
||||
'@destination' => 'temporary://' . $test_directory . '/' . $this->image->getFilename(),
|
||||
]), 'Found upload error log entry.');
|
||||
}
|
||||
|
||||
+5
-5
@@ -1,13 +1,13 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\file\Tests\Update;
|
||||
namespace Drupal\Tests\file\Functional\Update;
|
||||
|
||||
use Drupal\system\Tests\Update\UpdatePathTestBase;
|
||||
use Drupal\FunctionalTests\Update\UpdatePathTestBase;
|
||||
|
||||
/**
|
||||
* Tests File update path.
|
||||
*
|
||||
* @group file
|
||||
* @group legacy
|
||||
*/
|
||||
class FileUpdateTest extends UpdatePathTestBase {
|
||||
|
||||
@@ -21,8 +21,8 @@ class FileUpdateTest extends UpdatePathTestBase {
|
||||
*/
|
||||
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',
|
||||
__DIR__ . '/../../../../../system/tests/fixtures/update/drupal-8.bare.standard.php.gz',
|
||||
__DIR__ . '/../../../../tests/fixtures/update/drupal-8.file_formatters_update_2677990.php',
|
||||
];
|
||||
}
|
||||
|
||||
+1
@@ -10,6 +10,7 @@ use Drupal\FunctionalTests\Update\UpdatePathTestBase;
|
||||
* @see https://www.drupal.org/node/2801777
|
||||
*
|
||||
* @group Update
|
||||
* @group legacy
|
||||
*/
|
||||
class FileUsageTemporaryDeletionConfigurationUpdateTest extends UpdatePathTestBase {
|
||||
|
||||
|
||||
+2
-2
@@ -1,10 +1,10 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\file\Tests\Views;
|
||||
namespace Drupal\Tests\file\Functional\Views;
|
||||
|
||||
use Drupal\field\Entity\FieldConfig;
|
||||
use Drupal\file\Entity\File;
|
||||
use Drupal\views\Tests\ViewTestBase;
|
||||
use Drupal\Tests\views\Functional\ViewTestBase;
|
||||
use Drupal\views\Views;
|
||||
use Drupal\views\Tests\ViewTestData;
|
||||
use Drupal\field\Entity\FieldStorageConfig;
|
||||
@@ -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.');
|
||||
}
|
||||
|
||||
}
|
||||
+2
-2
@@ -3,7 +3,7 @@
|
||||
namespace Drupal\Tests\file\FunctionalJavascript;
|
||||
|
||||
use Drupal\Component\Utility\Bytes;
|
||||
use Drupal\FunctionalJavascriptTests\JavascriptTestBase;
|
||||
use Drupal\FunctionalJavascriptTests\WebDriverTestBase;
|
||||
use Drupal\Tests\TestFileCreationTrait;
|
||||
use Drupal\Tests\file\Functional\FileFieldCreationTrait;
|
||||
|
||||
@@ -12,7 +12,7 @@ use Drupal\Tests\file\Functional\FileFieldCreationTrait;
|
||||
*
|
||||
* @group file
|
||||
*/
|
||||
class MaximumFileSizeExceededUploadTest extends JavascriptTestBase {
|
||||
class MaximumFileSizeExceededUploadTest extends WebDriverTestBase {
|
||||
|
||||
use FileFieldCreationTrait;
|
||||
use TestFileCreationTrait;
|
||||
|
||||
@@ -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());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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).
|
||||
*/
|
||||
|
||||
@@ -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());
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -10,6 +10,7 @@ use Drupal\file\Entity\File;
|
||||
* @group file
|
||||
*/
|
||||
class LoadTest extends FileManagedUnitTestBase {
|
||||
|
||||
/**
|
||||
* Try to load a non-existent file by fid.
|
||||
*/
|
||||
|
||||
@@ -30,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']));
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
+1
-1
@@ -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']));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -2,36 +2,80 @@
|
||||
|
||||
namespace Drupal\Tests\file\Kernel\Migrate\d7;
|
||||
|
||||
use Drupal\Core\StreamWrapper\PublicStream;
|
||||
use Drupal\Core\StreamWrapper\StreamWrapperInterface;
|
||||
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->installSchema('file', ['file_usage']);
|
||||
$this->installEntitySchema('file');
|
||||
$this->container->get('stream_wrapper_manager')->registerWrapper('public', PublicStream::class, StreamWrapperInterface::NORMAL);
|
||||
$this->installSchema('file', ['file_usage']);
|
||||
|
||||
$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));
|
||||
$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('d7_file');
|
||||
$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('public://');
|
||||
$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());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
namespace Drupal\Tests\file\Kernel\Migrate\d7;
|
||||
|
||||
use Drupal\file\Entity\File;
|
||||
use Drupal\file\FileInterface;
|
||||
use Drupal\Tests\migrate_drupal\Kernel\d7\MigrateDrupal7TestBase;
|
||||
|
||||
/**
|
||||
@@ -15,6 +14,9 @@ class MigrateFileTest extends MigrateDrupal7TestBase {
|
||||
|
||||
use FileMigrationSetupTrait;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static $modules = ['file'];
|
||||
|
||||
/**
|
||||
@@ -22,44 +24,19 @@ class MigrateFileTest extends MigrateDrupal7TestBase {
|
||||
*/
|
||||
protected function setUp() {
|
||||
parent::setUp();
|
||||
|
||||
$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',
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -67,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));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -3,8 +3,6 @@
|
||||
namespace Drupal\Tests\file\Kernel\Migrate\d7;
|
||||
|
||||
use Drupal\Core\DependencyInjection\ContainerBuilder;
|
||||
use Drupal\file\Entity\File;
|
||||
use Drupal\file\FileInterface;
|
||||
use Drupal\Tests\migrate_drupal\Kernel\d7\MigrateDrupal7TestBase;
|
||||
|
||||
/**
|
||||
@@ -14,6 +12,8 @@ use Drupal\Tests\migrate_drupal\Kernel\d7\MigrateDrupal7TestBase;
|
||||
*/
|
||||
class MigratePrivateFileTest extends MigrateDrupal7TestBase {
|
||||
|
||||
use FileMigrationSetupTrait;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
@@ -25,22 +25,19 @@ class MigratePrivateFileTest extends MigrateDrupal7TestBase {
|
||||
protected function setUp() {
|
||||
parent::setUp();
|
||||
$this->setSetting('file_private_path', $this->container->get('site.path') . '/private');
|
||||
$this->installEntitySchema('file');
|
||||
$fs = $this->container->get('file_system');
|
||||
$this->fileMigrationSetup();
|
||||
}
|
||||
|
||||
// Ensure that the private files directory exists.
|
||||
$fs->mkdir('private://sites/default/private/', NULL, TRUE);
|
||||
// Put test file in the source directory.
|
||||
file_put_contents('private://sites/default/private/Babylon5.txt', str_repeat('*', 3));
|
||||
|
||||
/** @var \Drupal\migrate\Plugin\Migration $migration */
|
||||
$migration = $this->getMigration('d7_file_private');
|
||||
// Set the source plugin's source_file_private_path configuration value,
|
||||
// which would normally be set by the user running the migration.
|
||||
$source = $migration->getSourceConfiguration();
|
||||
$source['constants']['source_base_path'] = $fs->realpath('private://');
|
||||
$migration->set('source', $source);
|
||||
$this->executeMigration($migration);
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function getFileMigrationInfo() {
|
||||
return [
|
||||
'path' => 'private://sites/default/private/Babylon5.txt',
|
||||
'size' => '3',
|
||||
'base_path' => 'private://',
|
||||
'plugin_id' => 'd7_file_private',
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -52,42 +49,6 @@ class MigratePrivateFileTest extends MigrateDrupal7TestBase {
|
||||
->addTag('stream_wrapper', ['scheme' => 'private']);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
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());
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests that all expected files are migrated.
|
||||
*/
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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([
|
||||
|
||||
@@ -10,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();
|
||||
|
||||
|
||||
@@ -8,6 +8,7 @@ namespace Drupal\Tests\file\Kernel;
|
||||
* @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();
|
||||
|
||||
|
||||
@@ -33,7 +33,7 @@ class FileCckTest extends UnitTestCase {
|
||||
|
||||
$migration = $this->prophesize(MigrationInterface::class);
|
||||
|
||||
// The plugin's processFieldValues() method will call
|
||||
// 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().
|
||||
@@ -64,7 +64,7 @@ class FileCckTest extends UnitTestCase {
|
||||
return [
|
||||
['image', 'imagefield_widget'],
|
||||
['file', 'filefield_widget'],
|
||||
['file', 'x_widget']
|
||||
['file', 'x_widget'],
|
||||
];
|
||||
}
|
||||
|
||||
|
||||
@@ -33,7 +33,7 @@ class FileCckTest extends UnitTestCase {
|
||||
|
||||
$migration = $this->prophesize(MigrationInterface::class);
|
||||
|
||||
// The plugin's processFieldValues() method will call
|
||||
// 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().
|
||||
@@ -69,7 +69,7 @@ class FileCckTest extends UnitTestCase {
|
||||
return [
|
||||
['image', 'imagefield_widget'],
|
||||
['file', 'filefield_widget'],
|
||||
['file', 'x_widget']
|
||||
['file', 'x_widget'],
|
||||
];
|
||||
}
|
||||
|
||||
|
||||
@@ -32,7 +32,7 @@ class ImageCckTest extends UnitTestCase {
|
||||
|
||||
$migration = $this->prophesize(MigrationInterface::class);
|
||||
|
||||
// The plugin's processFieldValues() method will call
|
||||
// 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().
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -32,7 +32,7 @@ class FileFieldTest extends UnitTestCase {
|
||||
|
||||
$migration = $this->prophesize(MigrationInterface::class);
|
||||
|
||||
// The plugin's processFieldValues() method will call
|
||||
// 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().
|
||||
@@ -44,10 +44,10 @@ class FileFieldTest extends UnitTestCase {
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers ::processFieldValues
|
||||
* @covers ::defineValueProcessPipeline
|
||||
*/
|
||||
public function testProcessFieldValues() {
|
||||
$this->plugin->processFieldValues($this->migration, 'somefieldname', []);
|
||||
public function testDefineValueProcessPipeline($method = 'defineValueProcessPipeline') {
|
||||
$this->plugin->$method($this->migration, 'somefieldname', []);
|
||||
|
||||
$expected = [
|
||||
'plugin' => 'd6_field_file',
|
||||
@@ -63,7 +63,7 @@ class FileFieldTest extends UnitTestCase {
|
||||
return [
|
||||
['image', 'imagefield_widget'],
|
||||
['file', 'filefield_widget'],
|
||||
['file', 'x_widget']
|
||||
['file', 'x_widget'],
|
||||
];
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -32,7 +32,7 @@ class FileFieldTest extends UnitTestCase {
|
||||
|
||||
$migration = $this->prophesize(MigrationInterface::class);
|
||||
|
||||
// The plugin's processFieldValues() method will call
|
||||
// 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().
|
||||
@@ -44,10 +44,10 @@ class FileFieldTest extends UnitTestCase {
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers ::processFieldValues
|
||||
* @covers ::defineValueProcessPipeline
|
||||
*/
|
||||
public function testProcessFieldValues() {
|
||||
$this->plugin->processFieldValues($this->migration, 'somefieldname', []);
|
||||
public function testDefineValueProcessPipeline($method = 'defineValueProcessPipeline') {
|
||||
$this->plugin->$method($this->migration, 'somefieldname', []);
|
||||
|
||||
$expected = [
|
||||
'plugin' => 'sub_process',
|
||||
@@ -68,7 +68,7 @@ class FileFieldTest extends UnitTestCase {
|
||||
return [
|
||||
['image', 'imagefield_widget'],
|
||||
['file', 'filefield_widget'],
|
||||
['file', 'x_widget']
|
||||
['file', 'x_widget'],
|
||||
];
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -32,7 +32,7 @@ class ImageFieldTest extends UnitTestCase {
|
||||
|
||||
$migration = $this->prophesize(MigrationInterface::class);
|
||||
|
||||
// The plugin's processFieldValues() method will call
|
||||
// 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().
|
||||
@@ -44,11 +44,12 @@ class ImageFieldTest extends UnitTestCase {
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers ::processFieldValues
|
||||
* @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 testProcessFieldValues() {
|
||||
$this->plugin->processFieldValues($this->migration, 'somefieldname', []);
|
||||
public function testDefineValueProcessPipeline($method = 'defineValueProcessPipeline') {
|
||||
$this->plugin->$method($this->migration, 'somefieldname', []);
|
||||
|
||||
$expected = [
|
||||
'plugin' => 'sub_process',
|
||||
|
||||
Reference in New Issue
Block a user