diff --git a/core/modules/file/file.module b/core/modules/file/file.module index a6fc3f6e..0da20f23 100644 --- a/core/modules/file/file.module +++ b/core/modules/file/file.module @@ -842,7 +842,11 @@ function file_save_upload($form_field_name, $validators = [], $destination = FAL if (substr($destination, -1) != '/') { $destination .= '/'; } - $file->destination = file_destination($destination . $file->getFilename(), $replace); + + $filename = $file->getTransliteratedFilename(); + + $file->destination = file_destination($destination . $filename, $replace); + // If file_destination() returns FALSE then $replace === FILE_EXISTS_ERROR and // there's an existing file so we need to bail. if ($file->destination === FALSE) { diff --git a/core/modules/file/src/Entity/File.php b/core/modules/file/src/Entity/File.php index a68b9bae..45f091fc 100644 --- a/core/modules/file/src/Entity/File.php +++ b/core/modules/file/src/Entity/File.php @@ -2,6 +2,7 @@ namespace Drupal\file\Entity; +use Drupal\Component\Utility\Unicode; use Drupal\Core\Entity\ContentEntityBase; use Drupal\Core\Entity\EntityChangedTrait; use Drupal\Core\Entity\EntityStorageInterface; @@ -274,4 +275,37 @@ public static function baseFieldDefinitions(EntityTypeInterface $entity_type) { return $fields; } + /** + * Gets the transliterated filename. + * + * @return string + * The transliterated filename. If the filename transliteration options is + * disabled, the raw filename of the file. + */ + public function getTransliteratedFilename() { + + // If the transliteration option is enabled, transliterate the filename. + if (\Drupal::config('system.file')->get('filename_transliteration')) { + $langcode = $this->languageManager()->getCurrentLanguage()->getId(); + + // Transliterate and sanitize the destination filename. + $filename = \Drupal::transliteration() + ->transliterate($this->getFilename(), $langcode, ''); + + // Replace whitespace. + $filename = str_replace(' ', '_', $filename); + // Remove remaining unsafe characters. + $filename = preg_replace('![^0-9A-Za-z_.-]!', '', $filename); + // Remove multiple consecutive non-alphabetical characters. + $filename = preg_replace('/(_)_+|(\.)\.+|(-)-+/', '\\1\\2\\3', $filename); + // Force lowercase to prevent issues on case-insensitive file systems. + $filename = Unicode::strtolower($filename); + } + else { + $filename = $this->getFilename(); + } + + return $filename; + } + } diff --git a/core/modules/system/config/install/system.file.yml b/core/modules/system/config/install/system.file.yml index ec8c0533..73b6fd7d 100644 --- a/core/modules/system/config/install/system.file.yml +++ b/core/modules/system/config/install/system.file.yml @@ -3,3 +3,4 @@ default_scheme: 'public' path: temporary: '' temporary_maximum_age: 21600 +filename_transliteration: false diff --git a/core/modules/system/config/schema/system.schema.yml b/core/modules/system/config/schema/system.schema.yml index c23ed7e0..b90fd046 100644 --- a/core/modules/system/config/schema/system.schema.yml +++ b/core/modules/system/config/schema/system.schema.yml @@ -285,6 +285,9 @@ system.file: temporary_maximum_age: type: integer label: 'Maximum age for temporary files' + filename_transliteration: + type: boolean + label: 'Transliterate names of uploaded files' system.image: type: config_object diff --git a/core/modules/system/src/Form/FileSystemForm.php b/core/modules/system/src/Form/FileSystemForm.php index ff0b7924..eac22394 100644 --- a/core/modules/system/src/Form/FileSystemForm.php +++ b/core/modules/system/src/Form/FileSystemForm.php @@ -131,6 +131,13 @@ public function buildForm(array $form, FormStateInterface $form_state) { '#description' => t('Orphaned files are not referenced from any content but remain in the file system and may appear in administrative listings. Warning: If enabled, orphaned files will be permanently deleted and may not be recoverable.'), ]; + $form['filename_transliteration'] = [ + '#type' => 'checkbox', + '#title' => t('Enable filename transliteration'), + '#default_value' => $config->get('filename_transliteration'), + '#description' => t('Check if transliteration should be enabled for uploaded filenames.'), + ]; + return parent::buildForm($form, $form_state); } @@ -140,7 +147,8 @@ public function buildForm(array $form, FormStateInterface $form_state) { public function submitForm(array &$form, FormStateInterface $form_state) { $config = $this->config('system.file') ->set('path.temporary', $form_state->getValue('file_temporary_path')) - ->set('temporary_maximum_age', $form_state->getValue('temporary_maximum_age')); + ->set('temporary_maximum_age', $form_state->getValue('temporary_maximum_age')) + ->set('filename_transliteration', $form_state->getValue('filename_transliteration')); if ($form_state->hasValue('file_default_scheme')) { $config->set('default_scheme', $form_state->getValue('file_default_scheme'));