Make WordPress Core

Opened 9 years ago

Last modified 3 weeks ago

#32544 assigned enhancement

No function exposes all supported MIME types

Reported by: danrossiter's profile dan.rossiter Owned by: octalmage's profile octalmage
Milestone: Priority: low
Severity: normal Version: 4.2.2
Component: Media Keywords: good-first-bug has-patch has-unit-tests needs-testing
Focuses: Cc:

Description (last modified by rmccue)

wp_get_mime_types() returns the default WP MIME types, and get_allowed_mime_types() returns the default WP MIME types + added MIME types through the upload_mimes filter, but the kicker with the latter is that it is filtered based on the currently authenticated user.

There needs to be a way to retrieve all MIME types supported, both the default and the ones added through the upload_mimes filter, regardless of who is authenticated.

I understand there are security reasons for not allowing users to *add* (or write) attachments of a given MIME type, but when a user is reading there needs to be a way to retrieve an unrestricted list of all MIME types.

An example use case is below, where all supported MIME types for a service are retrieved from its API and then the subset of types that are both supported by the WordPress install and the service are kept.

function get_service_mime_types() {
   // the desired function to get un-sanitized MIME types
   $wp_types = wp_get_all_mime_types();

   // get intersection of WP / service MIME types
   $allowed = array_intersect($wp_types, get_service_mime_types());
   $allowed = array_keys($allowed);

   return $allowed;
}

As a work-around, I'm currently using the following, but it's flawed -- if a custom MIME type is added conditionally by user type, it won't be included which is not the desired behavior.

array_merge(wp_get_mime_types(), get_allowed_mime_types())

Attachments (4)

32544.diff (2.5 KB) - added by octalmage 8 years ago.
32544.1.patch (2.5 KB) - added by hozayx 3 weeks ago.
32544.1.2.patch (2.5 KB) - added by hozayx 3 weeks ago.
32544.1.3.patch (3.1 KB) - added by hozayx 3 weeks ago.

Download all attachments as: .zip

Change History (13)

#1 @rmccue
9 years ago

  • Description modified (diff)

#2 @johnbillion
9 years ago

  • Keywords needs-patch good-first-bug added
  • Priority changed from normal to low

#3 follow-up: @ipm-frommen
9 years ago

To me, it is not clear what the desired functionality exactly is.

Since the upload_mimes filter passes the current user ID, there is no way to include all MIME types, for every possible user.

For example, a plugin could use the above filter as well as the user ID like so:

add_filter( 'upload_mimes', 'user_mimes', 10, 2 );

function user_mimes( $mimes, $user_id ) {

    $user = get_userdata( $user_id );
    if ( $user && $user->user_firstname === 'Abe' ) {
        $mimes[ 'foo' ] = 'text/foo';
    }

    return $mimes;
}

If I understand your last sentence correctly, you would like to have 'foo' included in the result of your desired wp_get_all_mime_types function. Is this correct? If so, this is not possible.

Also, your example code is wrong (there is an endless loop).

#4 in reply to: ↑ 3 @dan.rossiter
9 years ago

Replying to ipm-frommen:

To me, it is not clear what the desired functionality exactly is.

Since the upload_mimes filter passes the current user ID, there is no way to include all MIME types, for every possible user.

I agree. This functionality cannot be achieved without a structural change to the way that additional MIME types are added.

For example, a plugin could use the above filter as well as the user ID like so:

add_filter( 'upload_mimes', 'user_mimes', 10, 2 );

function user_mimes( $mimes, $user_id ) {

    $user = get_userdata( $user_id );
    if ( $user && $user->user_firstname === 'Abe' ) {
        $mimes[ 'foo' ] = 'text/foo';
    }

    return $mimes;
}

If I understand your last sentence correctly, you would like to have 'foo' included in the result of your desired wp_get_all_mime_types function. Is this correct? If so, this is not possible.

It is absolutely possible. As stated above, it would require a structural change.

Also, your example code is wrong (there is an endless loop).

Not sure where you're seeing a looping construct...

#5 follow-up: @ipm-frommen
9 years ago

I'm talking about the recursion (i.e., get_service_mime_types being called within get_service_mime_types).

Regarding your desired functionality, could you (again) explain in more detail what you want exactly? With the current upload_mimes filter (and its parameters), I don't see any way to achieve what (I guess) you want. If your structural change implicates removing the $user ID field from the filter's parameters, this, of course, breaks backwards compatibility.

I'm afraid, I just didn't understand what you would like to have.

#6 in reply to: ↑ 5 @dan.rossiter
9 years ago

Replying to ipm-frommen:

I'm talking about the recursion (i.e., get_service_mime_types being called within get_service_mime_types).

Gotcha. That would be a typo; pretend the internal call gets a full unfiltered list of all MIME types supported by the service -- maybe via an HTTP request or some cached option.

Regarding your desired functionality, could you (again) explain in more detail what you want exactly? With the current upload_mimes filter (and its parameters), I don't see any way to achieve what (I guess) you want. If your structural change implicates removing the $user ID field from the filter's parameters, this, of course, breaks backwards compatibility.

I was thinking the opposite, actually. Add an additional "override" param which tells the function to unconditionally include all MIME types regardless of user. Short of a complete rework of how MIME types are tracked, this seems like the cleanest solution to me.

I'm afraid, I just didn't understand what you would like to have.

@octalmage
8 years ago

#7 @octalmage
8 years ago

  • Keywords has-patch has-unit-tests added; needs-patch removed

The patch I attached contains a solution. Like @dan.rossiter said, it's the best solution that doesn't involve refactoring how mime types are handled. This won't change anything unless plugin/theme developers obey the new $ignore_user flag. It works like this:

add_filter( 'upload_mimes', 'user_mimes', 10, 3 );

function user_mimes( $mimes, $user_id, $ignore_user ) {
        $mime_types = array( 'test' => 'text/test' );
        
        $user = get_userdata( $user_id );
        if ( $ignore_user ) {
                $mimes = array_merge( $mimes, $mime_types );
        }
        else if ( $user && $user->user_firstname === 'Abe' ) {
                $mimes = array_merge( $mimes, $mime_types );
        }

        return $mimes;
}

Basically developers would need to return all of the mime types their code adds if the $ignore_user flag is true.

Version 1, edited 8 years ago by octalmage (previous) (next) (diff)

#8 @DrewAPicture
8 years ago

  • Owner set to octalmage
  • Status changed from new to assigned

Assigning to mark the good-first-bug as "claimed".

See 32544.diff

@hozayx
3 weeks ago

@hozayx
3 weeks ago

#9 @hozayx
3 weeks ago

  • Keywords needs-testing added

Refreshed the patch and renamed the function so that it is more clear to what it does.

Testing Instructions

  1. Create a plugin or use your functions file from theme
  2. Add a custom mime type
  3. Test the new function by running get_allowed_mime_types(null, true)
  4. Verify that the custom mime type is in there

@hozayx
3 weeks ago

Note: See TracTickets for help on using tickets.