1

Having a perplexing issue... ...for a custom post-type called 'Resources' I used the 'Featured Image' or 'thumbnail' function within WordPress to allow users to attach documents to 'Resources'. The process itself works exactly as expected and anticipated.

However, setting the site up, someone made a mistake and uploaded two documents and assigned them to the wrong 'Resources'. So Resource A -> Document B and Resource B -> Document A.

When attempting to switch them and clicking 'Edit Featured Image' you are unable to see any of the documents. They clicked 'Remove Featured Image' and then 'Set Featured Image' and when the dialogue opens, still no documents.

In the Wordpress Media Library all of the uploaded and attached documents are there. Visible, with previews, etc. As expected. Here's the first two rows of the Media Library. You can see tons of PDFs that have been successfully uploaded. Media Library

The only place where this issue appears is that in the actual 'Featured Image' media dialogue box, WordPress will not display any PDFs.

Here's the CPT supports segment:

$rsc_supports = array(
     'title',
     'editor',
     'thumbnail',
     'page-attributes'
);

Like I said, everything works perfectly - even uploading and attaching PDFs as 'thumbnails' to be associated as attachments with the CPT. When a PDF is attached and you 'Click to edit' the dialogue opens up and you can see the attached PDF in the list. The only failing is that the 'Featured Image' modal/pop-up/dialogue box that loads, is designed to filter out everything except images. This is what that dialogue box looks like on a 'Resource' with nothing attached. Featured Image Dialogue

However, if you view another Resource that does have a PDF already attached, you get this: With PDF Attached

I have tried the filtering and date dropdown and they don't address this.

I believe this is by design. So my question is, "How do I modify that dialogue box to display all files rather than just images?"

6
  • 1
    How were they originally set as featured images on the site? It's Core behavior to only allow images as featured, so I'm surprised they were set, unless it was done programmatically.
    – WebElaine
    Jun 3, 2020 at 17:33
  • It just allowed it. Nothing was done any different than adding a standard image. That's why this caught me off guard because when I initially built it and set it all up, it allowed the addition of .pdf/.doc files. Had it not allowed it I would have built something different - but now that we've had people add dozens of attachments, I don't want to go back, build it different and then have them re-do all that work. :-( Jun 3, 2020 at 17:57
  • Worst case, you could manually assign them in the database. They're just postmeta that includes the attachment ID.
    – WebElaine
    Jun 3, 2020 at 20:25
  • That won’t be suitable for the client from a usability/UX experience. Jun 3, 2020 at 21:10
  • Since Core doesn't currently support it, you could build an options page where they select the post from a dropdown and assign the image there. Would take some custom coding, but that would give them a user-friendly UI to do it.
    – WebElaine
    Jun 4, 2020 at 13:36

2 Answers 2

1
+50

So this may be hacky..

I mean, compared to overriding the default Featured Image panel/component in the Gutenberg block editor, which is not exactly hard, but this one is much simpler and basically just needs a few lines of custom coding. (read till the end to see what I mean)

And I've also tried & tested it working (with both the old/classic editor and the Gutenberg block editor) on WordPress 5.4.2 (the latest release as of writing) as well as WordPress 5.4.1.

So for what you're trying to do, you can override wp.media.model.Query.prototype.sync() (defined in wp-includes/js/media-models.js) which is the function used by the default Featured Image modal for querying attachments via AJAX (admin-ajax.php?action=query-attachments).

Full (JS) Code

wp.media.model.Query.prototype.sync = function( method, model, options ) {
    var args, fallback;

    // Overload the read method so Attachment.fetch() functions correctly.
    if ( 'read' === method ) {
        options = options || {};
        options.context = this;
        options.data = _.extend( options.data || {}, {
            action:  'query-attachments',
            post_id: wp.media.model.settings.post.id
        });

        // Clone the args so manipulation is non-destructive.
        args = _.clone( this.args );

        // Determine which page to query.
        if ( -1 !== args.posts_per_page ) {
            args.paged = Math.round( this.length / args.posts_per_page ) + 1;
        }

        if ( wp.media.frame && 'featured-image' === wp.media.frame.options.state ) {
            // Here I'm allowing image and PDF files only.
            args.post_mime_type = 'image, application/pdf';
        }

        options.data.query = args;
        return wp.media.ajax( options );

    // Otherwise, fall back to `Backbone.sync()`.
    } else {
        /**
         * Call wp.media.model.Attachments.sync or Backbone.sync
         */
        fallback = Attachments.prototype.sync ? Attachments.prototype : Backbone;
        return fallback.sync.apply( this, arguments );
    }
};

