diff --git a/core/modules/file/file.module b/core/modules/file/file.module index c63fff4..4a93569 100644 --- a/core/modules/file/file.module +++ b/core/modules/file/file.module @@ -14,6 +14,7 @@ use Drupal\Core\Url; use Drupal\file\Entity\File; use Drupal\file\FileInterface; +use Drupal\image\Entity\ImageStyle; use Drupal\Component\Utility\NestedArray; use Drupal\Component\Utility\Unicode; use Drupal\Core\Entity\EntityStorageInterface; @@ -472,6 +473,44 @@ function file_validate_image_resolution(FileInterface $file, $maximum_dimensions } /** + * Verifies that the uploaded image is processed with an image style. + * + * @param \Drupal\file\FileInterface $file + * A file entity. This function may resize the file affecting its size. + * @param string $image_style_name + * The name of the image style to use to process the image. + * + * @return array + * An empty array if the image style was not specified, or the image file was + * processed successfully. An array containing the error messages otherwise. + * + * @see hook_file_validate() + */ +function file_validate_image_style_on_upload(FileInterface $file, $image_style_name) { + $errors = []; + + if (!empty($image_style_name)) { + $image_style = ImageStyle::load($image_style_name); + if ($image_style === NULL) { + $errors[] = t("The image style %image_style to be applied on the uploaded image does not exist.", ['%image_style' => $image_style_name]); + } + else { + $derived_uri = $file->getFileUri() . '.derived'; + if (!$image_style->createDerivative($file->getFileUri(), $derived_uri)) { + $errors[] = t('The uploaded image could not be processed with style %image_style. The image file may be invalid.', ['%image_style' => $image_style_name]); + } + else { + if (file_unmanaged_move($derived_uri, $file->getFileUri(), FILE_EXISTS_REPLACE) === FALSE) { + $errors[] = t('An error occurred while saving the uploaded image file.'); + } + } + } + } + + return $errors; +} + +/** * Saves a file to the specified destination and creates a database entry. * * @param string $data diff --git a/core/modules/image/config/schema/image.schema.yml b/core/modules/image/config/schema/image.schema.yml index 0006ad7..f3ff54b 100644 --- a/core/modules/image/config/schema/image.schema.yml +++ b/core/modules/image/config/schema/image.schema.yml @@ -102,6 +102,9 @@ field.field_settings.image: type: base_file_field_field_settings label: 'Image settings' mapping: + image_style: + type: string + label: 'Image style on upload' max_resolution: type: string label: 'Maximum image resolution' diff --git a/core/modules/image/src/Plugin/Field/FieldType/ImageItem.php b/core/modules/image/src/Plugin/Field/FieldType/ImageItem.php index c83e143..c992c56 100644 --- a/core/modules/image/src/Plugin/Field/FieldType/ImageItem.php +++ b/core/modules/image/src/Plugin/Field/FieldType/ImageItem.php @@ -76,6 +76,7 @@ public static function defaultFieldSettings() { 'alt_field_required' => 1, 'title_field' => 0, 'title_field_required' => 0, + 'image_style' => '', 'max_resolution' => '', 'min_resolution' => '', 'default_image' => array( @@ -199,13 +200,24 @@ public function fieldSettingsForm(array $form, FormStateInterface $form_state) { $settings = $this->getSettings(); + // Add image style on upload. + $element['image_style'] = [ + '#type' => 'select', + '#title' => t('Image style on upload'), + '#description' => t('Select if an image style should be applied to the uploaded image file.'), + '#options' => image_style_options(), + '#default_value' => $settings['image_style'], + '#empty_option' => $this->t('- No -'), + '#weight' => 4.1, + ]; + // Add maximum and minimum resolution settings. $max_resolution = explode('x', $settings['max_resolution']) + array('', ''); $element['max_resolution'] = array( '#type' => 'item', '#title' => t('Maximum image resolution'), '#element_validate' => array(array(get_class($this), 'validateResolution')), - '#weight' => 4.1, + '#weight' => 4.2, '#field_prefix' => '
', '#field_suffix' => '
', '#description' => t('The maximum allowed image size expressed as WIDTH×HEIGHT (e.g. 640×480). Leave blank for no restriction. If a larger image is uploaded, it will be resized to reflect the given width and height. Resizing images on upload will cause the loss of EXIF data in the image.'), @@ -232,7 +244,7 @@ public function fieldSettingsForm(array $form, FormStateInterface $form_state) { '#type' => 'item', '#title' => t('Minimum image resolution'), '#element_validate' => array(array(get_class($this), 'validateResolution')), - '#weight' => 4.2, + '#weight' => 4.3, '#field_prefix' => '
', '#field_suffix' => '
', '#description' => t('The minimum allowed image size expressed as WIDTH×HEIGHT (e.g. 640×480). Leave blank for no restriction. If a smaller image is uploaded, it will be rejected.'), diff --git a/core/modules/image/src/Plugin/Field/FieldWidget/ImageWidget.php b/core/modules/image/src/Plugin/Field/FieldWidget/ImageWidget.php index f881419..0f84cd5 100644 --- a/core/modules/image/src/Plugin/Field/FieldWidget/ImageWidget.php +++ b/core/modules/image/src/Plugin/Field/FieldWidget/ImageWidget.php @@ -112,17 +112,22 @@ public function formElement(FieldItemListInterface $items, $delta, array $elemen $field_settings = $this->getFieldSettings(); - // Add upload resolution validation. - if ($field_settings['max_resolution'] || $field_settings['min_resolution']) { - $element['#upload_validators']['file_validate_image_resolution'] = array($field_settings['max_resolution'], $field_settings['min_resolution']); - } - // If not using custom extension validation, ensure this is an image. $supported_extensions = array('png', 'gif', 'jpg', 'jpeg'); $extensions = isset($element['#upload_validators']['file_validate_extensions'][0]) ? $element['#upload_validators']['file_validate_extensions'][0] : implode(' ', $supported_extensions); $extensions = array_intersect(explode(' ', $extensions), $supported_extensions); $element['#upload_validators']['file_validate_extensions'][0] = implode(' ', $extensions); + // Add image style on upload validation. + if (!empty($field_settings['image_style'])) { + $element['#upload_validators']['file_validate_image_style_on_upload'][0] = $field_settings['image_style']; + } + + // Add upload resolution validation. + if ($field_settings['max_resolution'] || $field_settings['min_resolution']) { + $element['#upload_validators']['file_validate_image_resolution'] = array($field_settings['max_resolution'], $field_settings['min_resolution']); + } + // Add mobile device image capture acceptance. $element['#accept'] = 'image/*'; diff --git a/core/profiles/standard/config/install/field.field.node.article.field_image.yml b/core/profiles/standard/config/install/field.field.node.article.field_image.yml index b4b1c14..8816bab 100644 --- a/core/profiles/standard/config/install/field.field.node.article.field_image.yml +++ b/core/profiles/standard/config/install/field.field.node.article.field_image.yml @@ -20,6 +20,7 @@ settings: file_directory: '[date:custom:Y]-[date:custom:m]' file_extensions: 'png gif jpg jpeg' max_filesize: '' + image_style: '' max_resolution: '' min_resolution: '' alt_field: true diff --git a/core/profiles/standard/config/install/field.field.user.user.user_picture.yml b/core/profiles/standard/config/install/field.field.user.user.user_picture.yml index b2e61f6..51485e5 100644 --- a/core/profiles/standard/config/install/field.field.user.user.user_picture.yml +++ b/core/profiles/standard/config/install/field.field.user.user.user_picture.yml @@ -22,6 +22,7 @@ settings: max_filesize: '30 KB' alt_field: false title_field: false + image_style: '' max_resolution: 85x85 min_resolution: '' default_image: