17
17
use Drupal \Core \Render \RenderContext ;
18
18
use Drupal \Core \Render \RendererInterface ;
19
19
use Drupal \Core \Session \AccountProxyInterface ;
20
+ use Drupal \Core \StringTranslation \ByteSizeMarkup ;
20
21
use Drupal \Core \StringTranslation \StringTranslationTrait ;
21
22
use Drupal \Core \Utility \Token ;
22
23
use Drupal \file \FileInterface ;
24
+ use Drupal \file \Validation \FileValidatorInterface ;
23
25
use Drupal \graphql \GraphQL \Response \FileUploadResponse ;
24
26
use Symfony \Component \EventDispatcher \EventDispatcherInterface ;
25
27
use Symfony \Component \HttpFoundation \File \UploadedFile ;
@@ -111,6 +113,13 @@ class FileUpload {
111
113
*/
112
114
protected $ imageFactory ;
113
115
116
+ /**
117
+ * The file validator service.
118
+ *
119
+ * @var \Drupal\file\Validation\FileValidatorInterface
120
+ */
121
+ protected FileValidatorInterface $ fileValidator ;
122
+
114
123
/**
115
124
* Constructor.
116
125
*/
@@ -126,6 +135,7 @@ public function __construct(
126
135
RendererInterface $ renderer ,
127
136
EventDispatcherInterface $ eventDispatcher ,
128
137
ImageFactory $ image_factory ,
138
+ FileValidatorInterface $ file_validator ,
129
139
) {
130
140
/** @var \Drupal\file\FileStorageInterface $file_storage */
131
141
$ file_storage = $ entityTypeManager ->getStorage ('file ' );
@@ -140,6 +150,7 @@ public function __construct(
140
150
$ this ->renderer = $ renderer ;
141
151
$ this ->eventDispatcher = $ eventDispatcher ;
142
152
$ this ->imageFactory = $ image_factory ;
153
+ $ this ->fileValidator = $ file_validator ;
143
154
}
144
155
145
156
/**
@@ -193,10 +204,7 @@ public function saveFileUpload(UploadedFile $uploaded_file, array $settings): Fi
193
204
switch ($ uploaded_file ->getError ()) {
194
205
case UPLOAD_ERR_INI_SIZE :
195
206
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 ));
207
+ $ maxUploadSize = ByteSizeMarkup::create ($ this ->getMaxUploadSize ($ settings ));
200
208
$ response ->addViolation ($ this ->t ('The file @file could not be saved because it exceeds @maxsize, the maximum allowed size for uploads. ' , [
201
209
'@file ' => $ uploaded_file ->getClientOriginalName (),
202
210
'@maxsize ' => $ maxUploadSize ,
@@ -248,8 +256,8 @@ public function saveFileUpload(UploadedFile $uploaded_file, array $settings): Fi
248
256
249
257
$ temp_file_path = $ uploaded_file ->getRealPath ();
250
258
251
- // Drupal 10.2 compatibility: use the deprecated constant for now.
252
- // @phpstan-ignore-next-line
259
+ // Drupal 10.3 compatibility: use the deprecated constant for now.
260
+ // @phpstan-ignore-next-line as it is deprecated in D12.
253
261
$ file_uri = $ this ->fileSystem ->getDestinationFilename ($ file_uri , FileSystemInterface::EXISTS_RENAME );
254
262
255
263
// Lock based on the prepared file URI.
@@ -272,29 +280,31 @@ public function saveFileUpload(UploadedFile $uploaded_file, array $settings): Fi
272
280
// before it is saved.
273
281
$ file ->setSize (@filesize ($ temp_file_path ));
274
282
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
-
283
+ // Validate against fileValidator first with the temporary path.
284
+ /** @var \Symfony\Component\Validator\ConstraintViolationListInterface $errors */
285
+ $ errors = $ this ->fileValidator ->validate ($ file , $ validators );
286
286
if (!empty ($ errors )) {
287
287
$ response ->addViolations ($ errors );
288
288
return $ response ;
289
289
}
290
+ // Validate Image resolution.
291
+ $ maxResolution = $ settings ['max_resolution ' ] ?? 0 ;
292
+ $ minResolution = $ settings ['min_resolution ' ] ?? 0 ;
293
+ if (!empty ($ maxResolution ) || !empty ($ minResolution )) {
294
+ $ image_resolution_errors = $ this ->validateFileImageResolution ($ file , $ maxResolution , $ minResolution );
295
+ if (!empty ($ image_resolution_errors )) {
296
+ $ response ->addViolations ($ image_resolution_errors );
297
+ return $ response ;
298
+ }
299
+ }
290
300
291
301
$ file ->setFileUri ($ file_uri );
292
302
// Move the file to the correct location after validation. Use
293
303
// FileSystemInterface::EXISTS_ERROR as the file location has already been
294
304
// determined above in FileSystem::getDestinationFilename().
295
305
try {
296
- // Drupal 10.2 compatibility: use the deprecated constant for now.
297
- // @phpstan-ignore-next-line
306
+ // Drupal 10.3 compatibility: use the deprecated constant for now.
307
+ // @phpstan-ignore-next-line as it is deprecated in D12.
298
308
$ this ->fileSystem ->move ($ temp_file_path , $ file_uri , FileSystemInterface::EXISTS_ERROR );
299
309
}
300
310
catch (FileException $ e ) {
@@ -487,12 +497,12 @@ protected function validateFileImageResolution(FileInterface $file, $maximum_dim
487
497
protected function prepareFilename (string $ filename , array &$ validators ): string {
488
498
// Don't rename if 'allow_insecure_uploads' evaluates to TRUE.
489
499
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 ]);
500
+ if (!empty ($ validators ['FileExtension ' ][' extensions ' ])) {
501
+ // If there is a fileValidator service to validate FileExtension and
502
+ // a list of valid extensions, munge the filename to protect against
503
+ // possible malicious extension hiding within an unknown file type.
504
+ // For example, "filename.html.foo".
505
+ $ event = new FileUploadSanitizeNameEvent ($ filename , $ validators ['FileExtension ' ][' extensions ' ]);
496
506
$ this ->eventDispatcher ->dispatch ($ event );
497
507
$ filename = $ event ->getFilename ();
498
508
}
@@ -502,33 +512,31 @@ protected function prepareFilename(string $filename, array &$validators): string
502
512
// and filename._php.txt, respectively).
503
513
if (preg_match (FileSystemInterface::INSECURE_EXTENSION_REGEX , $ filename )) {
504
514
// 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.
515
+ // should not be renamed; rather, we'll let fileValidator service
516
+ // to validate FileExtension reject it below.
517
+
507
518
$ passes_validation = FALSE ;
508
- if (!empty ($ validators ['file_validate_extensions ' ][0 ])) {
519
+ if (!empty ($ validators ['FileExtension ' ][' extensions ' ])) {
509
520
/** @var \Drupal\file\FileInterface $file */
510
521
$ file = $ this ->fileStorage ->create ([]);
511
522
$ 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 ]));
523
+ $ passes_validation = empty ($ this ->fileValidator ->validate ($ file , $ validators ['FileExtension ' ]['extensions ' ]));
516
524
}
517
- if (empty ($ validators ['file_validate_extensions ' ][0 ]) || $ passes_validation ) {
525
+ if (empty ($ validators ['FileExtension ' ][' extensions ' ]) || $ passes_validation ) {
518
526
if ((substr ($ filename , -4 ) != '.txt ' )) {
519
527
// The destination filename will also later be used to create the
520
528
// URI.
521
529
$ filename .= '.txt ' ;
522
530
}
523
531
524
- $ event = new FileUploadSanitizeNameEvent ($ filename , $ validators ['file_validate_extensions ' ][0 ] ?? '' );
532
+ $ event = new FileUploadSanitizeNameEvent ($ filename , $ validators ['FileExtension ' ][' extensions ' ] ?? '' );
525
533
$ this ->eventDispatcher ->dispatch ($ event );
526
534
$ filename = $ event ->getFilename ();
527
535
528
536
// The .txt extension may not be in the allowed list of extensions. We
529
537
// 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 ' ;
538
+ if (!empty ($ validators ['FileExtension ' ][' extensions ' ])) {
539
+ $ validators ['FileExtension ' ][' extensions ' ] .= ' txt ' ;
532
540
}
533
541
}
534
542
}
@@ -579,7 +587,7 @@ protected function getUploadLocation(array $settings): string {
579
587
protected function getUploadValidators (array $ settings ): array {
580
588
$ validators = [
581
589
// Add in our check of the file name length.
582
- 'file_validate_name_length ' => [],
590
+ 'FileNameLength ' => [],
583
591
];
584
592
585
593
// Cap the upload size according to the PHP limit.
@@ -589,11 +597,11 @@ protected function getUploadValidators(array $settings): array {
589
597
}
590
598
591
599
// There is always a file size limit due to the PHP server limit.
592
- $ validators ['file_validate_size ' ] = [$ max_filesize ];
600
+ $ validators ['FileSizeLimit ' ] = [' fileLimit ' => $ max_filesize ];
593
601
594
602
// Add the extension check if necessary.
595
603
if (!empty ($ settings ['file_extensions ' ])) {
596
- $ validators ['file_validate_extensions ' ] = [$ settings ['file_extensions ' ]];
604
+ $ validators ['FileExtension ' ] = [' extensions ' => $ settings ['file_extensions ' ]];
597
605
}
598
606
599
607
return $ validators ;
0 commit comments