Problem/Motivation

When template_preprocess_file_link() is called, Drupal\file\IconMimeTypes cannot handle NULL value for mimetype well. Errors out pages with file references to file with NULL as the mimetype.

Steps to reproduce

Attempt to view or edit a page with a file reference to a file with NULL as the mimetype, where a variable icon is expected to display.

Instead you'll get a white error page, with watchdog errors, e.g., TypeError: Drupal\file\IconMimeTypes::getIconClass(): Argument #1 ($mimeType) must be of type string, null given ...

The problem is that the database table file_managed allows NULL for the filemime column, but the internal methods of Drupal\file\IconMimeTypes require strings and can't handle NULL at all.

Proposed resolution

If \Drupal\file\FileInterface::getMimeType() returns NULL then default to \Drupal\Core\File\MimeType\MimeTypeGuesser::DEFAULT_MIME_TYPE with value 'application/octet-stream'.

Remaining tasks

User interface changes

Introduced terminology

API changes

Data model changes

Release notes snippet

Issue fork drupal-3469280

Command icon Show commands

Start within a Git clone of the project using the version control instructions.

Or, if you do not have SSH keys set up on git.drupalcode.org:

Comments

msypes created an issue. See original summary.

msypes’s picture

Issue summary: View changes
asghar’s picture

StatusFileSize
new573 bytes

I created the Patch for it.

sahana _n made their first commit to this issue’s fork.

sahana _n’s picture

Status: Active » Needs review
StatusFileSize
new710.18 KB
new370.05 KB

Hi,
I can reproduce the issue in Drupal 10.3.x, when I attempt to view the page with a file reference to a file with NULL as the mimetype I got this error TypeError: Drupal\file\IconMimeTypes::getIconClass(): Argument #1 ($mimeType) must be of type string, null given, called in /var/www/html/core/modules/file/file.module on line 774 in Drupal\file\IconMimeTypes::getIconClass() (line 21 of core/modules/file/src/IconMimeTypes.php).

I tested the same scenario by applying the patch provided in comment #3. The patch is applied cleanly and the error was cleared. So, I created MR with the same code changes.

I am attaching before & after screenshots for reference.

This issue is also reproducible in 11.x and was able to fix the issue with the same code changes.

I'll be happy to create MR for 11.x also if required. Please suggest how we can proceed further.

smustgrave’s picture

Version: 10.3.x-dev » 11.x-dev
Status: Needs review » Needs work

Fixes should be against 11.x

Also we should probably do some debugging vs putting a null check. Could be masking a larger issue

sahana _n’s picture

Hi,
Created an MR for 11. x.

kim.pepper’s picture

Despite the db column allowing NULL. our API assumes there will always be a mime type. Why do you have NULL mimetypes?

msypes’s picture

@kim.pepper: Are you asking me why we had NULL mimetypes in the database? I don't know. Could be from a less-than-perfect migration, from when we moved from D7. They were generally pretty old records. Did the the API always assume there was a mimetype? If not, why would the db allow it to be NULL? At any rate, the fact that it does allow NULLs should mean that the system can handle them.

colan’s picture

Or the DB setting is wrong.

kim.pepper’s picture

Status: Needs work » Postponed (maintainer needs more info)

\Drupal\Core\File\MimeType\MimeTypeGuesser::guessMimeType() defaults to 'application/octet-stream' if it can't determine a mime type. Would it make sense to default to this rather than empty string?

colan’s picture

Well, it's better than getting an error, right?

didebru’s picture

Thanks for the patch.
In our case it happens if we send a webform graphql mutation with a pdf attached.

kim.pepper changed the visibility of the branch 3469280-File-mime-type-null to hidden.

kim.pepper changed the visibility of the branch 3469280-drupalfileiconmimetypes-doesnt-handle to hidden.

kim.pepper’s picture

Status: Postponed (maintainer needs more info) » Needs review

Added a default mime type constant of \Drupal\Core\File\MimeType\MimeTypeGuesser::DEFAULT_MIME_TYPE with value 'application/octet-stream' and use that instead of empty string.

Hiding some older patches and MRs.

kim.pepper’s picture

Issue summary: View changes

Updated IS to reflect latest proposed resolution.

kim.pepper’s picture

Title: Drupal\file\IconMimeTypes doesn't handle NULL mimetypes » Handle NULL mime types in template_preprocess_file_link()
Issue summary: View changes

Updated title.

smustgrave’s picture

Status: Needs review » Reviewed & tested by the community

Seems pretty straight forward, not sure test coverage is needed here.

alexpott’s picture

Status: Reviewed & tested by the community » Needs work

We have other code that assumes getMimeType() returns a string...

