18
18
use Drupal \Core \Session \AccountInterface ;
19
19
use Drupal \Core \Utility \Token ;
20
20
use Drupal \Component \Render \PlainTextOutput ;
21
+ use Drupal \Core \Entity \EntityConstraintViolationList ;
21
22
use Drupal \file \Entity \File ;
22
23
use Drupal \file \Plugin \Field \FieldType \FileFieldItemList ;
23
24
use Psr \Log \LoggerInterface ;
@@ -174,18 +175,37 @@ public function handleFileUploadForField(FieldDefinitionInterface $field_definit
174
175
$ file ->setOwnerId ($ owner ->id ());
175
176
$ file ->setFilename ($ prepared_filename );
176
177
$ file ->setMimeType ($ this ->mimeTypeGuesser ->guess ($ prepared_filename ));
177
- $ file ->setFileUri ($ file_uri );
178
+ $ file ->setFileUri ($ temp_file_path );
178
179
// Set the size. This is done in File::preSave() but we validate the file
179
180
// before it is saved.
180
181
$ file ->setSize (@filesize ($ temp_file_path ));
181
182
182
- // Validate the file entity against entity-level validation and field-level
183
- // validators.
184
- $ violations = $ this ->validate ($ file , $ validators );
185
- if ($ violations ->count () > 0 ) {
183
+ // Validate the file against field-level validators first while the file is
184
+ // still a temporary file. Validation is split up in 2 steps to be the same
185
+ // as in _file_save_upload_single().
186
+ // For backwards compatibility this part is copied from ::validate() to
187
+ // leave that method behavior unchanged.
188
+ // @todo Improve this with a file uploader service in
189
+ // https://www.drupal.org/project/drupal/issues/2940383
190
+ $ errors = file_validate ($ file , $ validators );
191
+ if (!empty ($ errors )) {
192
+ $ violations = new EntityConstraintViolationList ($ file );
193
+ $ translator = new DrupalTranslator ();
194
+ $ entity = EntityAdapter::createFromEntity ($ file );
195
+ foreach ($ errors as $ error ) {
196
+ $ violation = new ConstraintViolation ($ translator ->trans ($ error ),
197
+ $ error ,
198
+ [],
199
+ $ entity ,
200
+ '' ,
201
+ NULL
202
+ );
203
+ $ violations ->add ($ violation );
204
+ }
186
205
return $ violations ;
187
206
}
188
207
208
+ $ file ->setFileUri ($ file_uri );
189
209
// Move the file to the correct location after validation. Use
190
210
// FileSystemInterface::EXISTS_ERROR as the file location has already been
191
211
// determined above in FileSystem::getDestinationFilename().
@@ -196,6 +216,16 @@ public function handleFileUploadForField(FieldDefinitionInterface $field_definit
196
216
throw new HttpException (500 , 'Temporary file could not be moved to file location ' );
197
217
}
198
218
219
+ // Second step of the validation on the file object itself now.
220
+ $ violations = $ file ->validate ();
221
+
222
+ // Remove violations of inaccessible fields as they cannot stem from our
223
+ // changes.
224
+ $ violations ->filterByFieldAccess ();
225
+ if ($ violations ->count () > 0 ) {
226
+ return $ violations ;
227
+ }
228
+
199
229
$ file ->save ();
200
230
201
231
$ this ->lock ->release ($ lock_id );
@@ -334,6 +364,11 @@ protected function streamUploadData() {
334
364
/**
335
365
* Validates the file.
336
366
*
367
+ * @todo this method is unused in this class because file validation needs to
368
+ * be split up in 2 steps in ::handleFileUploadForField(). Add a deprecation
369
+ * notice as soon as a central core file upload service can be used in this
370
+ * class. See https://www.drupal.org/project/drupal/issues/2940383
371
+ *
337
372
* @param \Drupal\file\FileInterface $file
338
373
* The file entity to validate.
339
374
* @param array $validators
0 commit comments