Separate MIME type mapping from ExtensionMimeTypeGuesser

Created on 29 July 2014, over 10 years ago
Updated 30 January 2023, almost 2 years ago

Problem/Motivation

With #1921558: Convert file_get_mimetype() to use Symfony MimeTypeGuessers , the function file_mimetype_mapping() was removed. The mapping was placed as a protected property of the ExtensionMimeTypeGuesser class, as its main purpose was for the guesser to use it. But there are cases when the mapping, or just the list of MIME types, should be used in itself, outside the context of guessing. For instance, a form in the File entity module should present known MIME types for the user.

Proposed resolution

Move the default mapping to a new service and class, Drupal\Core\File\MimeType\MimeTypeMapper, with getter/setter methods.

Introduce an alterMapping() method which invokes the mimetype alter hook upon service instantiation to allow modules to play with MIME type<->extension mapping.

Change the ExtensionMimeTypeGuesser class to use the new mapper; deprecate its ::setMapping method.

Deprecate the file_mimetype_mapping alter hook.

Add tests.

Add tests.

Remaining tasks

Commit

User interface changes

None

API changes

A new service file.mime_type.mapper.

Beta phase evaluation

<!--Uncomment the relevant rows for the issue. -->
🐛 Bug report
Status

Needs work

Version

10.1

Component
File system 

Last updated about 20 hours ago

Created by

🇸🇪Sweden Arla

Live updates comments and jobs are added and updated live.
Sign in to follow issues

Merge Requests

Comments & Activities

Not all content is available!

