Issue #3426506 by kim.pepper, smustgrave, mstrelan, alexpott: Create enums for File exists options and deprecate consts

(cherry picked from commit 8ae0a0230f)
merge-requests/7413/head
Alex Pott 2024-04-09 08:50:53 +01:00
parent 2fc0e9b818
commit 24807f9cb4
No known key found for this signature in database
GPG Key ID: BDA67E7EE836E5CE
47 changed files with 488 additions and 290 deletions

View File

@ -4,6 +4,7 @@ namespace Drupal\Core\Asset;
use Drupal\Component\Utility\Crypt; use Drupal\Component\Utility\Crypt;
use Drupal\Core\File\Exception\FileException; use Drupal\Core\File\Exception\FileException;
use Drupal\Core\File\FileExists;
use Drupal\Core\File\FileSystemInterface; use Drupal\Core\File\FileSystemInterface;
/** /**
@ -52,7 +53,7 @@ class AssetDumper implements AssetDumperUriInterface {
// Create the CSS or JS file. // Create the CSS or JS file.
$this->fileSystem->prepareDirectory($path, FileSystemInterface::CREATE_DIRECTORY); $this->fileSystem->prepareDirectory($path, FileSystemInterface::CREATE_DIRECTORY);
try { try {
if (!file_exists($uri) && !$this->fileSystem->saveData($data, $uri, FileSystemInterface::EXISTS_REPLACE)) { if (!file_exists($uri) && !$this->fileSystem->saveData($data, $uri, FileExists::Replace)) {
return FALSE; return FALSE;
} }
} }
@ -69,7 +70,7 @@ class AssetDumper implements AssetDumperUriInterface {
// generating a file that won't be used. // generating a file that won't be used.
if (extension_loaded('zlib') && \Drupal::config('system.performance')->get($file_extension . '.gzip')) { if (extension_loaded('zlib') && \Drupal::config('system.performance')->get($file_extension . '.gzip')) {
try { try {
if (!file_exists($uri . '.gz') && !$this->fileSystem->saveData(gzencode($data, 9, FORCE_GZIP), $uri . '.gz', FileSystemInterface::EXISTS_REPLACE)) { if (!file_exists($uri . '.gz') && !$this->fileSystem->saveData(gzencode($data, 9, FORCE_GZIP), $uri . '.gz', FileExists::Replace)) {
return FALSE; return FALSE;
} }
} }

View File

@ -0,0 +1,41 @@
<?php
declare(strict_types=1);
namespace Drupal\Core\File;
/**
* A flag for defining the behavior when dealing with existing files.
*/
enum FileExists {
/* Appends a number until name is unique. */
case Rename;
/* Replace the existing file. */
case Replace;
/* Do nothing and return FALSE. */
case Error;
/**
* Provide backwards compatibility with legacy integer values.
*
* @param int $legacyInt
* The legacy constant value from \Drupal\Core\File\FileSystemInterface.
* @param string $methodName
* The method name for the deprecation message.
*
* @deprecated in drupal:10.3.0 and is removed from drupal:12.0.0. Use
* \Drupal\Core\File\FileExists enum directly instead.
*
* @see https://www.drupal.org/node/3426517
*/
public static function fromLegacyInt(int $legacyInt, string $methodName): self {
@trigger_error("Passing the \$fileExists argument as an integer to $methodName() is deprecated in drupal:10.3.0 and is removed from drupal:12.0.0. Use \Drupal\Core\File\FileExists enum instead. See https://www.drupal.org/node/3426517", E_USER_DEPRECATED);
return match ($legacyInt) {
0 => FileExists::Rename,
2 => FileExists::Error,
default => FileExists::Replace,
};
}
}

View File

