PluginProbe ʕ •ᴥ•ʔ
Jetpack – WP Security, Backup, Speed, & Growth / 7.4.1
Jetpack – WP Security, Backup, Speed, & Growth v7.4.1
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 6 years ago css 7 years ago extensions 6 years ago images 7 years ago json-endpoints 7 years ago languages 6 years ago logs 9 years ago modules 6 years ago sal 7 years ago scss 7 years ago sync 7 years ago vendor 6 years ago views 7 years ago wp-cli-templates 7 years ago .svnignore 12 years ago CODE-OF-CONDUCT.md 9 years ago changelog.txt 6 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 7 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 6 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 7 years ago class.jetpack-ixr-client.php 10 years ago class.jetpack-jitm.php 7 years ago class.jetpack-modules-list-table.php 7 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-plan.php 7 years ago class.jetpack-post-images.php 7 years ago class.jetpack-signature.php 7 years ago class.jetpack-tracks.php 7 years ago class.jetpack-twitter-cards.php 7 years ago class.jetpack-user-agent.php 7 years ago class.jetpack-xmlrpc-server.php 7 years ago class.jetpack.php 6 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 6 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 7 years ago jest.config.js 7 years ago jetpack.php 6 years ago json-api-config.php 10 years ago json-endpoints.php 7 years ago locales.php 7 years ago readme.txt 6 years ago require-lib.php 7 years ago uninstall.php 7 years ago wpml-config.xml 10 years ago
class.jetpack-post-images.php
790 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 ( 'attachment' === get_post_type( $post ) && wp_attachment_is_image( $post ) ) {
239 $thumb = $post_id;
240 } else {
241 $thumb = get_post_thumbnail_id( $post );
242 }
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 'alt_text' => self::get_alt_text( $thumb ),
281 ) );
282
283 }
284
285 if ( empty( $images ) && ( defined( 'IS_WPCOM' ) && IS_WPCOM ) ) {
286 $meta_thumbnail = get_post_meta( $post_id, '_jetpack_post_thumbnail', true );
287 if ( ! empty( $meta_thumbnail ) ) {
288 if ( ! isset( $meta_thumbnail['width'] ) || $meta_thumbnail['width'] < $width ) {
289 return $images;
290 }
291
292 if ( ! isset( $meta_thumbnail['height'] ) || $meta_thumbnail['height'] < $height ) {
293 return $images;
294 }
295
296 $images = array( array( // Other methods below all return an array of arrays
297 'type' => 'image',
298 'from' => 'thumbnail',
299 'src' => $meta_thumbnail['URL'],
300 'src_width' => $meta_thumbnail['width'],
301 'src_height' => $meta_thumbnail['height'],
302 'href' => $meta_thumbnail['URL'],
303 'alt_text' => self::get_alt_text( $thumb ),
304 ) );
305 }
306 }
307
308 return $images;
309 }
310
311 /**
312 * Get images from Gutenberg Image blocks.
313 *
314 * @since 6.9.0
315 *
316 * @param mixed $html_or_id The HTML string to parse for images, or a post id.
317 * @param int $width Minimum Image width.
318 * @param int $height Minimum Image height.
319 */
320 public static function from_blocks( $html_or_id, $width = 200, $height = 200 ) {
321 $images = array();
322
323 $html_info = self::get_post_html( $html_or_id );
324
325 if ( empty( $html_info['html'] ) ) {
326 return $images;
327 }
328
329 // Look for block information in the HTML.
330 $blocks = parse_blocks( $html_info['html'] );
331 if ( empty( $blocks ) ) {
332 return $images;
333 }
334
335 foreach ( $blocks as $block ) {
336 /**
337 * Parse content from Core Image blocks.
338 * If it is an image block for an image hosted on our site, it will have an ID.
339 * If it does not have an ID, let `from_html` parse that content later,
340 * and extract an image if it has size parameters.
341 */
342 if (
343 'core/image' === $block['blockName']
344 && ! empty( $block['attrs']['id'] )
345 ) {
346 $images[] = self::get_attachment_data( $block['attrs']['id'], $html_info['post_url'], $width, $height );
347 }
348
349 /**
350 * Parse content from Core Gallery blocks as well from Jetpack's Tiled Gallery and Slideshow blocks.
351 * Gallery blocks include the ID of each one of the images in the gallery.
352 */
353 if ( in_array( $block['blockName'], array( 'core/gallery', 'jetpack/tiled-gallery', 'jetpack/slideshow' ) )
354 && ! empty( $block['attrs']['ids'] )
355 ) {
356 foreach ( $block['attrs']['ids'] as $img_id ) {
357 $images[] = self::get_attachment_data( $img_id, $html_info['post_url'], $width, $height );
358 }
359 }
360 }
361
362 /**
363 * Returning a filtered array because get_attachment_data returns false
364 * for unsuccessful attempts.
365 */
366 return array_filter( $images );
367 }
368
369 /**
370 * Very raw -- just parse the HTML and pull out any/all img tags and return their src
371 *
372 * @param mixed $html_or_id The HTML string to parse for images, or a post id.
373 * @param int $width Minimum Image width.
374 * @param int $height Minimum Image height.
375 *
376 * @uses DOMDocument
377 *
378 * @return Array containing images
379 */
380 static function from_html( $html_or_id, $width = 200, $height = 200 ) {
381 $images = array();
382
383 $html_info = self::get_post_html( $html_or_id );
384
385 if ( empty( $html_info['html'] ) ) {
386 return $images;
387 }
388
389 // Do not go any further if DOMDocument is disabled on the server.
390 if ( ! class_exists( 'DOMDocument' ) ) {
391 return $images;
392 }
393
394 // Let's grab all image tags from the HTML.
395 $dom_doc = new DOMDocument;
396
397 // The @ is not enough to suppress errors when dealing with libxml,
398 // we have to tell it directly how we want to handle errors.
399 libxml_use_internal_errors( true );
400 @$dom_doc->loadHTML( $html_info['html'] );
401 libxml_use_internal_errors( false );
402
403 $image_tags = $dom_doc->getElementsByTagName( 'img' );
404
405 // For each image Tag, make sure it can be added to the $images array, and add it.
406 foreach ( $image_tags as $image_tag ) {
407 $img_src = $image_tag->getAttribute( 'src' );
408
409 if ( empty( $img_src ) ) {
410 continue;
411 }
412
413 // Do not grab smiley images that were automatically created by WP when entering text smilies.
414 if ( stripos( $img_src, '/smilies/' ) ) {
415 continue;
416 }
417
418 $meta = array(
419 'width' => (int) $image_tag->getAttribute( 'width' ),
420 'height' => (int) $image_tag->getAttribute( 'height' ),
421 'alt_text' => $image_tag->getAttribute( 'alt' ),
422 );
423
424 /**
425 * Filters the switch to ignore minimum image size requirements. Can be used
426 * to add custom logic to image dimensions, like only enforcing one of the dimensions,
427 * or disabling it entirely.
428 *
429 * @since 6.4.0
430 *
431 * @param bool $ignore Should the image dimensions be ignored?
432 * @param array $meta Array containing image dimensions parsed from the markup.
433 */
434 $ignore_dimensions = apply_filters( 'jetpack_postimages_ignore_minimum_dimensions', false, $meta );
435
436 // Must be larger than 200x200 (or user-specified).
437 if (
438 ! $ignore_dimensions
439 && (
440 empty( $meta['width'] )
441 || empty( $meta['height'] )
442 || $meta['width'] < $width
443 || $meta['height'] < $height
444 )
445 ) {
446 continue;
447 }
448
449 $images[] = array(
450 'type' => 'image',
451 'from' => 'html',
452 'src' => $img_src,
453 'src_width' => $meta['width'],
454 'src_height' => $meta['height'],
455 'href' => $html_info['post_url'],
456 'alt_text' => $meta['alt_text'],
457 );
458 }
459 return $images;
460 }
461
462 /**
463 * @param int $post_id The post ID to check
464 * @param int $size
465 * @return Array containing details of the image, or empty array if none.
466 */
467 static function from_blavatar( $post_id, $size = 96 ) {
468
469 $permalink = get_permalink( $post_id );
470
471 if ( function_exists( 'blavatar_domain' ) && function_exists( 'blavatar_exists' ) && function_exists( 'blavatar_url' ) ) {
472 $domain = blavatar_domain( $permalink );
473
474 if ( ! blavatar_exists( $domain ) ) {
475 return array();
476 }
477
478 $url = blavatar_url( $domain, 'img', $size );
479 } else {
480 $url = get_site_icon_url( $size );
481 if ( ! $url ) {
482 return array();
483 }
484 }
485
486 return array( array(
487 'type' => 'image',
488 'from' => 'blavatar',
489 'src' => $url,
490 'src_width' => $size,
491 'src_height' => $size,
492 'href' => $permalink,
493 'alt_text' => '',
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 'alt_text' => '',
530 ),
531 );
532 }
533
534 /**
535 * Run through the different methods that we have available to try to find a single good
536 * display image for this post.
537 * @param int $post_id
538 * @param array $args Other arguments (currently width and height required for images where possible to determine)
539 * @return Array containing details of the best image to be used
540 */
541 static function get_image( $post_id, $args = array() ) {
542 $image = '';
543
544 /**
545 * Fires before we find a single good image for a specific post.
546 *
547 * @since 2.2.0
548 *
549 * @param int $post_id Post ID.
550 */
551 do_action( 'jetpack_postimages_pre_get_image', $post_id );
552 $media = self::get_images( $post_id, $args );
553
554
555 if ( is_array( $media ) ) {
556 foreach ( $media as $item ) {
557 if ( 'image' == $item['type'] ) {
558 $image = $item;
559 break;
560 }
561 }
562 }
563
564 /**
565 * Fires after we find a single good image for a specific post.
566 *
567 * @since 2.2.0
568 *
569 * @param int $post_id Post ID.
570 */
571 do_action( 'jetpack_postimages_post_get_image', $post_id );
572
573 return $image;
574 }
575
576 /**
577 * Get an array containing a collection of possible images for this post, stopping once we hit a method
578 * that returns something useful.
579 * @param int $post_id
580 * @param array $args Optional args, see defaults list for details
581 * @return Array containing images that would be good for representing this post
582 */
583 static function get_images( $post_id, $args = array() ) {
584 // Figure out which image to attach to this post.
585 $media = false;
586
587 /**
588 * Filters the array of images that would be good for a specific post.
589 * This filter is applied before options ($args) filter the original array.
590 *
591 * @since 2.0.0
592 *
593 * @param array $media Array of images that would be good for a specific post.
594 * @param int $post_id Post ID.
595 * @param array $args Array of options to get images.
596 */
597 $media = apply_filters( 'jetpack_images_pre_get_images', $media, $post_id, $args );
598 if ( $media )
599 return $media;
600
601 $defaults = array(
602 'width' => 200, // Required minimum width (if possible to determine)
603 'height' => 200, // Required minimum height (if possible to determine)
604
605 'fallback_to_avatars' => false, // Optionally include Blavatar and Gravatar (in that order) in the image stack
606 'avatar_size' => 96, // Used for both Grav and Blav
607 'gravatar_default' => false, // Default image to use if we end up with no Gravatar
608
609 'from_thumbnail' => true, // Use these flags to specify which methods to use to find an image
610 'from_slideshow' => true,
611 'from_gallery' => true,
612 'from_attachment' => true,
613 'from_blocks' => true,
614 'from_html' => true,
615
616 'html_content' => '' // HTML string to pass to from_html()
617 );
618 $args = wp_parse_args( $args, $defaults );
619
620 $media = false;
621 if ( $args['from_thumbnail'] )
622 $media = self::from_thumbnail( $post_id, $args['width'], $args['height'] );
623 if ( !$media && $args['from_slideshow'] )
624 $media = self::from_slideshow( $post_id, $args['width'], $args['height'] );
625 if ( !$media && $args['from_gallery'] )
626 $media = self::from_gallery( $post_id );
627 if ( !$media && $args['from_attachment'] )
628 $media = self::from_attachment( $post_id, $args['width'], $args['height'] );
629 if ( ! $media && $args['from_blocks'] ) {
630 if ( empty( $args['html_content'] ) )
631 $media = self::from_blocks( $post_id, $args['width'], $args['height'] ); // Use the post_id, which will load the content
632 else
633 $media = self::from_blocks( $args['html_content'], $args['width'], $args['height'] ); // If html_content is provided, use that
634 }
635 if ( !$media && $args['from_html'] ) {
636 if ( empty( $args['html_content'] ) )
637 $media = self::from_html( $post_id, $args['width'], $args['height'] ); // Use the post_id, which will load the content
638 else
639 $media = self::from_html( $args['html_content'], $args['width'], $args['height'] ); // If html_content is provided, use that
640 }
641
642 if ( !$media && $args['fallback_to_avatars'] ) {
643 $media = self::from_blavatar( $post_id, $args['avatar_size'] );
644 if ( !$media )
645 $media = self::from_gravatar( $post_id, $args['avatar_size'], $args['gravatar_default'] );
646 }
647
648 /**
649 * Filters the array of images that would be good for a specific post.
650 * This filter is applied after options ($args) filter the original array.
651 *
652 * @since 2.0.0
653 *
654 * @param array $media Array of images that would be good for a specific post.
655 * @param int $post_id Post ID.
656 * @param array $args Array of options to get images.
657 */
658 return apply_filters( 'jetpack_images_get_images', $media, $post_id, $args );
659 }
660
661 /**
662 * Takes an image URL and pixel dimensions then returns a URL for the
663 * resized and cropped image.
664 *
665 * @param string $src
666 * @param int $dimension
667 * @return string Transformed image URL
668 */
669 static function fit_image_url( $src, $width, $height ) {
670 $width = (int) $width;
671 $height = (int) $height;
672
673 if ( $width < 1 || $height < 1 ) {
674 return $src;
675 }
676
677 // See if we should bypass WordPress.com SaaS resizing
678 if ( has_filter( 'jetpack_images_fit_image_url_override' ) ) {
679 /**
680 * Filters the image URL used after dimensions are set by Photon.
681 *
682 * @since 3.3.0
683 *
684 * @param string $src Image URL.
685 * @param int $width Image width.
686 * @param int $width Image height.
687 */
688 return apply_filters( 'jetpack_images_fit_image_url_override', $src, $width, $height );
689 }
690
691 // If WPCOM hosted image use native transformations
692 $img_host = parse_url( $src, PHP_URL_HOST );
693 if ( '.files.wordpress.com' == substr( $img_host, -20 ) ) {
694 return add_query_arg( array( 'w' => $width, 'h' => $height, 'crop' => 1 ), set_url_scheme( $src ) );
695 }
696
697 // Use Photon magic
698 if( function_exists( 'jetpack_photon_url' ) ) {
699 return jetpack_photon_url( $src, array( 'resize' => "$width,$height" ) );
700 }
701
702 // Arg... no way to resize image using WordPress.com infrastructure!
703 return $src;
704 }
705
706 /**
707 * Get HTML from given post content.
708 *
709 * @since 6.9.0
710 *
711 * @param mixed $html_or_id The HTML string to parse for images, or a post id.
712 *
713 * @return array $html_info {
714 * @type string $html Post content.
715 * @type string $post_url Post URL.
716 * }
717 */
718 static function get_post_html( $html_or_id ) {
719 if ( is_numeric( $html_or_id ) ) {
720 $post = get_post( $html_or_id );
721
722 if ( empty( $post ) || ! empty( $post->post_password ) ) {
723 return '';
724 }
725
726 $html_info = array(
727 'html' => $post->post_content, // DO NOT apply the_content filters here, it will cause loops.
728 'post_url' => get_permalink( $post->ID ),
729 );
730 } else {
731 $html_info = array(
732 'html' => $html_or_id,
733 'post_url' => '',
734 );
735 }
736 return $html_info;
737 }
738
739 /**
740 * Get info about a WordPress attachment.
741 *
742 * @since 6.9.0
743 *
744 * @param int $attachment_id Attachment ID.
745 * @param string $post_url URL of the post, if we have one.
746 * @param int $width Minimum Image width.
747 * @param int $height Minimum Image height.
748 * @return array|bool Image data or false if unavailable.
749 */
750 public static function get_attachment_data( $attachment_id, $post_url = '', $width, $height ) {
751 if ( empty( $attachment_id ) ) {
752 return false;
753 }
754
755 $meta = wp_get_attachment_metadata( $attachment_id );
756
757 // The image must be larger than 200x200.
758 if ( ! isset( $meta['width'] ) || $meta['width'] < $width ) {
759 return false;
760 }
761 if ( ! isset( $meta['height'] ) || $meta['height'] < $height ) {
762 return false;
763 }
764
765 $url = wp_get_attachment_url( $attachment_id );
766
767 return array(
768 'type' => 'image',
769 'from' => 'attachment',
770 'src' => $url,
771 'src_width' => $meta['width'],
772 'src_height' => $meta['height'],
773 'href' => $post_url,
774 'alt_text' => self::get_alt_text( $attachment_id ),
775 );
776 }
777
778 /**
779 * Get the alt text for an image or other media from the Media Library.
780 *
781 * @since 7.1
782 *
783 * @param int $attachment_id The Post ID of the media.
784 * @return string The alt text value or an emptry string.
785 */
786 public static function get_alt_text( $attachment_id ) {
787 return get_post_meta( $attachment_id, '_wp_attachment_image_alt', true );
788 }
789 }
790