But the only thing I added there is this conditional block:

if ( wp.media.frame && 'featured-image' === wp.media.frame.options.state ) {
    // Here I'm allowing image and PDF files only.
    args.post_mime_type = 'image, application/pdf';
}

Which checks if the currently opened modal is the featured image modal and if so, then we modify the post_mime_type argument which defines the MIME type(s) of the attachments being queried.

And that's how you can use this approach to force the Featured Image modal to include files other than images.

Sample PHP Code

Update Jun 13th (to other readers): Just to clarify why should we check for the media-models script, which is because we're overriding something in that script, so if the script is not being loaded on the current page, then there's no need to echo/enqueue our custom script. :)

The following is the PHP code I used to echo the script in the footer on the post editing screen for the default post and page post types:

add_action( 'admin_print_footer_scripts', function () {
    $screen_ids = [ 'post', 'page' ];
    if ( in_array( get_current_screen()->id, $screen_ids ) &&
        wp_script_is( 'media-models' ) // check if media-models.js was enqueued
    ) :
        ?>
            <script>
                // See/copy the FULL code above and place it here..
            </script>
        <?php
    endif;
} );

And if you put the script in an external JS file, you should also ensure that the media-models script has been enqueued:

add_action( 'admin_enqueue_scripts', function () {
    $screen_ids = [ 'post', 'page' ];
    if ( in_array( get_current_screen()->id, $screen_ids ) &&
        wp_script_is( 'media-models' ) // check if media-models.js was enqueued
    ) {
        wp_enqueue_script( 'my-script', '/path/to/my-script.js', [], '', true );
    }
} );
6
  • Sally CJ, I haven't attempted to test/implement this yet because I've been swamped with change requests for the same project (front end stuff for client review, so it currently takes priority over this), but I do have one question, this CPT isn't using the block editor but I'm assuming our solution should still work. The way these items are being displayed, we wanted the content to be extremely simplified as it's just summaries of what's in the attached resource, so I've implemented the Classic Editor on this post type, not Gutenberg. Jun 12, 2020 at 16:33
  • 1
    No worries, take your time. :) And yes, the solution in the answer should work with both the classic editor and the Gutenberg block editor because they both use the wp.media scripts. Btw, sorry about that "added 1 character in body" in the revision's description.. I have no idea how come it was like that. I mean, the system automatically added it.
    – Sally CJ
    Jun 12, 2020 at 18:53
  • 1
    Sally CJ, this IS perfect! I hope you don't mind but in the plugin's readme.md file, I included this: == Credits == * Media Modal Override provided by Sally CJ on WordPress StackExchange: https://wordpress.stackexchange.com/users/137402/sally-cj I can remove it if don't want it there. :-) Just figured it was fair to give credit where due. I've incorporated it into the plugin after a few modifications, I added other MIME types and I simplified the script enqueuing because I already have a series of conditions for loading scripts to just that one screen, so I simply placed it in there. Jun 13, 2020 at 4:45
  • Hi Tony, I'm glad the solution worked for you. But I revised the answer a bit, mainly because I noticed that there was a sentence missing in the first paragraph.. :) And about that credit thing, it's really not necessary for me, but I'm just fine with that, so thank you so much. :) Have a nice weekend!
    – Sally CJ
    Jun 13, 2020 at 14:09
  • Sally CJ, I only just realized that accepting your answer wasn't sufficient in awarding the bounty. Apologies for the delay. Jun 16, 2020 at 23:24
0

Have you tried this plugin PDF Thumbnails ?

This plugin generates a thumbnail from the first page in the uploaded document and names it as PDFNAME-thumbnail, then you can use this image as a featured image. this plugin is outdated, about 4 years ago so be sure for testing and compatibility.

1
  • 1
    WordPress now does this by default and it doesn't address the actual issue of being able to search and find the actual PDF document using the 'Set Featured Image' option in a post_type. Thanks though. Jun 12, 2020 at 16:30

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.