diff --git a/core/lib/Drupal/Core/File/MimeType/MimeTypeMapper.php b/core/lib/Drupal/Core/File/MimeType/MimeTypeMapper.php index b5b64de..f7c37a3 100644 --- a/core/lib/Drupal/Core/File/MimeType/MimeTypeMapper.php +++ b/core/lib/Drupal/Core/File/MimeType/MimeTypeMapper.php @@ -19,7 +19,7 @@ class MimeTypeMapper implements MimeTypeMapperInterface { * @var array * Array of mimetypes correlated to the extensions that relate to them. */ - protected $defaultMapping = array( + protected $mapping = array( 'mimetypes' => array( 0 => 'application/andrew-inset', 1 => 'application/atom', @@ -863,11 +863,11 @@ class MimeTypeMapper implements MimeTypeMapperInterface { ); /** - * The MIME types mapping array after going through the module handler. + * Track if hook_file_mimetype_mapping_alter() has been already invoked. * - * @var array + * @var bool */ - protected $mapping; + protected $isMappingAltered = FALSE; /** * The module handler. @@ -890,11 +890,10 @@ public function __construct(ModuleHandlerInterface $module_handler) { * {@inheritdoc} */ protected function getMapping() { - if ($this->mapping === NULL) { - $mapping = $this->defaultMapping; + if (!$this->isMappingAltered) { // Allow modules to alter the default mapping. - $this->moduleHandler->alter('file_mimetype_mapping', $mapping); - $this->mapping = $mapping; + $this->isMappingAltered = TRUE; + $this->moduleHandler->alter('file_mimetype_mapping', $this); } return $this->mapping; } @@ -903,10 +902,11 @@ protected function getMapping() { * {@inheritdoc} */ public function addMapping($mimetype, $extension) { - if (!in_array($mimetype, $this->getMapping()['mimetypes'])) { + $this->getMapping(); + if (!in_array($mimetype, $this->mapping['mimetypes'])) { $this->mapping['mimetypes'][] = $mimetype; } - $key = array_search($mimetype, $this->getMapping()['mimetypes']); + $key = array_search($mimetype, $this->mapping['mimetypes']); $this->mapping['extensions'][$extension] = $key; return TRUE; @@ -923,20 +923,22 @@ public function getMimeTypes() { * {@inheritdoc} */ public function getMimeTypeForExtension($extension) { + $mapping = $this->getMapping(); $extension = strtolower($extension); - $extensions = $this->getMapping()['extensions']; - return isset($extensions[$extension]) ? $this->getMapping()['mimetypes'][$extensions[$extension]] : NULL; + $extensions = $mapping['extensions']; + return isset($extensions[$extension]) ? $mapping['mimetypes'][$extensions[$extension]] : NULL; } /** * {@inheritdoc} */ public function getExtensionsForMimeType($mimetype) { - if (!in_array($mimetype, $this->getMapping()['mimetypes'])) { + $mapping = $this->getMapping(); + if (!in_array($mimetype, $mapping['mimetypes'])) { return []; } - $key = array_search($mimetype, $this->getMapping()['mimetypes']); - $extensions = array_keys($this->getMapping()['extensions'], $key, TRUE); + $key = array_search($mimetype, $mapping['mimetypes']); + $extensions = array_keys($mapping['extensions'], $key, TRUE); sort($extensions); return $extensions; } diff --git a/core/modules/file/tests/file_test/file_test.module b/core/modules/file/tests/file_test/file_test.module index 6ee2ecc..07f76cc 100644 --- a/core/modules/file/tests/file_test/file_test.module +++ b/core/modules/file/tests/file_test/file_test.module @@ -9,6 +9,7 @@ */ use Drupal\file\Entity\File; +use Drupal\Core\File\MimeType\MimeTypeMapperInterface; const FILE_URL_TEST_CDN_1 = 'http://cdn1.example.com'; const FILE_URL_TEST_CDN_2 = 'http://cdn2.example.com'; @@ -286,16 +287,14 @@ function file_test_file_url_alter(&$uri) { /** * Implements hook_file_mimetype_mapping_alter(). */ -function file_test_file_mimetype_mapping_alter(&$mapping) { +function file_test_file_mimetype_mapping_alter(MimeTypeMapperInterface $mime_type_mapper) { // Add new mappings. - $mapping['mimetypes']['file_test_mimetype_1'] = 'madeup/file_test_1'; - $mapping['mimetypes']['file_test_mimetype_2'] = 'madeup/file_test_2'; - $mapping['mimetypes']['file_test_mimetype_3'] = 'madeup/doc'; - $mapping['extensions']['file_test_1'] = 'file_test_mimetype_1'; - $mapping['extensions']['file_test_2'] = 'file_test_mimetype_2'; - $mapping['extensions']['file_test_3'] = 'file_test_mimetype_2'; + $mime_type_mapper->addMapping('madeup/file_test_1', 'file_test_1'); + $mime_type_mapper->addMapping('madeup/file_test_2', 'file_test_2'); + $mime_type_mapper->addMapping('madeup/file_test_2', 'file_test_3'); + $mime_type_mapper->addMapping('drupal/info', 'info.yml'); // Override existing mapping. - $mapping['extensions']['doc'] = 'file_test_mimetype_3'; + $mime_type_mapper->addMapping('madeup/doc', 'doc'); } /** diff --git a/core/modules/system/file.api.php b/core/modules/system/file.api.php index a4fd8e4..135a1de 100644 --- a/core/modules/system/file.api.php +++ b/core/modules/system/file.api.php @@ -102,25 +102,30 @@ function hook_file_url_alter(&$uri) { /** * Alter MIME type mappings used to determine MIME type from a file extension. * - * Invoked by \Drupal\Core\File\MimeType\ExtensionMimeTypeGuesser::guess(). It + * Invoked by \Drupal\Core\File\MimeType\MimeTypeMapper::getMapping(). It * is used to allow modules to add to or modify the default mapping from - * \Drupal\Core\File\MimeType\ExtensionMimeTypeGuesser::$defaultMapping. - * - * @param $mapping - * An array of mimetypes correlated to the extensions that relate to them. - * The array has 'mimetypes' and 'extensions' elements, each of which is an - * array. - * - * @see \Drupal\Core\File\MimeType\ExtensionMimeTypeGuesser::guess() - * @see \Drupal\Core\File\MimeType\ExtensionMimeTypeGuesser::$defaultMapping + * \Drupal\Core\File\MimeType\MimeTypeMapper::$mapping. Implementations + * should use the \Drupal\Core\File\MimeType\MimeTypeMapper::addMapping() + * method to add/override MIME type to extension mapping. The + * \Drupal\Core\File\MimeType\MimeTypeMapper::getMimeTypeForExtension() and + * \Drupal\Core\File\MimeType\MimeTypeMapper::getExtensionsForMimeType() + * methods can be used to get the current mapping respectively of the MIME + * type of a given extension, and of the extensions associated to a given + * MIME type. + * + * @param \Drupal\Core\File\MimeType\MimeTypeMapperInterface $mime_type_mapper + * The MIME type mapper object. + * + * @see \Drupal\Core\File\MimeType\MimeTypeMapper::addMapping() + * @see \Drupal\Core\File\MimeType\MimeTypeMapper::getMimeTypeForExtension() + * @see \Drupal\Core\File\MimeType\MimeTypeMapper::getExtensionsForMimeType() */ -function hook_file_mimetype_mapping_alter(&$mapping) { - // Add new MIME type 'drupal/info'. - $mapping['mimetypes']['example_info'] = 'drupal/info'; - // Add new extension '.info.yml' and map it to the 'drupal/info' MIME type. - $mapping['extensions']['info'] = 'example_info'; +function hook_file_mimetype_mapping_alter(\Drupal\Core\File\MimeType\MimeTypeMapperInterface $mime_type_mapper) { + // Add new MIME type 'drupal/info', and map it to a new extension + // '.info.yml'. + $mime_type_mapper->addMapping('drupal/info', 'info.yml'); // Override existing extension mapping for '.ogg' files. - $mapping['extensions']['ogg'] = 189; + $mime_type_mapper->addMapping('audio/ogg', 'ogg'); } /** diff --git a/core/modules/system/src/Tests/File/MimeTypeTest.php b/core/modules/system/src/Tests/File/MimeTypeTest.php index aa7e554..453e02f 100644 --- a/core/modules/system/src/Tests/File/MimeTypeTest.php +++ b/core/modules/system/src/Tests/File/MimeTypeTest.php @@ -44,6 +44,7 @@ public function testFileMimeTypeDetection() { 'foo.file_test_2' => 'madeup/file_test_2', 'foo.doc' => 'madeup/doc', 'test.ogg' => 'audio/ogg', + 'test.info.yml' => 'drupal/info', ); $guesser = $this->container->get('file.mime_type.guesser'); @@ -83,6 +84,7 @@ public function testFileMimeTypeDetection() { 'foo.file_test_2' => 'madeup/file_test_2', 'foo.doc' => 'madeup/doc', 'test.ogg' => 'audio/ogg', + 'test.info.yml' => 'drupal/info', ); foreach ($test_case as $input => $expected) { @@ -99,6 +101,7 @@ public function testFileMimeTypeDetection() { 'madeup/file_test_1' => ['file_test_1'], 'madeup/file_test_2' => ['file_test_2', 'file_test_3'], 'madeup/doc' => ['doc'], + 'drupal/info' => ['info.yml'], ]; foreach ($test_case as $input => $expected) { $extensions = $mime_type_mapper->getExtensionsForMimeType($input);