Rendering the uploaded file in a wp.media object

All we need is an easy explanation of the problem, so here it is.

I have seen this question asked a few times on SO and I don’t see any responses.

I have a wp.media object (upload dialog), that I am using in to store an upload to a post as a meta element. It works fine, except the ul.attachments frame is not refreshing upon upload, see the screenshot

ul.attachments frame

I have to manually refresh the page to get the new file (pdf.pdf in my screenshot example) to display.

Is there an uploaded event that I can hook into and re-render the view for the file list frame?

Thanks.

EDIT: I abstracted out the code so that I can demonstrate the issue. N.B. this is using extremely bad practices, but it was the easiest way to abstract.

Steps to replicate the issue:

  1. Drop https://gist.github.com/matgargano/36e76cf4bb2b55e88981 into theme and include it
  2. Go to add a post, click “set pdf” in the metabox at the very bottom
  3. Drag and drop a PDF, note that the left panel doesn’t refresh
  4. Refresh the post created/edit page and click “Set pdf” and see the
    panel appears as expected (with the PDF listed on the left hand
    side). *** The goal is to have the left panel refresh in step 3

How to solve :

I know you bored from this bug, So we are here to help you! Take a deep breath and look at the explanation of your problem. We have many solutions to this problem, But we recommend you to use the first method because it is tested & true method that will 100% work for you.

Method 1

I presume you’ve fixed this already but (in a blatant attempt to snaffle the bounty and) as mentioned in the comments there’s a simple fix, in your myplugin_meta_box_callback() function change the line

$mime_types      = array( 'application/pdf' );

to

$mime_types      = 'application/pdf';

The library.type option to wp.media expects a string (which can be comma-separated with additional types) not an array.

This actually threw up a bug in the media.model.Attachments because if you look at where it was failing, the validator type() filter (line 997 in “media-models.js”)

        type: function( attachment ) {
            var type = this.props.get('type');
            return ! type || -1 !== type.indexOf( attachment.get('type') );
        },

then what this isn’t taking account of is that an attachment type like application/pdf is split into type and subtype by wp_prepare_attachment_for_js() in “media.php”, and this is only validating type, ie application (and validating in a pretty sloppy way too with no delimiters).

Anyway all that’s moot if you add the upload validator given by @Bainternet – here’s a variation of it:

add_action( 'admin_init', function () {
    add_filter( 'wp_handle_upload_prefilter', function ( $file ) {
        if ( empty( $_POST['allowed_mime_types'] ) || empty( $file['type'] ) ) {
            return $file;
        }
        $allowed_mime_types = explode( ',', $_POST['allowed_mime_types'] );
        if ( in_array( $file['type'], $allowed_mime_types ) ) {
            return $file;
        }
        // Cater for "group" allowed mime types eg "image", "audio" etc. to match
        // files of type "image/png", "audio/mp3" etc.
        if ( ( $slash_pos = strpos( $file['type'], '/' ) ) > 0 ) {
            if ( in_array( substr( $file['type'], 0, $slash_pos ), $allowed_mime_types ) ) {
                return $file;
            }
        }
        $file['error'] = __( 'Sorry, you cannot upload this file type for this field.' );
        return $file;
    } );

    add_filter( 'media_view_settings', function ( $settings, $post ) {
        $settings['mimeTypes']['application/pdf'] = __( 'All PDF items' );
        return $settings;
    }, 10, 2 );
} );

(The additional media_view_settings filter just changes the select filter text from “All media items” to “All PDF items”.)
You can then set the allowed_mime_types param (in the new way mentioned by @estepix) in your openModal() function directly after calling wp.media()

                this.modal = wp.media.frames.file_frame = wp.media(options);
                if (options.library && options.library.type && this.modal.uploader) {
                    this.modal.uploader.options.uploader.params.allowed_mime_types = options.library.type;
                }

and non-PDF files won’t be allowed to be uploaded.

Note: Use and implement method 1 because this method fully tested our system.
Thank you 🙂

All methods was sourced from stackoverflow.com or stackexchange.com, is licensed under cc by-sa 2.5, cc by-sa 3.0 and cc by-sa 4.0

Leave a Reply