jsonapi.services.yml | 2 +- src/Controller/FileUpload.php | 4 +-- src/ForwardCompatibility/FileFieldUploader.php | 36 +++++++++++++++++--------- 3 files changed, 27 insertions(+), 15 deletions(-) diff --git a/jsonapi.services.yml b/jsonapi.services.yml index 6a59e8a..effdaac 100644 --- a/jsonapi.services.yml +++ b/jsonapi.services.yml @@ -226,4 +226,4 @@ services: jsonapi.file.uploader.field: class: Drupal\jsonapi\ForwardCompatibility\FileFieldUploader public: false - arguments: ['@logger.channel.file', '@file_system', '@file.mime_type.guesser', '@token', '@lock', '@config.factory'] + arguments: ['@entity_type.manager', '@logger.channel.file', '@file_system', '@file.mime_type.guesser', '@token', '@lock', '@config.factory'] diff --git a/src/Controller/FileUpload.php b/src/Controller/FileUpload.php index 813fcbf..7e0480a 100644 --- a/src/Controller/FileUpload.php +++ b/src/Controller/FileUpload.php @@ -112,7 +112,7 @@ class FileUpload { static::ensureFileUploadAccess($this->currentUser, $field_definition, $entity); - $filename = FileFieldUploader::validateAndParseContentDispositionHeader($request); + $filename = $this->fileUploader->validateAndParseContentDispositionHeader($request); $stream = FileFieldUploader::getUploadStream(); $file = $this->fileUploader->handleFileUploadForField($field_definition, $filename, $stream, $this->currentUser); fclose($stream); @@ -163,7 +163,7 @@ class FileUpload { static::ensureFileUploadAccess($this->currentUser, $field_definition); - $filename = FileFieldUploader::validateAndParseContentDispositionHeader($request); + $filename = $this->fileUploader->validateAndParseContentDispositionHeader($request); $stream = FileFieldUploader::getUploadStream(); $file = $this->fileUploader->handleFileUploadForField($field_definition, $filename, $stream, $this->currentUser); fclose($stream); diff --git a/src/ForwardCompatibility/FileFieldUploader.php b/src/ForwardCompatibility/FileFieldUploader.php index 970bdcf..f560ce6 100644 --- a/src/ForwardCompatibility/FileFieldUploader.php +++ b/src/ForwardCompatibility/FileFieldUploader.php @@ -4,9 +4,10 @@ namespace Drupal\jsonapi\ForwardCompatibility; use Drupal\Component\Utility\Bytes; use Drupal\Component\Utility\Crypt; -use Drupal\Core\Entity\EntityInterface; +use Drupal\Core\Entity\EntityTypeManagerInterface; use Drupal\Core\Entity\Plugin\DataType\EntityAdapter; use Drupal\Core\Field\FieldDefinitionInterface; +use Drupal\Core\File\Exception\FileException; use Drupal\Core\Validation\DrupalTranslator; use Drupal\file\FileInterface; use Drupal\Core\File\FileSystemInterface; @@ -16,7 +17,6 @@ use Drupal\Core\Render\BubbleableMetadata; use Drupal\Core\Session\AccountInterface; use Drupal\Core\Utility\Token; use Drupal\Component\Render\PlainTextOutput; -use Drupal\file\Entity\File; use Drupal\file\Plugin\Field\FieldType\FileFieldItemList; use Psr\Log\LoggerInterface; use Symfony\Component\HttpFoundation\File\MimeType\MimeTypeGuesserInterface; @@ -54,6 +54,13 @@ class FileFieldUploader { */ const BYTES_TO_READ = 8192; + /** + * The entity type manager. + * + * @var \Drupal\Core\Entity\EntityTypeManagerInterface + */ + protected $entityTypeManager; + /** * A logger instance. * @@ -97,8 +104,10 @@ class FileFieldUploader { protected $systemFileConfig; /** - * Constructs a FileUploadResource instance. + * Constructs a FileFieldUploader instance. * + * @param \Drupal\Core\Entity\EntityTypeManagerInterface $entity_type_manager + * The entity type manager. * @param \Psr\Log\LoggerInterface $logger * A logger instance. * @param \Drupal\Core\File\FileSystemInterface $file_system @@ -112,7 +121,8 @@ class FileFieldUploader { * @param \Drupal\Core\Config\ConfigFactoryInterface $config_factory * The config factory. */ - public function __construct(LoggerInterface $logger, FileSystemInterface $file_system, MimeTypeGuesserInterface $mime_type_guesser, Token $token, LockBackendInterface $lock, ConfigFactoryInterface $config_factory) { + public function __construct(EntityTypeManagerInterface $entity_type_manager, LoggerInterface $logger, FileSystemInterface $file_system, MimeTypeGuesserInterface $mime_type_guesser, Token $token, LockBackendInterface $lock, ConfigFactoryInterface $config_factory) { + $this->entityTypeManager = $entity_type_manager; $this->logger = $logger; $this->fileSystem = $file_system; $this->mimeTypeGuesser = $mime_type_guesser; @@ -147,7 +157,7 @@ class FileFieldUploader { $destination = $this->getUploadLocation($field_definition->getSettings()); // Check the destination file path is writable. - if (!file_prepare_directory($destination, FILE_CREATE_DIRECTORY)) { + if (!$this->fileSystem->prepareDirectory($destination, FileSystemInterface::CREATE_DIRECTORY)) { throw new HttpException(500, 'Destination file path is not writable'); } @@ -160,8 +170,7 @@ class FileFieldUploader { $temp_file_path = $this->readStreamDataToFile($stream); - // This will take care of altering $file_uri if a file already exists. - file_unmanaged_prepare($temp_file_path, $file_uri); + $file_uri = $this->fileSystem->getDestinationFilename($file_uri, FileSystemInterface::EXISTS_RENAME); // Lock based on the prepared file URI. $lock_id = $this->generateLockIdFromFileUri($file_uri); @@ -171,7 +180,7 @@ class FileFieldUploader { } // Begin building file entity. - $file = File::create([]); + $file = $this->entityTypeManager->getStorage('file')->create([]); $file->setOwnerId($owner->id()); $file->setFilename($prepared_filename); $file->setMimeType($this->mimeTypeGuesser->guess($prepared_filename)); @@ -189,9 +198,12 @@ class FileFieldUploader { // Move the file to the correct location after validation. Use // FILE_EXISTS_ERROR as the file location has already been determined above - // in file_unmanaged_prepare(). - if (!file_unmanaged_move($temp_file_path, $file_uri, FILE_EXISTS_ERROR)) { - throw new HttpException(500, 'Temporary file could not be moved to file location.'); + // in FileSystem::getDestinationFilename(). + try { + $this->fileSystem->move($temp_file_path, $file_uri, FileSystemInterface::EXISTS_ERROR); + } + catch (FileException $e) { + throw new HttpException(500, 'Temporary file could not be moved to file location'); } $file->save(); @@ -213,7 +225,7 @@ class FileFieldUploader { * @throws \Symfony\Component\HttpKernel\Exception\BadRequestHttpException * Thrown when the 'Content-Disposition' request header is invalid. */ - public static function validateAndParseContentDispositionHeader(Request $request) { + public function validateAndParseContentDispositionHeader(Request $request) { // First, check the header exists. if (!$request->headers->has('content-disposition')) { throw new BadRequestHttpException('"Content-Disposition" header is required. A file name in the format "filename=FILENAME" must be provided.');