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 ;
@@ -37,7 +39,7 @@ class FileUpload {
37
39
/**
38
40
* The file storage where we will create new file entities from.
39
41
*
40
- * @var \Drupal\file\FileStorageInterface
42
+ * @var \Drupal\Core\Entity\EntityStorageInterface
41
43
*/
42
44
protected $ fileStorage ;
43
45
@@ -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,10 +135,9 @@ public function __construct(
126
135
RendererInterface $ renderer ,
127
136
EventDispatcherInterface $ eventDispatcher ,
128
137
ImageFactory $ image_factory ,
138
+ FileValidatorInterface $ file_validator ,
129
139
) {
130
- /** @var \Drupal\file\FileStorageInterface $file_storage */
131
- $ file_storage = $ entityTypeManager ->getStorage ('file ' );
132
- $ this ->fileStorage = $ file_storage ;
140
+ $ this ->fileStorage = $ entityTypeManager ->getStorage ('file ' );
133
141
$ this ->currentUser = $ currentUser ;
134
142
$ this ->mimeTypeGuesser = $ mimeTypeGuesser ;
135
143
$ this ->fileSystem = $ fileSystem ;
@@ -140,6 +148,7 @@ public function __construct(
140
148
$ this ->renderer = $ renderer ;
141
149
$ this ->eventDispatcher = $ eventDispatcher ;
142
150
$ this ->imageFactory = $ image_factory ;
151
+ $ this ->fileValidator = $ file_validator ;
143
152
}
144
153
145
154
/**
@@ -193,10 +202,7 @@ public function saveFileUpload(UploadedFile $uploaded_file, array $settings): Fi
193
202
switch ($ uploaded_file ->getError ()) {
194
203
case UPLOAD_ERR_INI_SIZE :
195
204
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 ));
200
206
$ response ->addViolation ($ this ->t ('The file @file could not be saved because it exceeds @maxsize, the maximum allowed size for uploads. ' , [
201
207
'@file ' => $ uploaded_file ->getClientOriginalName (),
202
208
'@maxsize ' => $ maxUploadSize ,
@@ -248,8 +254,8 @@ public function saveFileUpload(UploadedFile $uploaded_file, array $settings): Fi
248
254
249
255
$ temp_file_path = $ uploaded_file ->getRealPath ();
250
256
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.
253
259
$ file_uri = $ this ->fileSystem ->getDestinationFilename ($ file_uri , FileSystemInterface::EXISTS_RENAME );
254
260
255
261
// Lock based on the prepared file URI.
@@ -262,7 +268,7 @@ public function saveFileUpload(UploadedFile $uploaded_file, array $settings): Fi
262
268
263
269
try {
264
270
// Begin building file entity.
265
- /** @var \Drupal\file\FileInterface $file */
271
+ /** @var \Drupal\Core\Entity\EntityInterface $file */
266
272
$ file = $ this ->fileStorage ->create ([]);
267
273
$ file ->setOwnerId ($ this ->currentUser ->id ());
268
274
$ file ->setFilename ($ prepared_filename );
@@ -272,29 +278,31 @@ public function saveFileUpload(UploadedFile $uploaded_file, array $settings): Fi
272
278
// before it is saved.
273
279
$ file ->setSize (@filesize ($ temp_file_path ));
274
280
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 );
286
284
if (!empty ($ errors )) {
287
285
$ response ->addViolations ($ errors );
288
286
return $ response ;
289
287
}
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
+ }
290
298
291
299
$ file ->setFileUri ($ file_uri );
292
300
// Move the file to the correct location after validation. Use
293
301
// FileSystemInterface::EXISTS_ERROR as the file location has already been
294
302
// determined above in FileSystem::getDestinationFilename().
295
303
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.
298
306
$ this ->fileSystem ->move ($ temp_file_path , $ file_uri , FileSystemInterface::EXISTS_ERROR );
299
307
}
300
308
catch (FileException $ e ) {
@@ -487,12 +495,12 @@ protected function validateFileImageResolution(FileInterface $file, $maximum_dim
487
495
protected function prepareFilename (string $ filename , array &$ validators ): string {
488
496
// Don't rename if 'allow_insecure_uploads' evaluates to TRUE.
489
497
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 ' ]);
496
504
$ this ->eventDispatcher ->dispatch ($ event );
497
505
$ filename = $ event ->getFilename ();
498
506
}
@@ -502,33 +510,31 @@ protected function prepareFilename(string $filename, array &$validators): string
502
510
// and filename._php.txt, respectively).
503
511
if (preg_match (FileSystemInterface::INSECURE_EXTENSION_REGEX , $ filename )) {
504
512
// 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
+
507
516
$ 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 */
510
519
$ file = $ this ->fileStorage ->create ([]);
511
520
$ 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 ' ]));
516
522
}
517
- if (empty ($ validators ['file_validate_extensions ' ][0 ]) || $ passes_validation ) {
523
+ if (empty ($ validators ['FileExtension ' ][' extensions ' ]) || $ passes_validation ) {
518
524
if ((substr ($ filename , -4 ) != '.txt ' )) {
519
525
// The destination filename will also later be used to create the
520
526
// URI.
521
527
$ filename .= '.txt ' ;
522
528
}
523
529
524
- $ event = new FileUploadSanitizeNameEvent ($ filename , $ validators ['file_validate_extensions ' ][0 ] ?? '' );
530
+ $ event = new FileUploadSanitizeNameEvent ($ filename , $ validators ['FileExtension ' ][' extensions ' ] ?? '' );
525
531
$ this ->eventDispatcher ->dispatch ($ event );
526
532
$ filename = $ event ->getFilename ();
527
533
528
534
// The .txt extension may not be in the allowed list of extensions. We
529
535
// 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 ' ;
532
538
}
533
539
}
534
540
}
@@ -579,7 +585,7 @@ protected function getUploadLocation(array $settings): string {
579
585
protected function getUploadValidators (array $ settings ): array {
580
586
$ validators = [
581
587
// Add in our check of the file name length.
582
- 'file_validate_name_length ' => [],
588
+ 'FileNameLength ' => [],
583
589
];
584
590
585
591
// Cap the upload size according to the PHP limit.
@@ -589,11 +595,11 @@ protected function getUploadValidators(array $settings): array {
589
595
}
590
596
591
597
// 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 ];
593
599
594
600
// Add the extension check if necessary.
595
601
if (!empty ($ settings ['file_extensions ' ])) {
596
- $ validators ['file_validate_extensions ' ] = [$ settings ['file_extensions ' ]];
602
+ $ validators ['FileExtension ' ] = [' extensions ' => $ settings ['file_extensions ' ]];
597
603
}
598
604
599
605
return $ validators ;
0 commit comments