diff --git a/core/modules/file/file.module b/core/modules/file/file.module index 687a62c70b..9f37d1363d 100644 --- a/core/modules/file/file.module +++ b/core/modules/file/file.module @@ -674,8 +674,83 @@ function file_cron() { } /** + * Saves form file uploads. + * + * The files will be added to the {file_managed} table as temporary files. + * Temporary files are periodically cleaned. Use the 'file.usage' service to + * register the usage of the file which will automatically mark it as permanent. + * + * @param array $element + * The FAPI element whose values are being saved. + * @param \Drupal\Core\Form\FormStateInterface $form_state + * The current state of the form. + * @param null|int $delta + * (optional) The delta of the file to return the file entity. + * Defaults to NULL. + * @param int $replace + * (optional) The replace behavior when the destination file already exists. + * Possible values include: + * - FILE_EXISTS_REPLACE: Replace the existing file. + * - FILE_EXISTS_RENAME: (default) Append _{incrementing number} until the + * filename is unique. + * - FILE_EXISTS_ERROR: Do nothing and return FALSE. + * + * @return array|\Drupal\file\FileInterface|null|false + * An array of file entities or a single file entity if $delta != NULL. Each + * array element contains the file entity if the upload succeeded or FALSE if + * there was an error. Function returns NULL if no file was uploaded. + */ +function file_save_upload_from_form($element, FormStateInterface $form_state, $delta = NULL, $replace = FILE_EXISTS_RENAME) { + $destination = isset($element['#upload_location']) ? $element['#upload_location'] : FALSE; + $validators = isset($element['#upload_validators']) ? $element['#upload_validators'] : array(); + $upload_name = implode('_', $element['#parents']); + $errors_before = drupal_get_messages('error'); + + $files = file_save_upload($upload_name, $validators, $destination, $delta, $replace); + + // Get all possible new errors that are generated while trying to save the + // upload. + $new_errors = array_diff(drupal_get_messages('error'), $errors_before); + + if (!empty($new_errors['error'])) { + $new_errors = $new_errors['error']; + + if (count($new_errors) > 1) { + // Render multiple errors into a single message. + $render_array = array( + 'error' => array( + '#markup' => t('One or more files could not be uploaded.'), + ), + 'item_list' => array( + '#theme' => 'item_list', + '#items' => $new_errors, + ), + ); + $error_message = \Drupal::service('renderer')->renderer->renderPlain($render_array); + } + else { + $error_message = reset($new_errors); + } + + \Drupal::logger('file')->notice('The file upload failed. %upload', array('%upload' => $upload_name)); + $form_state->setError($element, $error_message); + + // Empty the old queue and put the errors back as before. + drupal_get_messages('error', TRUE); + foreach ($errors_before as $error) { + drupal_set_message($error, 'error'); + } + } + return $files; +} + +/** * Saves file uploads to a new location. * + * @deprecated in Drupal 8.3.0, intended to be removed in Drupal 9.0.0. + * This function should not be used during form validation, use + * file_save_upload_from_form() instead. + * * The files will be added to the {file_managed} table as temporary files. * Temporary files are periodically cleaned. Use the 'file.usage' service to * register the usage of the file which will automatically mark it as permanent. @@ -1192,9 +1267,7 @@ function file_managed_file_save_upload($element, FormStateInterface $form_state) $files_uploaded = $element['#multiple'] && count(array_filter($file_upload)) > 0; $files_uploaded |= !$element['#multiple'] && !empty($file_upload); if ($files_uploaded) { - if (!$files = file_save_upload($upload_name, $element['#upload_validators'], $destination)) { - \Drupal::logger('file')->notice('The file upload failed. %upload', array('%upload' => $upload_name)); - $form_state->setError($element, t('Files in the @name field were unable to be uploaded.', array('@name' => $element['#title']))); + if (!$files = file_save_upload_from_form($element, $form_state)) { return array(); } diff --git a/core/modules/locale/src/Form/ImportForm.php b/core/modules/locale/src/Form/ImportForm.php index 0ea71809bc..60b2d50e74 100644 --- a/core/modules/locale/src/Form/ImportForm.php +++ b/core/modules/locale/src/Form/ImportForm.php @@ -108,6 +108,7 @@ public function buildForm(array $form, FormStateInterface $form_state) { ), '#size' => 50, '#upload_validators' => $validators, + '#upload_location' => 'translations://', '#attributes' => array('class' => array('file-import-input')), ); $form['langcode'] = array( @@ -154,7 +155,7 @@ public function buildForm(array $form, FormStateInterface $form_state) { * {@inheritdoc} */ public function validateForm(array &$form, FormStateInterface $form_state) { - $this->file = file_save_upload('file', $form['file']['#upload_validators'], 'translations://', 0); + $this->file = file_save_upload_from_form($form['file'], $form_state, 0); // Ensure we have the file uploaded. if (!$this->file) { diff --git a/core/modules/system/src/Form/ThemeSettingsForm.php b/core/modules/system/src/Form/ThemeSettingsForm.php index 37b5ea1364..e7b11ea730 100644 --- a/core/modules/system/src/Form/ThemeSettingsForm.php +++ b/core/modules/system/src/Form/ThemeSettingsForm.php @@ -357,9 +357,10 @@ public function validateForm(array &$form, FormStateInterface $form_state) { if ($this->moduleHandler->moduleExists('file')) { // Handle file uploads. $validators = array('file_validate_is_image' => array()); + $logo_upload_element = $form['logo']['settings']['logo_upload']; // Check for a new uploaded logo. - $file = file_save_upload('logo_upload', $validators, FALSE, 0); + $file = file_save_upload_from_form($logo_upload_element, $form_state, 0); if (isset($file)) { // File upload was attempted. if ($file) { @@ -368,14 +369,14 @@ public function validateForm(array &$form, FormStateInterface $form_state) { } else { // File upload failed. - $form_state->setErrorByName('logo_upload', $this->t('The logo could not be uploaded.')); + $form_state->setErrorByName($logo_upload_element, $this->t('The logo could not be uploaded.')); } } $validators = array('file_validate_extensions' => array('ico png gif jpg jpeg apng svg')); // Check for a new uploaded favicon. - $file = file_save_upload('favicon_upload', $validators, FALSE, 0); + $file = file_save_upload_from_form($form['favicon']['settings']['favicon_upload'], $form_state, 0); if (isset($file)) { // File upload was attempted. if ($file) {