@ -287,8 +287,12 @@ class FileSystem implements FileSystemInterface {
/** /**
* {@inheritdoc} * {@inheritdoc}
*/ */
public function copy($source, $destination, $replace = self::EXISTS_RENAME) { public function copy($source, $destination, /* FileExists */$fileExists = FileExists::Rename) {
$this->prepareDestination($source, $destination, $replace); if (!$fileExists instanceof FileExists) {
// @phpstan-ignore-next-line
$fileExists = FileExists::fromLegacyInt($fileExists, __METHOD__);
}
$this->prepareDestination($source, $destination, $fileExists);
if (!@copy($source, $destination)) { if (!@copy($source, $destination)) {
// If the copy failed and realpaths exist, retry the operation using them // If the copy failed and realpaths exist, retry the operation using them
@ -364,8 +368,12 @@ class FileSystem implements FileSystemInterface {
/** /**
* {@inheritdoc} * {@inheritdoc}
*/ */
public function move($source, $destination, $replace = self::EXISTS_RENAME) { public function move($source, $destination, /* FileExists */$fileExists = FileExists::Rename) {
$this->prepareDestination($source, $destination, $replace); if (!$fileExists instanceof FileExists) {
// @phpstan-ignore-next-line
$fileExists = FileExists::fromLegacyInt($fileExists, __METHOD__);
}
$this->prepareDestination($source, $destination, $fileExists);
// Ensure compatibility with Windows. // Ensure compatibility with Windows.
// @see \Drupal\Core\File\FileSystemInterface::unlink(). // @see \Drupal\Core\File\FileSystemInterface::unlink().
@ -412,17 +420,20 @@ class FileSystem implements FileSystemInterface {
* A URI containing the destination that $source should be moved/copied to. * A URI containing the destination that $source should be moved/copied to.
* The URI may be a bare filepath (without a scheme) and in that case the * The URI may be a bare filepath (without a scheme) and in that case the
* default scheme (file://) will be used. * default scheme (file://) will be used.
* @param int $replace * @param \Drupal\Core\File\FileExists|int $fileExists
* Replace behavior when the destination file already exists: * Replace behavior when the destination file already exists.
* - FileSystemInterface::EXISTS_REPLACE - Replace the existing file. *
* - FileSystemInterface::EXISTS_RENAME - Append _{incrementing number} * @throws \TypeError
* until the filename is unique. * Thrown when the $fileExists parameter is not an enum or legacy int.
* - FileSystemInterface::EXISTS_ERROR - Do nothing and return FALSE.
* *
* @see \Drupal\Core\File\FileSystemInterface::copy() * @see \Drupal\Core\File\FileSystemInterface::copy()
* @see \Drupal\Core\File\FileSystemInterface::move() * @see \Drupal\Core\File\FileSystemInterface::move()
*/ */
protected function prepareDestination($source, &$destination, $replace) { protected function prepareDestination($source, &$destination, /* FileExists */$fileExists) {
if (!$fileExists instanceof FileExists) {
// @phpstan-ignore-next-line
$fileExists = FileExists::fromLegacyInt($fileExists, __METHOD__);
}
$original_source = $source; $original_source = $source;
if (!file_exists($source)) { if (!file_exists($source)) {
@ -448,7 +459,7 @@ class FileSystem implements FileSystemInterface {
} }
// Determine whether we can perform this operation based on overwrite rules. // Determine whether we can perform this operation based on overwrite rules.
$destination = $this->getDestinationFilename($destination, $replace); $destination = $this->getDestinationFilename($destination, $fileExists);
if ($destination === FALSE) { if ($destination === FALSE) {
throw new FileExistsException("File '$original_source' could not be copied because a file by that name already exists in the destination directory ('$destination')."); throw new FileExistsException("File '$original_source' could not be copied because a file by that name already exists in the destination directory ('$destination').");
} }
@ -464,7 +475,11 @@ class FileSystem implements FileSystemInterface {
/** /**
* {@inheritdoc} * {@inheritdoc}
*/ */
public function saveData($data, $destination, $replace = self::EXISTS_RENAME) { public function saveData($data, $destination, /* FileExists */$fileExists = FileExists::Rename) {
if (!$fileExists instanceof FileExists) {
// @phpstan-ignore-next-line
$fileExists = FileExists::fromLegacyInt($fileExists, __METHOD__);
}
// Write the data to a temporary file. // Write the data to a temporary file.
$temp_name = $this->tempnam('temporary://', 'file'); $temp_name = $this->tempnam('temporary://', 'file');
if (file_put_contents($temp_name, $data) === FALSE) { if (file_put_contents($temp_name, $data) === FALSE) {
@ -472,7 +487,7 @@ class FileSystem implements FileSystemInterface {
} }
// Move the file to its final destination. // Move the file to its final destination.
return $this->move($temp_name, $destination, $replace); return $this->move($temp_name, $destination, $fileExists);
} }
/** /**
@ -514,23 +529,27 @@ class FileSystem implements FileSystemInterface {
/** /**
* {@inheritdoc} * {@inheritdoc}
*/ */
public function getDestinationFilename($destination, $replace) { public function getDestinationFilename($destination, /* FileExists */$fileExists) {
if (!$fileExists instanceof FileExists) {
// @phpstan-ignore-next-line
$fileExists = FileExists::fromLegacyInt($fileExists, __METHOD__);
}
$basename = $this->basename($destination); $basename = $this->basename($destination);
if (!Unicode::validateUtf8($basename)) { if (!Unicode::validateUtf8($basename)) {
throw new FileException(sprintf("Invalid filename '%s'", $basename)); throw new FileException(sprintf("Invalid filename '%s'", $basename));
} }
if (file_exists($destination)) { if (file_exists($destination)) {
switch ($replace) { switch ($fileExists) {
case FileSystemInterface::EXISTS_REPLACE: case FileExists::Replace:
// Do nothing here, we want to overwrite the existing file. // Do nothing here, we want to overwrite the existing file.
break; break;
case FileSystemInterface::EXISTS_RENAME: case FileExists::Rename:
$directory = $this->dirname($destination); $directory = $this->dirname($destination);
$destination = $this->createFilename($basename, $directory); $destination = $this->createFilename($basename, $directory);
break; break;
case FileSystemInterface::EXISTS_ERROR: case FileExists::Error:
// Error reporting handled by calling function. // Error reporting handled by calling function.
return FALSE; return FALSE;
} }

View File

@ -9,16 +9,31 @@ interface FileSystemInterface {
/** /**
* Flag for dealing with existing files: Appends number until name is unique. * Flag for dealing with existing files: Appends number until name is unique.
*
* @deprecated in drupal:10.3.0 and is removed from drupal:12.0.0. Use
* \Drupal\Core\File\FileExists::Rename instead.
*
* @see https://www.drupal.org/node/3426517
*/ */
const EXISTS_RENAME = 0; const EXISTS_RENAME = 0;
/** /**
* Flag for dealing with existing files: Replace the existing file. * Flag for dealing with existing files: Replace the existing file.
*
* @deprecated in drupal:10.3.0 and is removed from drupal:12.0.0. Use
* \Drupal\Core\File\FileExists::Replace instead.
*
* @see https://www.drupal.org/node/3426517
*/ */
const EXISTS_REPLACE = 1; const EXISTS_REPLACE = 1;
/** /**
* Flag for dealing with existing files: Do nothing and return FALSE. * Flag for dealing with existing files: Do nothing and return FALSE.
*
* @deprecated in drupal:10.3.0 and is removed from drupal:12.0.0. Use
* \Drupal\Core\File\FileExists::Error instead.
*
* @see https://www.drupal.org/node/3426517
*/ */
const EXISTS_ERROR = 2; const EXISTS_ERROR = 2;
@ -253,12 +268,9 @@ interface FileSystemInterface {
* version of copy(). * version of copy().
* - Checks if $source and $destination are valid and readable/writable. * - Checks if $source and $destination are valid and readable/writable.
* - If file already exists in $destination either the call will error out, * - If file already exists in $destination either the call will error out,
* replace the file or rename the file based on the $replace parameter. * replace the file or rename the file based on the $fileExists parameter.
* - If the $source and $destination are equal, the behavior depends on the * - If the $source and $destination are equal, the behavior depends on the
* $replace parameter. FileSystemInterface::EXISTS_REPLACE will replace the * $fileExists parameter.
* existing file. FileSystemInterface::EXISTS_ERROR will error out.
* FileSystemInterface::EXISTS_RENAME will rename the file until the
* $destination is unique.
* - Provides a fallback using realpaths if the move fails using stream * - Provides a fallback using realpaths if the move fails using stream
* wrappers. This can occur because PHP's copy() function does not properly * wrappers. This can occur because PHP's copy() function does not properly
* support streams if open_basedir is enabled. See * support streams if open_basedir is enabled. See
@ -269,20 +281,18 @@ interface FileSystemInterface {
* @param string $destination * @param string $destination
* A URI containing the destination that $source should be copied to. The * A URI containing the destination that $source should be copied to. The
* URI may be a bare filepath (without a scheme). * URI may be a bare filepath (without a scheme).
* @param int $replace * @param \Drupal\Core\File\FileExists|int $fileExists
* Replace behavior when the destination file already exists: * The behavior when the destination file already exists.
* - FileSystemInterface::EXISTS_REPLACE - Replace the existing file.
* - FileSystemInterface::EXISTS_RENAME - Append _{incrementing number}
* until the filename is unique.
* - FileSystemInterface::EXISTS_ERROR - Throw an exception.
* *
* @return string * @return string
* The path to the new file. * The path to the new file.
* *
* @throws \Drupal\Core\File\Exception\FileException * @throws \Drupal\Core\File\Exception\FileException
* Implementation may throw FileException or its subtype on failure. * Implementation may throw FileException or its subtype on failure.
* @throws \ValueError
* Thrown if $fileExists is a legacy int and not a valid value.
*/ */
public function copy($source, $destination, $replace = self::EXISTS_RENAME); public function copy($source, $destination, /* FileExists */$fileExists = FileExists::Rename);
/** /**
* Deletes a file without database changes or hook invocations. * Deletes a file without database changes or hook invocations.
@ -331,7 +341,7 @@ interface FileSystemInterface {
* - Checks that $source is not equal to $destination; if they are an error * - Checks that $source is not equal to $destination; if they are an error
* is reported. * is reported.
* - If file already exists in $destination either the call will error out, * - If file already exists in $destination either the call will error out,
* replace the file or rename the file based on the $replace parameter. * replace the file or rename the file based on the $fileExists parameter.
* - Works around a PHP bug where rename() does not properly support streams * - Works around a PHP bug where rename() does not properly support streams
* if safe_mode or open_basedir are enabled. * if safe_mode or open_basedir are enabled.
* *
@ -341,22 +351,20 @@ interface FileSystemInterface {
* A URI containing the destination that $source should be moved to. The * A URI containing the destination that $source should be moved to. The
* URI may be a bare filepath (without a scheme) and in that case the * URI may be a bare filepath (without a scheme) and in that case the
* default scheme (public://) will be used. * default scheme (public://) will be used.
* @param int $replace * @param \Drupal\Core\File\FileExists|int $fileExists
* Replace behavior when the destination file already exists: * Replace behavior when the destination file already exists.
* - FileSystemInterface::EXISTS_REPLACE - Replace the existing file.
* - FileSystemInterface::EXISTS_RENAME - Append _{incrementing number}
* until the filename is unique.
* - FileSystemInterface::EXISTS_ERROR - Do nothing and return FALSE.
* *
* @return string * @return string
* The path to the new file. * The path to the new file.
* *
* @throws \Drupal\Core\File\Exception\FileException * @throws \Drupal\Core\File\Exception\FileException
* Implementation may throw FileException or its subtype on failure. * Implementation may throw FileException or its subtype on failure.
* @throws \ValueError
* Thrown if $fileExists is a legacy int and not a valid value.
* *
* @see https://bugs.php.net/bug.php?id=60456 * @see https://bugs.php.net/bug.php?id=60456
*/ */
public function move($source, $destination, $replace = self::EXISTS_RENAME); public function move($source, $destination, /* FileExists */$fileExists = FileExists::Rename);
/** /**
* Saves a file to the specified destination without invoking file API. * Saves a file to the specified destination without invoking file API.
@ -370,22 +378,20 @@ interface FileSystemInterface {
* @param string $destination * @param string $destination
* A string containing the destination location. This must be a stream * A string containing the destination location. This must be a stream
* wrapper URI. * wrapper URI.
* @param int $replace * @param \Drupal\Core\File\FileExists|int $fileExists
* Replace behavior when the destination file already exists: * Replace behavior when the destination file already exists.
* - FileSystemInterface::EXISTS_REPLACE - Replace the existing file.
* - FileSystemInterface::EXISTS_RENAME - Append _{incrementing number}
* until the filename is unique.
* - FileSystemInterface::EXISTS_ERROR - Do nothing and return FALSE.
* *
* @return string * @return string
* A string with the path of the resulting file, or FALSE on error. * A string with the path of the resulting file, or FALSE on error.
* *
* @throws \Drupal\Core\File\Exception\FileException * @throws \Drupal\Core\File\Exception\FileException
* Implementation may throw FileException or its subtype on failure. * Implementation may throw FileException or its subtype on failure.
* @throws \ValueError
* Thrown if $fileExists is a legacy int and not a valid value.
* *
* @see \Drupal\file\FileRepositoryInterface::writeData() * @see \Drupal\file\FileRepositoryInterface::writeData()
*/ */
public function saveData($data, $destination, $replace = self::EXISTS_RENAME); public function saveData($data, $destination, /* FileExists */$fileExists = FileExists::Rename);
/** /**
* Checks that the directory exists and is writable. * Checks that the directory exists and is writable.
@ -432,21 +438,19 @@ interface FileSystemInterface {
* *
* @param string $destination * @param string $destination
* The desired final URI or filepath. * The desired final URI or filepath.
* @param int $replace * @param \Drupal\Core\File\FileExists|int $fileExists
* Replace behavior when the destination file already exists. * Replace behavior when the destination file already exists.
* - FileSystemInterface::EXISTS_REPLACE - Replace the existing file.
* - FileSystemInterface::EXISTS_RENAME - Append _{incrementing number}
* until the filename is unique.
* - FileSystemInterface::EXISTS_ERROR - Do nothing and return FALSE.
* *
* @return string|bool * @return string|bool
* The destination filepath, or FALSE if the file already exists * The destination filepath, or FALSE if the file already exists
* and FileSystemInterface::EXISTS_ERROR is specified. * and FileExists::Error is specified.
* *
* @throws \Drupal\Core\File\Exception\FileException * @throws \Drupal\Core\File\Exception\FileException
* Implementation may throw FileException or its subtype on failure. * Implementation may throw FileException or its subtype on failure.
* @throws \ValueError
* Thrown if $fileExists is a legacy int and not a valid value.
*/ */
public function getDestinationFilename($destination, $replace); public function getDestinationFilename($destination, /* FileExists */$fileExists);
/** /**
* Gets the path of the configured temporary directory. * Gets the path of the configured temporary directory.

View File

@ -10,6 +10,7 @@ use Drupal\Component\Utility\Environment;
use Drupal\Core\Access\AccessResult; use Drupal\Core\Access\AccessResult;
use Drupal\Core\Controller\ControllerBase; use Drupal\Core\Controller\ControllerBase;
use Drupal\Core\File\Exception\FileException; use Drupal\Core\File\Exception\FileException;
use Drupal\Core\File\FileExists;
use Drupal\Core\File\FileSystemInterface; use Drupal\Core\File\FileSystemInterface;
use Drupal\Core\Lock\LockBackendInterface; use Drupal\Core\Lock\LockBackendInterface;
use Drupal\Core\Session\AccountInterface; use Drupal\Core\Session\AccountInterface;
@ -138,7 +139,7 @@ class CKEditor5ImageController extends ControllerBase {
$validators = $this->getImageUploadValidators($settings); $validators = $this->getImageUploadValidators($settings);
$file_uri = "{$destination}/{$filename}"; $file_uri = "{$destination}/{$filename}";
$file_uri = $this->fileSystem->getDestinationFilename($file_uri, FileSystemInterface::EXISTS_RENAME); $file_uri = $this->fileSystem->getDestinationFilename($file_uri, FileExists::Rename);
// Lock based on the prepared file URI. // Lock based on the prepared file URI.
$lock_id = $this->generateLockIdFromFileUri($file_uri); $lock_id = $this->generateLockIdFromFileUri($file_uri);
@ -149,7 +150,7 @@ class CKEditor5ImageController extends ControllerBase {
try { try {
$uploadedFile = new FormUploadedFile($upload); $uploadedFile = new FormUploadedFile($upload);
$uploadResult = $this->fileUploadHandler->handleFileUpload($uploadedFile, $validators, $destination, FileSystemInterface::EXISTS_RENAME, FALSE); $uploadResult = $this->fileUploadHandler->handleFileUpload($uploadedFile, $validators, $destination, FileExists::Rename, FALSE);
if ($uploadResult->hasViolations()) { if ($uploadResult->hasViolations()) {
throw new UnprocessableEntityHttpException((string) $uploadResult->getViolations()); throw new UnprocessableEntityHttpException((string) $uploadResult->getViolations());
} }

View File

@ -5,7 +5,7 @@ declare(strict_types=1);
namespace Drupal\Tests\ckeditor5\Functional; namespace Drupal\Tests\ckeditor5\Functional;
use Drupal\Component\Utility\Crypt; use Drupal\Component\Utility\Crypt;
use Drupal\Core\File\FileSystemInterface; use Drupal\Core\File\FileExists;
/** /**
* Test image upload access. * Test image upload access.
@ -48,7 +48,7 @@ class ImageUploadAccessTest extends ImageUploadTest {
// Ensure lock failures are reported correctly. // Ensure lock failures are reported correctly.
$d = 'public://inline-images/test.jpg'; $d = 'public://inline-images/test.jpg';
$f = $this->container->get('file_system')->getDestinationFilename($d, FileSystemInterface::EXISTS_RENAME); $f = $this->container->get('file_system')->getDestinationFilename($d, FileExists::Rename);
$this->container->get('lock') $this->container->get('lock')
->acquire('file:ckeditor5:' . Crypt::hashBase64($f)); ->acquire('file:ckeditor5:' . Crypt::hashBase64($f));
$response = $this->uploadRequest($url, $test_image, 'test.jpg'); $response = $this->uploadRequest($url, $test_image, 'test.jpg');

View File

@ -3,7 +3,7 @@
namespace Drupal\Tests\editor\Kernel; namespace Drupal\Tests\editor\Kernel;
use Drupal\Core\Cache\Cache; use Drupal\Core\Cache\Cache;
use Drupal\Core\File\FileSystemInterface; use Drupal\Core\File\FileExists;
use Drupal\file\Entity\File; use Drupal\file\Entity\File;
use Drupal\filter\FilterPluginCollection; use Drupal\filter\FilterPluginCollection;
use Drupal\KernelTests\KernelTestBase; use Drupal\KernelTests\KernelTestBase;
@ -134,7 +134,7 @@ class EditorFileReferenceFilterTest extends KernelTestBase {
/** @var array stdClass */ /** @var array stdClass */
$files = $this->getTestFiles('image'); $files = $this->getTestFiles('image');
$image = reset($files); $image = reset($files);
\Drupal::service('file_system')->copy($image->uri, 'public://llama.jpg', FileSystemInterface::EXISTS_REPLACE); \Drupal::service('file_system')->copy($image->uri, 'public://llama.jpg', FileExists::Replace);
[$width, $height] = getimagesize('public://llama.jpg'); [$width, $height] = getimagesize('public://llama.jpg');
$dimensions = 'width="' . $width . '" height="' . $height . '"'; $dimensions = 'width="' . $width . '" height="' . $height . '"';

View File

@ -14,6 +14,7 @@ use Drupal\Core\File\Exception\FileException;
use Drupal\Core\File\Exception\FileExistsException; use Drupal\Core\File\Exception\FileExistsException;
use Drupal\Core\File\Exception\FileWriteException; use Drupal\Core\File\Exception\FileWriteException;
use Drupal\Core\File\Exception\InvalidStreamWrapperException; use Drupal\Core\File\Exception\InvalidStreamWrapperException;
use Drupal\Core\File\FileExists;
use Drupal\Core\File\FileSystemInterface; use Drupal\Core\File\FileSystemInterface;
use Drupal\Core\Form\FormStateInterface; use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Link; use Drupal\Core\Link;
@ -499,19 +500,17 @@ function file_cron() {
* @param null|int $delta * @param null|int $delta
* (optional) The delta of the file to return the file entity. * (optional) The delta of the file to return the file entity.
* Defaults to NULL. * Defaults to NULL.
* @param int $replace * @param \Drupal\Core\File\FileExists|int $fileExists
* (optional) The replace behavior when the destination file already exists. * (optional) The replace behavior when the destination file already exists.
* Possible values include:
* - FileSystemInterface::EXISTS_REPLACE: Replace the existing file.
* - FileSystemInterface::EXISTS_RENAME: (default) Append
* _{incrementing number} until the filename is unique.
* - FileSystemInterface::EXISTS_ERROR: Do nothing and return FALSE.
* *
* @return array|\Drupal\file\FileInterface|null|false * @return array|\Drupal\file\FileInterface|null|false
* An array of file entities or a single file entity if $delta != NULL. Each * An array of file entities or a single file entity if $delta != NULL. Each
* array element contains the file entity if the upload succeeded or FALSE if * array element contains the file entity if the upload succeeded or FALSE if
* there was an error. Function returns NULL if no file was uploaded. * there was an error. Function returns NULL if no file was uploaded.
* *
* @throws \ValueError
* Thrown if $fileExists is a legacy int and not a valid value.
*
* @internal * @internal
* This function is internal, and may be removed in a minor version release. * This function is internal, and may be removed in a minor version release.
* It wraps file_save_upload() to allow correct error handling in forms. * It wraps file_save_upload() to allow correct error handling in forms.
@ -521,7 +520,11 @@ function file_cron() {
* @see https://www.drupal.org/project/drupal/issues/3069020 * @see https://www.drupal.org/project/drupal/issues/3069020
* @see https://www.drupal.org/project/drupal/issues/2482783 * @see https://www.drupal.org/project/drupal/issues/2482783
*/ */
function _file_save_upload_from_form(array $element, FormStateInterface $form_state, $delta = NULL, $replace = FileSystemInterface::EXISTS_RENAME) { function _file_save_upload_from_form(array $element, FormStateInterface $form_state, $delta = NULL, FileExists|int $fileExists = FileExists::Rename) {
if (!$fileExists instanceof FileExists) {
// @phpstan-ignore-next-line
$fileExists = FileExists::fromLegacyInt($fileExists, __METHOD__);
}
// Get all errors set before calling this method. This will also clear them // Get all errors set before calling this method. This will also clear them
// from the messenger service. // from the messenger service.
$errors_before = \Drupal::messenger()->deleteByType(MessengerInterface::TYPE_ERROR); $errors_before = \Drupal::messenger()->deleteByType(MessengerInterface::TYPE_ERROR);
@ -530,7 +533,7 @@ function _file_save_upload_from_form(array $element, FormStateInterface $form_st
$upload_name = implode('_', $element['#parents']); $upload_name = implode('_', $element['#parents']);
$upload_validators = $element['#upload_validators'] ?? []; $upload_validators = $element['#upload_validators'] ?? [];
$result = file_save_upload($upload_name, $upload_validators, $upload_location, $delta, $replace); $result = file_save_upload($upload_name, $upload_validators, $upload_location, $delta, $fileExists);
// Get new errors that are generated while trying to save the upload. This // Get new errors that are generated while trying to save the upload. This
// will also clear them from the messenger service. // will also clear them from the messenger service.
@ -598,22 +601,24 @@ function _file_save_upload_from_form(array $element, FormStateInterface $form_st
* @param null|int $delta * @param null|int $delta
* (optional) The delta of the file to return the file entity. * (optional) The delta of the file to return the file entity.
* Defaults to NULL. * Defaults to NULL.
* @param int $replace * @param \Drupal\Core\File\FileExists|int $fileExists
* (optional) The replace behavior when the destination file already exists. * (optional) The replace behavior when the destination file already exists.
* Possible values include:
* - FileSystemInterface::EXISTS_REPLACE: Replace the existing file.
* - FileSystemInterface::EXISTS_RENAME: (default) Append
* _{incrementing number} until the filename is unique.
* - FileSystemInterface::EXISTS_ERROR: Do nothing and return FALSE.
* *
* @return array|\Drupal\file\FileInterface|null|false * @return array|\Drupal\file\FileInterface|null|false
* An array of file entities or a single file entity if $delta != NULL. Each * An array of file entities or a single file entity if $delta != NULL. Each
* array element contains the file entity if the upload succeeded or FALSE if * array element contains the file entity if the upload succeeded or FALSE if
* there was an error. Function returns NULL if no file was uploaded. * there was an error. Function returns NULL if no file was uploaded.
* *
* @throws \ValueError
* Thrown if $fileExists is a legacy int and not a valid value.
*
* @see _file_save_upload_from_form() * @see _file_save_upload_from_form()
*/ */
function file_save_upload($form_field_name, $validators = [], $destination = FALSE, $delta = NULL, $replace = FileSystemInterface::EXISTS_RENAME) { function file_save_upload($form_field_name, $validators = [], $destination = FALSE, $delta = NULL, FileExists|int $fileExists = FileExists::Rename) {
if (!$fileExists instanceof FileExists) {
// @phpstan-ignore-next-line
$fileExists = FileExists::fromLegacyInt($fileExists, __METHOD__);
}
static $upload_cache; static $upload_cache;
$all_files = \Drupal::request()->files->get('files', []); $all_files = \Drupal::request()->files->get('files', []);
@ -661,7 +666,7 @@ function file_save_upload($form_field_name, $validators = [], $destination = FAL
continue; continue;
} }
$form_uploaded_file = new FormUploadedFile($uploaded_file); $form_uploaded_file = new FormUploadedFile($uploaded_file);
$result = $file_upload_handler->handleFileUpload($form_uploaded_file, $validators, $destination, $replace, FALSE); $result = $file_upload_handler->handleFileUpload($form_uploaded_file, $validators, $destination, $fileExists, FALSE);
if ($result->hasViolations()) { if ($result->hasViolations()) {
$errors = []; $errors = [];
foreach ($result->getViolations() as $violation) { foreach ($result->getViolations() as $violation) {

View File

@ -5,6 +5,7 @@ namespace Drupal\file;
use Drupal\Core\Entity\EntityTypeManagerInterface; use Drupal\Core\Entity\EntityTypeManagerInterface;
use Drupal\Core\Extension\ModuleHandlerInterface; use Drupal\Core\Extension\ModuleHandlerInterface;
use Drupal\Core\File\Exception\InvalidStreamWrapperException; use Drupal\Core\File\Exception\InvalidStreamWrapperException;
use Drupal\Core\File\FileExists;
use Drupal\Core\File\FileSystemInterface; use Drupal\Core\File\FileSystemInterface;
use Drupal\Core\Session\AccountInterface; use Drupal\Core\Session\AccountInterface;
use Drupal\Core\StreamWrapper\StreamWrapperManagerInterface; use Drupal\Core\StreamWrapper\StreamWrapperManagerInterface;
@ -86,12 +87,16 @@ class FileRepository implements FileRepositoryInterface {
/** /**
* {@inheritdoc} * {@inheritdoc}
*/ */
public function writeData(string $data, string $destination, int $replace = FileSystemInterface::EXISTS_RENAME): FileInterface { public function writeData(string $data, string $destination, FileExists|int $fileExists = FileExists::Rename): FileInterface {
if (!$fileExists instanceof FileExists) {
// @phpstan-ignore-next-line
$fileExists = FileExists::fromLegacyInt($fileExists, __METHOD__);
}
if (!$this->streamWrapperManager->isValidUri($destination)) { if (!$this->streamWrapperManager->isValidUri($destination)) {
throw new InvalidStreamWrapperException("Invalid stream wrapper: {$destination}"); throw new InvalidStreamWrapperException("Invalid stream wrapper: {$destination}");
} }
$uri = $this->fileSystem->saveData($data, $destination, $replace); $uri = $this->fileSystem->saveData($data, $destination, $fileExists);
return $this->createOrUpdate($uri, $destination, $replace === FileSystemInterface::EXISTS_RENAME); return $this->createOrUpdate($uri, $destination, $fileExists === FileExists::Rename);
} }
/** /**
@ -130,14 +135,18 @@ class FileRepository implements FileRepositoryInterface {
/** /**
* {@inheritdoc} * {@inheritdoc}
*/ */
public function copy(FileInterface $source, string $destination, int $replace = FileSystemInterface::EXISTS_RENAME): FileInterface { public function copy(FileInterface $source, string $destination, FileExists|int $fileExists = FileExists::Rename): FileInterface {
if (!$fileExists instanceof FileExists) {
// @phpstan-ignore-next-line
$fileExists = FileExists::fromLegacyInt($fileExists, __METHOD__);
}
if (!$this->streamWrapperManager->isValidUri($destination)) { if (!$this->streamWrapperManager->isValidUri($destination)) {
throw new InvalidStreamWrapperException("Invalid stream wrapper: {$destination}"); throw new InvalidStreamWrapperException("Invalid stream wrapper: {$destination}");
} }
$uri = $this->fileSystem->copy($source->getFileUri(), $destination, $replace); $uri = $this->fileSystem->copy($source->getFileUri(), $destination, $fileExists);
// If we are replacing an existing file, load it. // If we are replacing an existing file, load it.
if ($replace === FileSystemInterface::EXISTS_REPLACE && $existing = $this->loadByUri($uri)) { if ($fileExists === FileExists::Replace && $existing = $this->loadByUri($uri)) {
$file = $existing; $file = $existing;
} }
else { else {
@ -146,7 +155,7 @@ class FileRepository implements FileRepositoryInterface {
// If we are renaming around an existing file (rather than a directory), // If we are renaming around an existing file (rather than a directory),
// use its basename for the filename. // use its basename for the filename.
if ($replace === FileSystemInterface::EXISTS_RENAME && is_file($destination)) { if ($fileExists === FileExists::Rename && is_file($destination)) {
$file->setFilename($this->fileSystem->basename($destination)); $file->setFilename($this->fileSystem->basename($destination));
} }
else { else {
@ -164,17 +173,21 @@ class FileRepository implements FileRepositoryInterface {
/** /**
* {@inheritdoc} * {@inheritdoc}
*/ */
public function move(FileInterface $source, string $destination, int $replace = FileSystemInterface::EXISTS_RENAME): FileInterface { public function move(FileInterface $source, string $destination, FileExists|int $fileExists = FileExists::Rename): FileInterface {
if (!$fileExists instanceof FileExists) {
// @phpstan-ignore-next-line
$fileExists = FileExists::fromLegacyInt($fileExists, __METHOD__);
}
if (!$this->streamWrapperManager->isValidUri($destination)) { if (!$this->streamWrapperManager->isValidUri($destination)) {
throw new InvalidStreamWrapperException("Invalid stream wrapper: {$destination}"); throw new InvalidStreamWrapperException("Invalid stream wrapper: {$destination}");
} }
$uri = $this->fileSystem->move($source->getFileUri(), $destination, $replace); $uri = $this->fileSystem->move($source->getFileUri(), $destination, $fileExists);
$delete_source = FALSE; $delete_source = FALSE;
$file = clone $source; $file = clone $source;
$file->setFileUri($uri); $file->setFileUri($uri);
// If we are replacing an existing file re-use its database record. // If we are replacing an existing file re-use its database record.
if ($replace === FileSystemInterface::EXISTS_REPLACE) { if ($fileExists === FileExists::Replace) {
if ($existing = $this->loadByUri($uri)) { if ($existing = $this->loadByUri($uri)) {
$delete_source = TRUE; $delete_source = TRUE;
$file->fid = $existing->id(); $file->fid = $existing->id();
@ -183,7 +196,7 @@ class FileRepository implements FileRepositoryInterface {
} }
// If we are renaming around an existing file (rather than a directory), // If we are renaming around an existing file (rather than a directory),
// use its basename for the filename. // use its basename for the filename.
elseif ($replace === FileSystemInterface::EXISTS_RENAME && is_file($destination)) { elseif ($fileExists === FileExists::Rename && is_file($destination)) {
$file->setFilename($this->fileSystem->basename($destination)); $file->setFilename($this->fileSystem->basename($destination));
} }

View File

@ -2,7 +2,7 @@
namespace Drupal\file; namespace Drupal\file;
use Drupal\Core\File\FileSystemInterface; use Drupal\Core\File\FileExists;
/** /**
* Performs file system operations and updates database records accordingly. * Performs file system operations and updates database records accordingly.
@ -17,17 +17,8 @@ interface FileRepositoryInterface {
* @param string $destination * @param string $destination
* A string containing the destination URI. This must be a stream * A string containing the destination URI. This must be a stream
* wrapper URI. * wrapper URI.
* @param int $replace * @param \Drupal\Core\File\FileExists|int $fileExists
* (optional) The replace behavior when the destination file already exists. * (optional) The replace behavior when the destination file already exists.
* Possible values include:
* - FileSystemInterface::EXISTS_RENAME: (default) Append
* _{incrementing number} until the filename is unique.
* - FileSystemInterface::EXISTS_REPLACE: Replace the existing file. If a
* managed file with the destination name exists, then its database entry
* will be updated. If no database entry is found, then a new one will be
* created.
* - FileSystemInterface::EXISTS_ERROR: Do nothing and throw a
* \Drupal\Core\File\Exception\FileExistsException.
* *
* @return \Drupal\file\FileInterface * @return \Drupal\file\FileInterface
* The file entity. * The file entity.
@ -36,7 +27,7 @@ interface FileRepositoryInterface {
* Thrown when there is an error writing to the file system. * Thrown when there is an error writing to the file system.
* @throws \Drupal\Core\File\Exception\FileExistsException * @throws \Drupal\Core\File\Exception\FileExistsException
* Thrown when the destination exists and $replace is set to * Thrown when the destination exists and $replace is set to
* FileSystemInterface::EXISTS_ERROR. * FileExists::Error.
* @throws \Drupal\Core\File\Exception\InvalidStreamWrapperException * @throws \Drupal\Core\File\Exception\InvalidStreamWrapperException
* Thrown when the destination is an invalid stream wrapper. * Thrown when the destination is an invalid stream wrapper.
* @throws \Drupal\Core\Entity\EntityStorageException * @throws \Drupal\Core\Entity\EntityStorageException
@ -44,7 +35,7 @@ interface FileRepositoryInterface {
* *
* @see \Drupal\Core\File\FileSystemInterface::saveData() * @see \Drupal\Core\File\FileSystemInterface::saveData()
*/ */
public function writeData(string $data, string $destination, int $replace = FileSystemInterface::EXISTS_RENAME): FileInterface; public function writeData(string $data, string $destination, FileExists|int $fileExists = FileExists::Rename): FileInterface;
/** /**
* Copies a file to a new location and adds a file record to the database. * Copies a file to a new location and adds a file record to the database.
@ -56,8 +47,8 @@ interface FileRepositoryInterface {
* - If file already exists in $destination either the call will error out, * - If file already exists in $destination either the call will error out,
* replace the file or rename the file based on the $replace parameter. * replace the file or rename the file based on the $replace parameter.
* - If the $source and $destination are equal, the behavior depends on the * - If the $source and $destination are equal, the behavior depends on the
* $replace parameter. FileSystemInterface::EXISTS_REPLACE will error out. * $replace parameter. FileExists::Replace will error out.
* FileSystemInterface::EXISTS_RENAME will rename the file until the * FileExists::Rename will rename the file until the
* $destination is unique. * $destination is unique.
* - Adds the new file to the files database. If the source file is a * - Adds the new file to the files database. If the source file is a
* temporary file, the resulting file will also be a temporary file. See * temporary file, the resulting file will also be a temporary file. See
@ -68,17 +59,8 @@ interface FileRepositoryInterface {
* @param string $destination * @param string $destination
* A string containing the destination that $source should be * A string containing the destination that $source should be
* copied to. This must be a stream wrapper URI. * copied to. This must be a stream wrapper URI.
* @param int $replace * @param \Drupal\Core\File\FileExists|int $fileExists
* (optional) Replace behavior when the destination file already exists. * (optional) Replace behavior when the destination file already exists.
* Possible values include:
* - FileSystemInterface::EXISTS_RENAME: (default) Append
* _{incrementing number} until the filename is unique.
* - FileSystemInterface::EXISTS_REPLACE: Replace the existing file. If a
* managed file with the destination name exists, then its database entry
* will be updated. If no database entry is found, then a new one will be
* created.
* - FileSystemInterface::EXISTS_ERROR: Do nothing and throw a
* \Drupal\Core\File\Exception\FileExistsException.
* *
* @return \Drupal\file\FileInterface * @return \Drupal\file\FileInterface
* The file entity. * The file entity.
@ -87,7 +69,7 @@ interface FileRepositoryInterface {
* Thrown when there is an error writing to the file system. * Thrown when there is an error writing to the file system.
* @throws \Drupal\Core\File\Exception\FileExistsException * @throws \Drupal\Core\File\Exception\FileExistsException
* Thrown when the destination exists and $replace is set to * Thrown when the destination exists and $replace is set to
* FileSystemInterface::EXISTS_ERROR. * FileExists::Error.
* @throws \Drupal\Core\File\Exception\InvalidStreamWrapperException * @throws \Drupal\Core\File\Exception\InvalidStreamWrapperException
* Thrown when the destination is an invalid stream wrapper. * Thrown when the destination is an invalid stream wrapper.
* @throws \Drupal\Core\Entity\EntityStorageException * @throws \Drupal\Core\Entity\EntityStorageException
@ -96,7 +78,7 @@ interface FileRepositoryInterface {
* @see \Drupal\Core\File\FileSystemInterface::copy() * @see \Drupal\Core\File\FileSystemInterface::copy()
* @see hook_file_copy() * @see hook_file_copy()
*/ */
public function copy(FileInterface $source, string $destination, int $replace = FileSystemInterface::EXISTS_RENAME): FileInterface; public function copy(FileInterface $source, string $destination, FileExists|int $fileExists = FileExists::Rename): FileInterface;
/** /**
* Moves a file to a new location and update the file's database entry. * Moves a file to a new location and update the file's database entry.
@ -112,18 +94,8 @@ interface FileRepositoryInterface {
* @param string $destination * @param string $destination
* A string containing the destination that $source should be moved * A string containing the destination that $source should be moved
* to. This must be a stream wrapper URI. * to. This must be a stream wrapper URI.
* @param int $replace * @param \Drupal\Core\File\FileExists|int $fileExists
* (optional) The replace behavior when the destination file already exists. * (optional) The replace behavior when the destination file already exists.
* Possible values include:
* - FileSystemInterface::EXISTS_RENAME: (default) Append
* _{incrementing number} until the filename is unique.
* - FileSystemInterface::EXISTS_REPLACE: Replace the existing file. If a
* managed file with the destination name exists then its database entry
* will be updated and $source->delete() called after invoking
* hook_file_move(). If no database entry is found, then the source files
* record will be updated.
* - FileSystemInterface::EXISTS_ERROR: Do nothing and throw a
* \Drupal\Core\File\Exception\FileExistsException.
* *
* @return \Drupal\file\FileInterface * @return \Drupal\file\FileInterface
* The file entity. * The file entity.
@ -132,7 +104,7 @@ interface FileRepositoryInterface {
* Thrown when there is an error writing to the file system. * Thrown when there is an error writing to the file system.
* @throws \Drupal\Core\File\Exception\FileExistsException * @throws \Drupal\Core\File\Exception\FileExistsException
* Thrown when the destination exists and $replace is set to * Thrown when the destination exists and $replace is set to
* FileSystemInterface::EXISTS_ERROR. * FileExists::Error.
* @throws \Drupal\Core\File\Exception\InvalidStreamWrapperException * @throws \Drupal\Core\File\Exception\InvalidStreamWrapperException
* Thrown when the destination is an invalid stream wrapper. * Thrown when the destination is an invalid stream wrapper.
* @throws \Drupal\Core\Entity\EntityStorageException * @throws \Drupal\Core\Entity\EntityStorageException
@ -141,7 +113,7 @@ interface FileRepositoryInterface {
* @see \Drupal\Core\File\FileSystemInterface::move() * @see \Drupal\Core\File\FileSystemInterface::move()
* @see hook_file_move() * @see hook_file_move()
*/ */
public function move(FileInterface $source, string $destination, int $replace = FileSystemInterface::EXISTS_RENAME): FileInterface; public function move(FileInterface $source, string $destination, FileExists|int $fileExists = FileExists::Rename): FileInterface;
/** /**
* Loads the first File entity found with the specified URI. * Loads the first File entity found with the specified URI.

View File

@ -9,6 +9,7 @@ use Drupal\Component\Utility\Random;
use Drupal\Core\Field\FieldDefinitionInterface; use Drupal\Core\Field\FieldDefinitionInterface;
use Drupal\Core\Field\FieldStorageDefinitionInterface; use Drupal\Core\Field\FieldStorageDefinitionInterface;
use Drupal\Core\Field\Plugin\Field\FieldType\EntityReferenceItem; use Drupal\Core\Field\Plugin\Field\FieldType\EntityReferenceItem;
use Drupal\Core\File\FileExists;
use Drupal\Core\File\FileSystemInterface; use Drupal\Core\File\FileSystemInterface;
use Drupal\Core\Form\FormStateInterface; use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\StreamWrapper\StreamWrapperInterface; use Drupal\Core\StreamWrapper\StreamWrapperInterface;
@ -349,7 +350,7 @@ class FileItem extends EntityReferenceItem {
$data = $random->paragraphs(3); $data = $random->paragraphs(3);
/** @var \Drupal\file\FileRepositoryInterface $file_repository */ /** @var \Drupal\file\FileRepositoryInterface $file_repository */
$file_repository = \Drupal::service('file.repository'); $file_repository = \Drupal::service('file.repository');
$file = $file_repository->writeData($data, $destination, FileSystemInterface::EXISTS_ERROR); $file = $file_repository->writeData($data, $destination, FileExists::Error);
$values = [ $values = [
'target_id' => $file->id(), 'target_id' => $file->id(),
'display' => (int) $settings['display_default'], 'display' => (int) $settings['display_default'],

View File

@ -9,6 +9,7 @@ use Drupal\Core\Entity\EntityFieldManagerInterface;
use Drupal\Core\Entity\EntityTypeManagerInterface; use Drupal\Core\Entity\EntityTypeManagerInterface;
use Drupal\Core\File\Event\FileUploadSanitizeNameEvent; use Drupal\Core\File\Event\FileUploadSanitizeNameEvent;
use Drupal\Core\File\Exception\FileException; use Drupal\Core\File\Exception\FileException;
use Drupal\Core\File\FileExists;
use Drupal\Core\File\FileSystemInterface; use Drupal\Core\File\FileSystemInterface;
use Drupal\Core\Lock\LockBackendInterface; use Drupal\Core\Lock\LockBackendInterface;
use Drupal\Core\Session\AccountInterface; use Drupal\Core\Session\AccountInterface;
@ -297,7 +298,7 @@ class FileUploadResource extends ResourceBase {
$temp_file_path = $this->streamUploadData(); $temp_file_path = $this->streamUploadData();
$file_uri = $this->fileSystem->getDestinationFilename($file_uri, FileSystemInterface::EXISTS_RENAME); $file_uri = $this->fileSystem->getDestinationFilename($file_uri, FileExists::Rename);
// Lock based on the prepared file URI. // Lock based on the prepared file URI.
$lock_id = $this->generateLockIdFromFileUri($file_uri); $lock_id = $this->generateLockIdFromFileUri($file_uri);
@ -344,10 +345,10 @@ class FileUploadResource extends ResourceBase {
$file->setFilename($this->fileSystem->basename($file->getFileUri())); $file->setFilename($this->fileSystem->basename($file->getFileUri()));
// Move the file to the correct location after validation. Use // Move the file to the correct location after validation. Use
// FileSystemInterface::EXISTS_ERROR as the file location has already been // FileExists::Error as the file location has already been
// determined above in FileSystem::getDestinationFilename(). // determined above in FileSystem::getDestinationFilename().
try { try {
$this->fileSystem->move($temp_file_path, $file_uri, FileSystemInterface::EXISTS_ERROR); $this->fileSystem->move($temp_file_path, $file_uri, FileExists::Error);
} }
catch (FileException $e) { catch (FileException $e) {
throw new HttpException(500, 'Temporary file could not be moved to file location'); throw new HttpException(500, 'Temporary file could not be moved to file location');

View File

@ -8,6 +8,7 @@ use Drupal\Core\File\Event\FileUploadSanitizeNameEvent;
use Drupal\Core\File\Exception\FileExistsException; use Drupal\Core\File\Exception\FileExistsException;
use Drupal\Core\File\Exception\FileWriteException; use Drupal\Core\File\Exception\FileWriteException;
use Drupal\Core\File\Exception\InvalidStreamWrapperException; use Drupal\Core\File\Exception\InvalidStreamWrapperException;
use Drupal\Core\File\FileExists;
use Drupal\Core\File\FileSystemInterface; use Drupal\Core\File\FileSystemInterface;
use Drupal\Core\Lock\LockAcquiringException; use Drupal\Core\Lock\LockAcquiringException;
use Drupal\Core\Lock\LockBackendInterface; use Drupal\Core\Lock\LockBackendInterface;
@ -170,12 +171,8 @@ class FileUploadHandler {
* The validators to run against the uploaded file. * The validators to run against the uploaded file.
* @param string $destination * @param string $destination
* The destination directory. * The destination directory.
* @param int $replace * @param \Drupal\Core\File\FileExists|int $fileExists
* Replace behavior when the destination file already exists: * The behavior when the destination file already exists.
* - FileSystemInterface::EXISTS_REPLACE - Replace the existing file.
* - FileSystemInterface::EXISTS_RENAME - Append _{incrementing number}
* until the filename is unique.
* - FileSystemInterface::EXISTS_ERROR - Throw an exception.
* @param bool $throw * @param bool $throw
* (optional) Whether to throw an exception if the file is invalid. * (optional) Whether to throw an exception if the file is invalid.
* *
@ -192,8 +189,14 @@ class FileUploadHandler {
* Thrown when file validation fails and $throws is TRUE. * Thrown when file validation fails and $throws is TRUE.
* @throws \Drupal\Core\Lock\LockAcquiringException * @throws \Drupal\Core\Lock\LockAcquiringException
* Thrown when a lock cannot be acquired. * Thrown when a lock cannot be acquired.
* @throws \ValueError
* Thrown if $fileExists is a legacy int and not a valid value.
*/ */
public function handleFileUpload(UploadedFileInterface $uploadedFile, array $validators = [], string $destination = 'temporary://', int $replace = FileSystemInterface::EXISTS_REPLACE, bool $throw = TRUE): FileUploadResult { public function handleFileUpload(UploadedFileInterface $uploadedFile, array $validators = [], string $destination = 'temporary://', /*FileExists*/$fileExists = FileExists::Replace, bool $throw = TRUE): FileUploadResult {
if (!$fileExists instanceof FileExists) {
// @phpstan-ignore-next-line
$fileExists = FileExists::fromLegacyInt($fileExists, __METHOD__);
}
$originalName = $uploadedFile->getClientOriginalName(); $originalName = $uploadedFile->getClientOriginalName();
// @phpstan-ignore-next-line // @phpstan-ignore-next-line
if ($throw && !$uploadedFile->isValid()) { if ($throw && !$uploadedFile->isValid()) {
@ -253,7 +256,7 @@ class FileUploadHandler {
$filename = $event->getFilename(); $filename = $event->getFilename();
$mimeType = $this->mimeTypeGuesser->guessMimeType($filename); $mimeType = $this->mimeTypeGuesser->guessMimeType($filename);
$destinationFilename = $this->fileSystem->getDestinationFilename($destination . $filename, $replace); $destinationFilename = $this->fileSystem->getDestinationFilename($destination . $filename, $fileExists);
if ($destinationFilename === FALSE) { if ($destinationFilename === FALSE) {
throw new FileExistsException(sprintf('Destination file "%s" exists', $destinationFilename)); throw new FileExistsException(sprintf('Destination file "%s" exists', $destinationFilename));
} }
@ -321,7 +324,7 @@ class FileUploadHandler {
// renaming due to an existing file. // renaming due to an existing file.
$file->setFilename($this->fileSystem->basename($file->getFileUri())); $file->setFilename($this->fileSystem->basename($file->getFileUri()));
if ($replace === FileSystemInterface::EXISTS_REPLACE) { if ($fileExists === FileExists::Replace) {
$existingFile = $this->fileRepository->loadByUri($file->getFileUri()); $existingFile = $this->fileRepository->loadByUri($file->getFileUri());
if ($existingFile) { if ($existingFile) {
$file->fid = $existingFile->id(); $file->fid = $existingFile->id();

View File

@ -2,9 +2,11 @@
namespace Drupal\file_test\Form; namespace Drupal\file_test\Form;
use Drupal\Core\File\FileExists;
use Drupal\Core\File\FileSystemInterface; use Drupal\Core\File\FileSystemInterface;
use Drupal\Core\Form\FormInterface; use Drupal\Core\Form\FormInterface;
use Drupal\Core\Form\FormStateInterface; use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\StringTranslation\TranslatableMarkup;
/** /**
* File test form class. * File test form class.
@ -30,11 +32,11 @@ class FileTestForm implements FormInterface {
'#type' => 'select', '#type' => 'select',
'#title' => t('Replace existing image'), '#title' => t('Replace existing image'),
'#options' => [ '#options' => [
FileSystemInterface::EXISTS_RENAME => t('Appends number until name is unique'), FileExists::Rename->name => new TranslatableMarkup('Appends number until name is unique'),
FileSystemInterface::EXISTS_REPLACE => t('Replace the existing file'), FileExists::Replace->name => new TranslatableMarkup('Replace the existing file'),
FileSystemInterface::EXISTS_ERROR => t('Fail with an error'), FileExists::Error->name => new TranslatableMarkup('Fail with an error'),
], ],
'#default_value' => FileSystemInterface::EXISTS_RENAME, '#default_value' => FileExists::Rename->name,
]; ];
$form['file_subdir'] = [ $form['file_subdir'] = [
'#type' => 'textfield', '#type' => 'textfield',
@ -115,7 +117,7 @@ class FileTestForm implements FormInterface {
define('SIMPLETEST_COLLECT_ERRORS', FALSE); define('SIMPLETEST_COLLECT_ERRORS', FALSE);
} }
$file = file_save_upload('file_test_upload', $validators, $destination, 0, $form_state->getValue('file_test_replace')); $file = file_save_upload('file_test_upload', $validators, $destination, 0, static::fileExistsFromName($form_state->getValue('file_test_replace')));
if ($file) { if ($file) {
$form_state->setValue('file_test_upload', $file); $form_state->setValue('file_test_upload', $file);
\Drupal::messenger()->addStatus(t('File @filepath was uploaded.', ['@filepath' => $file->getFileUri()])); \Drupal::messenger()->addStatus(t('File @filepath was uploaded.', ['@filepath' => $file->getFileUri()]));
@ -128,4 +130,15 @@ class FileTestForm implements FormInterface {
} }
} }
/**
* Get a FileExists enum from its name.
*/
protected static function fileExistsFromName(string $name): FileExists {
return match ($name) {
FileExists::Replace->name => FileExists::Replace,
FileExists::Error->name => FileExists::Error,
default => FileExists::Rename,
};
}
} }

View File

@ -2,11 +2,13 @@
namespace Drupal\file_test\Form; namespace Drupal\file_test\Form;
use Drupal\Core\File\FileExists;
use Drupal\Core\File\FileSystemInterface; use Drupal\Core\File\FileSystemInterface;
use Drupal\Core\Form\FormBase; use Drupal\Core\Form\FormBase;
use Drupal\Core\Form\FormStateInterface; use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Messenger\MessengerInterface; use Drupal\Core\Messenger\MessengerInterface;
use Drupal\Core\State\StateInterface; use Drupal\Core\State\StateInterface;
use Drupal\Core\StringTranslation\TranslatableMarkup;
use Symfony\Component\DependencyInjection\ContainerInterface; use Symfony\Component\DependencyInjection\ContainerInterface;
/** /**
@ -71,11 +73,11 @@ class FileTestSaveUploadFromForm extends FormBase {
'#type' => 'select', '#type' => 'select',
'#title' => $this->t('Replace existing image'), '#title' => $this->t('Replace existing image'),
'#options' => [ '#options' => [
FileSystemInterface::EXISTS_RENAME => $this->t('Appends number until name is unique'), FileExists::Rename->name => new TranslatableMarkup('Appends number until name is unique'),
FileSystemInterface::EXISTS_REPLACE => $this->t('Replace the existing file'), FileExists::Replace->name => new TranslatableMarkup('Replace the existing file'),
FileSystemInterface::EXISTS_ERROR => $this->t('Fail with an error'), FileExists::Error->name => new TranslatableMarkup('Fail with an error'),
], ],
'#default_value' => FileSystemInterface::EXISTS_RENAME, '#default_value' => FileExists::Rename->name,
]; ];
$form['file_subdir'] = [ $form['file_subdir'] = [
'#type' => 'textfield', '#type' => 'textfield',
@ -166,7 +168,7 @@ class FileTestSaveUploadFromForm extends FormBase {
$form['file_test_upload']['#upload_location'] = $destination; $form['file_test_upload']['#upload_location'] = $destination;
$this->messenger->addStatus($this->t('Number of error messages before _file_save_upload_from_form(): @count.', ['@count' => count($this->messenger->messagesByType(MessengerInterface::TYPE_ERROR))])); $this->messenger->addStatus($this->t('Number of error messages before _file_save_upload_from_form(): @count.', ['@count' => count($this->messenger->messagesByType(MessengerInterface::TYPE_ERROR))]));
$file = _file_save_upload_from_form($form['file_test_upload'], $form_state, 0, $form_state->getValue('file_test_replace')); $file = _file_save_upload_from_form($form['file_test_upload'], $form_state, 0, static::fileExistsFromName($form_state->getValue('file_test_replace')));
$this->messenger->addStatus($this->t('Number of error messages after _file_save_upload_from_form(): @count.', ['@count' => count($this->messenger->messagesByType(MessengerInterface::TYPE_ERROR))])); $this->messenger->addStatus($this->t('Number of error messages after _file_save_upload_from_form(): @count.', ['@count' => count($this->messenger->messagesByType(MessengerInterface::TYPE_ERROR))]));
if ($file) { if ($file) {
@ -186,4 +188,15 @@ class FileTestSaveUploadFromForm extends FormBase {
*/ */
public function submitForm(array &$form, FormStateInterface $form_state) {} public function submitForm(array &$form, FormStateInterface $form_state) {}
/**
* Get a FileExists enum from its name.
*/
protected static function fileExistsFromName(string $name): FileExists {
return match ($name) {
FileExists::Replace->name => FileExists::Replace,
FileExists::Error->name => FileExists::Error,
default => FileExists::Rename,
};
}
} }

View File

@ -4,7 +4,7 @@ declare(strict_types=1);
namespace Drupal\Tests\file\Functional; namespace Drupal\Tests\file\Functional;
use Drupal\Core\File\FileSystemInterface; use Drupal\Core\File\FileExists;
use Drupal\file\Entity\File; use Drupal\file\Entity\File;
use Drupal\Tests\TestFileCreationTrait; use Drupal\Tests\TestFileCreationTrait;
@ -88,7 +88,7 @@ class SaveUploadFormTest extends FileManagedTestBase {
$file_system = \Drupal::service('file_system'); $file_system = \Drupal::service('file_system');
// Upload with replace to guarantee there's something there. // Upload with replace to guarantee there's something there.
$edit = [ $edit = [
'file_test_replace' => FileSystemInterface::EXISTS_REPLACE, 'file_test_replace' => FileExists::Replace->name,
'files[file_test_upload][]' => $file_system->realpath($this->image->getFileUri()), 'files[file_test_upload][]' => $file_system->realpath($this->image->getFileUri()),
]; ];
$this->drupalGet('file-test/save_upload_from_form_test'); $this->drupalGet('file-test/save_upload_from_form_test');
@ -174,7 +174,7 @@ class SaveUploadFormTest extends FileManagedTestBase {
// _file_save_upload_from_form() to only allow ".foo". // _file_save_upload_from_form() to only allow ".foo".
$extensions = 'foo'; $extensions = 'foo';
$edit = [ $edit = [
'file_test_replace' => FileSystemInterface::EXISTS_REPLACE, 'file_test_replace' => FileExists::Replace->name,
'files[file_test_upload][]' => $file_system->realpath($this->image->getFileUri()), 'files[file_test_upload][]' => $file_system->realpath($this->image->getFileUri()),
'extensions' => $extensions, 'extensions' => $extensions,
]; ];
@ -194,7 +194,7 @@ class SaveUploadFormTest extends FileManagedTestBase {
$extensions = 'foo ' . $this->imageExtension; $extensions = 'foo ' . $this->imageExtension;
// Now tell _file_save_upload_from_form() to allow the extension of our test image. // Now tell _file_save_upload_from_form() to allow the extension of our test image.
$edit = [ $edit = [
'file_test_replace' => FileSystemInterface::EXISTS_REPLACE, 'file_test_replace' => FileExists::Replace->name,
'files[file_test_upload][]' => $file_system->realpath($this->image->getFileUri()), 'files[file_test_upload][]' => $file_system->realpath($this->image->getFileUri()),
'extensions' => $extensions, 'extensions' => $extensions,
]; ];
@ -213,7 +213,7 @@ class SaveUploadFormTest extends FileManagedTestBase {
// Now tell _file_save_upload_from_form() to allow any extension. // Now tell _file_save_upload_from_form() to allow any extension.
$edit = [ $edit = [
'file_test_replace' => FileSystemInterface::EXISTS_REPLACE, 'file_test_replace' => FileExists::Replace->name,
'files[file_test_upload][]' => $file_system->realpath($this->image->getFileUri()), 'files[file_test_upload][]' => $file_system->realpath($this->image->getFileUri()),
'allow_all_extensions' => 'empty_array', 'allow_all_extensions' => 'empty_array',
]; ];
@ -237,7 +237,7 @@ class SaveUploadFormTest extends FileManagedTestBase {
// Allow the .php extension and make sure it gets renamed to .txt for // Allow the .php extension and make sure it gets renamed to .txt for
// safety. Also check to make sure its MIME type was changed. // safety. Also check to make sure its MIME type was changed.
$edit = [ $edit = [
'file_test_replace' => FileSystemInterface::EXISTS_REPLACE, 'file_test_replace' => FileExists::Replace->name,
'files[file_test_upload][]' => $file_system->realpath($this->phpFile->uri), 'files[file_test_upload][]' => $file_system->realpath($this->phpFile->uri),
'is_image_file' => FALSE, 'is_image_file' => FALSE,
'extensions' => 'php txt', 'extensions' => 'php txt',
@ -276,7 +276,7 @@ class SaveUploadFormTest extends FileManagedTestBase {
file_test_reset(); file_test_reset();
$edit = [ $edit = [
'file_test_replace' => FileSystemInterface::EXISTS_REPLACE, 'file_test_replace' => FileExists::Replace->name,
'files[file_test_upload]' => \Drupal::service('file_system')->realpath($this->phpFile->uri), 'files[file_test_upload]' => \Drupal::service('file_system')->realpath($this->phpFile->uri),
'is_image_file' => FALSE, 'is_image_file' => FALSE,
'extensions' => 'php', 'extensions' => 'php',
@ -399,7 +399,7 @@ class SaveUploadFormTest extends FileManagedTestBase {
/** @var \Drupal\Core\File\FileSystemInterface $file_system */ /** @var \Drupal\Core\File\FileSystemInterface $file_system */
$file_system = \Drupal::service('file_system'); $file_system = \Drupal::service('file_system');
$edit = [ $edit = [
'file_test_replace' => FileSystemInterface::EXISTS_RENAME, 'file_test_replace' => FileExists::Rename->name,
'files[file_test_upload][]' => $file_system->realpath($this->image->getFileUri()), 'files[file_test_upload][]' => $file_system->realpath($this->image->getFileUri()),
]; ];
$this->drupalGet('file-test/save_upload_from_form_test'); $this->drupalGet('file-test/save_upload_from_form_test');
@ -418,7 +418,7 @@ class SaveUploadFormTest extends FileManagedTestBase {
/** @var \Drupal\Core\File\FileSystemInterface $file_system */ /** @var \Drupal\Core\File\FileSystemInterface $file_system */
$file_system = \Drupal::service('file_system'); $file_system = \Drupal::service('file_system');
$edit = [ $edit = [
'file_test_replace' => FileSystemInterface::EXISTS_REPLACE, 'file_test_replace' => FileExists::Replace->name,
'files[file_test_upload][]' => $file_system->realpath($this->image->getFileUri()), 'files[file_test_upload][]' => $file_system->realpath($this->image->getFileUri()),
]; ];
$this->drupalGet('file-test/save_upload_from_form_test'); $this->drupalGet('file-test/save_upload_from_form_test');
@ -437,7 +437,7 @@ class SaveUploadFormTest extends FileManagedTestBase {
/** @var \Drupal\Core\File\FileSystemInterface $file_system */ /** @var \Drupal\Core\File\FileSystemInterface $file_system */
$file_system = \Drupal::service('file_system'); $file_system = \Drupal::service('file_system');
$edit = [ $edit = [
'file_test_replace' => FileSystemInterface::EXISTS_ERROR, 'file_test_replace' => FileExists::Error->name,
'files[file_test_upload][]' => $file_system->realpath($this->image->getFileUri()), 'files[file_test_upload][]' => $file_system->realpath($this->image->getFileUri()),
]; ];
$this->drupalGet('file-test/save_upload_from_form_test'); $this->drupalGet('file-test/save_upload_from_form_test');

View File

@ -5,7 +5,7 @@ declare(strict_types=1);
namespace Drupal\Tests\file\Functional; namespace Drupal\Tests\file\Functional;
use Drupal\Component\Render\FormattableMarkup; use Drupal\Component\Render\FormattableMarkup;
use Drupal\Core\File\FileSystemInterface; use Drupal\Core\File\FileExists;
use Drupal\Core\Url; use Drupal\Core\Url;
use Drupal\file\Entity\File; use Drupal\file\Entity\File;
use Drupal\Tests\TestFileCreationTrait; use Drupal\Tests\TestFileCreationTrait;
@ -95,7 +95,7 @@ class SaveUploadTest extends FileManagedTestBase {
// Upload with replace to guarantee there's something there. // Upload with replace to guarantee there's something there.
$edit = [ $edit = [
'file_test_replace' => FileSystemInterface::EXISTS_REPLACE, 'file_test_replace' => FileExists::Replace->name,
'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->drupalGet('file-test/upload'); $this->drupalGet('file-test/upload');
@ -214,7 +214,7 @@ class SaveUploadTest extends FileManagedTestBase {
// file_save_upload() to only allow ".foo". // file_save_upload() to only allow ".foo".
$extensions = 'foo'; $extensions = 'foo';
$edit = [ $edit = [
'file_test_replace' => FileSystemInterface::EXISTS_REPLACE, 'file_test_replace' => FileExists::Replace->name,
'files[file_test_upload]' => \Drupal::service('file_system')->realpath($this->image->getFileUri()), 'files[file_test_upload]' => \Drupal::service('file_system')->realpath($this->image->getFileUri()),
'extensions' => $extensions, 'extensions' => $extensions,
]; ];
@ -234,7 +234,7 @@ class SaveUploadTest extends FileManagedTestBase {
$extensions = 'foo ' . $this->imageExtension; $extensions = 'foo ' . $this->imageExtension;
// Now tell file_save_upload() to allow the extension of our test image. // Now tell file_save_upload() to allow the extension of our test image.
$edit = [ $edit = [
'file_test_replace' => FileSystemInterface::EXISTS_REPLACE, 'file_test_replace' => FileExists::Replace->name,
'files[file_test_upload]' => \Drupal::service('file_system')->realpath($this->image->getFileUri()), 'files[file_test_upload]' => \Drupal::service('file_system')->realpath($this->image->getFileUri()),
'extensions' => $extensions, 'extensions' => $extensions,
]; ];
@ -253,7 +253,7 @@ class SaveUploadTest extends FileManagedTestBase {
// Now tell file_save_upload() to allow any extension. // Now tell file_save_upload() to allow any extension.
$edit = [ $edit = [
'file_test_replace' => FileSystemInterface::EXISTS_REPLACE, 'file_test_replace' => FileExists::Replace->name,
'files[file_test_upload]' => \Drupal::service('file_system')->realpath($this->image->getFileUri()), 'files[file_test_upload]' => \Drupal::service('file_system')->realpath($this->image->getFileUri()),
'allow_all_extensions' => 'empty_array', 'allow_all_extensions' => 'empty_array',
]; ];
@ -272,7 +272,7 @@ class SaveUploadTest extends FileManagedTestBase {
// Now tell file_save_upload() to allow any extension and try and upload a // Now tell file_save_upload() to allow any extension and try and upload a
// malicious file. // malicious file.
$edit = [ $edit = [
'file_test_replace' => FileSystemInterface::EXISTS_REPLACE, 'file_test_replace' => FileExists::Replace->name,
'files[file_test_upload]' => \Drupal::service('file_system')->realpath($this->phpFile->uri), 'files[file_test_upload]' => \Drupal::service('file_system')->realpath($this->phpFile->uri),
'allow_all_extensions' => 'empty_array', 'allow_all_extensions' => 'empty_array',
'is_image_file' => FALSE, 'is_image_file' => FALSE,
@ -296,7 +296,7 @@ class SaveUploadTest extends FileManagedTestBase {
// Allow the .php extension and make sure it gets munged and given a .txt // Allow the .php extension and make sure it gets munged and given a .txt
// extension for safety. Also check to make sure its MIME type was changed. // extension for safety. Also check to make sure its MIME type was changed.
$edit = [ $edit = [
'file_test_replace' => FileSystemInterface::EXISTS_REPLACE, 'file_test_replace' => FileExists::Replace->name,
'files[file_test_upload]' => \Drupal::service('file_system')->realpath($this->phpFile->uri), 'files[file_test_upload]' => \Drupal::service('file_system')->realpath($this->phpFile->uri),
'is_image_file' => FALSE, 'is_image_file' => FALSE,
'extensions' => 'php txt', 'extensions' => 'php txt',
@ -366,7 +366,7 @@ class SaveUploadTest extends FileManagedTestBase {
\Drupal::service('cache.config')->deleteAll(); \Drupal::service('cache.config')->deleteAll();
$edit = [ $edit = [
'file_test_replace' => FileSystemInterface::EXISTS_REPLACE, 'file_test_replace' => FileExists::Replace->name,
'files[file_test_upload]' => \Drupal::service('file_system')->realpath($this->phpFile->uri), 'files[file_test_upload]' => \Drupal::service('file_system')->realpath($this->phpFile->uri),
'is_image_file' => FALSE, 'is_image_file' => FALSE,
'extensions' => 'php', 'extensions' => 'php',
@ -390,7 +390,7 @@ class SaveUploadTest extends FileManagedTestBase {
file_put_contents($dot_file, 'This is a test'); file_put_contents($dot_file, 'This is a test');
$config = $this->config('system.file'); $config = $this->config('system.file');
$edit = [ $edit = [
'file_test_replace' => FileSystemInterface::EXISTS_REPLACE, 'file_test_replace' => FileExists::Replace->name,
'files[file_test_upload]' => \Drupal::service('file_system')->realpath($dot_file), 'files[file_test_upload]' => \Drupal::service('file_system')->realpath($dot_file),
'is_image_file' => FALSE, 'is_image_file' => FALSE,
]; ];
@ -404,7 +404,7 @@ class SaveUploadTest extends FileManagedTestBase {
$this->assertFileHooksCalled(['validate']); $this->assertFileHooksCalled(['validate']);
$edit = [ $edit = [
'file_test_replace' => FileSystemInterface::EXISTS_RENAME, 'file_test_replace' => FileExists::Rename->name,
'files[file_test_upload]' => \Drupal::service('file_system')->realpath($dot_file), 'files[file_test_upload]' => \Drupal::service('file_system')->realpath($dot_file),
'is_image_file' => FALSE, 'is_image_file' => FALSE,
'allow_all_extensions' => 'empty_array', 'allow_all_extensions' => 'empty_array',
@ -601,7 +601,7 @@ class SaveUploadTest extends FileManagedTestBase {
*/ */
public function testExistingRename() { public function testExistingRename() {
$edit = [ $edit = [
'file_test_replace' => FileSystemInterface::EXISTS_RENAME, 'file_test_replace' => FileExists::Rename->name,
'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->drupalGet('file-test/upload'); $this->drupalGet('file-test/upload');
@ -619,7 +619,7 @@ class SaveUploadTest extends FileManagedTestBase {
*/ */
public function testExistingReplace() { public function testExistingReplace() {
$edit = [ $edit = [
'file_test_replace' => FileSystemInterface::EXISTS_REPLACE, 'file_test_replace' => FileExists::Replace->name,
'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->drupalGet('file-test/upload'); $this->drupalGet('file-test/upload');
@ -637,7 +637,7 @@ class SaveUploadTest extends FileManagedTestBase {
*/ */
public function testExistingError() { public function testExistingError() {
$edit = [ $edit = [
'file_test_replace' => FileSystemInterface::EXISTS_ERROR, 'file_test_replace' => FileExists::Error->name,
'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->drupalGet('file-test/upload'); $this->drupalGet('file-test/upload');
@ -704,7 +704,7 @@ class SaveUploadTest extends FileManagedTestBase {
'multipart' => [ 'multipart' => [
[ [
'name' => 'file_test_replace', 'name' => 'file_test_replace',
'contents' => FileSystemInterface::EXISTS_RENAME, 'contents' => FileExists::Rename->name,
], ],
[ [
'name' => 'form_id', 'name' => 'form_id',

View File

@ -6,7 +6,7 @@ use Drupal\Core\Entity\EntityStorageException;
use Drupal\Core\Entity\EntityTypeManager; use Drupal\Core\Entity\EntityTypeManager;
use Drupal\Core\File\Exception\FileExistsException; use Drupal\Core\File\Exception\FileExistsException;
use Drupal\Core\File\Exception\InvalidStreamWrapperException; use Drupal\Core\File\Exception\InvalidStreamWrapperException;
use Drupal\Core\File\FileSystemInterface; use Drupal\Core\File\FileExists;
use Drupal\file\Entity\File; use Drupal\file\Entity\File;
use Drupal\file\FileRepository; use Drupal\file\FileRepository;
@ -45,7 +45,7 @@ class CopyTest extends FileManagedUnitTestBase {
// Clone the object so we don't have to worry about the function changing // Clone the object so we don't have to worry about the function changing
// our reference copy. // our reference copy.
$result = $this->fileRepository->copy(clone $source, $desired_uri, FileSystemInterface::EXISTS_ERROR); $result = $this->fileRepository->copy(clone $source, $desired_uri, FileExists::Error);
// Check the return status and that the contents changed. // Check the return status and that the contents changed.
$this->assertNotFalse($result, 'File copied successfully.'); $this->assertNotFalse($result, 'File copied successfully.');
@ -78,7 +78,7 @@ class CopyTest extends FileManagedUnitTestBase {
// Clone the object so we don't have to worry about the function changing // Clone the object so we don't have to worry about the function changing
// our reference copy. // our reference copy.
$result = $this->fileRepository->copy(clone $source, $target->getFileUri(), FileSystemInterface::EXISTS_RENAME); $result = $this->fileRepository->copy(clone $source, $target->getFileUri(), FileExists::Rename);
// Check the return status and that the contents changed. // Check the return status and that the contents changed.
$this->assertNotFalse($result, 'File copied successfully.'); $this->assertNotFalse($result, 'File copied successfully.');
@ -120,7 +120,7 @@ class CopyTest extends FileManagedUnitTestBase {
// Clone the object so we don't have to worry about the function changing // Clone the object so we don't have to worry about the function changing
// our reference copy. // our reference copy.
$result = $this->fileRepository->copy(clone $source, $target->getFileUri(), FileSystemInterface::EXISTS_REPLACE); $result = $this->fileRepository->copy(clone $source, $target->getFileUri(), FileExists::Replace);
// Check the return status and that the contents changed. // Check the return status and that the contents changed.
$this->assertNotFalse($result, 'File copied successfully.'); $this->assertNotFalse($result, 'File copied successfully.');
@ -160,7 +160,7 @@ class CopyTest extends FileManagedUnitTestBase {
// Clone the object so we don't have to worry about the function changing // Clone the object so we don't have to worry about the function changing
// our reference copy. // our reference copy.
try { try {
$result = $this->fileRepository->copy(clone $source, $target->getFileUri(), FileSystemInterface::EXISTS_ERROR); $result = $this->fileRepository->copy(clone $source, $target->getFileUri(), FileExists::Error);
$this->fail('expected FileExistsException'); $this->fail('expected FileExistsException');
} }
// FileExistsException is a subclass of FileException. // FileExistsException is a subclass of FileException.
@ -213,7 +213,7 @@ class CopyTest extends FileManagedUnitTestBase {
$this->expectException(EntityStorageException::class); $this->expectException(EntityStorageException::class);
$source = $this->createFile(); $source = $this->createFile();
$target = $this->createFile(); $target = $this->createFile();
$fileRepository->copy($source, $target->getFileUri(), FileSystemInterface::EXISTS_REPLACE); $fileRepository->copy($source, $target->getFileUri(), FileExists::Replace);
} }
} }

View File

@ -6,7 +6,7 @@ use Drupal\Core\Entity\EntityStorageException;
use Drupal\Core\Entity\EntityTypeManager; use Drupal\Core\Entity\EntityTypeManager;
use Drupal\Core\File\Exception\FileExistsException; use Drupal\Core\File\Exception\FileExistsException;
use Drupal\Core\File\Exception\InvalidStreamWrapperException; use Drupal\Core\File\Exception\InvalidStreamWrapperException;
use Drupal\Core\File\FileSystemInterface; use Drupal\Core\File\FileExists;
use Drupal\Core\StreamWrapper\StreamWrapperManagerInterface; use Drupal\Core\StreamWrapper\StreamWrapperManagerInterface;
use Drupal\file\Entity\File; use Drupal\file\Entity\File;
use Drupal\file\FileRepository; use Drupal\file\FileRepository;
@ -114,7 +114,7 @@ class FileRepositoryTest extends FileManagedUnitTestBase {
$existing = $this->createFile(); $existing = $this->createFile();
$contents = $this->randomMachineName(); $contents = $this->randomMachineName();
$result = $this->fileRepository->writeData($contents, $existing->getFileUri(), FileSystemInterface::EXISTS_REPLACE); $result = $this->fileRepository->writeData($contents, $existing->getFileUri(), FileExists::Replace);
$this->assertNotFalse($result, 'File saved successfully.'); $this->assertNotFalse($result, 'File saved successfully.');
$stream_wrapper_manager = \Drupal::service('stream_wrapper_manager'); $stream_wrapper_manager = \Drupal::service('stream_wrapper_manager');
@ -146,7 +146,7 @@ class FileRepositoryTest extends FileManagedUnitTestBase {
// Check the overwrite error. // Check the overwrite error.
try { try {
$this->fileRepository->writeData('asdf', $existing->getFileUri(), FileSystemInterface::EXISTS_ERROR); $this->fileRepository->writeData('asdf', $existing->getFileUri(), FileExists::Error);
$this->fail('expected FileExistsException'); $this->fail('expected FileExistsException');
} }
// FileExistsException is a subclass of FileException. // FileExistsException is a subclass of FileException.
@ -196,7 +196,7 @@ class FileRepositoryTest extends FileManagedUnitTestBase {
$this->expectException(EntityStorageException::class); $this->expectException(EntityStorageException::class);
$target = $this->createFile(); $target = $this->createFile();
$fileRepository->writeData('asdf', $target->getFileUri(), FileSystemInterface::EXISTS_REPLACE); $fileRepository->writeData('asdf', $target->getFileUri(), FileExists::Replace);
} }
/** /**

View File

@ -7,7 +7,7 @@ use Drupal\Core\Entity\EntityStorageException;
use Drupal\Core\Entity\EntityTypeManager; use Drupal\Core\Entity\EntityTypeManager;
use Drupal\Core\File\Exception\FileExistsException; use Drupal\Core\File\Exception\FileExistsException;
use Drupal\Core\File\Exception\InvalidStreamWrapperException; use Drupal\Core\File\Exception\InvalidStreamWrapperException;
use Drupal\Core\File\FileSystemInterface; use Drupal\Core\File\FileExists;
use Drupal\file\Entity\File; use Drupal\file\Entity\File;
use Drupal\file\FileRepository; use Drupal\file\FileRepository;
@ -46,7 +46,7 @@ class MoveTest extends FileManagedUnitTestBase {
// Clone the object so we don't have to worry about the function changing // Clone the object so we don't have to worry about the function changing
// our reference copy. // our reference copy.
$result = $this->fileRepository->move(clone $source, $desired_filepath, FileSystemInterface::EXISTS_ERROR); $result = $this->fileRepository->move(clone $source, $desired_filepath, FileExists::Error);
// Check the return status and that the contents changed. // Check the return status and that the contents changed.
$this->assertNotFalse($result, 'File moved successfully.'); $this->assertNotFalse($result, 'File moved successfully.');
@ -117,7 +117,7 @@ class MoveTest extends FileManagedUnitTestBase {
// Clone the object so we don't have to worry about the function changing // Clone the object so we don't have to worry about the function changing
// our reference copy. // our reference copy.
$result = $this->fileRepository->move(clone $source, $target->getFileUri(), FileSystemInterface::EXISTS_REPLACE); $result = $this->fileRepository->move(clone $source, $target->getFileUri(), FileExists::Replace);
// Look at the results. // Look at the results.
$this->assertEquals($contents, file_get_contents($result->getFileUri()), 'Contents of file were overwritten.'); $this->assertEquals($contents, file_get_contents($result->getFileUri()), 'Contents of file were overwritten.');
@ -150,7 +150,7 @@ class MoveTest extends FileManagedUnitTestBase {
// Copy the file over itself. Clone the object so we don't have to worry // Copy the file over itself. Clone the object so we don't have to worry
// about the function changing our reference copy. // about the function changing our reference copy.
try { try {
$this->fileRepository->move(clone $source, $source->getFileUri(), FileSystemInterface::EXISTS_ERROR); $this->fileRepository->move(clone $source, $source->getFileUri(), FileExists::Error);
$this->fail('expected FileExistsException'); $this->fail('expected FileExistsException');
} }
catch (FileExistsException $e) { catch (FileExistsException $e) {
@ -181,7 +181,7 @@ class MoveTest extends FileManagedUnitTestBase {
// Clone the object so we don't have to worry about the function changing // Clone the object so we don't have to worry about the function changing
// our reference copy. // our reference copy.
try { try {
$this->fileRepository->move(clone $source, $target->getFileUri(), FileSystemInterface::EXISTS_ERROR); $this->fileRepository->move(clone $source, $target->getFileUri(), FileExists::Error);
$this->fail('expected FileExistsException'); $this->fail('expected FileExistsException');
} }
// FileExistsException is a subclass of FileException. // FileExistsException is a subclass of FileException.
@ -237,7 +237,7 @@ class MoveTest extends FileManagedUnitTestBase {
$this->expectException(EntityStorageException::class); $this->expectException(EntityStorageException::class);
$source = $this->createFile(); $source = $this->createFile();
$target = $this->createFile(); $target = $this->createFile();
$fileRepository->move($source, $target->getFileUri(), FileSystemInterface::EXISTS_REPLACE); $fileRepository->move($source, $target->getFileUri(), FileExists::Replace);
} }

View File

@ -4,7 +4,7 @@ declare(strict_types=1);
namespace Drupal\Tests\image\Functional; namespace Drupal\Tests\image\Functional;
use Drupal\Core\File\FileSystemInterface; use Drupal\Core\File\FileExists;
use Drupal\image\Entity\ImageStyle; use Drupal\image\Entity\ImageStyle;
use Drupal\Tests\BrowserTestBase; use Drupal\Tests\BrowserTestBase;
use Drupal\Tests\TestFileCreationTrait; use Drupal\Tests\TestFileCreationTrait;
@ -45,7 +45,7 @@ class ImageDimensionsTest extends BrowserTestBase {
$file = reset($files); $file = reset($files);
/** @var \Drupal\Core\File\FileSystemInterface $file_system */ /** @var \Drupal\Core\File\FileSystemInterface $file_system */
$file_system = \Drupal::service('file_system'); $file_system = \Drupal::service('file_system');
$original_uri = $file_system->copy($file->uri, 'public://', FileSystemInterface::EXISTS_RENAME); $original_uri = $file_system->copy($file->uri, 'public://', FileExists::Rename);
// Create a style. // Create a style.
/** @var \Drupal\image\ImageStyleInterface $style */ /** @var \Drupal\image\ImageStyleInterface $style */
@ -281,7 +281,7 @@ class ImageDimensionsTest extends BrowserTestBase {
$this->assertEquals(100, $image_file->getHeight()); $this->assertEquals(100, $image_file->getHeight());
// GIF original image. Should be resized to 50x50. // GIF original image. Should be resized to 50x50.
$file = $files[1]; $file = $files[1];
$original_uri = $file_system->copy($file->uri, 'public://', FileSystemInterface::EXISTS_RENAME); $original_uri = $file_system->copy($file->uri, 'public://', FileExists::Rename);
$generated_uri = 'public://styles/test_uri/public/' . $file_system->basename($original_uri); $generated_uri = 'public://styles/test_uri/public/' . $file_system->basename($original_uri);
$url = $file_url_generator->transformRelative($style->buildUrl($original_uri)); $url = $file_url_generator->transformRelative($style->buildUrl($original_uri));
$variables['#uri'] = $original_uri; $variables['#uri'] = $original_uri;

View File

@ -4,7 +4,7 @@ declare(strict_types=1);
namespace Drupal\Tests\image\Functional\ImageEffect; namespace Drupal\Tests\image\Functional\ImageEffect;
use Drupal\Core\File\FileSystemInterface; use Drupal\Core\File\FileExists;
use Drupal\image\Entity\ImageStyle; use Drupal\image\Entity\ImageStyle;
use Drupal\Tests\BrowserTestBase; use Drupal\Tests\BrowserTestBase;
@ -45,7 +45,7 @@ class ConvertTest extends BrowserTestBase {
// Create a copy of a test image file in root. // Create a copy of a test image file in root.
$test_uri = 'public://image-test-do.png'; $test_uri = 'public://image-test-do.png';
\Drupal::service('file_system')->copy('core/tests/fixtures/files/image-test.png', $test_uri, FileSystemInterface::EXISTS_REPLACE); \Drupal::service('file_system')->copy('core/tests/fixtures/files/image-test.png', $test_uri, FileExists::Replace);
$this->assertFileExists($test_uri); $this->assertFileExists($test_uri);
// Execute the image style on the test image via a GET request. // Execute the image style on the test image via a GET request.

View File

@ -5,10 +5,10 @@ declare(strict_types=1);
namespace Drupal\Tests\image\Functional; namespace Drupal\Tests\image\Functional;
use Drupal\Core\Entity\Entity\EntityViewDisplay; use Drupal\Core\Entity\Entity\EntityViewDisplay;
use Drupal\Core\File\FileSystemInterface; use Drupal\Core\File\FileExists;
use Drupal\field\Entity\FieldConfig; use Drupal\field\Entity\FieldConfig;
use Drupal\file\Entity\File;
use Drupal\field\Entity\FieldStorageConfig; use Drupal\field\Entity\FieldStorageConfig;
use Drupal\file\Entity\File;
use Drupal\Tests\EntityViewTrait; use Drupal\Tests\EntityViewTrait;
use Drupal\Tests\TestFileCreationTrait; use Drupal\Tests\TestFileCreationTrait;
@ -50,7 +50,7 @@ class ImageFieldDefaultImagesTest extends ImageFieldTestBase {
for ($i = 1; $i <= 10; $i++) { for ($i = 1; $i <= 10; $i++) {
$filename = $this->randomMachineName() . "$i"; $filename = $this->randomMachineName() . "$i";
$desired_filepath = 'public://' . $filename; $desired_filepath = 'public://' . $filename;
\Drupal::service('file_system')->copy($files[0]->uri, $desired_filepath, FileSystemInterface::EXISTS_ERROR); \Drupal::service('file_system')->copy($files[0]->uri, $desired_filepath, FileExists::Error);
$file = File::create(['uri' => $desired_filepath, 'filename' => $filename, 'name' => $filename]); $file = File::create(['uri' => $desired_filepath, 'filename' => $filename, 'name' => $filename]);
$file->save(); $file->save();
} }

View File

@ -4,6 +4,7 @@ declare(strict_types=1);
namespace Drupal\Tests\image\Functional; namespace Drupal\Tests\image\Functional;
use Drupal\Core\File\FileExists;
use Drupal\Core\File\FileSystemInterface; use Drupal\Core\File\FileSystemInterface;
use Drupal\Core\StreamWrapper\StreamWrapperManager; use Drupal\Core\StreamWrapper\StreamWrapperManager;
use Drupal\image\Entity\ImageStyle; use Drupal\image\Entity\ImageStyle;
@ -158,7 +159,7 @@ class ImageStylesPathAndUrlTest extends BrowserTestBase {
$file = array_shift($files); $file = array_shift($files);
/** @var \Drupal\Core\File\FileSystemInterface $file_system */ /** @var \Drupal\Core\File\FileSystemInterface $file_system */
$file_system = \Drupal::service('file_system'); $file_system = \Drupal::service('file_system');
$original_uri = $file_system->copy($file->uri, $scheme . '://', FileSystemInterface::EXISTS_RENAME); $original_uri = $file_system->copy($file->uri, $scheme . '://', FileExists::Rename);
// Let the image_module_test module know about this file, so it can claim // Let the image_module_test module know about this file, so it can claim
// ownership in hook_file_download(). // ownership in hook_file_download().
\Drupal::state()->set('image.test_file_download', $original_uri); \Drupal::state()->set('image.test_file_download', $original_uri);
@ -243,7 +244,7 @@ class ImageStylesPathAndUrlTest extends BrowserTestBase {
// Repeat this with a different file that we do not have access to and // Repeat this with a different file that we do not have access to and
// make sure that access is denied. // make sure that access is denied.
$file_no_access = array_shift($files); $file_no_access = array_shift($files);
$original_uri_no_access = $file_system->copy($file_no_access->uri, $scheme . '://', FileSystemInterface::EXISTS_RENAME); $original_uri_no_access = $file_system->copy($file_no_access->uri, $scheme . '://', FileExists::Rename);
$generated_uri_no_access = $scheme . '://styles/' . $this->style->id() . '/' . $scheme . '/' . $file_system->basename($original_uri_no_access); $generated_uri_no_access = $scheme . '://styles/' . $this->style->id() . '/' . $scheme . '/' . $file_system->basename($original_uri_no_access);
$this->assertFileDoesNotExist($generated_uri_no_access); $this->assertFileDoesNotExist($generated_uri_no_access);
$generate_url_no_access = $this->style->buildUrl($original_uri_no_access); $generate_url_no_access = $this->style->buildUrl($original_uri_no_access);
@ -283,7 +284,7 @@ class ImageStylesPathAndUrlTest extends BrowserTestBase {
// Create another working copy of the file. // Create another working copy of the file.
$files = $this->drupalGetTestFiles('image'); $files = $this->drupalGetTestFiles('image');
$file = array_shift($files); $file = array_shift($files);
$original_uri = $file_system->copy($file->uri, $scheme . '://', FileSystemInterface::EXISTS_RENAME); $original_uri = $file_system->copy($file->uri, $scheme . '://', FileExists::Rename);
// Let the image_module_test module know about this file, so it can claim // Let the image_module_test module know about this file, so it can claim
// ownership in hook_file_download(). // ownership in hook_file_download().
\Drupal::state()->set('image.test_file_download', $original_uri); \Drupal::state()->set('image.test_file_download', $original_uri);

View File

@ -2,7 +2,7 @@
namespace Drupal\Tests\image\Kernel; namespace Drupal\Tests\image\Kernel;
use Drupal\Core\File\FileSystemInterface; use Drupal\Core\File\FileExists;
use Drupal\file\Entity\File; use Drupal\file\Entity\File;
use Drupal\file\FileRepository; use Drupal\file\FileRepository;
use Drupal\image\Entity\ImageStyle; use Drupal\image\Entity\ImageStyle;
@ -75,7 +75,7 @@ class FileMoveTest extends KernelTestBase {
// Clone the object, so we don't have to worry about the function changing // Clone the object, so we don't have to worry about the function changing
// our reference copy. // our reference copy.
$desired_filepath = 'public://' . $this->randomMachineName(); $desired_filepath = 'public://' . $this->randomMachineName();
$result = $this->fileRepository->move(clone $file, $desired_filepath, FileSystemInterface::EXISTS_ERROR); $result = $this->fileRepository->move(clone $file, $desired_filepath, FileExists::Error);
// Check if image has been moved. // Check if image has been moved.
$this->assertFileExists($result->getFileUri()); $this->assertFileExists($result->getFileUri());

View File

@ -3,14 +3,14 @@
namespace Drupal\Tests\image\Kernel; namespace Drupal\Tests\image\Kernel;
use Drupal\Core\Field\FieldStorageDefinitionInterface; use Drupal\Core\Field\FieldStorageDefinitionInterface;
use Drupal\Core\File\FileSystemInterface; use Drupal\Core\File\FileExists;
use Drupal\Core\Url; use Drupal\Core\Url;
use Drupal\entity_test\Entity\EntityTest; use Drupal\entity_test\Entity\EntityTest;
use Drupal\field\Entity\FieldConfig; use Drupal\field\Entity\FieldConfig;
use Drupal\field\Entity\FieldStorageConfig;
use Drupal\file\Entity\File; use Drupal\file\Entity\File;
use Drupal\image\Entity\ImageStyle; use Drupal\image\Entity\ImageStyle;
use Drupal\KernelTests\KernelTestBase; use Drupal\KernelTests\KernelTestBase;
use Drupal\field\Entity\FieldStorageConfig;
use Drupal\Tests\TestFileCreationTrait; use Drupal\Tests\TestFileCreationTrait;
/** /**
@ -91,7 +91,7 @@ class ImageThemeFunctionTest extends KernelTestBase {
// Create an image. // Create an image.
$files = $this->drupalGetTestFiles('image'); $files = $this->drupalGetTestFiles('image');
$file = reset($files); $file = reset($files);
$original_uri = \Drupal::service('file_system')->copy($file->uri, 'public://', FileSystemInterface::EXISTS_RENAME); $original_uri = \Drupal::service('file_system')->copy($file->uri, 'public://', FileExists::Rename);
// Create a style. // Create a style.
$style = ImageStyle::create(['name' => 'test', 'label' => 'Test']); $style = ImageStyle::create(['name' => 'test', 'label' => 'Test']);
@ -153,7 +153,7 @@ class ImageThemeFunctionTest extends KernelTestBase {
// Create an image. // Create an image.
$files = $this->drupalGetTestFiles('image'); $files = $this->drupalGetTestFiles('image');
$file = reset($files); $file = reset($files);
$original_uri = \Drupal::service('file_system')->copy($file->uri, 'public://', FileSystemInterface::EXISTS_RENAME); $original_uri = \Drupal::service('file_system')->copy($file->uri, 'public://', FileExists::Rename);
// Create a style. // Create a style.
$style = ImageStyle::create(['name' => 'image_test', 'label' => 'Test']); $style = ImageStyle::create(['name' => 'image_test', 'label' => 'Test']);

View File

@ -9,6 +9,7 @@ use Drupal\Core\Entity\EntityInterface;
use Drupal\Core\Field\FieldDefinitionInterface; use Drupal\Core\Field\FieldDefinitionInterface;
use Drupal\Core\File\Event\FileUploadSanitizeNameEvent; use Drupal\Core\File\Event\FileUploadSanitizeNameEvent;
use Drupal\Core\File\Exception\FileException; use Drupal\Core\File\Exception\FileException;
use Drupal\Core\File\FileExists;
use Drupal\Core\File\FileSystemInterface; use Drupal\Core\File\FileSystemInterface;
use Drupal\Core\Lock\LockBackendInterface; use Drupal\Core\Lock\LockBackendInterface;
use Drupal\Core\Render\BubbleableMetadata; use Drupal\Core\Render\BubbleableMetadata;
@ -219,7 +220,7 @@ class TemporaryJsonapiFileFieldUploader {
$temp_file_path = $this->streamUploadData(); $temp_file_path = $this->streamUploadData();
$file_uri = $this->fileSystem->getDestinationFilename($file_uri, FileSystemInterface::EXISTS_RENAME); $file_uri = $this->fileSystem->getDestinationFilename($file_uri, FileExists::Rename);
// Lock based on the prepared file URI. // Lock based on the prepared file URI.
$lock_id = $this->generateLockIdFromFileUri($file_uri); $lock_id = $this->generateLockIdFromFileUri($file_uri);
@ -259,10 +260,10 @@ class TemporaryJsonapiFileFieldUploader {
$file->setFilename($this->fileSystem->basename($file->getFileUri())); $file->setFilename($this->fileSystem->basename($file->getFileUri()));
// Move the file to the correct location after validation. Use // Move the file to the correct location after validation. Use
// FileSystemInterface::EXISTS_ERROR as the file location has already been // FileExists::Error as the file location has already been
// determined above in FileSystem::getDestinationFilename(). // determined above in FileSystem::getDestinationFilename().
try { try {
$this->fileSystem->move($temp_file_path, $file_uri, FileSystemInterface::EXISTS_ERROR); $this->fileSystem->move($temp_file_path, $file_uri, FileExists::Error);
} }
catch (FileException $e) { catch (FileException $e) {
throw new HttpException(500, 'Temporary file could not be moved to file location'); throw new HttpException(500, 'Temporary file could not be moved to file location');

View File

@ -6,7 +6,7 @@ namespace Drupal\Tests\layout_builder\Functional;
use Drupal\Core\Entity\FieldableEntityInterface; use Drupal\Core\Entity\FieldableEntityInterface;
use Drupal\Core\Field\FieldDefinitionInterface; use Drupal\Core\Field\FieldDefinitionInterface;
use Drupal\Core\File\FileSystemInterface; use Drupal\Core\File\FileExists;
use Drupal\field\Entity\FieldConfig; use Drupal\field\Entity\FieldConfig;
use Drupal\field\Entity\FieldStorageConfig; use Drupal\field\Entity\FieldStorageConfig;
use Drupal\file\Entity\File; use Drupal\file\Entity\File;
@ -291,7 +291,7 @@ class LayoutBuilderDefaultValuesTest extends BrowserTestBase {
for ($i = 1; $i <= 6; $i++) { for ($i = 1; $i <= 6; $i++) {
$filename = "test-file-$i"; $filename = "test-file-$i";
$desired_filepath = 'public://' . $filename; $desired_filepath = 'public://' . $filename;
\Drupal::service('file_system')->copy($files[0]->uri, $desired_filepath, FileSystemInterface::EXISTS_ERROR); \Drupal::service('file_system')->copy($files[0]->uri, $desired_filepath, FileExists::Error);
$file = File::create([ $file = File::create([
'uri' => $desired_filepath, 'uri' => $desired_filepath,
'filename' => $filename, 'filename' => $filename,

View File

@ -7,7 +7,7 @@
use Drupal\Core\File\Exception\FileException; use Drupal\Core\File\Exception\FileException;
use Drupal\Core\File\Exception\InvalidStreamWrapperException; use Drupal\Core\File\Exception\InvalidStreamWrapperException;
use Drupal\Core\File\FileSystemInterface; use Drupal\Core\File\FileExists;
use Drupal\Core\Url; use Drupal\Core\Url;
use GuzzleHttp\Exception\ConnectException; use GuzzleHttp\Exception\ConnectException;
use GuzzleHttp\Exception\RequestException; use GuzzleHttp\Exception\RequestException;
@ -345,7 +345,7 @@ function locale_translation_download_source($source_file, $directory = 'temporar
/** @var \Drupal\Core\File\FileSystemInterface $fileSystem */ /** @var \Drupal\Core\File\FileSystemInterface $fileSystem */
$fileSystem = \Drupal::service('file_system'); $fileSystem = \Drupal::service('file_system');
$filename = $fileSystem->basename($source_file->uri); $filename = $fileSystem->basename($source_file->uri);
if ($uri = $fileSystem->saveData($data, $directory . $filename, FileSystemInterface::EXISTS_REPLACE)) { if ($uri = $fileSystem->saveData($data, $directory . $filename, FileExists::Replace)) {
$file = clone($source_file); $file = clone($source_file);
$file->type = LOCALE_TRANSLATION_LOCAL; $file->type = LOCALE_TRANSLATION_LOCAL;
$file->uri = $uri; $file->uri = $uri;

View File

@ -4,7 +4,7 @@ declare(strict_types=1);
namespace Drupal\Tests\locale\Functional; namespace Drupal\Tests\locale\Functional;
use Drupal\Core\File\FileSystemInterface; use Drupal\Core\File\FileExists;
use Drupal\Tests\BrowserTestBase; use Drupal\Tests\BrowserTestBase;
// cspell:ignore janvier lundi // cspell:ignore janvier lundi
@ -47,8 +47,8 @@ class LocaleExportTest extends BrowserTestBase {
$this->drupalLogin($this->adminUser); $this->drupalLogin($this->adminUser);
// Copy test po files to the translations directory. // Copy test po files to the translations directory.
\Drupal::service('file_system')->copy(__DIR__ . '/../../../tests/test.de.po', 'translations://', FileSystemInterface::EXISTS_REPLACE); \Drupal::service('file_system')->copy(__DIR__ . '/../../../tests/test.de.po', 'translations://', FileExists::Replace);
\Drupal::service('file_system')->copy(__DIR__ . '/../../../tests/test.xx.po', 'translations://', FileSystemInterface::EXISTS_REPLACE); \Drupal::service('file_system')->copy(__DIR__ . '/../../../tests/test.xx.po', 'translations://', FileExists::Replace);
} }
/** /**

View File

@ -4,11 +4,11 @@ declare(strict_types=1);
namespace Drupal\Tests\locale\Functional; namespace Drupal\Tests\locale\Functional;
use Drupal\Core\Url;
use Drupal\Core\Database\Database; use Drupal\Core\Database\Database;
use Drupal\Core\File\FileSystemInterface; use Drupal\Core\File\FileExists;
use Drupal\Tests\BrowserTestBase;
use Drupal\Core\Language\LanguageInterface; use Drupal\Core\Language\LanguageInterface;
use Drupal\Core\Url;
use Drupal\Tests\BrowserTestBase;
// cspell:ignore chien chiens deutsch januari lundi moutons műveletek svibanj // cspell:ignore chien chiens deutsch januari lundi moutons műveletek svibanj
@ -54,8 +54,8 @@ class LocaleImportFunctionalTest extends BrowserTestBase {
// Copy test po files to the translations directory. // Copy test po files to the translations directory.
/** @var \Drupal\Core\File\FileSystemInterface $file_system */ /** @var \Drupal\Core\File\FileSystemInterface $file_system */
$file_system = \Drupal::service('file_system'); $file_system = \Drupal::service('file_system');
$file_system->copy(__DIR__ . '/../../../tests/test.de.po', 'translations://', FileSystemInterface::EXISTS_REPLACE); $file_system->copy(__DIR__ . '/../../../tests/test.de.po', 'translations://', FileExists::Replace);
$file_system->copy(__DIR__ . '/../../../tests/test.xx.po', 'translations://', FileSystemInterface::EXISTS_REPLACE); $file_system->copy(__DIR__ . '/../../../tests/test.xx.po', 'translations://', FileExists::Replace);
$this->adminUser = $this->drupalCreateUser([ $this->adminUser = $this->drupalCreateUser([
'administer languages', 'administer languages',

View File

@ -6,14 +6,15 @@
*/ */
use Drupal\Core\File\Exception\FileException; use Drupal\Core\File\Exception\FileException;
use Drupal\Core\File\FileExists;
use Drupal\Core\File\FileSystemInterface; use Drupal\Core\File\FileSystemInterface;
use Drupal\Core\StringTranslation\TranslatableMarkup;
use Drupal\Core\Url; use Drupal\Core\Url;
use Drupal\image\Plugin\Field\FieldType\ImageItem;
use Drupal\media\Entity\MediaType; use Drupal\media\Entity\MediaType;
use Drupal\media\MediaTypeInterface; use Drupal\media\MediaTypeInterface;
use Drupal\media\Plugin\media\Source\OEmbedInterface; use Drupal\media\Plugin\media\Source\OEmbedInterface;
use Drupal\user\RoleInterface; use Drupal\user\RoleInterface;
use Drupal\image\Plugin\Field\FieldType\ImageItem;
use Drupal\Core\StringTranslation\TranslatableMarkup;
/** /**
* Implements hook_install(). * Implements hook_install().
@ -35,7 +36,7 @@ function media_install() {
// possible to copy the files is also confusing, we silently do nothing. // possible to copy the files is also confusing, we silently do nothing.
if (!file_exists($destination . DIRECTORY_SEPARATOR . $file->filename)) { if (!file_exists($destination . DIRECTORY_SEPARATOR . $file->filename)) {
try { try {
$file_system->copy($file->uri, $destination, FileSystemInterface::EXISTS_ERROR); $file_system->copy($file->uri, $destination, FileExists::Error);
} }
catch (FileException $e) { catch (FileException $e) {
// Ignore and continue. // Ignore and continue.

View File

@ -11,6 +11,7 @@ use Drupal\Core\Entity\EntityFieldManagerInterface;
use Drupal\Core\Entity\EntityTypeManagerInterface; use Drupal\Core\Entity\EntityTypeManagerInterface;
use Drupal\Core\Field\FieldTypePluginManagerInterface; use Drupal\Core\Field\FieldTypePluginManagerInterface;
use Drupal\Core\File\Exception\FileException; use Drupal\Core\File\Exception\FileException;
use Drupal\Core\File\FileExists;
use Drupal\Core\File\FileSystemInterface; use Drupal\Core\File\FileSystemInterface;
use Drupal\Core\Form\FormStateInterface; use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Messenger\MessengerInterface; use Drupal\Core\Messenger\MessengerInterface;
@ -19,11 +20,11 @@ use Drupal\Core\Url;
use Drupal\Core\Utility\Token; use Drupal\Core\Utility\Token;
use Drupal\media\Attribute\OEmbedMediaSource; use Drupal\media\Attribute\OEmbedMediaSource;
use Drupal\media\IFrameUrlHelper; use Drupal\media\IFrameUrlHelper;
use Drupal\media\MediaInterface;
use Drupal\media\MediaSourceBase;
use Drupal\media\MediaTypeInterface;
use Drupal\media\OEmbed\Resource; use Drupal\media\OEmbed\Resource;
use Drupal\media\OEmbed\ResourceException; use Drupal\media\OEmbed\ResourceException;
use Drupal\media\MediaSourceBase;
use Drupal\media\MediaInterface;
use Drupal\media\MediaTypeInterface;
use Drupal\media\OEmbed\ResourceFetcherInterface; use Drupal\media\OEmbed\ResourceFetcherInterface;
use Drupal\media\OEmbed\UrlResolverInterface; use Drupal\media\OEmbed\UrlResolverInterface;
use GuzzleHttp\ClientInterface; use GuzzleHttp\ClientInterface;
@ -451,7 +452,7 @@ class OEmbed extends MediaSourceBase implements OEmbedInterface {
$response = $this->httpClient->request('GET', $remote_thumbnail_url); $response = $this->httpClient->request('GET', $remote_thumbnail_url);
if ($response->getStatusCode() === 200) { if ($response->getStatusCode() === 200) {
$local_thumbnail_uri = $directory . DIRECTORY_SEPARATOR . $hash . '.' . $this->getThumbnailFileExtensionFromUrl($remote_thumbnail_url, $response); $local_thumbnail_uri = $directory . DIRECTORY_SEPARATOR . $hash . '.' . $this->getThumbnailFileExtensionFromUrl($remote_thumbnail_url, $response);
$this->fileSystem->saveData((string) $response->getBody(), $local_thumbnail_uri, FileSystemInterface::EXISTS_REPLACE); $this->fileSystem->saveData((string) $response->getBody(), $local_thumbnail_uri, FileExists::Replace);
return $local_thumbnail_uri; return $local_thumbnail_uri;
} }
} }

View File

@ -2,9 +2,9 @@
namespace Drupal\migrate\Plugin\migrate\process; namespace Drupal\migrate\Plugin\migrate\process;
use Drupal\migrate\Attribute\MigrateProcess;
use Drupal\Core\File\FileSystemInterface; use Drupal\Core\File\FileSystemInterface;
use Drupal\Core\Plugin\ContainerFactoryPluginInterface; use Drupal\Core\Plugin\ContainerFactoryPluginInterface;
use Drupal\migrate\Attribute\MigrateProcess;
use Drupal\migrate\MigrateException; use Drupal\migrate\MigrateException;
use Drupal\migrate\MigrateExecutableInterface; use Drupal\migrate\MigrateExecutableInterface;
use Drupal\migrate\Row; use Drupal\migrate\Row;

View File

@ -4,6 +4,7 @@ namespace Drupal\migrate\Plugin\migrate\process;
use Drupal\migrate\Attribute\MigrateProcess; use Drupal\migrate\Attribute\MigrateProcess;
use Drupal\Core\File\Exception\FileException; use Drupal\Core\File\Exception\FileException;
use Drupal\Core\File\FileExists;
use Drupal\Core\File\FileSystemInterface; use Drupal\Core\File\FileSystemInterface;
use Drupal\Core\Plugin\ContainerFactoryPluginInterface; use Drupal\Core\Plugin\ContainerFactoryPluginInterface;
use Drupal\Core\StreamWrapper\LocalStream; use Drupal\Core\StreamWrapper\LocalStream;
@ -164,26 +165,30 @@ class FileCopy extends FileProcessBase implements ContainerFactoryPluginInterfac
* The source path or URI. * The source path or URI.
* @param string $destination * @param string $destination
* The destination path or URI. * The destination path or URI.
* @param int $replace * @param \Drupal\Core\File\FileExists|int $fileExists
* (optional) FileSystemInterface::EXISTS_REPLACE (default) or * (optional) FileExists::Replace (default) or
* FileSystemInterface::EXISTS_RENAME. * FileExists::Rename.
* *
* @return string|bool * @return string|bool
* File destination on success, FALSE on failure. * File destination on success, FALSE on failure.
*/ */
protected function writeFile($source, $destination, $replace = FileSystemInterface::EXISTS_REPLACE) { protected function writeFile($source, $destination, FileExists|int $fileExists = FileExists::Replace) {
if (!$fileExists instanceof FileExists) {
// @phpstan-ignore-next-line
$fileExists = FileExists::fromLegacyInt($fileExists, __METHOD__);
}
// Check if there is a destination available for copying. If there isn't, // Check if there is a destination available for copying. If there isn't,
// it already exists at the destination and the replace flag tells us to not // it already exists at the destination and the replace flag tells us to not
// replace it. In that case, return the original destination. // replace it. In that case, return the original destination.
if ($this->fileSystem->getDestinationFilename($destination, $replace) === FALSE) { if ($this->fileSystem->getDestinationFilename($destination, $fileExists) === FALSE) {
return $destination; return $destination;
} }
try { try {
if ($this->configuration['move']) { if ($this->configuration['move']) {
return $this->fileSystem->move($source, $destination, $replace); return $this->fileSystem->move($source, $destination, $fileExists);
} }
else { else {
return $this->fileSystem->copy($source, $destination, $replace); return $this->fileSystem->copy($source, $destination, $fileExists);
} }
} }
catch (FileException $e) { catch (FileException $e) {

View File

@ -2,7 +2,7 @@
namespace Drupal\migrate\Plugin\migrate\process; namespace Drupal\migrate\Plugin\migrate\process;
use Drupal\Core\File\FileSystemInterface; use Drupal\Core\File\FileExists;
use Drupal\migrate\ProcessPluginBase; use Drupal\migrate\ProcessPluginBase;
/** /**
@ -32,18 +32,18 @@ abstract class FileProcessBase extends ProcessPluginBase {
if (array_key_exists('file_exists', $configuration)) { if (array_key_exists('file_exists', $configuration)) {
switch ($configuration['file_exists']) { switch ($configuration['file_exists']) {
case 'use existing': case 'use existing':
$configuration['file_exists'] = FileSystemInterface::EXISTS_ERROR; $configuration['file_exists'] = FileExists::Error;
break; break;
case 'rename': case 'rename':
$configuration['file_exists'] = FileSystemInterface::EXISTS_RENAME; $configuration['file_exists'] = FileExists::Rename;
break; break;
default: default:
$configuration['file_exists'] = FileSystemInterface::EXISTS_REPLACE; $configuration['file_exists'] = FileExists::Replace;
} }
} }
$configuration += ['file_exists' => FileSystemInterface::EXISTS_REPLACE]; $configuration += ['file_exists' => FileExists::Replace];
parent::__construct($configuration, $plugin_id, $plugin_definition); parent::__construct($configuration, $plugin_id, $plugin_definition);
} }

View File

@ -4,6 +4,7 @@ declare(strict_types=1);
namespace Drupal\Tests\migrate\Unit\process; namespace Drupal\Tests\migrate\Unit\process;
use Drupal\Core\File\FileExists;
use Drupal\Core\File\FileSystemInterface; use Drupal\Core\File\FileSystemInterface;
use Drupal\Core\StreamWrapper\StreamWrapperManagerInterface; use Drupal\Core\StreamWrapper\StreamWrapperManagerInterface;
use Drupal\migrate\Plugin\migrate\process\FileCopy; use Drupal\migrate\Plugin\migrate\process\FileCopy;
@ -37,11 +38,11 @@ class FileCopyTest extends MigrateProcessTestCase {
*/ */
public static function providerFileProcessBaseConstructor() { public static function providerFileProcessBaseConstructor() {
return [ return [
[['file_exists' => 'replace'], FileSystemInterface::EXISTS_REPLACE], [['file_exists' => 'replace'], FileExists::Replace],
[['file_exists' => 'rename'], FileSystemInterface::EXISTS_RENAME], [['file_exists' => 'rename'], FileExists::Rename],
[['file_exists' => 'use existing'], FileSystemInterface::EXISTS_ERROR], [['file_exists' => 'use existing'], FileExists::Error],
[['file_exists' => 'foobar'], FileSystemInterface::EXISTS_REPLACE], [['file_exists' => 'foobar'], FileExists::Replace],
[[], FileSystemInterface::EXISTS_REPLACE], [[], FileExists::Replace],
]; ];
} }
@ -50,12 +51,12 @@ class FileCopyTest extends MigrateProcessTestCase {
* *
* @param array $configuration * @param array $configuration
* The plugin configuration. * The plugin configuration.
* @param int $expected * @param \Drupal\Core\File\FileExists $expected
* The expected value of the plugin configuration. * The expected value of the plugin configuration.
* *
* @internal * @internal
*/ */
protected function assertPlugin(array $configuration, int $expected): void { protected function assertPlugin(array $configuration, FileExists $expected): void {
$stream_wrapper_manager = $this->prophesize(StreamWrapperManagerInterface::class)->reveal(); $stream_wrapper_manager = $this->prophesize(StreamWrapperManagerInterface::class)->reveal();
$file_system = $this->prophesize(FileSystemInterface::class)->reveal(); $file_system = $this->prophesize(FileSystemInterface::class)->reveal();
$download_plugin = $this->prophesize(MigrateProcessInterface::class)->reveal(); $download_plugin = $this->prophesize(MigrateProcessInterface::class)->reveal();

View File

@ -5,6 +5,7 @@ namespace Drupal\system\Plugin\ImageToolkit;
use Drupal\Component\Utility\Color; use Drupal\Component\Utility\Color;
use Drupal\Core\Config\ConfigFactoryInterface; use Drupal\Core\Config\ConfigFactoryInterface;
use Drupal\Core\File\Exception\FileException; use Drupal\Core\File\Exception\FileException;
use Drupal\Core\File\FileExists;
use Drupal\Core\File\FileSystemInterface; use Drupal\Core\File\FileSystemInterface;
use Drupal\Core\Form\FormStateInterface; use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\ImageToolkit\Attribute\ImageToolkit; use Drupal\Core\ImageToolkit\Attribute\ImageToolkit;
@ -368,7 +369,7 @@ class GDToolkit extends ImageToolkitBase {
// Move temporary local file to remote destination. // Move temporary local file to remote destination.
if (isset($permanent_destination) && $success) { if (isset($permanent_destination) && $success) {
try { try {
$this->fileSystem->move($destination, $permanent_destination, FileSystemInterface::EXISTS_REPLACE); $this->fileSystem->move($destination, $permanent_destination, FileExists::Replace);
return TRUE; return TRUE;
} }
catch (FileException $e) { catch (FileException $e) {

View File

@ -4,7 +4,7 @@ namespace Drupal\update\Form;
use Drupal\Core\Archiver\ArchiverManager; use Drupal\Core\Archiver\ArchiverManager;
use Drupal\Core\Extension\ModuleHandlerInterface; use Drupal\Core\Extension\ModuleHandlerInterface;
use Drupal\Core\File\FileSystemInterface; use Drupal\Core\File\FileExists;
use Drupal\Core\FileTransfer\Local; use Drupal\Core\FileTransfer\Local;
use Drupal\Core\Form\FormBase; use Drupal\Core\Form\FormBase;
use Drupal\Core\Form\FormStateInterface; use Drupal\Core\Form\FormStateInterface;
@ -168,7 +168,7 @@ class UpdateManagerInstall extends FormBase {
} }
elseif (!empty($all_files['project_upload']) && $this->moduleHandler->moduleExists('file')) { elseif (!empty($all_files['project_upload']) && $this->moduleHandler->moduleExists('file')) {
$validators = ['FileExtension' => ['extensions' => $this->archiverManager->getExtensions()]]; $validators = ['FileExtension' => ['extensions' => $this->archiverManager->getExtensions()]];
if (!($finfo = file_save_upload('project_upload', $validators, NULL, 0, FileSystemInterface::EXISTS_REPLACE))) { if (!($finfo = file_save_upload('project_upload', $validators, NULL, 0, FileExists::Replace))) {
// Failed to upload the file. file_save_upload() calls // Failed to upload the file. file_save_upload() calls
// \Drupal\Core\Messenger\MessengerInterface::addError() on failure. // \Drupal\Core\Messenger\MessengerInterface::addError() on failure.
return; return;

View File

@ -38,7 +38,7 @@
use Drupal\Core\File\Exception\FileException; use Drupal\Core\File\Exception\FileException;
use Drupal\Core\File\Exception\InvalidStreamWrapperException; use Drupal\Core\File\Exception\InvalidStreamWrapperException;
use Drupal\Core\File\FileSystemInterface; use Drupal\Core\File\FileExists;
use Drupal\Core\Url; use Drupal\Core\Url;
use Psr\Http\Client\ClientExceptionInterface; use Psr\Http\Client\ClientExceptionInterface;
use Symfony\Component\HttpFoundation\RedirectResponse; use Symfony\Component\HttpFoundation\RedirectResponse;
@ -231,7 +231,7 @@ function update_manager_file_get($url) {
if (!file_exists($local) || update_delete_file_if_stale($local)) { if (!file_exists($local) || update_delete_file_if_stale($local)) {
try { try {
$data = (string) \Drupal::httpClient()->get($url)->getBody(); $data = (string) \Drupal::httpClient()->get($url)->getBody();
return \Drupal::service('file_system')->saveData($data, $local, FileSystemInterface::EXISTS_REPLACE); return \Drupal::service('file_system')->saveData($data, $local, FileExists::Replace);
} }
catch (ClientExceptionInterface $exception) { catch (ClientExceptionInterface $exception) {
\Drupal::messenger()->addError(t('Failed to fetch file due to error "%error"', ['%error' => $exception->getMessage()])); \Drupal::messenger()->addError(t('Failed to fetch file due to error "%error"', ['%error' => $exception->getMessage()]));

View File

@ -7,6 +7,7 @@ use Drupal\Core\DependencyInjection\ContainerInjectionInterface;
use Drupal\Core\Entity\EntityTypeManagerInterface; use Drupal\Core\Entity\EntityTypeManagerInterface;
use Drupal\Core\Extension\ModuleHandlerInterface; use Drupal\Core\Extension\ModuleHandlerInterface;
use Drupal\Core\File\Exception\FileException; use Drupal\Core\File\Exception\FileException;
use Drupal\Core\File\FileExists;
use Drupal\Core\File\FileSystemInterface; use Drupal\Core\File\FileSystemInterface;
use Drupal\Core\State\StateInterface; use Drupal\Core\State\StateInterface;
use Symfony\Component\DependencyInjection\ContainerInterface; use Symfony\Component\DependencyInjection\ContainerInterface;
@ -863,7 +864,7 @@ class InstallHelper implements ContainerInjectionInterface {
protected function createFileEntity($path) { protected function createFileEntity($path) {
$filename = basename($path); $filename = basename($path);
try { try {
$uri = $this->fileSystem->copy($path, 'public://' . $filename, FileSystemInterface::EXISTS_REPLACE); $uri = $this->fileSystem->copy($path, 'public://' . $filename, FileExists::Replace);
} }
catch (FileException $e) { catch (FileException $e) {
$uri = FALSE; $uri = FALSE;

View File

@ -6,6 +6,7 @@ use Drupal\Component\FileSecurity\FileSecurity;
use Drupal\Component\FileSystem\FileSystem; use Drupal\Component\FileSystem\FileSystem;
use Drupal\Core\Database\Database; use Drupal\Core\Database\Database;
use Drupal\Core\File\Exception\FileException; use Drupal\Core\File\Exception\FileException;
use Drupal\Core\File\FileExists;
use Drupal\Core\File\FileSystemInterface; use Drupal\Core\File\FileSystemInterface;
/** /**
@ -143,9 +144,9 @@ class DirectoryTest extends FileTestBase {
* *
* If a file exists, ::getDestinationFilename($destination, $replace) will * If a file exists, ::getDestinationFilename($destination, $replace) will
* either return: * either return:
* - the existing filepath, if $replace is FileSystemInterface::EXISTS_REPLACE * - the existing filepath, if $replace is FileExists::Replace
* - a new filepath if FileSystemInterface::EXISTS_RENAME * - a new filepath if FileExists::Rename
* - an error (returning FALSE) if FileSystemInterface::EXISTS_ERROR. * - an error (returning FALSE) if FileExists::Error.
* If the file doesn't currently exist, then it will simply return the * If the file doesn't currently exist, then it will simply return the
* filepath. * filepath.
*/ */
@ -154,25 +155,25 @@ class DirectoryTest extends FileTestBase {
$destination = 'core/misc/xyz.txt'; $destination = 'core/misc/xyz.txt';
/** @var \Drupal\Core\File\FileSystemInterface $file_system */ /** @var \Drupal\Core\File\FileSystemInterface $file_system */
$file_system = \Drupal::service('file_system'); $file_system = \Drupal::service('file_system');
$path = $file_system->getDestinationFilename($destination, FileSystemInterface::EXISTS_REPLACE); $path = $file_system->getDestinationFilename($destination, FileExists::Replace);
$this->assertEquals($destination, $path, 'Non-existing filepath destination is correct with FileSystemInterface::EXISTS_REPLACE.'); $this->assertEquals($destination, $path, 'Non-existing filepath destination is correct with FileExists::Replace.');
$path = $file_system->getDestinationFilename($destination, FileSystemInterface::EXISTS_RENAME); $path = $file_system->getDestinationFilename($destination, FileExists::Rename);
$this->assertEquals($destination, $path, 'Non-existing filepath destination is correct with FileSystemInterface::EXISTS_RENAME.'); $this->assertEquals($destination, $path, 'Non-existing filepath destination is correct with FileExists::Rename.');
$path = $file_system->getDestinationFilename($destination, FileSystemInterface::EXISTS_ERROR); $path = $file_system->getDestinationFilename($destination, FileExists::Error);
$this->assertEquals($destination, $path, 'Non-existing filepath destination is correct with FileSystemInterface::EXISTS_ERROR.'); $this->assertEquals($destination, $path, 'Non-existing filepath destination is correct with FileExists::Error.');
$destination = 'core/misc/druplicon.png'; $destination = 'core/misc/druplicon.png';
$path = $file_system->getDestinationFilename($destination, FileSystemInterface::EXISTS_REPLACE); $path = $file_system->getDestinationFilename($destination, FileExists::Replace);
$this->assertEquals($destination, $path, 'Existing filepath destination remains the same with FileSystemInterface::EXISTS_REPLACE.'); $this->assertEquals($destination, $path, 'Existing filepath destination remains the same with FileExists::Replace.');
$path = $file_system->getDestinationFilename($destination, FileSystemInterface::EXISTS_RENAME); $path = $file_system->getDestinationFilename($destination, FileExists::Rename);
$this->assertNotEquals($destination, $path, 'A new filepath destination is created when filepath destination already exists with FileSystemInterface::EXISTS_RENAME.'); $this->assertNotEquals($destination, $path, 'A new filepath destination is created when filepath destination already exists with FileExists::Rename.');
$path = $file_system->getDestinationFilename($destination, FileSystemInterface::EXISTS_ERROR); $path = $file_system->getDestinationFilename($destination, FileExists::Error);
$this->assertFalse($path, 'An error is returned when filepath destination already exists with FileSystemInterface::EXISTS_ERROR.'); $this->assertFalse($path, 'An error is returned when filepath destination already exists with FileExists::Error.');
// Invalid UTF-8 causes an exception. // Invalid UTF-8 causes an exception.
$this->expectException(FileException::class); $this->expectException(FileException::class);
$this->expectExceptionMessage("Invalid filename 'a\xFFtest\x80€.txt'"); $this->expectExceptionMessage("Invalid filename 'a\xFFtest\x80€.txt'");
$file_system->getDestinationFilename("core/misc/a\xFFtest\x80€.txt", FileSystemInterface::EXISTS_REPLACE); $file_system->getDestinationFilename("core/misc/a\xFFtest\x80€.txt", FileExists::Replace);
} }
/** /**

View File

@ -4,8 +4,8 @@ namespace Drupal\KernelTests\Core\File;
use Drupal\Core\File\Exception\FileExistsException; use Drupal\Core\File\Exception\FileExistsException;
use Drupal\Core\File\Exception\FileNotExistsException; use Drupal\Core\File\Exception\FileNotExistsException;
use Drupal\Core\File\FileExists;
use Drupal\Core\File\FileSystem; use Drupal\Core\File\FileSystem;
use Drupal\Core\File\FileSystemInterface;
use Drupal\Core\Site\Settings; use Drupal\Core\Site\Settings;
/** /**
@ -24,7 +24,7 @@ class FileCopyTest extends FileTestBase {
// Copying to a new name. // Copying to a new name.
$desired_filepath = 'public://' . $this->randomMachineName(); $desired_filepath = 'public://' . $this->randomMachineName();
$new_filepath = \Drupal::service('file_system')->copy($uri, $desired_filepath, FileSystemInterface::EXISTS_ERROR); $new_filepath = \Drupal::service('file_system')->copy($uri, $desired_filepath, FileExists::Error);
$this->assertNotFalse($new_filepath, 'Copy was successful.'); $this->assertNotFalse($new_filepath, 'Copy was successful.');
$this->assertEquals($desired_filepath, $new_filepath, 'Returned expected filepath.'); $this->assertEquals($desired_filepath, $new_filepath, 'Returned expected filepath.');
$this->assertFileExists($uri); $this->assertFileExists($uri);
@ -34,7 +34,7 @@ class FileCopyTest extends FileTestBase {
// Copying with rename. // Copying with rename.
$desired_filepath = 'public://' . $this->randomMachineName(); $desired_filepath = 'public://' . $this->randomMachineName();
$this->assertNotFalse(file_put_contents($desired_filepath, ' '), 'Created a file so a rename will have to happen.'); $this->assertNotFalse(file_put_contents($desired_filepath, ' '), 'Created a file so a rename will have to happen.');
$newer_filepath = \Drupal::service('file_system')->copy($uri, $desired_filepath, FileSystemInterface::EXISTS_RENAME); $newer_filepath = \Drupal::service('file_system')->copy($uri, $desired_filepath, FileExists::Rename);
$this->assertNotFalse($newer_filepath, 'Copy was successful.'); $this->assertNotFalse($newer_filepath, 'Copy was successful.');
$this->assertNotEquals($desired_filepath, $newer_filepath, 'Returned expected filepath.'); $this->assertNotEquals($desired_filepath, $newer_filepath, 'Returned expected filepath.');
$this->assertFileExists($uri); $this->assertFileExists($uri);
@ -67,7 +67,7 @@ class FileCopyTest extends FileTestBase {
// Copy the file onto itself with renaming works. // Copy the file onto itself with renaming works.
/** @var \Drupal\Core\File\FileSystemInterface $file_system */ /** @var \Drupal\Core\File\FileSystemInterface $file_system */
$file_system = \Drupal::service('file_system'); $file_system = \Drupal::service('file_system');
$new_filepath = $file_system->copy($uri, $uri, FileSystemInterface::EXISTS_RENAME); $new_filepath = $file_system->copy($uri, $uri, FileExists::Rename);
$this->assertNotFalse($new_filepath, 'Copying onto itself with renaming works.'); $this->assertNotFalse($new_filepath, 'Copying onto itself with renaming works.');
$this->assertNotEquals($uri, $new_filepath, 'Copied file has a new name.'); $this->assertNotEquals($uri, $new_filepath, 'Copied file has a new name.');
$this->assertFileExists($uri); $this->assertFileExists($uri);
@ -76,17 +76,17 @@ class FileCopyTest extends FileTestBase {
// Copy the file onto itself without renaming fails. // Copy the file onto itself without renaming fails.
$this->expectException(FileExistsException::class); $this->expectException(FileExistsException::class);
$new_filepath = $file_system->copy($uri, $uri, FileSystemInterface::EXISTS_ERROR); $new_filepath = $file_system->copy($uri, $uri, FileExists::Error);
$this->assertFalse($new_filepath, 'Copying onto itself without renaming fails.'); $this->assertFalse($new_filepath, 'Copying onto itself without renaming fails.');
$this->assertFileExists($uri); $this->assertFileExists($uri);
// Copy the file into same directory without renaming fails. // Copy the file into same directory without renaming fails.
$new_filepath = $file_system->copy($uri, $file_system->dirname($uri), FileSystemInterface::EXISTS_ERROR); $new_filepath = $file_system->copy($uri, $file_system->dirname($uri), FileExists::Error);
$this->assertFalse($new_filepath, 'Copying onto itself fails.'); $this->assertFalse($new_filepath, 'Copying onto itself fails.');
$this->assertFileExists($uri); $this->assertFileExists($uri);
// Copy the file into same directory with renaming works. // Copy the file into same directory with renaming works.
$new_filepath = $file_system->copy($uri, $file_system->dirname($uri), FileSystemInterface::EXISTS_RENAME); $new_filepath = $file_system->copy($uri, $file_system->dirname($uri), FileExists::Rename);
$this->assertNotFalse($new_filepath, 'Copying into same directory works.'); $this->assertNotFalse($new_filepath, 'Copying into same directory works.');
$this->assertNotEquals($uri, $new_filepath, 'Copied file has a new name.'); $this->assertNotEquals($uri, $new_filepath, 'Copied file has a new name.');
$this->assertFileExists($uri); $this->assertFileExists($uri);

View File

@ -4,9 +4,9 @@ namespace Drupal\KernelTests\Core\File;
use Drupal\Core\File\Exception\FileException; use Drupal\Core\File\Exception\FileException;
use Drupal\Core\File\Exception\FileNotExistsException; use Drupal\Core\File\Exception\FileNotExistsException;
use Drupal\Core\File\FileSystemInterface; use Drupal\Core\File\FileExists;
use Drupal\Core\Site\Settings;
use Drupal\Core\File\FileSystem; use Drupal\Core\File\FileSystem;
use Drupal\Core\Site\Settings;
/** /**
* Tests the unmanaged file move function. * Tests the unmanaged file move function.
@ -26,7 +26,7 @@ class FileMoveTest extends FileTestBase {
$desired_filepath = 'public://' . $this->randomMachineName(); $desired_filepath = 'public://' . $this->randomMachineName();
/** @var \Drupal\Core\File\FileSystemInterface $file_system */ /** @var \Drupal\Core\File\FileSystemInterface $file_system */
$file_system = \Drupal::service('file_system'); $file_system = \Drupal::service('file_system');
$new_filepath = $file_system->move($uri, $desired_filepath, FileSystemInterface::EXISTS_ERROR); $new_filepath = $file_system->move($uri, $desired_filepath, FileExists::Error);
$this->assertNotFalse($new_filepath, 'Move was successful.'); $this->assertNotFalse($new_filepath, 'Move was successful.');
$this->assertEquals($desired_filepath, $new_filepath, 'Returned expected filepath.'); $this->assertEquals($desired_filepath, $new_filepath, 'Returned expected filepath.');
$this->assertFileExists($new_filepath); $this->assertFileExists($new_filepath);
@ -37,7 +37,7 @@ class FileMoveTest extends FileTestBase {
$desired_filepath = 'public://' . $this->randomMachineName(); $desired_filepath = 'public://' . $this->randomMachineName();
$this->assertFileExists($new_filepath); $this->assertFileExists($new_filepath);
$this->assertNotFalse(file_put_contents($desired_filepath, ' '), 'Created a file so a rename will have to happen.'); $this->assertNotFalse(file_put_contents($desired_filepath, ' '), 'Created a file so a rename will have to happen.');
$newer_filepath = $file_system->move($new_filepath, $desired_filepath, FileSystemInterface::EXISTS_RENAME); $newer_filepath = $file_system->move($new_filepath, $desired_filepath, FileExists::Rename);
$this->assertNotFalse($newer_filepath, 'Move was successful.'); $this->assertNotFalse($newer_filepath, 'Move was successful.');
$this->assertNotEquals($desired_filepath, $newer_filepath, 'Returned expected filepath.'); $this->assertNotEquals($desired_filepath, $newer_filepath, 'Returned expected filepath.');
$this->assertFileExists($newer_filepath); $this->assertFileExists($newer_filepath);
@ -68,12 +68,12 @@ class FileMoveTest extends FileTestBase {
/** @var \Drupal\Core\File\FileSystemInterface $file_system */ /** @var \Drupal\Core\File\FileSystemInterface $file_system */
$file_system = \Drupal::service('file_system'); $file_system = \Drupal::service('file_system');
$this->expectException(FileException::class); $this->expectException(FileException::class);
$new_filepath = $file_system->move($uri, $uri, FileSystemInterface::EXISTS_REPLACE); $new_filepath = $file_system->move($uri, $uri, FileExists::Replace);
$this->assertFalse($new_filepath, 'Moving onto itself without renaming fails.'); $this->assertFalse($new_filepath, 'Moving onto itself without renaming fails.');
$this->assertFileExists($uri); $this->assertFileExists($uri);
// Move the file onto itself with renaming will result in a new filename. // Move the file onto itself with renaming will result in a new filename.
$new_filepath = $file_system->move($uri, $uri, FileSystemInterface::EXISTS_RENAME); $new_filepath = $file_system->move($uri, $uri, FileExists::Rename);
$this->assertNotFalse($new_filepath, 'Moving onto itself with renaming works.'); $this->assertNotFalse($new_filepath, 'Moving onto itself with renaming works.');
$this->assertFileDoesNotExist($uri); $this->assertFileDoesNotExist($uri);
$this->assertFileExists($new_filepath); $this->assertFileExists($new_filepath);

View File

@ -2,7 +2,7 @@
namespace Drupal\KernelTests\Core\File; namespace Drupal\KernelTests\Core\File;
use Drupal\Core\File\FileSystemInterface; use Drupal\Core\File\FileExists;
/** /**
* Tests the file_unmanaged_save_data() function. * Tests the file_unmanaged_save_data() function.
@ -23,7 +23,7 @@ class FileSaveDataTest extends FileTestBase {
$file_system = \Drupal::service('file_system'); $file_system = \Drupal::service('file_system');
// Provide a filename. // Provide a filename.
$filepath = $file_system->saveData($contents, 'public://asdf.txt', FileSystemInterface::EXISTS_REPLACE); $filepath = $file_system->saveData($contents, 'public://asdf.txt', FileExists::Replace);
$this->assertNotFalse($filepath, 'Unnamed file saved correctly.'); $this->assertNotFalse($filepath, 'Unnamed file saved correctly.');
$this->assertEquals('asdf.txt', \Drupal::service('file_system')->basename($filepath), 'File was named correctly.'); $this->assertEquals('asdf.txt', \Drupal::service('file_system')->basename($filepath), 'File was named correctly.');
$this->assertEquals($contents, file_get_contents($filepath), 'Contents of the file are correct.'); $this->assertEquals($contents, file_get_contents($filepath), 'Contents of the file are correct.');

View File

@ -6,7 +6,7 @@ use Drupal\Core\File\Exception\DirectoryNotReadyException;
use Drupal\Core\File\Exception\FileException; use Drupal\Core\File\Exception\FileException;
use Drupal\Core\File\Exception\FileExistsException; use Drupal\Core\File\Exception\FileExistsException;
use Drupal\Core\File\Exception\FileNotExistsException; use Drupal\Core\File\Exception\FileNotExistsException;
use Drupal\Core\File\FileSystemInterface; use Drupal\Core\File\FileExists;
use Drupal\KernelTests\KernelTestBase; use Drupal\KernelTests\KernelTestBase;
/** /**
@ -67,7 +67,7 @@ class FileSystemTest extends KernelTestBase {
$this->expectExceptionMessage("File 'public://test.txt' could not be copied because a file by that name already exists in the destination directory ('')"); $this->expectExceptionMessage("File 'public://test.txt' could not be copied because a file by that name already exists in the destination directory ('')");
$uri = 'public://test.txt'; $uri = 'public://test.txt';
touch($uri); touch($uri);
$this->fileSystem->copy($uri, $uri, FileSystemInterface::EXISTS_ERROR); $this->fileSystem->copy($uri, $uri, FileExists::Error);
} }
/** /**
@ -78,7 +78,7 @@ class FileSystemTest extends KernelTestBase {
$this->expectExceptionMessage("'public://test.txt' could not be copied because it would overwrite itself"); $this->expectExceptionMessage("'public://test.txt' could not be copied because it would overwrite itself");
$uri = 'public://test.txt'; $uri = 'public://test.txt';
touch($uri); touch($uri);
$this->fileSystem->copy($uri, $uri, FileSystemInterface::EXISTS_REPLACE); $this->fileSystem->copy($uri, $uri, FileExists::Replace);
} }
/** /**

View File

@ -0,0 +1,98 @@
<?php
declare(strict_types=1);
namespace Drupal\KernelTests\Core\File;
use Drupal\Core\File\FileSystemInterface;
/**
* Tests the legacy file system functions.
*
* @group file
* @group legacy
* @coversDefaultClass \Drupal\Core\File\FileSystem
*/
class LegacyFileSystemTest extends FileTestBase {
/**
* The file system under test.
*/
protected FileSystemInterface $fileSystem;
/**
* {@inheritdoc}
*/
protected function setUp(): void {
parent::setUp();
$this->fileSystem = $this->container->get('file_system');
}
/**
* @covers ::copy
*/
public function testCopyWithDeprecatedFileExists(): void {
$uri = 'public://test.txt';
touch($uri);
$this->expectDeprecation('Passing the $fileExists argument as an integer to Drupal\Core\File\FileSystem::copy() is deprecated in drupal:10.3.0 and is removed from drupal:12.0.0. Use \Drupal\Core\File\FileExists enum instead. See https://www.drupal.org/node/3426517');
$newUri = $this->fileSystem->copy($uri, $uri, FileSystemInterface::EXISTS_RENAME);
$this->assertFileExists($newUri);
}
/**
* @covers ::move
*/
public function testMoveWithDeprecatedFileExists(): void {
$uri = 'public://test.txt';
touch($uri);
$this->expectDeprecation('Passing the $fileExists argument as an integer to Drupal\Core\File\FileSystem::move() is deprecated in drupal:10.3.0 and is removed from drupal:12.0.0. Use \Drupal\Core\File\FileExists enum instead. See https://www.drupal.org/node/3426517');
$newUri = $this->fileSystem->move($uri, $uri, FileSystemInterface::EXISTS_RENAME);
$this->assertFileExists($newUri);
}
/**
* @covers ::saveData
*/
public function testSaveDataWithDeprecatedFileExists(): void {
$data = $this->randomMachineName(8);
$uri = 'public://test.txt';
touch($uri);
$this->expectDeprecation('Passing the $fileExists argument as an integer to Drupal\Core\File\FileSystem::saveData() is deprecated in drupal:10.3.0 and is removed from drupal:12.0.0. Use \Drupal\Core\File\FileExists enum instead. See https://www.drupal.org/node/3426517');
$newUri = $this->fileSystem->saveData($data, $uri, FileSystemInterface::EXISTS_RENAME);
$this->assertFileExists($newUri);
}
/**
* @covers ::getDestinationFilename
*/
public function testGetDestinationFilenameWithDeprecatedFileExists(): void {
$uri = 'public://test.txt';
touch($uri);
$newUri = $this->fileSystem->getDestinationFilename($uri, FileSystemInterface::EXISTS_RENAME);
$this->assertStringStartsWith('public://test_', $newUri);
$this->assertNotEquals($newUri, $uri);
}
/**
* @covers ::copy
*/
public function testCopyWithOutOfBoundsIntPositive(): void {
$uri = 'public://test.txt';
$destination = 'public://test2.txt';
touch($uri);
$this->expectDeprecation('Passing the $fileExists argument as an integer to Drupal\Core\File\FileSystem::copy() is deprecated in drupal:10.3.0 and is removed from drupal:12.0.0. Use \Drupal\Core\File\FileExists enum instead. See https://www.drupal.org/node/3426517');
$this->fileSystem->copy($uri, $destination, \PHP_INT_MAX);
}
/**
* @covers ::copy
*/
public function testCopyWithOutOfBoundsIntNegative(): void {
$uri = 'public://test.txt';
$destination = 'public://test2.txt';
touch($uri);
$this->expectDeprecation('Passing the $fileExists argument as an integer to Drupal\Core\File\FileSystem::copy() is deprecated in drupal:10.3.0 and is removed from drupal:12.0.0. Use \Drupal\Core\File\FileExists enum instead. See https://www.drupal.org/node/3426517');
$this->fileSystem->copy($uri, $destination, \PHP_INT_MIN);
}
}