0

Is there a way to alter/change core has_post_thumbnail function?

I need to check folder on server with images first before code looks for post image attachment.

I see lots of filters to change image html but they either affect single post page or loop thumbnail and with woocommerce several other places plus admin tables, etc.

I need to place the server directory check before it even hits _post_thumbnail() or get_image so it looks like has_post_thumbnail is very first check unless I'm wrong.

Please help, suggest what can be done.

Thank you

EDIT: tried putting if statement inside post-thumbnail-template.php has_post_thumbnail function but did not work. Where can I check for image in folder early and possibly not edit WordPress core file?

EDIT: it somewhat works I think. Issue is I need to match image name in directory to another post meta, woocommerce product in my case.

I check for image in custom folder first then for post attachment here is how I have done that so far overiding product template files:

global $post;
$picname = get_post_meta( get_the_ID(), '_box_upc', true );
$file = '/var/www/html/images/products/' . $picname  . '.jpg';
if (file_exists($file)) {
$filesrc = home_url( '/' ).'images/products/' . $picname  . '.jpg';
//show the image
$result = '<img src="' . $filesrc. '" class="attachment-shop_thumbnail size-shop_thumbnail wp-post-image" alt="" title="">';
}else{
//return post attachment if exists code
}

using @krzysiek-dróżdż code this is what I have but seems like I can't use global $post to get other post meta to match file name, nor post title it gives server error:

function my_override_has_post_thumbnail( $result, $object_id, $meta_key, $single ) {
    global $post;
 // Get post other meta, neither one works so I uncommeneted
    //$picname = get_post_meta( $post->get_id(), '_box_upc', true );
    //$picname = get_post_meta( get_the_ID(), '_box_upc', true );
    if ( '_thumbnail_id' === $meta_key ) {
        // perform your checks and return some ID if thumbnail exists

     // Get image from custom folder
    $filelocation = '/var/www/html/images/products/' . $picname  . '.jpg';

    if (file_exists($filelocation)) {


    $filesrc = home_url( '/' ).'images/products/' . $picname  . '.jpg';

                //show the image
    $result = '<img src="' . $filesrc. '" class="attachment-shop_thumbnail size-shop_thumbnail wp-post-image" alt="'.$post->get_title().'" title="'.$post->get_title().'">';


    }
    }

    return $result;
}
add_filter( 'get_post_metadata', 'my_override_has_post_thumbnail', 10, 4 );
2

Yes, there is a way to do that... Let's take a look at has_post_thumbnail function itself:

function has_post_thumbnail( $post = null ) {
    return (bool) get_post_thumbnail_id( $post );
}

As you can see, all it really does is getting post thumbnail ID and checking if it exists. But there are no filters in here. Let's go deeper:

function get_post_thumbnail_id( $post = null ) {
    $post = get_post( $post );
    if ( ! $post ) {
        return '';
    }
    return get_post_meta( $post->ID, '_thumbnail_id', true );
}

Still no filters, but there is a hope:

function get_post_meta( $post_id, $key = '', $single = false ) {
    return get_metadata('post', $post_id, $key, $single);
}

And at last in get_metadata...

function get_metadata($meta_type, $object_id, $meta_key = '', $single = false) {
    if ( ! $meta_type || ! is_numeric( $object_id ) ) {
        return false;
    }

    $object_id = absint( $object_id );
    if ( ! $object_id ) {
        return false;
    }

    /**
     * Filters whether to retrieve metadata of a specific type.
     *
     * The dynamic portion of the hook, `$meta_type`, refers to the meta
     * object type (comment, post, or user). Returning a non-null value
     * will effectively short-circuit the function.
     *
     * @since 3.1.0
     *
     * @param null|array|string $value     The value get_metadata() should return - a single metadata value,
     *                                     or an array of values.
     * @param int               $object_id Object ID.
     * @param string            $meta_key  Meta key.
     * @param bool              $single    Whether to return only the first value of the specified $meta_key.
     */
    $check = apply_filters( "get_{$meta_type}_metadata", null, $object_id, $meta_key, $single );
    if ( null !== $check ) {
        if ( $single && is_array( $check ) )
            return $check[0];
        else
            return $check;
    }
    ...

It looks like we can use get_post_metadata hook to override has_post_thumbnail result. The only thing you have to remember is that it will change the behavior of get_post_thumbnail_id also...

Something like this should do the trick:

function my_override_has_post_thumbnail( $result, $object_id, $meta_key, $single ) {
    if ( '_thumbnail_id' === $meta_key ) {
        // perform your checks and return some ID if thumbnail exists
    }

    return $result;
}
add_filter( 'get_post_metadata', 'my_override_has_post_thumbnail', 10, 4 );
3
  • +1 as being very technically correct, but this probably not going to integrate well with code you have no control of. – Mark Kaplun Apr 15 '18 at 7:01
  • @MarkKaplun Yes, that’s true. It can get very messy, I guess. – Krzysiek Dróżdż Apr 15 '18 at 7:05
  • @krzysiek-dróżdż Thank you for your help, look at my updated code – Damir Gasparlin Apr 15 '18 at 13:44
1

@Krzysiek Dróżdż answer is a very correct one to the question you are asking, but you should ask yourself whether you are asking the right question....

Wordpress assumes that some amount of image related information is properly stored in the DB for its APIs to be able to properly handle them. Images that are not in the DB are external and the APIs will just not apply to them. Right now you have identified one API which gives you problems, but the more complex your code becomes, or the more 3rd party code is used on the site, you are going to run into more APIs which do not work for your images.

So the right answer might be to avoid the problem in the first place and properly import the images into wordpress.

1

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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