1717use Drupal \Core \Render \RenderContext ;
1818use Drupal \Core \Render \RendererInterface ;
1919use Drupal \Core \Session \AccountProxyInterface ;
20+ use Drupal \Core \StringTranslation \ByteSizeMarkup ;
2021use Drupal \Core \StringTranslation \StringTranslationTrait ;
2122use Drupal \Core \Utility \Token ;
2223use Drupal \file \FileInterface ;
24+ use Drupal \file \Validation \FileValidatorInterface ;
2325use Drupal \graphql \GraphQL \Response \FileUploadResponse ;
2426use Symfony \Component \EventDispatcher \EventDispatcherInterface ;
2527use Symfony \Component \HttpFoundation \File \UploadedFile ;
@@ -37,7 +39,7 @@ class FileUpload {
3739 /**
3840 * The file storage where we will create new file entities from.
3941 *
40- * @var \Drupal\file\FileStorageInterface
42+ * @var \Drupal\Core\Entity\EntityStorageInterface
4143 */
4244 protected $ fileStorage ;
4345
@@ -111,6 +113,13 @@ class FileUpload {
111113 */
112114 protected $ imageFactory ;
113115
116+ /**
117+ * The file validator service.
118+ *
119+ * @var \Drupal\file\Validation\FileValidatorInterface
120+ */
121+ protected FileValidatorInterface $ fileValidator ;
122+
114123 /**
115124 * Constructor.
116125 */
@@ -126,10 +135,9 @@ public function __construct(
126135 RendererInterface $ renderer ,
127136 EventDispatcherInterface $ eventDispatcher ,
128137 ImageFactory $ image_factory ,
138+ FileValidatorInterface $ file_validator ,
129139 ) {
130- /** @var \Drupal\file\FileStorageInterface $file_storage */
131- $ file_storage = $ entityTypeManager ->getStorage ('file ' );
132- $ this ->fileStorage = $ file_storage ;
140+ $ this ->fileStorage = $ entityTypeManager ->getStorage ('file ' );
133141 $ this ->currentUser = $ currentUser ;
134142 $ this ->mimeTypeGuesser = $ mimeTypeGuesser ;
135143 $ this ->fileSystem = $ fileSystem ;
@@ -140,6 +148,7 @@ public function __construct(
140148 $ this ->renderer = $ renderer ;
141149 $ this ->eventDispatcher = $ eventDispatcher ;
142150 $ this ->imageFactory = $ image_factory ;
151+ $ this ->fileValidator = $ file_validator ;
143152 }
144153
145154 /**
@@ -193,10 +202,7 @@ public function saveFileUpload(UploadedFile $uploaded_file, array $settings): Fi
193202 switch ($ uploaded_file ->getError ()) {
194203 case UPLOAD_ERR_INI_SIZE :
195204 case UPLOAD_ERR_FORM_SIZE :
196- // @todo Drupal 10.1 compatibility, needs to be converted to
197- // ByteSizeMarkup later.
198- // @phpstan-ignore-next-line
199- $ maxUploadSize = format_size ($ this ->getMaxUploadSize ($ settings ));
205+ $ maxUploadSize = ByteSizeMarkup::create ($ this ->getMaxUploadSize ($ settings ));
200206 $ response ->addViolation ($ this ->t ('The file @file could not be saved because it exceeds @maxsize, the maximum allowed size for uploads. ' , [
201207 '@file ' => $ uploaded_file ->getClientOriginalName (),
202208 '@maxsize ' => $ maxUploadSize ,
@@ -248,8 +254,8 @@ public function saveFileUpload(UploadedFile $uploaded_file, array $settings): Fi
248254
249255 $ temp_file_path = $ uploaded_file ->getRealPath ();
250256
251- // Drupal 10.2 compatibility: use the deprecated constant for now.
252- // @phpstan-ignore-next-line
257+ // Drupal 10.3 compatibility: use the deprecated constant for now.
258+ // @phpstan-ignore-next-line as it is deprecated in D12.
253259 $ file_uri = $ this ->fileSystem ->getDestinationFilename ($ file_uri , FileSystemInterface::EXISTS_RENAME );
254260
255261 // Lock based on the prepared file URI.
@@ -262,7 +268,7 @@ public function saveFileUpload(UploadedFile $uploaded_file, array $settings): Fi
262268
263269 try {
264270 // Begin building file entity.
265- /** @var \Drupal\file\FileInterface $file */
271+ /** @var \Drupal\Core\Entity\EntityInterface $file */
266272 $ file = $ this ->fileStorage ->create ([]);
267273 $ file ->setOwnerId ($ this ->currentUser ->id ());
268274 $ file ->setFilename ($ prepared_filename );
@@ -272,29 +278,31 @@ public function saveFileUpload(UploadedFile $uploaded_file, array $settings): Fi
272278 // before it is saved.
273279 $ file ->setSize (@filesize ($ temp_file_path ));
274280
275- // Validate against file_validate() first with the temporary path.
276- // @todo Drupal 10.1 compatibility, needs to be converted to file validate
277- // service later.
278- // @phpstan-ignore-next-line
279- $ errors = file_validate ($ file , $ validators );
280- $ maxResolution = $ settings ['max_resolution ' ] ?? 0 ;
281- $ minResolution = $ settings ['min_resolution ' ] ?? 0 ;
282- if (!empty ($ maxResolution ) || !empty ($ minResolution )) {
283- $ errors += $ this ->validateFileImageResolution ($ file , $ maxResolution , $ minResolution );
284- }
285-
281+ // Validate against fileValidator first with the temporary path.
282+ /** @var \Symfony\Component\Validator\ConstraintViolationListInterface $errors */
283+ $ errors = $ this ->fileValidator ->validate ($ file , $ validators );
286284 if (!empty ($ errors )) {
287285 $ response ->addViolations ($ errors );
288286 return $ response ;
289287 }
288+ // Validate Image resolution.
289+ $ maxResolution = $ settings ['max_resolution ' ] ?? 0 ;
290+ $ minResolution = $ settings ['min_resolution ' ] ?? 0 ;
291+ if (!empty ($ maxResolution ) || !empty ($ minResolution )) {
292+ $ image_resolution_errors = $ this ->validateFileImageResolution ($ file , $ maxResolution , $ minResolution );
293+ if (!empty ($ image_resolution_errors )) {
294+ $ response ->addViolations ($ image_resolution_errors );
295+ return $ response ;
296+ }
297+ }
290298
291299 $ file ->setFileUri ($ file_uri );
292300 // Move the file to the correct location after validation. Use
293301 // FileSystemInterface::EXISTS_ERROR as the file location has already been
294302 // determined above in FileSystem::getDestinationFilename().
295303 try {
296- // Drupal 10.2 compatibility: use the deprecated constant for now.
297- // @phpstan-ignore-next-line
304+ // Drupal 10.3 compatibility: use the deprecated constant for now.
305+ // @phpstan-ignore-next-line as it is deprecated in D12.
298306 $ this ->fileSystem ->move ($ temp_file_path , $ file_uri , FileSystemInterface::EXISTS_ERROR );
299307 }
300308 catch (FileException $ e ) {
@@ -487,12 +495,12 @@ protected function validateFileImageResolution(FileInterface $file, $maximum_dim
487495 protected function prepareFilename (string $ filename , array &$ validators ): string {
488496 // Don't rename if 'allow_insecure_uploads' evaluates to TRUE.
489497 if (!$ this ->systemFileConfig ->get ('allow_insecure_uploads ' )) {
490- if (!empty ($ validators ['file_validate_extensions ' ][0 ])) {
491- // If there is a file_validate_extensions validator and a list of
492- // valid extensions, munge the filename to protect against possible
493- // malicious extension hiding within an unknown file type. For example,
494- // "filename.html.foo".
495- $ event = new FileUploadSanitizeNameEvent ($ filename , $ validators ['file_validate_extensions ' ][0 ]);
498+ if (!empty ($ validators ['FileExtension ' ][' extensions ' ])) {
499+ // If there is a fileValidator service to validate FileExtension and
500+ // a list of valid extensions, munge the filename to protect against
501+ // possible malicious extension hiding within an unknown file type.
502+ // For example, "filename.html.foo".
503+ $ event = new FileUploadSanitizeNameEvent ($ filename , $ validators ['FileExtension ' ][' extensions ' ]);
496504 $ this ->eventDispatcher ->dispatch ($ event );
497505 $ filename = $ event ->getFilename ();
498506 }
@@ -502,33 +510,31 @@ protected function prepareFilename(string $filename, array &$validators): string
502510 // and filename._php.txt, respectively).
503511 if (preg_match (FileSystemInterface::INSECURE_EXTENSION_REGEX , $ filename )) {
504512 // If the file will be rejected anyway due to a disallowed extension, it
505- // should not be renamed; rather, we'll let file_validate_extensions()
506- // reject it below.
513+ // should not be renamed; rather, we'll let fileValidator service
514+ // to validate FileExtension reject it below.
515+
507516 $ passes_validation = FALSE ;
508- if (!empty ($ validators ['file_validate_extensions ' ][0 ])) {
509- /** @var \Drupal\file\FileInterface $file */
517+ if (!empty ($ validators ['FileExtension ' ][' extensions ' ])) {
518+ /** @var \Drupal\Core\Entity\EntityInterface $file */
510519 $ file = $ this ->fileStorage ->create ([]);
511520 $ file ->setFilename ($ filename );
512- // @todo Drupal 10.1 compatibility, needs to be converted to file
513- // validator service later.
514- // @phpstan-ignore-next-line
515- $ passes_validation = empty (file_validate_extensions ($ file , $ validators ['file_validate_extensions ' ][0 ]));
521+ $ passes_validation = empty ($ this ->fileValidator ->validate ($ file , $ validators ['FileExtension ' ]['extensions ' ]));
516522 }
517- if (empty ($ validators ['file_validate_extensions ' ][0 ]) || $ passes_validation ) {
523+ if (empty ($ validators ['FileExtension ' ][' extensions ' ]) || $ passes_validation ) {
518524 if ((substr ($ filename , -4 ) != '.txt ' )) {
519525 // The destination filename will also later be used to create the
520526 // URI.
521527 $ filename .= '.txt ' ;
522528 }
523529
524- $ event = new FileUploadSanitizeNameEvent ($ filename , $ validators ['file_validate_extensions ' ][0 ] ?? '' );
530+ $ event = new FileUploadSanitizeNameEvent ($ filename , $ validators ['FileExtension ' ][' extensions ' ] ?? '' );
525531 $ this ->eventDispatcher ->dispatch ($ event );
526532 $ filename = $ event ->getFilename ();
527533
528534 // The .txt extension may not be in the allowed list of extensions. We
529535 // have to add it here or else the file upload will fail.
530- if (!empty ($ validators ['file_validate_extensions ' ][0 ])) {
531- $ validators ['file_validate_extensions ' ][0 ] .= ' txt ' ;
536+ if (!empty ($ validators ['FileExtension ' ][' extensions ' ])) {
537+ $ validators ['FileExtension ' ][' extensions ' ] .= ' txt ' ;
532538 }
533539 }
534540 }
@@ -579,7 +585,7 @@ protected function getUploadLocation(array $settings): string {
579585 protected function getUploadValidators (array $ settings ): array {
580586 $ validators = [
581587 // Add in our check of the file name length.
582- 'file_validate_name_length ' => [],
588+ 'FileNameLength ' => [],
583589 ];
584590
585591 // Cap the upload size according to the PHP limit.
@@ -589,11 +595,11 @@ protected function getUploadValidators(array $settings): array {
589595 }
590596
591597 // There is always a file size limit due to the PHP server limit.
592- $ validators ['file_validate_size ' ] = [$ max_filesize ];
598+ $ validators ['FileSizeLimit ' ] = [' fileLimit ' => $ max_filesize ];
593599
594600 // Add the extension check if necessary.
595601 if (!empty ($ settings ['file_extensions ' ])) {
596- $ validators ['file_validate_extensions ' ] = [$ settings ['file_extensions ' ]];
602+ $ validators ['FileExtension ' ] = [' extensions ' => $ settings ['file_extensions ' ]];
597603 }
598604
599605 return $ validators ;
0 commit comments