PluginProbe ʕ •ᴥ•ʔ
Jetpack – WP Security, Backup, Speed, & Growth / 7.0.3
Jetpack – WP Security, Backup, Speed, & Growth v7.0.3
15.9-a.7 15.9-a.5 15.9-a.3 15.9-a.1 15.8 15.8-beta 15.8-a.7 15.8-a.5 5.2.5 5.3.4 5.4.4 5.5.5 5.6.5 5.7.5 5.8.4 5.9.4 6.0.4 6.1 6.1.1 6.1.2 6.1.3 6.1.4 6.1.5 6.2 6.2.1 6.2.2 6.2.3 6.2.4 6.2.5 6.3 6.3.1 6.3.2 6.3.3 6.3.4 6.3.5 6.3.6 6.3.7 6.4 6.4.1 6.4.2 6.4.3 6.4.4 6.4.5 6.4.6 6.5 6.5.1 6.5.2 6.5.3 6.5.4 6.6 6.6.1 6.6.2 6.6.3 6.6.4 6.6.5 6.7 6.7.1 6.7.2 6.7.3 6.7.4 6.8 6.8.1 6.8.2 6.8.3 6.8.4 6.8.5 6.9 6.9.1 6.9.2 6.9.3 6.9.4 7.0 7.0.1 7.0.2 7.0.3 7.0.4 7.0.5 7.1 7.1.1 7.1.2 7.1.3 7.1.4 7.1.5 7.2 7.2.1 7.2.1.1 7.2.2 7.2.3 7.2.4 7.2.5 7.3 7.3.0.1 7.3.1 7.3.1.1 7.3.2 7.3.3 7.3.4 7.3.5 7.4 7.4.1 7.4.2 7.4.3 7.4.4 7.4.5 7.5 7.5.0.1 7.5.1 7.5.2 7.5.3 7.5.4 7.5.5 7.5.6 7.5.7 7.6 7.6.1 7.6.2 7.6.3 7.6.4 7.7 7.7.1 7.7.2 7.7.3 7.7.4 7.7.5 7.7.6 7.8 7.8.1 7.8.2 7.8.3 7.8.4 7.9 7.9.1 7.9.2 7.9.3 7.9.4 8.0 8.0.1 8.0.2 8.0.3 8.1 8.1.1 8.1.2 8.1.3 8.1.4 8.2 8.2.0.1 8.2.1 8.2.2 8.2.3 8.2.4 8.2.5 8.2.6 8.3 8.3.1 8.3.2 8.3.3 8.4 8.4.1 8.4.2 8.4.3 8.4.4 8.4.5 8.5 8.5.1 8.5.2 8.5.3 8.6 8.6.1 8.6.2 8.6.3 8.6.4 8.7 8.7.0.1 8.7.1 8.7.2 8.7.3 8.7.4 8.8 8.8.1 8.8.2 8.8.3 8.8.4 8.8.5 8.9 8.9.1 8.9.2 8.9.3 8.9.4 9.0 9.0.1 9.0.2 9.0.3 9.0.4 9.0.5 9.1 9.1.1 9.1.2 9.1.3 9.2 9.2.1 9.2.2 9.2.3 9.2.4 9.3 9.3.1 9.3.2 9.3.3 9.3.4 9.3.5 9.4 9.4.1 9.4.2 9.4.3 9.4.4 9.5 9.5.1 9.5.2 9.5.3 9.5.4 9.5.5 9.6 9.6.1 9.6.2 9.6.3 9.6.4 9.7 9.7.1 9.7.2 15.7-beta.2 9.7.3 15.7.1 9.8 15.8-a.1 9.8.1 15.8-a.3 9.8.2 2.0.9 9.8.3 2.1.7 9.9 2.2.10 9.9.1 2.3.10 9.9.2 2.4.7 9.9.3 2.5.5 2.6.6 2.7.5 2.8.5 2.9.6 3.0.6 3.1.5 3.2.5 3.3.6 3.4.6 3.5.6 3.6.4 3.7.5 3.8.5 3.9.10 4.0.7 4.1.4 4.2.5 4.3.5 4.4.5 4.5.3 4.6.3 4.7.4 4.8.5 4.9.3 5.0.3 5.1.4 trunk 10.0 10.0.1 10.0.2 10.1 10.1.1 10.1.2 10.2 10.2.1 10.2.2 10.2.3 10.3 10.3.1 10.3.2 10.4 10.4.1 10.4.2 10.5 10.5.1 10.5.2 10.5.3 10.6 10.6.1 10.6.2 10.7 10.7.1 10.7.2 10.8 10.8.1 10.8.2 10.9 10.9.1 10.9.2 10.9.3 11.0 11.0.1 11.0.2 11.1 11.1.1 11.1.2 11.1.3 11.1.4 11.2 11.2.1 11.2.2 11.3 11.3.1 11.3.2 11.3.3 11.3.4 11.4 11.4.1 11.4.2 11.5 11.5.1 11.5.2 11.5.3 11.6 11.6.1 11.6.2 11.7 11.7.1 11.7.2 11.7.3 11.8 11.8.3 11.8.4 11.8.5 11.8.6 11.9 11.9.1 11.9.2 11.9.3 12.0 12.0.1 12.0.2 12.1 12.1.1 12.1.2 12.2 12.2.1 12.2.2 12.3 12.3.1 12.4 12.4.1 12.5 12.5.1 12.6 12.6.1 12.6.2 12.6.3 12.7 12.7.1 12.7.2 12.8 12.8.1 12.8.2 12.9 12.9.1 12.9.2 12.9.3 12.9.4 13.0 13.0.1 13.1 13.1.1 13.1.2 13.1.3 13.1.4 13.2 13.2.1 13.2.2 13.2.3 13.3 13.3.1 13.3.2 13.4 13.4.1 13.4.2 13.4.3 13.4.4 13.5 13.5.1 13.6 13.6.1 13.7 13.7.1 13.8 13.8.1 13.8.2 13.9 13.9.1 14.0 14.1 14.2 14.2.1 14.3 14.4 14.4.1 14.5 14.6 14.7 14.8 14.9 14.9.1 15.0 15.0.1 15.0.2 15.1 15.1.1 15.2 15.3 15.3.1 15.4 15.5 15.6 15.7 15.7-a.1 15.7-a.3 15.7-a.5 15.7-a.7 15.7-beta
jetpack / class.jetpack-post-images.php
jetpack Last commit date
3rd-party 7 years ago _inc 6 years ago bin 7 years ago css 7 years ago images 6 years ago json-endpoints 7 years ago languages 7 years ago modules 5 years ago sal 7 years ago scss 7 years ago sync 7 years ago views 7 years ago .svnignore 12 years ago CODE-OF-CONDUCT.md 9 years ago changelog.txt 7 years ago class.frame-nonce-preview.php 9 years ago class.jetpack-admin.php 7 years ago class.jetpack-affiliate.php 7 years ago class.jetpack-autoupdate.php 8 years ago class.jetpack-bbpress-json-api-compat.php 9 years ago class.jetpack-cli.php 7 years ago class.jetpack-client-server.php 8 years ago class.jetpack-client.php 7 years ago class.jetpack-connection-banner.php 7 years ago class.jetpack-constants.php 8 years ago class.jetpack-data.php 7 years ago class.jetpack-debugger.php 7 years ago class.jetpack-error.php 10 years ago class.jetpack-gutenberg.php 7 years ago class.jetpack-heartbeat.php 7 years ago class.jetpack-idc.php 8 years ago class.jetpack-ixr-client.php 10 years ago class.jetpack-jitm.php 7 years ago class.jetpack-modules-list-table.php 8 years ago class.jetpack-network-sites-list-table.php 9 years ago class.jetpack-network.php 7 years ago class.jetpack-options.php 7 years ago class.jetpack-post-images.php 7 years ago class.jetpack-signature.php 7 years ago class.jetpack-tracks.php 8 years ago class.jetpack-twitter-cards.php 7 years ago class.jetpack-user-agent.php 8 years ago class.jetpack-xmlrpc-server.php 7 years ago class.jetpack.php 7 years ago class.json-api-endpoints.php 7 years ago class.json-api.php 7 years ago class.photon.php 7 years ago composer.json 7 years ago functions.compat.php 7 years ago functions.gallery.php 8 years ago functions.global.php 7 years ago functions.opengraph.php 7 years ago functions.photon.php 8 years ago jetpack.php 5 years ago json-api-config.php 10 years ago json-endpoints.php 7 years ago locales.php 7 years ago readme.txt 5 years ago require-lib.php 7 years ago uninstall.php 8 years ago wpml-config.xml 10 years ago
class.jetpack-post-images.php
776 lines
1 <?php
2
3 /**
4 * Useful for finding an image to display alongside/in representation of a specific post.
5 *
6 * Includes a few different methods, all of which return a similar-format array containing
7 * details of any images found. Everything can (should) be called statically, it's just a
8 * function-bucket. You can also call Jetpack_PostImages::get_image() to cycle through all of the methods until
9 * one of them finds something useful.
10 *
11 * This file is included verbatim in Jetpack
12 */
13 class Jetpack_PostImages {
14 /**
15 * If a slideshow is embedded within a post, then parse out the images involved and return them
16 */
17 static function from_slideshow( $post_id, $width = 200, $height = 200 ) {
18 $images = array();
19
20 $post = get_post( $post_id );
21
22 if ( ! $post ) {
23 return $images;
24 }
25
26 if ( ! empty( $post->post_password ) ) {
27 return $images;
28 }
29
30 if ( false === has_shortcode( $post->post_content, 'slideshow' ) ) {
31 return $images; // no slideshow - bail
32 }
33
34 $permalink = get_permalink( $post->ID );
35
36 // Mechanic: Somebody set us up the bomb
37 $old_post = $GLOBALS['post'];
38 $GLOBALS['post'] = $post;
39 $old_shortcodes = $GLOBALS['shortcode_tags'];
40 $GLOBALS['shortcode_tags'] = array( 'slideshow' => $old_shortcodes['slideshow'] );
41
42 // Find all the slideshows
43 preg_match_all( '/' . get_shortcode_regex() . '/sx', $post->post_content, $slideshow_matches, PREG_SET_ORDER );
44
45 ob_start(); // The slideshow shortcode handler calls wp_print_scripts and wp_print_styles... not too happy about that
46
47 foreach ( $slideshow_matches as $slideshow_match ) {
48 $slideshow = do_shortcode_tag( $slideshow_match );
49 if ( false === $pos = stripos( $slideshow, 'jetpack-slideshow' ) ) // must be something wrong - or we changed the output format in which case none of the following will work
50 continue;
51 $start = strpos( $slideshow, '[', $pos );
52 $end = strpos( $slideshow, ']', $start );
53 $post_images = json_decode( wp_specialchars_decode( str_replace( "'", '"', substr( $slideshow, $start, $end - $start + 1 ) ), ENT_QUOTES ) ); // parse via JSON
54 // If the JSON didn't decode don't try and act on it.
55 if ( is_array( $post_images ) ) {
56 foreach ( $post_images as $post_image ) {
57 if ( !$post_image_id = absint( $post_image->id ) )
58 continue;
59
60 $meta = wp_get_attachment_metadata( $post_image_id );
61
62 // Must be larger than 200x200 (or user-specified)
63 if ( !isset( $meta['width'] ) || $meta['width'] < $width )
64 continue;
65 if ( !isset( $meta['height'] ) || $meta['height'] < $height )
66 continue;
67
68 $url = wp_get_attachment_url( $post_image_id );
69
70 $images[] = array(
71 'type' => 'image',
72 'from' => 'slideshow',
73 'src' => $url,
74 'src_width' => $meta['width'],
75 'src_height' => $meta['height'],
76 'href' => $permalink,
77 );
78 }
79 }
80 }
81 ob_end_clean();
82
83 // Operator: Main screen turn on
84 $GLOBALS['shortcode_tags'] = $old_shortcodes;
85 $GLOBALS['post'] = $old_post;
86
87 return $images;
88 }
89
90 /**
91 * If a gallery is detected, then get all the images from it.
92 */
93 static function from_gallery( $post_id ) {
94 $images = array();
95
96 $post = get_post( $post_id );
97
98 if ( ! $post ) {
99 return $images;
100 }
101
102 if ( ! empty( $post->post_password ) ) {
103 return $images;
104 }
105
106 $permalink = get_permalink( $post->ID );
107
108 /**
109 * Juggle global post object because the gallery shortcode uses the
110 * global object.
111 *
112 * See core ticket:
113 * https://core.trac.wordpress.org/ticket/39304
114 */
115 if ( isset( $GLOBALS['post'] ) ) {
116 $juggle_post = $GLOBALS['post'];
117 $GLOBALS['post'] = $post;
118 $galleries = get_post_galleries( $post->ID, false );
119 $GLOBALS['post'] = $juggle_post;
120 } else {
121 $GLOBALS['post'] = $post;
122 $galleries = get_post_galleries( $post->ID, false );
123 unset( $GLOBALS['post'] );
124 }
125
126 foreach ( $galleries as $gallery ) {
127 if ( isset( $gallery['type'] ) && 'slideshow' === $gallery['type'] && ! empty( $gallery['ids'] ) ) {
128 $image_ids = explode( ',', $gallery['ids'] );
129 $image_size = isset( $gallery['size'] ) ? $gallery['size'] : 'thumbnail';
130 foreach ( $image_ids as $image_id ) {
131 $image = wp_get_attachment_image_src( $image_id, $image_size );
132 if ( ! empty( $image[0] ) ) {
133 list( $raw_src ) = explode( '?', $image[0] ); // pull off any Query string (?w=250)
134 $raw_src = wp_specialchars_decode( $raw_src ); // rawify it
135 $raw_src = esc_url_raw( $raw_src ); // clean it
136 $images[] = array(
137 'type' => 'image',
138 'from' => 'gallery',
139 'src' => $raw_src,
140 'href' => $permalink,
141 );
142 }
143 }
144 } elseif ( ! empty( $gallery['src'] ) ) {
145 foreach ( $gallery['src'] as $src ) {
146 list( $raw_src ) = explode( '?', $src ); // pull off any Query string (?w=250)
147 $raw_src = wp_specialchars_decode( $raw_src ); // rawify it
148 $raw_src = esc_url_raw( $raw_src ); // clean it
149 $images[] = array(
150 'type' => 'image',
151 'from' => 'gallery',
152 'src' => $raw_src,
153 'href' => $permalink,
154 );
155 }
156 }
157 }
158
159 return $images;
160 }
161
162 /**
163 * Get attachment images for a specified post and return them. Also make sure
164 * their dimensions are at or above a required minimum.
165 */
166 static function from_attachment( $post_id, $width = 200, $height = 200 ) {
167 $images = array();
168
169 $post = get_post( $post_id );
170
171 if ( ! empty( $post->post_password ) ) {
172 return $images;
173 }
174
175 $post_images = get_posts( array(
176 'post_parent' => $post_id, // Must be children of post
177 'numberposts' => 5, // No more than 5
178 'post_type' => 'attachment', // Must be attachments
179 'post_mime_type' => 'image', // Must be images
180 'suppress_filters' => false,
181 ) );
182
183 if ( ! $post_images ) {
184 return $images;
185 }
186
187 $permalink = get_permalink( $post_id );
188
189 foreach ( $post_images as $post_image ) {
190 $current_image = self::get_attachment_data( $post_image->ID, $permalink, $width, $height );
191 if ( false !== $current_image ) {
192 $images[] = $current_image;
193 }
194 }
195
196 /*
197 * We only want to pass back attached images that were actually inserted.
198 * We can load up all the images found in the HTML source and then
199 * compare URLs to see if an image is attached AND inserted.
200 */
201 $html_images = self::from_html( $post_id );
202 $inserted_images = array();
203
204 foreach( $html_images as $html_image ) {
205 $src = parse_url( $html_image['src'] );
206 // strip off any query strings from src
207 if( ! empty( $src['scheme'] ) && ! empty( $src['host'] ) ) {
208 $inserted_images[] = $src['scheme'] . '://' . $src['host'] . $src['path'];
209 } elseif( ! empty( $src['host'] ) ) {
210 $inserted_images[] = set_url_scheme( 'http://' . $src['host'] . $src['path'] );
211 } else {
212 $inserted_images[] = site_url( '/' ) . $src['path'];
213 }
214 }
215 foreach( $images as $i => $image ) {
216 if ( !in_array( $image['src'], $inserted_images ) )
217 unset( $images[$i] );
218 }
219
220 return $images;
221 }
222
223 /**
224 * Check if a Featured Image is set for this post, and return it in a similar
225 * format to the other images?_from_*() methods.
226 * @param int $post_id The post ID to check
227 * @return Array containing details of the Featured Image, or empty array if none.
228 */
229 static function from_thumbnail( $post_id, $width = 200, $height = 200 ) {
230 $images = array();
231
232 $post = get_post( $post_id );
233
234 if ( ! empty( $post->post_password ) ) {
235 return $images;
236 }
237
238 if ( ! function_exists( 'get_post_thumbnail_id' ) ) {
239 return $images;
240 }
241
242 $thumb = get_post_thumbnail_id( $post_id );
243
244 if ( $thumb ) {
245 $meta = wp_get_attachment_metadata( $thumb );
246 // Must be larger than requested minimums
247 if ( !isset( $meta['width'] ) || $meta['width'] < $width )
248 return $images;
249 if ( !isset( $meta['height'] ) || $meta['height'] < $height )
250 return $images;
251
252 $too_big = ( ( ! empty( $meta['width'] ) && $meta['width'] > 1200 ) || ( ! empty( $meta['height'] ) && $meta['height'] > 1200 ) );
253
254 if (
255 $too_big &&
256 (
257 ( method_exists( 'Jetpack', 'is_module_active' ) && Jetpack::is_module_active( 'photon' ) ) ||
258 ( defined( 'IS_WPCOM' ) && IS_WPCOM )
259 )
260 ) {
261 $img_src = wp_get_attachment_image_src( $thumb, array( 1200, 1200 ) );
262 } else {
263 $img_src = wp_get_attachment_image_src( $thumb, 'full' );
264 }
265 if ( ! is_array( $img_src ) ) {
266 // If wp_get_attachment_image_src returns false but we know that there should be an image that could be used.
267 // we try a bit harder and user the data that we have.
268 $thumb_post_data = get_post( $thumb );
269 $img_src = array( $thumb_post_data->guid, $meta['width'], $meta['height'] );
270 }
271
272 $url = $img_src[0];
273 $images = array( array( // Other methods below all return an array of arrays
274 'type' => 'image',
275 'from' => 'thumbnail',
276 'src' => $url,
277 'src_width' => $img_src[1],
278 'src_height' => $img_src[2],
279 'href' => get_permalink( $thumb ),
280 ) );
281
282 }
283
284 if ( empty( $images ) && ( defined( 'IS_WPCOM' ) && IS_WPCOM ) ) {
285 $meta_thumbnail = get_post_meta( $post_id, '_jetpack_post_thumbnail', true );
286 if ( ! empty( $meta_thumbnail ) ) {
287 if ( ! isset( $meta_thumbnail['width'] ) || $meta_thumbnail['width'] < $width ) {
288 return $images;
289 }
290
291 if ( ! isset( $meta_thumbnail['height'] ) || $meta_thumbnail['height'] < $height ) {
292 return $images;
293 }
294
295 $images = array( array( // Other methods below all return an array of arrays
296 'type' => 'image',
297 'from' => 'thumbnail',
298 'src' => $meta_thumbnail['URL'],
299 'src_width' => $meta_thumbnail['width'],
300 'src_height' => $meta_thumbnail['height'],
301 'href' => $meta_thumbnail['URL'],
302 ) );
303 }
304 }
305
306 return $images;
307 }
308
309 /**
310 * Get images from Gutenberg Image blocks.
311 *
312 * @since 6.9.0
313 *
314 * @param mixed $html_or_id The HTML string to parse for images, or a post id.
315 * @param int $width Minimum Image width.
316 * @param int $height Minimum Image height.
317 */
318 public static function from_blocks( $html_or_id, $width = 200, $height = 200 ) {
319 $images = array();
320
321 // Bail early if the site does not support the block editor.
322 if ( ! function_exists( 'parse_blocks' ) ) {
323 return $images;
324 }
325
326 $html_info = self::get_post_html( $html_or_id );
327
328 if ( empty( $html_info['html'] ) ) {
329 return $images;
330 }
331
332 // Look for block information in the HTML.
333 $blocks = parse_blocks( $html_info['html'] );
334 if ( empty( $blocks ) ) {
335 return $images;
336 }
337
338 foreach ( $blocks as $block ) {
339 /**
340 * Parse content from Core Image blocks.
341 * If it is an image block for an image hosted on our site, it will have an ID.
342 * If it does not have an ID, let `from_html` parse that content later,
343 * and extract an image if it has size parameters.
344 */
345 if (
346 'core/image' === $block['blockName']
347 && ! empty( $block['attrs']['id'] )
348 ) {
349 $images[] = self::get_attachment_data( $block['attrs']['id'], $html_info['post_url'], $width, $height );
350 }
351
352 /**
353 * Parse content from Core Gallery blocks and Jetpack's Tiled Gallery blocks.
354 * Gallery blocks include the ID of each one of the images in the gallery.
355 */
356 if (
357 ( 'core/gallery' === $block['blockName'] || 'jetpack/tiled-gallery' === $block['blockName'] )
358 && ! empty( $block['attrs']['ids'] )
359 ) {
360 foreach ( $block['attrs']['ids'] as $img_id ) {
361 $images[] = self::get_attachment_data( $img_id, $html_info['post_url'], $width, $height );
362 }
363 }
364 }
365
366 /**
367 * Returning a filtered array because get_attachment_data returns false
368 * for unsuccessful attempts.
369 */
370 return array_filter( $images );
371 }
372
373 /**
374 * Very raw -- just parse the HTML and pull out any/all img tags and return their src
375 *
376 * @param mixed $html_or_id The HTML string to parse for images, or a post id.
377 * @param int $width Minimum Image width.
378 * @param int $height Minimum Image height.
379 *
380 * @uses DOMDocument
381 *
382 * @return Array containing images
383 */
384 static function from_html( $html_or_id, $width = 200, $height = 200 ) {
385 $images = array();
386
387 $html_info = self::get_post_html( $html_or_id );
388
389 if ( empty( $html_info['html'] ) ) {
390 return $images;
391 }
392
393 // Do not go any further if DOMDocument is disabled on the server.
394 if ( ! class_exists( 'DOMDocument' ) ) {
395 return $images;
396 }
397
398 // Let's grab all image tags from the HTML.
399 $dom_doc = new DOMDocument;
400
401 // The @ is not enough to suppress errors when dealing with libxml,
402 // we have to tell it directly how we want to handle errors.
403 libxml_use_internal_errors( true );
404 @$dom_doc->loadHTML( $html_info['html'] );
405 libxml_use_internal_errors( false );
406
407 $image_tags = $dom_doc->getElementsByTagName( 'img' );
408
409 // For each image Tag, make sure it can be added to the $images array, and add it.
410 foreach ( $image_tags as $image_tag ) {
411 $img_src = $image_tag->getAttribute( 'src' );
412
413 if ( empty( $img_src ) ) {
414 continue;
415 }
416
417 // Do not grab smiley images that were automatically created by WP when entering text smilies.
418 if ( stripos( $img_src, '/smilies/' ) ) {
419 continue;
420 }
421
422 $meta = array(
423 'width' => (int) $image_tag->getAttribute( 'width' ),
424 'height' => (int) $image_tag->getAttribute( 'height' ),
425 );
426
427 /**
428 * Filters the switch to ignore minimum image size requirements. Can be used
429 * to add custom logic to image dimensions, like only enforcing one of the dimensions,
430 * or disabling it entirely.
431 *
432 * @since 6.4.0
433 *
434 * @param bool $ignore Should the image dimensions be ignored?
435 * @param array $meta Array containing image dimensions parsed from the markup.
436 */
437 $ignore_dimensions = apply_filters( 'jetpack_postimages_ignore_minimum_dimensions', false, $meta );
438
439 // Must be larger than 200x200 (or user-specified).
440 if (
441 ! $ignore_dimensions
442 && (
443 empty( $meta['width'] )
444 || empty( $meta['height'] )
445 || $meta['width'] < $width
446 || $meta['height'] < $height
447 )
448 ) {
449 continue;
450 }
451
452 $images[] = array(
453 'type' => 'image',
454 'from' => 'html',
455 'src' => $img_src,
456 'src_width' => $meta['width'],
457 'src_height' => $meta['height'],
458 'href' => $html_info['post_url'],
459 );
460 }
461 return $images;
462 }
463
464 /**
465 * @param int $post_id The post ID to check
466 * @param int $size
467 * @return Array containing details of the image, or empty array if none.
468 */
469 static function from_blavatar( $post_id, $size = 96 ) {
470
471 $permalink = get_permalink( $post_id );
472
473 if ( function_exists( 'blavatar_domain' ) && function_exists( 'blavatar_exists' ) && function_exists( 'blavatar_url' ) ) {
474 $domain = blavatar_domain( $permalink );
475
476 if ( ! blavatar_exists( $domain ) ) {
477 return array();
478 }
479
480 $url = blavatar_url( $domain, 'img', $size );
481 } elseif ( function_exists( 'has_site_icon' ) && has_site_icon() ) {
482 $url = get_site_icon_url( $size );
483 } else {
484 return array();
485 }
486
487 return array( array(
488 'type' => 'image',
489 'from' => 'blavatar',
490 'src' => $url,
491 'src_width' => $size,
492 'src_height' => $size,
493 'href' => $permalink,
494 ) );
495 }
496
497 /**
498 * Gets a post image from the author avatar.
499 *
500 * @param int $post_id The post ID to check.
501 * @param int $size The size of the avatar to get.
502 * @param string $default The default image to use.
503 * @return Array containing details of the image, or empty array if none.
504 */
505 static function from_gravatar( $post_id, $size = 96, $default = false ) {
506 $post = get_post( $post_id );
507 $permalink = get_permalink( $post_id );
508
509 if ( function_exists( 'wpcom_get_avatar_url' ) ) {
510 $url = wpcom_get_avatar_url( $post->post_author, $size, $default, true );
511 if ( $url && is_array( $url ) ) {
512 $url = $url[0];
513 }
514 } else {
515 $url = get_avatar_url( $post->post_author, array(
516 'size' => $size,
517 'default' => $default,
518 ) );
519 }
520
521 return array(
522 array(
523 'type' => 'image',
524 'from' => 'gravatar',
525 'src' => $url,
526 'src_width' => $size,
527 'src_height' => $size,
528 'href' => $permalink,
529 ),
530 );
531 }
532
533 /**
534 * Run through the different methods that we have available to try to find a single good
535 * display image for this post.
536 * @param int $post_id
537 * @param array $args Other arguments (currently width and height required for images where possible to determine)
538 * @return Array containing details of the best image to be used
539 */
540 static function get_image( $post_id, $args = array() ) {
541 $image = '';
542
543 /**
544 * Fires before we find a single good image for a specific post.
545 *
546 * @since 2.2.0
547 *
548 * @param int $post_id Post ID.
549 */
550 do_action( 'jetpack_postimages_pre_get_image', $post_id );
551 $media = self::get_images( $post_id, $args );
552
553
554 if ( is_array( $media ) ) {
555 foreach ( $media as $item ) {
556 if ( 'image' == $item['type'] ) {
557 $image = $item;
558 break;
559 }
560 }
561 }
562
563 /**
564 * Fires after we find a single good image for a specific post.
565 *
566 * @since 2.2.0
567 *
568 * @param int $post_id Post ID.
569 */
570 do_action( 'jetpack_postimages_post_get_image', $post_id );
571
572 return $image;
573 }
574
575 /**
576 * Get an array containing a collection of possible images for this post, stopping once we hit a method
577 * that returns something useful.
578 * @param int $post_id
579 * @param array $args Optional args, see defaults list for details
580 * @return Array containing images that would be good for representing this post
581 */
582 static function get_images( $post_id, $args = array() ) {
583 // Figure out which image to attach to this post.
584 $media = false;
585
586 /**
587 * Filters the array of images that would be good for a specific post.
588 * This filter is applied before options ($args) filter the original array.
589 *
590 * @since 2.0.0
591 *
592 * @param array $media Array of images that would be good for a specific post.
593 * @param int $post_id Post ID.
594 * @param array $args Array of options to get images.
595 */
596 $media = apply_filters( 'jetpack_images_pre_get_images', $media, $post_id, $args );
597 if ( $media )
598 return $media;
599
600 $defaults = array(
601 'width' => 200, // Required minimum width (if possible to determine)
602 'height' => 200, // Required minimum height (if possible to determine)
603
604 'fallback_to_avatars' => false, // Optionally include Blavatar and Gravatar (in that order) in the image stack
605 'avatar_size' => 96, // Used for both Grav and Blav
606 'gravatar_default' => false, // Default image to use if we end up with no Gravatar
607
608 'from_thumbnail' => true, // Use these flags to specify which methods to use to find an image
609 'from_slideshow' => true,
610 'from_gallery' => true,
611 'from_attachment' => true,
612 'from_blocks' => true,
613 'from_html' => true,
614
615 'html_content' => '' // HTML string to pass to from_html()
616 );
617 $args = wp_parse_args( $args, $defaults );
618
619 $media = false;
620 if ( $args['from_thumbnail'] )
621 $media = self::from_thumbnail( $post_id, $args['width'], $args['height'] );
622 if ( !$media && $args['from_slideshow'] )
623 $media = self::from_slideshow( $post_id, $args['width'], $args['height'] );
624 if ( !$media && $args['from_gallery'] )
625 $media = self::from_gallery( $post_id );
626 if ( !$media && $args['from_attachment'] )
627 $media = self::from_attachment( $post_id, $args['width'], $args['height'] );
628 if ( ! $media && $args['from_blocks'] ) {
629 if ( empty( $args['html_content'] ) )
630 $media = self::from_blocks( $post_id, $args['width'], $args['height'] ); // Use the post_id, which will load the content
631 else
632 $media = self::from_blocks( $args['html_content'], $args['width'], $args['height'] ); // If html_content is provided, use that
633 }
634 if ( !$media && $args['from_html'] ) {
635 if ( empty( $args['html_content'] ) )
636 $media = self::from_html( $post_id, $args['width'], $args['height'] ); // Use the post_id, which will load the content
637 else
638 $media = self::from_html( $args['html_content'], $args['width'], $args['height'] ); // If html_content is provided, use that
639 }
640
641 if ( !$media && $args['fallback_to_avatars'] ) {
642 $media = self::from_blavatar( $post_id, $args['avatar_size'] );
643 if ( !$media )
644 $media = self::from_gravatar( $post_id, $args['avatar_size'], $args['gravatar_default'] );
645 }
646
647 /**
648 * Filters the array of images that would be good for a specific post.
649 * This filter is applied after options ($args) filter the original array.
650 *
651 * @since 2.0.0
652 *
653 * @param array $media Array of images that would be good for a specific post.
654 * @param int $post_id Post ID.
655 * @param array $args Array of options to get images.
656 */
657 return apply_filters( 'jetpack_images_get_images', $media, $post_id, $args );
658 }
659
660 /**
661 * Takes an image URL and pixel dimensions then returns a URL for the
662 * resized and cropped image.
663 *
664 * @param string $src
665 * @param int $dimension
666 * @return string Transformed image URL
667 */
668 static function fit_image_url( $src, $width, $height ) {
669 $width = (int) $width;
670 $height = (int) $height;
671
672 if ( $width < 1 || $height < 1 ) {
673 return $src;
674 }
675
676 // See if we should bypass WordPress.com SaaS resizing
677 if ( has_filter( 'jetpack_images_fit_image_url_override' ) ) {
678 /**
679 * Filters the image URL used after dimensions are set by Photon.
680 *
681 * @since 3.3.0
682 *
683 * @param string $src Image URL.
684 * @param int $width Image width.
685 * @param int $width Image height.
686 */
687 return apply_filters( 'jetpack_images_fit_image_url_override', $src, $width, $height );
688 }
689
690 // If WPCOM hosted image use native transformations
691 $img_host = parse_url( $src, PHP_URL_HOST );
692 if ( '.files.wordpress.com' == substr( $img_host, -20 ) ) {
693 return add_query_arg( array( 'w' => $width, 'h' => $height, 'crop' => 1 ), set_url_scheme( $src ) );
694 }
695
696 // Use Photon magic
697 if( function_exists( 'jetpack_photon_url' ) ) {
698 return jetpack_photon_url( $src, array( 'resize' => "$width,$height" ) );
699 }
700
701 // Arg... no way to resize image using WordPress.com infrastructure!
702 return $src;
703 }
704
705 /**
706 * Get HTML from given post content.
707 *
708 * @since 6.9.0
709 *
710 * @param mixed $html_or_id The HTML string to parse for images, or a post id.
711 *
712 * @return array $html_info {
713 * @type string $html Post content.
714 * @type string $post_url Post URL.
715 * }
716 */
717 static function get_post_html( $html_or_id ) {
718 if ( is_numeric( $html_or_id ) ) {
719 $post = get_post( $html_or_id );
720
721 if ( empty( $post ) || ! empty( $post->post_password ) ) {
722 return '';
723 }
724
725 $html_info = array(
726 'html' => $post->post_content, // DO NOT apply the_content filters here, it will cause loops.
727 'post_url' => get_permalink( $post->ID ),
728 );
729 } else {
730 $html_info = array(
731 'html' => $html_or_id,
732 'post_url' => '',
733 );
734 }
735 return $html_info;
736 }
737
738 /**
739 * Get info about a WordPress attachment.
740 *
741 * @since 6.9.0
742 *
743 * @param int $attachment_id Attachment ID.
744 * @param string $post_url URL of the post, if we have one.
745 * @param int $width Minimum Image width.
746 * @param int $height Minimum Image height.
747 * @return array|bool Image data or false if unavailable.
748 */
749 public static function get_attachment_data( $attachment_id, $post_url = '', $width, $height ) {
750 if ( empty( $attachment_id ) ) {
751 return false;
752 }
753
754 $meta = wp_get_attachment_metadata( $attachment_id );
755
756 // The image must be larger than 200x200.
757 if ( ! isset( $meta['width'] ) || $meta['width'] < $width ) {
758 return false;
759 }
760 if ( ! isset( $meta['height'] ) || $meta['height'] < $height ) {
761 return false;
762 }
763
764 $url = wp_get_attachment_url( $attachment_id );
765
766 return array(
767 'type' => 'image',
768 'from' => 'attachment',
769 'src' => $url,
770 'src_width' => $meta['width'],
771 'src_height' => $meta['height'],
772 'href' => $post_url,
773 );
774 }
775 }
776