1<?php
2/**
3 * WordPress Post Thumbnail Template Functions.
4 *
5 * Support for post thumbnails.
6 * Theme's functions.php must call add_theme_support( 'post-thumbnails' ) to use these.
7 *
8 * @package WordPress
9 * @subpackage Template
10 */
11
12/**
13 * Determines whether a post has an image attached.
14 *
15 * For more information on this and similar theme functions, check out
16 * the {@link https://developer.wordpress.org/themes/basics/conditional-tags/
17 * Conditional Tags} article in the Theme Developer Handbook.
18 *
19 * @since 2.9.0
20 * @since 4.4.0 `$post` can be a post ID or WP_Post object.
21 *
22 * @param int|WP_Post|null $post Optional. Post ID or WP_Post object. Default is global `$post`.
23 * @return bool Whether the post has an image attached.
24 */
25function has_post_thumbnail( $post = null ) {
26 $thumbnail_id = get_post_thumbnail_id( $post );
27 $has_thumbnail = (bool) $thumbnail_id;
28
29 /**
30 * Filters whether a post has a post thumbnail.
31 *
32 * @since 5.1.0
33 *
34 * @param bool $has_thumbnail true if the post has a post thumbnail, otherwise false.
35 * @param int|WP_Post|null $post Post ID or WP_Post object. Default is global `$post`.
36 * @param int|false $thumbnail_id Post thumbnail ID or false if the post does not exist.
37 */
38 return (bool) apply_filters( 'has_post_thumbnail', $has_thumbnail, $post, $thumbnail_id );
39}
40
41/**
42 * Retrieves the post thumbnail ID.
43 *
44 * @since 2.9.0
45 * @since 4.4.0 `$post` can be a post ID or WP_Post object.
46 * @since 5.5.0 The return value for a non-existing post
47 * was changed to false instead of an empty string.
48 *
49 * @param int|WP_Post|null $post Optional. Post ID or WP_Post object. Default is global `$post`.
50 * @return int|false Post thumbnail ID (which can be 0 if the thumbnail is not set),
51 * or false if the post does not exist.
52 */
53function get_post_thumbnail_id( $post = null ) {
54 $post = get_post( $post );
55
56 if ( ! $post ) {
57 return false;
58 }
59
60 $thumbnail_id = (int) get_post_meta( $post->ID, '_thumbnail_id', true );
61
62 /**
63 * Filters the post thumbnail ID.
64 *
65 * @since 5.9.0
66 *
67 * @param int|false $thumbnail_id Post thumbnail ID or false if the post does not exist.
68 * @param int|WP_Post|null $post Post ID or WP_Post object. Default is global `$post`.
69 */
70 return (int) apply_filters( 'post_thumbnail_id', $thumbnail_id, $post );
71}
72
73/**
74 * Displays the post thumbnail.
75 *
76 * When a theme adds 'post-thumbnail' support, a special 'post-thumbnail' image size
77 * is registered, which differs from the 'thumbnail' image size managed via the
78 * Settings > Media screen.
79 *
80 * When using the_post_thumbnail() or related functions, the 'post-thumbnail' image
81 * size is used by default, though a different size can be specified instead as needed.
82 *
83 * @since 2.9.0
84 *
85 * @see get_the_post_thumbnail()
86 *
87 * @param string|int[] $size Optional. Image size. Accepts any registered image size name, or an array of
88 * width and height values in pixels (in that order). Default 'post-thumbnail'.
89 * @param string|array $attr Optional. Query string or array of attributes. Default empty.
90 */
91function the_post_thumbnail( $size = 'post-thumbnail', $attr = '' ) {
92 echo get_the_post_thumbnail( null, $size, $attr );
93}
94
95/**
96 * Updates cache for thumbnails in the current loop.
97 *
98 * @since 3.2.0
99 *
100 * @global WP_Query $wp_query WordPress Query object.
101 *
102 * @param WP_Query|null $wp_query Optional. A WP_Query instance. Defaults to the $wp_query global.
103 */
104function update_post_thumbnail_cache( $wp_query = null ) {
105 if ( ! $wp_query ) {
106 $wp_query = $GLOBALS['wp_query'];
107 }
108
109 if ( $wp_query->thumbnails_cached ) {
110 return;
111 }
112
113 $thumb_ids = array();
114
115 /*
116 * $wp_query may contain an array of post objects or post IDs.
117 *
118 * This ensures the cache is primed for all post objects to avoid
119 * `get_post()` calls in `get_the_post_thumbnail()` triggering an
120 * additional database call for each post.
121 */
122 $parent_post_ids = array();
123 foreach ( $wp_query->posts as $post ) {
124 if ( $post instanceof WP_Post ) {
125 $parent_post_ids[] = $post->ID;
126 } elseif ( is_int( $post ) ) {
127 $parent_post_ids[] = $post;
128 }
129 }
130 _prime_post_caches( $parent_post_ids, false, true );
131
132 foreach ( $wp_query->posts as $post ) {
133 $id = get_post_thumbnail_id( $post );
134 if ( $id ) {
135 $thumb_ids[] = $id;
136 }
137 }
138
139 if ( ! empty( $thumb_ids ) ) {
140 _prime_post_caches( $thumb_ids, false, true );
141 }
142
143 $wp_query->thumbnails_cached = true;
144}
145
146/**
147 * Retrieves the post thumbnail.
148 *
149 * When a theme adds 'post-thumbnail' support, a special 'post-thumbnail' image size
150 * is registered, which differs from the 'thumbnail' image size managed via the
151 * Settings > Media screen.
152 *
153 * When using the_post_thumbnail() or related functions, the 'post-thumbnail' image
154 * size is used by default, though a different size can be specified instead as needed.
155 *
156 * @since 2.9.0
157 * @since 4.4.0 `$post` can be a post ID or WP_Post object.
158 *
159 * @param int|WP_Post|null $post Optional. Post ID or WP_Post object. Default is global `$post`.
160 * @param string|int[] $size Optional. Image size. Accepts any registered image size name, or an array of
161 * width and height values in pixels (in that order). Default 'post-thumbnail'.
162 * @param string|array $attr Optional. Query string or array of attributes. Default empty.
163 * @return string The post thumbnail image tag.
164 */
165function get_the_post_thumbnail( $post = null, $size = 'post-thumbnail', $attr = '' ) {
166 $post = get_post( $post );
167
168 if ( ! $post ) {
169 return '';
170 }
171
172 $post_thumbnail_id = get_post_thumbnail_id( $post );
173
174 /**
175 * Filters the post thumbnail size.
176 *
177 * @since 2.9.0
178 * @since 4.9.0 Added the `$post_id` parameter.
179 *
180 * @param string|int[] $size Requested image size. Can be any registered image size name, or
181 * an array of width and height values in pixels (in that order).
182 * @param int $post_id The post ID.
183 */
184 $size = apply_filters( 'post_thumbnail_size', $size, $post->ID );
185
186 if ( $post_thumbnail_id ) {
187
188 /**
189 * Fires before fetching the post thumbnail HTML.
190 *
191 * Provides "just in time" filtering of all filters in wp_get_attachment_image().
192 *
193 * @since 2.9.0
194 *
195 * @param int $post_id The post ID.
196 * @param int $post_thumbnail_id The post thumbnail ID.
197 * @param string|int[] $size Requested image size. Can be any registered image size name, or
198 * an array of width and height values in pixels (in that order).
199 */
200 do_action( 'begin_fetch_post_thumbnail_html', $post->ID, $post_thumbnail_id, $size );
201
202 if ( in_the_loop() ) {
203 update_post_thumbnail_cache();
204 }
205
206 $html = wp_get_attachment_image( $post_thumbnail_id, $size, false, $attr );
207
208 /**
209 * Fires after fetching the post thumbnail HTML.
210 *
211 * @since 2.9.0
212 *
213 * @param int $post_id The post ID.
214 * @param int $post_thumbnail_id The post thumbnail ID.
215 * @param string|int[] $size Requested image size. Can be any registered image size name, or
216 * an array of width and height values in pixels (in that order).
217 */
218 do_action( 'end_fetch_post_thumbnail_html', $post->ID, $post_thumbnail_id, $size );
219
220 } else {
221 $html = '';
222 }
223
224 /**
225 * Filters the post thumbnail HTML.
226 *
227 * @since 2.9.0
228 *
229 * @param string $html The post thumbnail HTML.
230 * @param int $post_id The post ID.
231 * @param int $post_thumbnail_id The post thumbnail ID, or 0 if there isn't one.
232 * @param string|int[] $size Requested image size. Can be any registered image size name, or
233 * an array of width and height values in pixels (in that order).
234 * @param string|array $attr Query string or array of attributes.
235 */
236 return apply_filters( 'post_thumbnail_html', $html, $post->ID, $post_thumbnail_id, $size, $attr );
237}
238
239/**
240 * Returns the post thumbnail URL.
241 *
242 * @since 4.4.0
243 *
244 * @param int|WP_Post|null $post Optional. Post ID or WP_Post object. Default is global `$post`.
245 * @param string|int[] $size Optional. Registered image size to retrieve the source for or a flat array
246 * of height and width dimensions. Default 'post-thumbnail'.
247 * @return string|false Post thumbnail URL or false if no image is available. If `$size` does not match
248 * any registered image size, the original image URL will be returned.
249 */
250function get_the_post_thumbnail_url( $post = null, $size = 'post-thumbnail' ) {
251 $post_thumbnail_id = get_post_thumbnail_id( $post );
252
253 if ( ! $post_thumbnail_id ) {
254 return false;
255 }
256
257 $thumbnail_url = wp_get_attachment_image_url( $post_thumbnail_id, $size );
258
259 /**
260 * Filters the post thumbnail URL.
261 *
262 * @since 5.9.0
263 *
264 * @param string|false $thumbnail_url Post thumbnail URL or false if the post does not exist.
265 * @param int|WP_Post|null $post Post ID or WP_Post object. Default is global `$post`.
266 * @param string|int[] $size Registered image size to retrieve the source for or a flat array
267 * of height and width dimensions. Default 'post-thumbnail'.
268 */
269 return apply_filters( 'post_thumbnail_url', $thumbnail_url, $post, $size );
270}
271
272/**
273 * Displays the post thumbnail URL.
274 *
275 * @since 4.4.0
276 *
277 * @param string|int[] $size Optional. Image size to use. Accepts any valid image size,
278 * or an array of width and height values in pixels (in that order).
279 * Default 'post-thumbnail'.
280 */
281function the_post_thumbnail_url( $size = 'post-thumbnail' ) {
282 $url = get_the_post_thumbnail_url( null, $size );
283
284 if ( $url ) {
285 echo esc_url( $url );
286 }
287}
288
289/**
290 * Returns the post thumbnail caption.
291 *
292 * @since 4.6.0
293 *
294 * @param int|WP_Post|null $post Optional. Post ID or WP_Post object. Default is global `$post`.
295 * @return string Post thumbnail caption.
296 */
297function get_the_post_thumbnail_caption( $post = null ) {
298 $post_thumbnail_id = get_post_thumbnail_id( $post );
299
300 if ( ! $post_thumbnail_id ) {
301 return '';
302 }
303
304 $caption = wp_get_attachment_caption( $post_thumbnail_id );
305
306 if ( ! $caption ) {
307 $caption = '';
308 }
309
310 return $caption;
311}
312
313/**
314 * Displays the post thumbnail caption.
315 *
316 * @since 4.6.0
317 *
318 * @param int|WP_Post|null $post Optional. Post ID or WP_Post object. Default is global `$post`.
319 */
320function the_post_thumbnail_caption( $post = null ) {
321 /**
322 * Filters the displayed post thumbnail caption.
323 *
324 * @since 4.6.0
325 *
326 * @param string $caption Caption for the given attachment.
327 */
328 echo apply_filters( 'the_post_thumbnail_caption', get_the_post_thumbnail_caption( $post ) );
329}
330