Consider

    $mimetype = $file->getMimeType();
    $mimetype = explode('/', $mimetype);

in

\Drupal\media\Plugin\media\Source\File::getThumbnail

This will also cause a deprection.

I think we should change \Drupal\file\Entity\File::getMimeType() to return the default value - or it could even do something like File::preCreate()... and guess the mimetype if we have a URI

  /**
   * {@inheritdoc}
   */
  public function getMimeType() {
    $mimetype = $this->get('filemime')->value;
    if ($mimetype === NULL) {
      $uri = $this->getFileUri();
      $mimetype = $uri !== NULL ? \Drupal::service('file.mime_type.guesser')->guess($uri) : MimeTypeGuesser::DEFAULT_MIME_TYPE;
    }
    return $mimetype;
  }

We should also update the interface to tell people not to return a NULL

I think this would be a good change because then all code can rely on getMimeType() returning something sensible rather than having to deal with the NULL situation (which must be very rare given the preCreate().

oily made their first commit to this issue’s fork.

kim.pepper’s picture

Status: Needs work » Needs review

Re: #23 I updated \Drupal\file\Entity\File::getMimeType() to return the default mime type if NULL, and also the docs on \Drupal\file\FileInterface::getMimeType() to match this behaviour.

smustgrave’s picture

Status: Needs review » Reviewed & tested by the community

Feedback appears to be addressed.

larowlan’s picture

Status: Reviewed & tested by the community » Needs work

One minor change, fine to self RTBC

ironnuts’s picture

Status: Needs work » Reviewed & tested by the community

Self-RTBTC

larowlan’s picture

Status: Reviewed & tested by the community » Needs work

We can clean up a bit more here \Drupal\file\Plugin\Field\FieldFormatter\FileMediaFormatterBase::getSourceFiles has code that checks for NULL, which is no longer possible.

In searching for callers of this method, the number of places we're treating the return as a string is an excellent case to make this change.

Version: 11.x-dev » main

Drupal core is now using the main branch as the primary development branch. New developments and disruptive changes should now be targeted to the main branch.

Read more in the announcement.

didebru’s picture

Rebased bump.

fathershawn changed the visibility of the branch 3469280-default-mime-type to hidden.

fathershawn changed the visibility of the branch 3469280-default-mime-type-rebase to hidden.

fathershawn’s picture

Moved changes to a new branch from main and opened a new MR

fathershawn changed the visibility of the branch 11.x to hidden.

kim.pepper’s picture

Status: Needs work » Reviewed & tested by the community

MR !16258 looks ready to me.

larowlan’s picture

Status: Reviewed & tested by the community » Needs work
Issue tags: +Needs tests

I don't think we should be changing the way File::getMimeType works - we should handle it in the theme layer

We also need a test here - thanks!

longwave-bot made their first commit to this issue’s fork.

longwave’s picture

Status: Needs work » Needs review
Issue tags: -Needs tests

Reduced the change to the bare minimum and added a test.

kim.pepper’s picture

Status: Needs review » Reviewed & tested by the community

The minimal change in the preprocess hook addresses the earlier concerns. Test coverage looks good too. Back to RTBC

godotislate’s picture

Status: Reviewed & tested by the community » Needs work

I think we can consolidate the test into the Drupal\Tests\file\Kernel\Formatter\FileEntityFormatterTest class. Maybe even just modify testFormatterFileLinkWithQueryString to do the assertions there.

kim.pepper’s picture

Status: Needs work » Needs review

Consolidated the test into FileEntityFormatterTest.

smustgrave’s picture

Status: Needs review » Reviewed & tested by the community

Feedback appears to be addressed.

  • godotislate committed 61a6cb28 on main
    fix: #3469280 Handle NULL mime types in template_preprocess_file_link...

  • godotislate committed 4210702d on 11.x
    fix: #3469280 Handle NULL mime types in template_preprocess_file_link...
godotislate’s picture

Version: main » 11.x-dev
Status: Reviewed & tested by the community » Patch (to be ported)

Committed and pushed 61a6cb2 to main and 4210702 to 11.x. Thanks!

I think this can go to 11.4.x as well, confirming with other committers.

  • godotislate committed 1f518f87 on 11.4.x
    fix: #3469280 Handle NULL mime types in template_preprocess_file_link...
godotislate’s picture

Version: 11.x-dev » 11.4.x-dev
Status: Patch (to be ported) » Fixed

Confirmed with @longwave for 11.4.x backport.

Now that this issue is closed, review the contribution record.

As a contributor, attribute any organization that helped you, or if you volunteered your own time.

Maintainers, credit people who helped resolve this issue.

Status: Fixed » Closed (fixed)

Automatically closed - issue fixed for 2 weeks with no activity.