It's likely this issue predates Contrib.social: some issue and comment data are missing.

  • Merge request !3166Resolve #2311679 "Separate mime type" → (Open) created by bhanu951
  • The Needs Review Queue Bot tested this issue. It either no longer applies to Drupal core, or fails the Drupal core commit checks. Therefore, this issue status is now "Needs work".

    Apart from a re-roll or rebase, this issue may need more work to address feedback in the issue or MR comments. To progress an issue, incorporate this feedback as part of the process of updating the issue. This helps other contributors to know what is outstanding.

    Consult the Drupal Contributor Guide to find step-by-step guides for working with issues.

  • 🇦🇺Australia kim.pepper 🏄‍♂️🇦🇺Sydney, Australia

    kim.pepper made their first commit to this issue’s fork.

  • Pipeline finished with Failed
    4 months ago
    Total: 236s
    #296581
  • Pipeline finished with Failed
    4 months ago
    Total: 259s
    #296583
  • 🇦🇺Australia kim.pepper 🏄‍♂️🇦🇺Sydney, Australia

    kim.pepper changed the visibility of the branch 11.x to hidden.

  • Pipeline finished with Failed
    4 months ago
    Total: 520s
    #296763
  • Pipeline finished with Failed
    4 months ago
    Total: 594s
    #297556
  • Pipeline finished with Failed
    4 months ago
    Total: 202s
    #297614
  • Pipeline finished with Failed
    4 months ago
    Total: 588s
    #297618
  • Pipeline finished with Success
    4 months ago
    Total: 904s
    #297631
  • 🇦🇺Australia kim.pepper 🏄‍♂️🇦🇺Sydney, Australia

    Did a fair amount of cleanup on this issue.

    • ExtensionMimeTypeGuesser is now using the MimeTypeMapper
    • Removed the getMapping() method which was temporary anyway and refactored tests to not call it
    • Split up tests and moved them to the Drupal\KernelTests\Core\File\MimeType namespace to make the namespace under lib/
    • Handle NULL returned from ExtensionMimeTypeGuesser::guessMimeType()
    • Updated the changes to the default map that went in since this was last worked on a year ago
    • Added typehints
    • Added more dependency injection
    • Fixed linting errors
    • Updated the deprecation message to refer to 11.1.0 and 12.0.0
  • 🇦🇺Australia kim.pepper 🏄‍♂️🇦🇺Sydney, Australia
  • 🇺🇸United States mfb San Francisco

    Why not allow contrib modules to call getMapping() so they can arbitrarily alter the mapping?

  • 🇦🇺Australia kim.pepper 🏄‍♂️🇦🇺Sydney, Australia

    Can't already alter the mapping with the alter hook?

  • 🇦🇺Australia kim.pepper 🏄‍♂️🇦🇺Sydney, Australia

    Also different mapping implementations could use different data structures, so what gets returned from getMapping() could be different.

  • 🇺🇸United States mfb San Francisco

    Well I'm looking at how to still allow File MIME module work without using the deprecated hook_file_mimetype_mapping_alter(). It looks like the new alter hook doesn't allow contrib module to get the mapping so it can make various changes, and then apply it via setMapping().

    And different data structures? Well that would make it even more difficult for a contrib module to alter the mapping, lol sigh. I confess to not actually following this issue.

  • 🇦🇺Australia kim.pepper 🏄‍♂️🇦🇺Sydney, Australia

    function hook_mimetype_alter(?MimeTypeMapperInterface $mime_type_mapper = NULL) gives you the ability to add/remove/update mappings by using the API interface rather than the raw data structure, which is better IMO.

  • 🇺🇸United States mfb San Francisco

    Yes I see know it's possible to call addMapping(). But I'd have to iterate through and make hundreds of method calls (if someone configures File MIME module to parse their /etc/mime.types file), with an array_search() in each one, so it just seems slower, that's all. And I'd have to double check there is no behavior change from how it worked previously.

  • 🇺🇸United States mfb San Francisco

    Realized I was being lazy and I should benchmark it. So, I found that implementing the new hook in File MIME module (configured to add all the MIME types from the /etc/mime.types file) adds about 10 milliseconds of execution time. This is probably fine for those cases where the hook is invoked during file uploads - such requests are going to be extremely slow regardless - but not ideal for other pages where the hook might be invoked (e.g. managing display of an entity with a file field). Admittedly, File MIME module doesn't have very many installs (and more installs of the Drupal 7 branch than the current branch).

  • 🇦🇺Australia kim.pepper 🏄‍♂️🇦🇺Sydney, Australia

    #128 Thinking about this further, we should probably remove setMapping() to hide the underlying data structure. Projects like https://www.drupal.org/project/sophron that use the https://github.com/FileEye/MimeMap library have a different data structure.

    #129 hmm. Shouldn't that hook only get fired on container build? It should be cached after that.

  • 🇺🇸United States mfb San Francisco

    @kim.pepper no, there is nothing caching the map, whether in the container or otherwise. Both the old and new alter hooks run whenever the map is used.

  • 🇺🇸United States mfb San Francisco

    Projects like https://www.drupal.org/project/sophron that use the https://github.com/FileEye/MimeMap library have a different data structure.

    I looked at Sophron module, and it has a totally different mechanism for allowing other modules to alter its mapping - it dispatches an event. I guess you are saying that a future version of Sophron module could start invoking this alter hook?

  • Pipeline finished with Success
    4 months ago
    Total: 666s
    #299507
  • 🇦🇺Australia kim.pepper 🏄‍♂️🇦🇺Sydney, Australia

    #131 I don't think that's right.

      file.mime_type.mapper:
        class: Drupal\Core\File\MimeType\MimeTypeMapper
        calls:
          - [alterMapping, ['@module_handler']]
    

    The hook gets fired when this service is created.

  • 🇺🇸United States mfb San Francisco

    alterMapping is called whenever the file.mime_type.mapper service is created (for example when ExtensionMimeTypeGuesser is constructed). So the alter hook fires on any request that needs to create that service.

    E.g. if a page renders an entity that displays an audio file field, the service is needed and the alter hook fires. But once that entity is cached in the render cache, it will no longer render, and therefore the service won't be created, so the alter hook won't fire. Maybe that is the caching you were referring to, I'm not sure? There are also admin pages where the service is created, and the alter hook fires, without any sort of cache being involved (e.g. managing display of an entity with a file field).

  • Pipeline finished with Failed
    4 months ago
    Total: 145s
    #299549
  • 🇦🇺Australia kim.pepper 🏄‍♂️🇦🇺Sydney, Australia

    #134 Yeah I guess I was talking about the container cache. I misunderstood what you meant by 'Both the old and new alter hooks run whenever the map is used.' thinking you meant when we call guessMimeType() but it's when the service is created.

    I did some more work removing setMapping(). I don't think that's going to cause too many issues.

  • Pipeline finished with Success
    4 months ago
    Total: 796s
    #299557
  • 🇺🇸United States mfb San Francisco

    I was timing the alter hook on requests where the service is created (e.g. because guessMimeType() was called at least once). Since it's when the service is created, the 10ms slowdown only happens at most once per request.

  • Pipeline finished with Failed
    4 months ago
    Total: 114s
    #300408
  • Pipeline finished with Failed
    4 months ago
    Total: 531s
    #300409
  • Pipeline finished with Failed
    4 months ago
    Total: 588s
    #300414
  • Pipeline finished with Failed
    4 months ago
    Total: 115s
    #300574
  • 🇦🇺Australia kim.pepper 🏄‍♂️🇦🇺Sydney, Australia

    I've done a fair bit of rework to replace the new hook with tagged services. I think triggering hooks during container build is a bit of an antipattern, and this approach uses a more symfony native approach.

  • Pipeline finished with Failed
    4 months ago
    Total: 552s
    #300596
  • Pipeline finished with Failed
    4 months ago
    Total: 1015s
    #300615
  • Pipeline finished with Failed
    4 months ago
    Total: 368s
    #300635
  • 🇺🇸United States mfb San Francisco

    @kim.pepper I don't understand why you say "triggering hooks during container build" - the hook was triggered when the service was created, i.e. when a request needs to use it for the first time, not when the container is built.

  • Pipeline finished with Failed
    4 months ago
    Total: 557s
    #301374
  • 🇦🇺Australia kim.pepper 🏄‍♂️🇦🇺Sydney, Australia

    the hook was triggered when the service was created

    Fair enough.

    As for the test fail, I have no idea why \Drupal\Tests\block\Functional\BlockCacheTest::testCachePerPage() is failing. It's passing locally for me. Could it be a random fail?

  • Pipeline finished with Failed
    4 months ago
    Total: 701s
    #301380
  • Pipeline finished with Failed
    4 months ago
    Total: 1068s
    #301427
  • Pipeline finished with Failed
    4 months ago
    Total: 451s
    #301447
  • Pipeline finished with Success
    4 months ago
    Total: 414s
    #301460
  • 🇦🇺Australia kim.pepper 🏄‍♂️🇦🇺Sydney, Australia

    Found the source of the test fails was a deprecation warning on the legacy hook_file_mimetype_mapping_alter() in file_test.module. We already test this in file_deprecated_test.module so I removed it.

    Ready for reviews again!

  • 🇮🇹Italy mondrake 🇮🇹

    mondrake changed the visibility of the branch 2311679-separate-mime-type to hidden.

  • 🇮🇹Italy mondrake 🇮🇹

    I did a review. I am definitely biased by having developed Sophron, feel free to push back.

    Also, adding a related issue that should be committed before this IMHO

  • 🇦🇺Australia kim.pepper 🏄‍♂️🇦🇺Sydney, Australia

    Thanks for the detailed review @mondrake. Much appreciated. I've responded to all your comments and made changes where I agree. I resolved a few where I did not agree, but feel free to re-open those threads if you disagree.

  • Pipeline finished with Failed
    4 months ago
    Total: 122s
    #302045
  • Pipeline finished with Failed
    4 months ago
    Total: 589s
    #302046
  • Pipeline finished with Failed
    4 months ago
    Total: 632s
    #302496
  • Pipeline finished with Success
    4 months ago
    Total: 427s
    #302508
  • 🇦🇺Australia kim.pepper 🏄‍♂️🇦🇺Sydney, Australia

    I created a POC MR with a FileEye MIME map implementation to check if our interfaces and factory approach works with 3rd party libs.

  • Pipeline finished with Failed
    4 months ago
    Total: 132s
    #302541
  • Pipeline finished with Failed
    4 months ago
    Total: 106s
    #302542
  • The Needs Review Queue Bot tested this issue. It no longer applies to Drupal core. Therefore, this issue status is now "Needs work".

    This does not mean that the patch necessarily needs to be re-rolled or the MR rebased. Read the Issue Summary, the issue tags and the latest discussion here to determine what needs to be done.

    Consult the Drupal Contributor Guide to find step-by-step guides for working with issues.

  • 🇦🇺Australia kim.pepper 🏄‍♂️🇦🇺Sydney, Australia

    Rebased.

  • Pipeline finished with Failed
    4 months ago
    Total: 163s
    #305806
  • The Needs Review Queue Bot tested this issue. It fails the Drupal core commit checks. Therefore, this issue status is now "Needs work".

    This does not mean that the patch necessarily needs to be re-rolled or the MR rebased. Read the Issue Summary, the issue tags and the latest discussion here to determine what needs to be done.

    Consult the Drupal Contributor Guide to find step-by-step guides for working with issues.

  • Pipeline finished with Failed
    4 months ago
    Total: 130s
    #305856
  • Pipeline finished with Failed
    4 months ago
    Total: 134s
    #305864
  • Pipeline finished with Success
    4 months ago
    Total: 979s
    #305870
  • 🇦🇺Australia kim.pepper 🏄‍♂️🇦🇺Sydney, Australia

    Tests are passing.

  • 🇮🇹Italy mondrake 🇮🇹

    A bunch of nitpickeries from me. I think this is almost ready, cannot RTBC it though.

  • Pipeline finished with Failed
    4 months ago
    Total: 719s
    #308896
  • 🇦🇺Australia kim.pepper 🏄‍♂️🇦🇺Sydney, Australia

    Addressed all feedback. Thanks again.

  • Pipeline finished with Failed
    4 months ago
    Total: 570s
    #308902
  • Pipeline finished with Success
    4 months ago
    Total: 1063s
    #308910
  • One small deprecation docblock issue with version numbers.

  • Pipeline finished with Canceled
    3 months ago
    Total: 91s
    #313117
  • Pipeline finished with Success
    3 months ago
    Total: 2230s
    #313118
  • 🇦🇺Australia kim.pepper 🏄‍♂️🇦🇺Sydney, Australia

    Thanks. Feedback addressed.

  • 🇦🇺Australia kim.pepper 🏄‍♂️🇦🇺Sydney, Australia

    Added tests and answered question.

  • Pipeline finished with Success
    3 months ago
    Total: 602s
    #314406
  • godotislate changed the visibility of the branch 2311679-separate-mime-type-11.x to hidden.

  • godotislate changed the visibility of the branch 2311679-separate-mime-type-11.x to active.

  • godotislate changed the visibility of the branch 2311679-separate-mime-type-fileeye to hidden.

  • 🇮🇹Italy mondrake 🇮🇹

    working on this

  • Pipeline finished with Failed
    3 months ago
    Total: 136s
    #322267
  • Pipeline finished with Failed
    3 months ago
    Total: 692s
    #322288
  • Pipeline finished with Success
    3 months ago
    Total: 2566s
    #322298
  • 🇮🇹Italy mondrake 🇮🇹

    rerolled

  • Pipeline finished with Failed
    3 months ago
    #328067
  • Pipeline finished with Failed
    3 months ago
    Total: 596s
    #328071
  • Pipeline finished with Failed
    3 months ago
    Total: 737s
    #334844
  • Pipeline finished with Running
    3 months ago
    #334873
  • The Needs Review Queue Bot tested this issue. It no longer applies to Drupal core. Therefore, this issue status is now "Needs work".

    This does not mean that the patch necessarily needs to be re-rolled or the MR rebased. Read the Issue Summary, the issue tags and the latest discussion here to determine what needs to be done.

    Consult the Drupal Contributor Guide to find step-by-step guides for working with issues.

  • Pipeline finished with Failed
    2 months ago
    Total: 643s
    #345397
  • Pipeline finished with Failed
    2 months ago
    Total: 680s
    #345407
  • 🇦🇺Australia kim.pepper 🏄‍♂️🇦🇺Sydney, Australia

    I've merged 11.x into this MR. Looks like the Hook Attributes work that got merged is triggering some deprecations that will need looking at.

  • Pipeline finished with Running
    2 months ago
    #346684
  • Pipeline finished with Success
    2 months ago
    Total: 2767s
    #347455
  • 🇦🇺Australia kim.pepper 🏄‍♂️🇦🇺Sydney, Australia

    This was just a rebase on 11.x so putting back to RTBC

  • Status changed to RTBC about 2 months ago
  • 🇦🇺Australia kim.pepper 🏄‍♂️🇦🇺Sydney, Australia

    Spoke to @xjm at DrupalCon Singapore contribution day, and she recommended tagging as Needs framework manager review.

  • 🇦🇺Australia kim.pepper 🏄‍♂️🇦🇺Sydney, Australia

    Discussed with @larowlan and this should be a task.

  • Pipeline finished with Failed
    about 2 months ago
    Total: 506s
    #366332
  • 🇦🇺Australia kim.pepper 🏄‍♂️🇦🇺Sydney, Australia

    I squashed all the commits in the MR to make rebasing on 11.x easier.

  • Pipeline finished with Failed
    about 2 months ago
    Total: 494s
    #367316
  • Pipeline finished with Failed
    about 2 months ago
    Total: 435s
    #367373
  • 🇦🇺Australia kim.pepper 🏄‍♂️🇦🇺Sydney, Australia

    Looks like we are triggering deprecation errors in Drupal\Core\File\MimeType\DefaultMimeTypeMap::getMapping() and Drupal\Core\File\MimeType\DefaultMimeTypeMap::setMapping()

  • Pipeline finished with Failed
    about 2 months ago
    Total: 587s
    #367938
  • Pipeline finished with Canceled
    about 2 months ago
    Total: 311s
    #367961
  • Pipeline finished with Canceled
    about 2 months ago
    Total: 295s
    #367972
  • Pipeline finished with Success
    about 2 months ago
    Total: 381s
    #367977
  • 🇦🇺Australia kim.pepper 🏄‍♂️🇦🇺Sydney, Australia

    Removing 'Needs framework manager review' tag as @larowlan has reviewed.

  • 🇦🇺Australia kim.pepper 🏄‍♂️🇦🇺Sydney, Australia

    Thanks for the review. Addressed feedback.

  • Pipeline finished with Success
    about 2 months ago
    Total: 933s
    #368235
  • Apologies, seeing a couple new things with fresh eyes that I missed last pass:

  • 🇦🇺Australia kim.pepper 🏄‍♂️🇦🇺Sydney, Australia

    Applied suggestions.

  • Pipeline finished with Failed
    about 2 months ago
    Total: 697s
    #368729
  • Pipeline finished with Success
    about 2 months ago
    Total: 1919s
    #368758
  • 🇮🇹Italy mondrake 🇮🇹

    Just noticed the CR links redirect to this issue and not to a CR. A CR for this is actually missing.

  • 🇦🇺Australia kim.pepper 🏄‍♂️🇦🇺Sydney, Australia

    Created a draft CR. Will look at changing the links in the morning unless someone else gets there first.

  • Pipeline finished with Success
    about 2 months ago
    Total: 1145s
    #369274
  • 🇦🇺Australia kim.pepper 🏄‍♂️🇦🇺Sydney, Australia

    Updated links to CR.

  • Pipeline finished with Failed
    about 2 months ago
    #369311
  • LGTM. Nice work, @kim.pepper. Thanks for sticking with this.

  • Pipeline finished with Failed
    13 days ago
    Total: 172s
    #398398
  • Pipeline finished with Failed
    13 days ago
    Total: 143s
    #398437
  • Pipeline finished with Failed
    13 days ago
    Total: 201s
    #398442
  • Pipeline finished with Failed
    13 days ago
    Total: 328s
    #398450
  • Pipeline finished with Failed
    13 days ago
    Total: 474s
    #398458
  • Pipeline finished with Success
    12 days ago
    Total: 662s
    #399179
  • 🇮🇹Italy mondrake 🇮🇹

    Working on BC fixes.

  • Pipeline finished with Failed
    12 days ago
    Total: 202s
    #399434
  • Pipeline finished with Failed
    12 days ago
    Total: 678s
    #399437
  • Pipeline finished with Failed
    12 days ago
    Total: 669s
    #399448
  • Pipeline finished with Failed
    12 days ago
    Total: 152s
    #399469
  • Pipeline finished with Failed
    12 days ago
    Total: 110s
    #399472
  • Pipeline finished with Failed
    12 days ago
    Total: 620s
    #399475
  • Pipeline finished with Success
    12 days ago
    Total: 525s
    #399485
  • 🇮🇹Italy mondrake 🇮🇹

    Now Sophron is passing tests with this MR applied (deprecation errors are thrown but that is OK). https://github.com/mondrake/d8-unit/actions/runs/12844774697/job/3581814...

    We need to keep the protected properties as they are and cannot rely on the new ones (the map and the file system) to be initialised when the methods are called, as the classes that today extend ExtensionMimeTypeGuesser overriding the constructor will not have done that.

  • 🇦🇺Australia kim.pepper 🏄‍♂️🇦🇺Sydney, Australia

    I think we have resolved all threads except one question for @alexpott about changes to MimeTypeMapFactory

Production build 0.71.5 2024