PluginProbe ʕ •ᴥ•ʔ
Jetpack – WP Security, Backup, Speed, & Growth / 2.9.6
Jetpack – WP Security, Backup, Speed, & Growth v2.9.6
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 10 years ago _inc 10 years ago languages 10 years ago modules 5 years ago views 10 years ago .svnignore 10 years ago class.jetpack-bbpress-json-api-compat.php 10 years ago class.jetpack-cli.php 10 years ago class.jetpack-client-server.php 10 years ago class.jetpack-client.php 10 years ago class.jetpack-data.php 10 years ago class.jetpack-debugger.php 10 years ago class.jetpack-error.php 10 years ago class.jetpack-heartbeat.php 10 years ago class.jetpack-ixr-client.php 10 years ago class.jetpack-network-sites-list-table.php 10 years ago class.jetpack-network.php 10 years ago class.jetpack-options.php 10 years ago class.jetpack-post-images.php 10 years ago class.jetpack-signature.php 10 years ago class.jetpack-sync.php 10 years ago class.jetpack-user-agent.php 10 years ago class.jetpack-xmlrpc-server.php 10 years ago class.jetpack.php 10 years ago class.json-api-endpoints.php 3 years ago class.json-api.php 10 years ago class.media-extractor.php 10 years ago class.media-summary.php 10 years ago class.photon.php 10 years ago composer.json 10 years ago functions.compat.php 10 years ago functions.gallery.php 10 years ago functions.opengraph.php 10 years ago functions.photon.php 10 years ago functions.twitter-cards.php 10 years ago jetpack.php 3 years ago locales.php 10 years ago readme.txt 3 years ago require-lib.php 10 years ago uninstall.php 10 years ago
class.jetpack-post-images.php
485 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 if ( !empty( $post->post_password ) )
22 return $images;
23
24 if ( false === strpos( $post->post_content, '[slideshow' ) )
25 return false; // no slideshow - bail
26
27 $permalink = get_permalink( $post->ID );
28
29 // Mechanic: Somebody set us up the bomb
30 $old_post = $GLOBALS['post'];
31 $GLOBALS['post'] = $post;
32 $old_shortcodes = $GLOBALS['shortcode_tags'];
33 $GLOBALS['shortcode_tags'] = array( 'slideshow' => $old_shortcodes['slideshow'] );
34
35 // Find all the slideshows
36 preg_match_all( '/' . get_shortcode_regex() . '/sx', $post->post_content, $slideshow_matches, PREG_SET_ORDER );
37
38 ob_start(); // The slideshow shortcode handler calls wp_print_scripts and wp_print_styles... not too happy about that
39
40 foreach ( $slideshow_matches as $slideshow_match ) {
41 $slideshow = do_shortcode_tag( $slideshow_match );
42 if ( false === $pos = stripos( $slideshow, 'slideShow.images' ) ) // must be something wrong - or we changed the output format in which case none of the following will work
43 continue;
44 $start = strpos( $slideshow, '[', $pos );
45 $end = strpos( $slideshow, ']', $start );
46 $post_images = json_decode( str_replace( "'", '"', substr( $slideshow, $start, $end - $start + 1 ) ) ); // parse via JSON
47 foreach ( $post_images as $post_image ) {
48 if ( !$post_image_id = absint( $post_image->id ) )
49 continue;
50
51 $meta = wp_get_attachment_metadata( $post_image_id );
52
53 // Must be larger than 200x200 (or user-specified)
54 if ( !isset( $meta['width'] ) || $meta['width'] < $width )
55 continue;
56 if ( !isset( $meta['height'] ) || $meta['height'] < $height )
57 continue;
58
59 $url = wp_get_attachment_url( $post_image_id );
60
61 $images[] = array(
62 'type' => 'image',
63 'from' => 'slideshow',
64 'src' => $url,
65 'src_width' => $meta['width'],
66 'src_height' => $meta['height'],
67 'href' => $permalink,
68 );
69 }
70 }
71 ob_end_clean();
72
73 // Operator: Main screen turn on
74 $GLOBALS['shortcode_tags'] = $old_shortcodes;
75 $GLOBALS['post'] = $old_post;
76
77 return $images;
78 }
79
80 /**
81 * If a gallery is detected, then get all the images from it.
82 */
83 static function from_gallery( $post_id ) {
84 $images = array();
85
86 $post = get_post( $post_id );
87 if ( !empty( $post->post_password ) )
88 return $images;
89
90 if ( false === strpos( $post->post_content, '[gallery' ) )
91 return false; // no gallery - bail
92
93 $permalink = get_permalink( $post->ID );
94
95 // CATS: All your base are belong to us
96 $old_post = $GLOBALS['post'];
97 $GLOBALS['post'] = $post;
98 $old_shortcodes = $GLOBALS['shortcode_tags'];
99 $GLOBALS['shortcode_tags'] = array( 'gallery' => $old_shortcodes['gallery'] );
100
101 // Find all the galleries
102 preg_match_all( '/' . get_shortcode_regex() . '/s', $post->post_content, $gallery_matches, PREG_SET_ORDER );
103
104 foreach ( $gallery_matches as $gallery_match ) {
105 $gallery = do_shortcode_tag( $gallery_match );
106
107 // Um... no images in the gallery - bail
108 if ( false === $pos = stripos( $gallery, '<img' ) )
109 continue;
110
111 preg_match_all( '/<img\s+[^>]*src=([\'"])([^\'"]*)\\1/', $gallery, $image_match, PREG_PATTERN_ORDER | PREG_OFFSET_CAPTURE );
112
113 $a_pos = 0;
114 foreach ( $image_match[2] as $src ) {
115 list( $raw_src ) = explode( '?', $src[0] ); // pull off any Query string (?w=250)
116 $raw_src = wp_specialchars_decode( $raw_src ); // rawify it
117 $raw_src = esc_url_raw( $raw_src ); // clean it
118
119 $a_pos = strrpos( substr( $gallery, 0, $src[1] ), '<a', $a_pos ); // is there surrounding <a>?
120
121 if ( false !== $a_pos && preg_match( '/<a\s+[^>]*href=([\'"])([^\'"]*)\\1/', $gallery, $href_match, 0, $a_pos ) ) {
122 $href = wp_specialchars_decode( $href_match[2] );
123 $href = esc_url_raw( $href );
124 } else {
125 // CATS: You have no chance to survive make your time
126 $href = $raw_src;
127 }
128
129 $a_pos = $src[1];
130
131 $images[] = array(
132 'type' => 'image',
133 'from' => 'gallery',
134 'src' => $raw_src,
135 'href' => $permalink, // $href,
136 );
137 }
138 }
139
140 // Captain: For great justice
141 $GLOBALS['shortcode_tags'] = $old_shortcodes;
142 $GLOBALS['post'] = $old_post;
143
144 return $images;
145 }
146
147 /**
148 * Get attachment images for a specified post and return them. Also make sure
149 * their dimensions are at or above a required minimum.
150 */
151 static function from_attachment( $post_id, $width = 200, $height = 200 ) {
152 $images = array();
153
154 $post = get_post( $post_id );
155 if ( !empty( $post->post_password ) )
156 return $images;
157
158 $post_images = get_posts( array(
159 'post_parent' => $post_id, // Must be children of post
160 'numberposts' => 5, // No more than 5
161 'post_type' => 'attachment', // Must be attachments
162 'post_mime_type' => 'image', // Must be images
163 ) );
164
165 if ( !$post_images )
166 return false;
167
168 $permalink = get_permalink( $post_id );
169
170 foreach ( $post_images as $post_image ) {
171 $meta = wp_get_attachment_metadata( $post_image->ID );
172 // Must be larger than 200x200
173 if ( !isset( $meta['width'] ) || $meta['width'] < $width )
174 continue;
175 if ( !isset( $meta['height'] ) || $meta['height'] < $height )
176 continue;
177
178 $url = wp_get_attachment_url( $post_image->ID );
179
180 $images[] = array(
181 'type' => 'image',
182 'from' => 'attachment',
183 'src' => $url,
184 'src_width' => $meta['width'],
185 'src_height' => $meta['height'],
186 'href' => $permalink,
187 );
188 }
189
190 /*
191 * We only want to pass back attached images that were actually inserted.
192 * We can load up all the images found in the HTML source and then
193 * compare URLs to see if an image is attached AND inserted.
194 */
195 $html_images = array();
196 $html_images = self::from_html( $post_id );
197 $inserted_images = array();
198
199 foreach( $html_images as $html_image ) {
200 $src = parse_url( $html_image['src'] );
201 $inserted_images[] = $src['scheme'] . '://' . $src['host'] . $src['path']; // strip off any query strings
202 }
203 foreach( $images as $i => $image ) {
204 if ( !in_array( $image['src'], $inserted_images ) )
205 unset( $images[$i] );
206 }
207
208 return $images;
209 }
210
211 /**
212 * Check if a Featured Image is set for this post, and return it in a similar
213 * format to the other images?_from_*() methods.
214 * @param int $post_id The post ID to check
215 * @return Array containing details of the Featured Image, or empty array if none.
216 */
217 static function from_thumbnail( $post_id, $width = 200, $height = 200 ) {
218 $images = array();
219
220 $post = get_post( $post_id );
221 if ( !empty( $post->post_password ) )
222 return $images;
223
224 if ( !function_exists( 'get_post_thumbnail_id' ) )
225 return $images;
226
227 $thumb = get_post_thumbnail_id( $post_id );
228
229 if ( $thumb ) {
230 $meta = wp_get_attachment_metadata( $thumb );
231
232 // Must be larger than requested minimums
233 if ( !isset( $meta['width'] ) || $meta['width'] < $width )
234 return $images;
235 if ( !isset( $meta['height'] ) || $meta['height'] < $height )
236 return $images;
237
238 $url = wp_get_attachment_url( $thumb );
239 if ( stristr( $url, '?' ) )
240 $url = substr( $url, 0, strpos( $url, '?' ) );
241
242 $images = array( array( // Other methods below all return an array of arrays
243 'type' => 'image',
244 'from' => 'thumbnail',
245 'src' => $url,
246 'src_width' => $meta['width'],
247 'src_height' => $meta['height'],
248 'href' => get_permalink( $thumb ),
249 ) );
250 }
251 return $images;
252 }
253
254 /**
255 * Very raw -- just parse the HTML and pull out any/all img tags and return their src
256 * @param mixed $html_or_id The HTML string to parse for images, or a post id
257 * @return Array containing images
258 */
259 static function from_html( $html_or_id ) {
260 $images = array();
261
262 if ( is_numeric( $html_or_id ) ) {
263 $post = get_post( $html_or_id );
264 if ( empty( $post ) || !empty( $post->post_password ) )
265 return $images;
266
267 $html = $post->post_content; // DO NOT apply the_content filters here, it will cause loops
268 } else {
269 $html = $html_or_id;
270 }
271
272 if ( !$html )
273 return $images;
274
275 preg_match_all( '!<img.*src=[\'"]([^"]+)[\'"].*/?>!iUs', $html, $matches );
276 if ( !empty( $matches[1] ) ) {
277 foreach ( $matches[1] as $match ) {
278 if ( stristr( $match, '/smilies/' ) )
279 continue;
280
281 $images[] = array(
282 'type' => 'image',
283 'from' => 'html',
284 'src' => html_entity_decode( $match ),
285 'href' => '', // No link to apply to these. Might potentially parse for that as well, but not for now
286 );
287 }
288 }
289
290 return $images;
291 }
292
293 /**
294 * @param int $post_id The post ID to check
295 * @param int $size
296 * @return Array containing details of the image, or empty array if none.
297 */
298 static function from_blavatar( $post_id, $size = 96 ) {
299 if ( !function_exists( 'blavatar_domain' ) || !function_exists( 'blavatar_exists' ) || !function_exists( 'blavatar_url' ) ) {
300 return array();
301 }
302
303 $permalink = get_permalink( $post_id );
304 $domain = blavatar_domain( $permalink );
305
306 if ( !blavatar_exists( $domain ) ) {
307 return array();
308 }
309
310 $url = blavatar_url( $domain, 'img', $size );
311
312 return array( array(
313 'type' => 'image',
314 'from' => 'blavatar',
315 'src' => $url,
316 'src_width' => $size,
317 'src_height' => $size,
318 'href' => $permalink,
319 ) );
320 }
321
322 /**
323 * @param int $post_id The post ID to check
324 * @param int $size
325 * @param string $default The default image to use.
326 * @return Array containing details of the image, or empty array if none.
327 */
328 static function from_gravatar( $post_id, $size = 96, $default = false ) {
329 $post = get_post( $post_id );
330 $permalink = get_permalink( $post_id );
331
332 if ( function_exists( 'get_avatar_url' ) ) {
333 $url = get_avatar_url( $post->post_author, $size, $default, true );
334 if ( $url && is_array( $url ) ) {
335 $url = $url[0];
336 }
337 } else {
338 $has_filter = has_filter( 'pre_option_show_avatars', '__return_true' );
339 if ( !$has_filter ) {
340 add_filter( 'pre_option_show_avatars', '__return_true' );
341 }
342 $avatar = get_avatar( $post->post_author, $size, $default );
343 if ( !$has_filter ) {
344 remove_filter( 'pre_option_show_avatars', '__return_true' );
345 }
346
347 if ( !$avatar ) {
348 return array();
349 }
350
351 if ( !preg_match( '/src=["\']([^"\']+)["\']/', $avatar, $matches ) ) {
352 return array();
353 }
354
355 $url = wp_specialchars_decode( $matches[1], ENT_QUOTES );
356 }
357
358 return array( array(
359 'type' => 'image',
360 'from' => 'gravatar',
361 'src' => $url,
362 'src_width' => $size,
363 'src_height' => $size,
364 'href' => $permalink,
365 ) );
366 }
367
368 /**
369 * Run through the different methods that we have available to try to find a single good
370 * display image for this post.
371 * @param int $post_id
372 * @param array $args Other arguments (currently width and height required for images where possible to determine)
373 * @return Array containing details of the best image to be used
374 */
375 static function get_image( $post_id, $args = array() ) {
376 $image = '';
377 do_action( 'jetpack_postimages_pre_get_image', $post_id );
378 $media = self::get_images( $post_id, $args );
379
380
381 if ( is_array( $media ) ) {
382 foreach ( $media as $item ) {
383 if ( 'image' == $item['type'] ) {
384 $image = $item;
385 break;
386 }
387 }
388 }
389
390 do_action( 'jetpack_postimages_post_get_image', $post_id );
391
392 return $image;
393 }
394
395 /**
396 * Get an array containing a collection of possible images for this post, stopping once we hit a method
397 * that returns something useful.
398 * @param int $post_id
399 * @param array $args Optional args, see defaults list for details
400 * @return Array containing images that would be good for representing this post
401 */
402 static function get_images( $post_id, $args = array() ) {
403 // Figure out which image to attach to this post.
404 $media = false;
405
406 $media = apply_filters( 'jetpack_images_pre_get_images', $media, $post_id, $args );
407 if ( $media )
408 return $media;
409
410 $defaults = array(
411 'width' => 200, // Required minimum width (if possible to determine)
412 'height' => 200, // Required minimum height (if possible to determine)
413
414 'fallback_to_avatars' => false, // Optionally include Blavatar and Gravatar (in that order) in the image stack
415 'avatar_size' => 96, // Used for both Grav and Blav
416 'gravatar_default' => false, // Default image to use if we end up with no Gravatar
417
418 'from_thumbnail' => true, // Use these flags to specifcy which methods to use to find an image
419 'from_slideshow' => true,
420 'from_gallery' => true,
421 'from_attachment' => true,
422 'from_html' => true,
423
424 'html_content' => '' // HTML string to pass to from_html()
425 );
426 $args = wp_parse_args( $args, $defaults );
427
428 $media = false;
429 if ( $args['from_thumbnail'] )
430 $media = self::from_thumbnail( $post_id, $args['width'], $args['height'] );
431 if ( !$media && $args['from_slideshow'] )
432 $media = self::from_slideshow( $post_id, $args['width'], $args['height'] );
433 if ( !$media && $args['from_gallery'] )
434 $media = self::from_gallery( $post_id );
435 if ( !$media && $args['from_attachment'] )
436 $media = self::from_attachment( $post_id, $args['width'], $args['height'] );
437 if ( !$media && $args['from_html'] ) {
438 if ( empty( $args['html_content'] ) )
439 $media = self::from_html( $post_id ); // Use the post_id, which will load the content
440 else
441 $media = self::from_html( $args['html_content'] ); // If html_content is provided, use that
442 }
443
444 if ( !$media && $args['fallback_to_avatars'] ) {
445 $media = self::from_blavatar( $post_id, $args['avatar_size'] );
446 if ( !$media )
447 $media = self::from_gravatar( $post_id, $args['avatar_size'], $args['gravatar_default'] );
448 }
449
450 return apply_filters( 'jetpack_images_get_images', $media, $post_id, $args );
451 }
452
453 /**
454 * Takes an image URL and pixel dimensions then returns a URL for the
455 * resized and croped image.
456 *
457 * @param string $src
458 * @param int $dimension
459 * @return string Transformed image URL
460 */
461 static function fit_image_url( $src, $width, $height ) {
462 $width = (int) $width;
463 $height = (int) $height;
464
465 // Umm...
466 if ( $width < 1 || $height < 1 ) {
467 return $src;
468 }
469
470 // If WPCOM hosted image use native transformations
471 $img_host = parse_url( $src, PHP_URL_HOST );
472 if ( '.files.wordpress.com' == substr( $img_host, -20 ) ) {
473 return add_query_arg( array( 'w' => $width, 'h' => $height, 'crop' => 1 ), $src );
474 }
475
476 // Use Photon magic
477 if( function_exists( 'jetpack_photon_url' ) ) {
478 return jetpack_photon_url( $src, array( 'resize' => "$width,$height" ) );
479 }
480
481 // Arg... no way to resize image using WordPress.com infrastructure!
482 return $src;
483 }
484 }
485