PluginProbe
Jetpack – WP Security, Backup, Speed, & Growth / 3.6.4
Jetpack – WP Security, Backup, Speed, & Growth v3.6.4
12.0.3 12.1.3 12.2.3 12.3.2 12.4.2 12.5.2 12.6.4 12.7.3 12.8.3 12.9.5 13.0.2 13.1.5 13.2.4 13.3.3 13.4.5 13.5.2 13.6.2 13.7.2 13.8.3 13.9.2 14.0.1 14.1.1 14.2.2 14.3.1 14.4.2 All 500 releases
jetpack / class.photon.php
class.photon.php
620 lines 22.2 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 class Jetpack_Photon {
4 /**
5 * Class variables
6 */
7 // Oh look, a singleton
8 private static $__instance = null;
9
10 // Allowed extensions must match http://code.trac.wordpress.org/browser/photon/index.php#L31
11 protected static $extensions = array(
12 'gif',
13 'jpg',
14 'jpeg',
15 'png'
16 );
17
18 // Don't access this directly. Instead, use self::image_sizes() so it's actually populated with something.
19 protected static $image_sizes = null;
20
21 /**
22 * Singleton implementation
23 *
24 * @return object
25 */
26 public static function instance() {
27 if ( ! is_a( self::$__instance, 'Jetpack_Photon' ) ) {
28 self::$__instance = new Jetpack_Photon;
29 self::$__instance->setup();
30 }
31
32 return self::$__instance;
33 }
34
35 /**
36 * Silence is golden.
37 */
38 private function __construct() {}
39
40 /**
41 * Register actions and filters, but only if basic Photon functions are available.
42 * The basic functions are found in ./functions.photon.php.
43 *
44 * @uses add_action, add_filter
45 * @return null
46 */
47 private function setup() {
48 // Display warning if site is private
49 add_action( 'jetpack_activate_module_photon', array( $this, 'action_jetpack_activate_module_photon' ) );
50
51 if ( ! function_exists( 'jetpack_photon_url' ) )
52 return;
53
54 // Images in post content and galleries
55 add_filter( 'the_content', array( __CLASS__, 'filter_the_content' ), 999999 );
56 add_filter( 'get_post_galleries', array( __CLASS__, 'filter_the_galleries' ), 999999 );
57
58 // Core image retrieval
59 add_filter( 'image_downsize', array( $this, 'filter_image_downsize' ), 10, 3 );
60
61 // Helpers for maniuplated images
62 add_action( 'wp_enqueue_scripts', array( $this, 'action_wp_enqueue_scripts' ), 9 );
63 }
64
65 /**
66 * Check if site is private and warn user if it is
67 *
68 * @uses Jetpack::check_privacy
69 * @action jetpack_activate_module_photon
70 * @return null
71 */
72 public function action_jetpack_activate_module_photon() {
73 Jetpack::check_privacy( __FILE__ );
74 }
75
76 /**
77 ** IN-CONTENT IMAGE MANIPULATION FUNCTIONS
78 **/
79
80 /**
81 * Match all images and any relevant <a> tags in a block of HTML.
82 *
83 * @param string $content Some HTML.
84 * @return array An array of $images matches, where $images[0] is
85 * an array of full matches, and the link_url, img_tag,
86 * and img_url keys are arrays of those matches.
87 */
88 public static function parse_images_from_html( $content ) {
89 $images = array();
90
91 if ( preg_match_all( '#(?:<a[^>]+?href=["|\'](?P<link_url>[^\s]+?)["|\'][^>]*?>\s*)?(?P<img_tag><img[^>]+?src=["|\'](?P<img_url>[^\s]+?)["|\'].*?>){1}(?:\s*</a>)?#is', $content, $images ) ) {
92 foreach ( $images as $key => $unused ) {
93 // Simplify the output as much as possible, mostly for confirming test results.
94 if ( is_numeric( $key ) && $key > 0 )
95 unset( $images[$key] );
96 }
97
98 return $images;
99 }
100
101 return array();
102 }
103
104 /**
105 * Try to determine height and width from strings WP appends to resized image filenames.
106 *
107 * @param string $src The image URL.
108 * @return array An array consisting of width and height.
109 */
110 public static function parse_dimensions_from_filename( $src ) {
111 $width_height_string = array();
112
113 if ( preg_match( '#-(\d+)x(\d+)\.(?:' . implode('|', self::$extensions ) . '){1}$#i', $src, $width_height_string ) ) {
114 $width = (int) $width_height_string[1];
115 $height = (int) $width_height_string[2];
116
117 if ( $width && $height )
118 return array( $width, $height );
119 }
120
121 return array( false, false );
122 }
123
124 /**
125 * Identify images in post content, and if images are local (uploaded to the current site), pass through Photon.
126 *
127 * @param string $content
128 * @uses self::validate_image_url, apply_filters, jetpack_photon_url, esc_url
129 * @filter the_content
130 * @return string
131 */
132 public static function filter_the_content( $content ) {
133 $images = Jetpack_Photon::parse_images_from_html( $content );
134
135 if ( ! empty( $images ) ) {
136 $content_width = Jetpack::get_content_width();
137
138 $image_sizes = self::image_sizes();
139 $upload_dir = wp_upload_dir();
140
141 foreach ( $images[0] as $index => $tag ) {
142 // Default to resize, though fit may be used in certain cases where a dimension cannot be ascertained
143 $transform = 'resize';
144
145 // Start with a clean attachment ID each time
146 $attachment_id = false;
147
148 // Flag if we need to munge a fullsize URL
149 $fullsize_url = false;
150
151 // Identify image source
152 $src = $src_orig = $images['img_url'][ $index ];
153
154 // Allow specific images to be skipped
155 if ( apply_filters( 'jetpack_photon_skip_image', false, $src, $tag ) )
156 continue;
157
158 // Support Automattic's Lazy Load plugin
159 // Can't modify $tag yet as we need unadulterated version later
160 if ( preg_match( '#data-lazy-src=["|\'](.+?)["|\']#i', $images['img_tag'][ $index ], $lazy_load_src ) ) {
161 $placeholder_src = $placeholder_src_orig = $src;
162 $src = $src_orig = $lazy_load_src[1];
163 } elseif ( preg_match( '#data-lazy-original=["|\'](.+?)["|\']#i', $images['img_tag'][ $index ], $lazy_load_src ) ) {
164 $placeholder_src = $placeholder_src_orig = $src;
165 $src = $src_orig = $lazy_load_src[1];
166 }
167
168 // Check if image URL should be used with Photon
169 if ( self::validate_image_url( $src ) ) {
170 // Find the width and height attributes
171 $width = $height = false;
172
173 // First, check the image tag
174 if ( preg_match( '#width=["|\']?([\d%]+)["|\']?#i', $images['img_tag'][ $index ], $width_string ) )
175 $width = $width_string[1];
176
177 if ( preg_match( '#height=["|\']?([\d%]+)["|\']?#i', $images['img_tag'][ $index ], $height_string ) )
178 $height = $height_string[1];
179
180 // Can't pass both a relative width and height, so unset the height in favor of not breaking the horizontal layout.
181 if ( false !== strpos( $width, '%' ) && false !== strpos( $height, '%' ) )
182 $width = $height = false;
183
184 // Detect WP registered image size from HTML class
185 if ( preg_match( '#class=["|\']?[^"\']*size-([^"\'\s]+)[^"\']*["|\']?#i', $images['img_tag'][ $index ], $size ) ) {
186 $size = array_pop( $size );
187
188 if ( false === $width && false === $height && 'full' != $size && array_key_exists( $size, $image_sizes ) ) {
189 $width = (int) $image_sizes[ $size ]['width'];
190 $height = (int) $image_sizes[ $size ]['height'];
191 $transform = $image_sizes[ $size ]['crop'] ? 'resize' : 'fit';
192 }
193 } else {
194 unset( $size );
195 }
196
197 // WP Attachment ID, if uploaded to this site
198 if ( preg_match( '#class=["|\']?[^"\']*wp-image-([\d]+)[^"\']*["|\']?#i', $images['img_tag'][ $index ], $attachment_id ) && ( 0 === strpos( $src, $upload_dir['baseurl'] ) || apply_filters( 'jetpack_photon_image_is_local', false, compact( 'src', 'tag', 'images', 'index' ) ) ) ) {
199 $attachment_id = intval( array_pop( $attachment_id ) );
200
201 if ( $attachment_id ) {
202 $attachment = get_post( $attachment_id );
203
204 // Basic check on returned post object
205 if ( is_object( $attachment ) && ! is_wp_error( $attachment ) && 'attachment' == $attachment->post_type ) {
206 $src_per_wp = wp_get_attachment_image_src( $attachment_id, isset( $size ) ? $size : 'full' );
207
208 if ( self::validate_image_url( $src_per_wp[0] ) ) {
209 $src = $src_per_wp[0];
210 $fullsize_url = true;
211
212 // Prevent image distortion if a detected dimension exceeds the image's natural dimensions
213 if ( ( false !== $width && $width > $src_per_wp[1] ) || ( false !== $height && $height > $src_per_wp[2] ) ) {
214 $width = false == $width ? false : min( $width, $src_per_wp[1] );
215 $height = false == $height ? false : min( $height, $src_per_wp[2] );
216 }
217
218 // If no width and height are found, max out at source image's natural dimensions
219 // Otherwise, respect registered image sizes' cropping setting
220 if ( false == $width && false == $height ) {
221 $width = $src_per_wp[1];
222 $height = $src_per_wp[2];
223 $transform = 'fit';
224 } elseif ( isset( $size ) && array_key_exists( $size, $image_sizes ) && isset( $image_sizes[ $size ]['crop'] ) ) {
225 $transform = (bool) $image_sizes[ $size ]['crop'] ? 'resize' : 'fit';
226 }
227 }
228 } else {
229 unset( $attachment_id );
230 unset( $attachment );
231 }
232 }
233 }
234
235 // If image tag lacks width and height arguments, try to determine from strings WP appends to resized image filenames.
236 if ( false === $width && false === $height ) {
237 list( $width, $height ) = Jetpack_Photon::parse_dimensions_from_filename( $src );
238 }
239
240 // If width is available, constrain to $content_width
241 if ( false !== $width && false === strpos( $width, '%' ) && is_numeric( $content_width ) ) {
242 if ( $width > $content_width && false !== $height && false === strpos( $height, '%' ) ) {
243 $height = round( ( $content_width * $height ) / $width );
244 $width = $content_width;
245 } elseif ( $width > $content_width ) {
246 $width = $content_width;
247 }
248 }
249
250 // Set a width if none is found and $content_width is available
251 // If width is set in this manner and height is available, use `fit` instead of `resize` to prevent skewing
252 if ( false === $width && is_numeric( $content_width ) ) {
253 $width = (int) $content_width;
254
255 if ( false !== $height )
256 $transform = 'fit';
257 }
258
259 // Detect if image source is for a custom-cropped thumbnail and prevent further URL manipulation.
260 if ( ! $fullsize_url && preg_match_all( '#-e[a-z0-9]+(-\d+x\d+)?\.(' . implode('|', self::$extensions ) . '){1}$#i', basename( $src ), $filename ) )
261 $fullsize_url = true;
262
263 // Build URL, first maybe removing WP's resized string so we pass the original image to Photon
264 if ( ! $fullsize_url ) {
265 $src = self::strip_image_dimensions_maybe( $src );
266 }
267
268 // Build array of Photon args and expose to filter before passing to Photon URL function
269 $args = array();
270
271 if ( false !== $width && false !== $height && false === strpos( $width, '%' ) && false === strpos( $height, '%' ) )
272 $args[ $transform ] = $width . ',' . $height;
273 elseif ( false !== $width )
274 $args['w'] = $width;
275 elseif ( false !== $height )
276 $args['h'] = $height;
277
278 $args = apply_filters( 'jetpack_photon_post_image_args', $args, compact( 'tag', 'src', 'src_orig', 'width', 'height' ) );
279
280 $photon_url = jetpack_photon_url( $src, $args );
281
282 // Modify image tag if Photon function provides a URL
283 // Ensure changes are only applied to the current image by copying and modifying the matched tag, then replacing the entire tag with our modified version.
284 if ( $src != $photon_url ) {
285 $new_tag = $tag;
286
287 // If present, replace the link href with a Photoned URL for the full-size image.
288 if ( ! empty( $images['link_url'][ $index ] ) && self::validate_image_url( $images['link_url'][ $index ] ) )
289 $new_tag = preg_replace( '#(href=["|\'])' . $images['link_url'][ $index ] . '(["|\'])#i', '\1' . jetpack_photon_url( $images['link_url'][ $index ] ) . '\2', $new_tag, 1 );
290
291 // Supplant the original source value with our Photon URL
292 $photon_url = esc_url( $photon_url );
293 $new_tag = str_replace( $src_orig, $photon_url, $new_tag );
294
295 // If Lazy Load is in use, pass placeholder image through Photon
296 if ( isset( $placeholder_src ) && self::validate_image_url( $placeholder_src ) ) {
297 $placeholder_src = jetpack_photon_url( $placeholder_src );
298
299 if ( $placeholder_src != $placeholder_src_orig )
300 $new_tag = str_replace( $placeholder_src_orig, esc_url( $placeholder_src ), $new_tag );
301
302 unset( $placeholder_src );
303 }
304
305 // Remove the width and height arguments from the tag to prevent distortion
306 $new_tag = preg_replace( '#(?<=\s)(width|height)=["|\']?[\d%]+["|\']?\s?#i', '', $new_tag );
307
308 // Tag an image for dimension checking
309 $new_tag = preg_replace( '#(\s?/)?>(\s*</a>)?$#i', ' data-recalc-dims="1"\1>\2', $new_tag );
310
311 // Replace original tag with modified version
312 $content = str_replace( $tag, $new_tag, $content );
313 }
314 } elseif ( preg_match( '#^http(s)?://i[\d]{1}.wp.com#', $src ) && ! empty( $images['link_url'][ $index ] ) && self::validate_image_url( $images['link_url'][ $index ] ) ) {
315 $new_tag = preg_replace( '#(href=["|\'])' . $images['link_url'][ $index ] . '(["|\'])#i', '\1' . jetpack_photon_url( $images['link_url'][ $index ] ) . '\2', $tag, 1 );
316
317 $content = str_replace( $tag, $new_tag, $content );
318 }
319 }
320 }
321
322 return $content;
323 }
324
325 public static function filter_the_galleries( $galleries ) {
326 if ( empty( $galleries ) || ! is_array( $galleries ) ) {
327 return $galleries;
328 }
329
330 // Pass by reference, so we can modify them in place.
331 foreach ( $galleries as &$this_gallery ) {
332 if ( is_string( $this_gallery ) ) {
333 $this_gallery = self::filter_the_content( $this_gallery );
334 // LEAVING COMMENTED OUT as for the moment it doesn't seem
335 // necessary and I'm not sure how it would propagate through.
336 // } elseif ( is_array( $this_gallery )
337 // && ! empty( $this_gallery['src'] )
338 // && ! empty( $this_gallery['type'] )
339 // && in_array( $this_gallery['type'], array( 'rectangle', 'square', 'circle' ) ) ) {
340 // $this_gallery['src'] = array_map( 'jetpack_photon_url', $this_gallery['src'] );
341 }
342 }
343 unset( $this_gallery ); // break the reference.
344
345 return $galleries;
346 }
347
348 /**
349 ** CORE IMAGE RETRIEVAL
350 **/
351
352 /**
353 * Filter post thumbnail image retrieval, passing images through Photon
354 *
355 * @param string|bool $image
356 * @param int $attachment_id
357 * @param string|array $size
358 * @uses is_admin, apply_filters, wp_get_attachment_url, self::validate_image_url, this::image_sizes, jetpack_photon_url
359 * @filter image_downsize
360 * @return string|bool
361 */
362 public function filter_image_downsize( $image, $attachment_id, $size ) {
363 // Don't foul up the admin side of things, and provide plugins a way of preventing Photon from being applied to images.
364 if ( is_admin() || apply_filters( 'jetpack_photon_override_image_downsize', false, compact( 'image', 'attachment_id', 'size' ) ) )
365 return $image;
366
367 // Get the image URL and proceed with Photon-ification if successful
368 $image_url = wp_get_attachment_url( $attachment_id );
369
370 if ( $image_url ) {
371 // Check if image URL should be used with Photon
372 if ( ! self::validate_image_url( $image_url ) )
373 return $image;
374
375 // If an image is requested with a size known to WordPress, use that size's settings with Photon
376 if ( ( is_string( $size ) || is_int( $size ) ) && array_key_exists( $size, self::image_sizes() ) ) {
377 $image_args = self::image_sizes();
378 $image_args = $image_args[ $size ];
379
380 $photon_args = array();
381
382 // `full` is a special case in WP
383 // To ensure filter receives consistent data regardless of requested size, `$image_args` is overridden with dimensions of original image.
384 if ( 'full' == $size ) {
385 $image_meta = wp_get_attachment_metadata( $attachment_id );
386 if ( isset( $image_meta['width'], $image_meta['height'] ) ) {
387 // 'crop' is true so Photon's `resize` method is used
388 $image_args = array(
389 'width' => $image_meta['width'],
390 'height' => $image_meta['height'],
391 'crop' => true
392 );
393 }
394 }
395
396 // Expose determined arguments to a filter before passing to Photon
397 $transform = $image_args['crop'] ? 'resize' : 'fit';
398
399 // Check specified image dimensions and account for possible zero values; photon fails to resize if a dimension is zero.
400 if ( 0 == $image_args['width'] || 0 == $image_args['height'] ) {
401 if ( 0 == $image_args['width'] && 0 < $image_args['height'] ) {
402 $photon_args['h'] = $image_args['height'];
403 } elseif ( 0 == $image_args['height'] && 0 < $image_args['width'] ) {
404 $photon_args['w'] = $image_args['width'];
405 }
406 } else {
407 if ( ( 'resize' === $transform ) && $image_meta = wp_get_attachment_metadata( $attachment_id ) ) {
408 // Lets make sure that we don't upscale images since wp never upscales them as well
409 $smaller_width = ( ( $image_meta['width'] < $image_args['width'] ) ? $image_meta['width'] : $image_args['width'] );
410 $smaller_height = ( ( $image_meta['height'] < $image_args['height'] ) ? $image_meta['height'] : $image_args['height'] );
411
412 $photon_args[ $transform ] = $smaller_width . ',' . $smaller_height;
413 } else {
414 $photon_args[ $transform ] = $image_args['width'] . ',' . $image_args['height'];
415 }
416
417 }
418
419 $photon_args = apply_filters( 'jetpack_photon_image_downsize_string', $photon_args, compact( 'image_args', 'image_url', 'attachment_id', 'size', 'transform' ) );
420
421 // Generate Photon URL
422 $image = array(
423 jetpack_photon_url( $image_url, $photon_args ),
424 false,
425 false
426 );
427 } elseif ( is_array( $size ) ) {
428 // Pull width and height values from the provided array, if possible
429 $width = isset( $size[0] ) ? (int) $size[0] : false;
430 $height = isset( $size[1] ) ? (int) $size[1] : false;
431
432 // Don't bother if necessary parameters aren't passed.
433 if ( ! $width || ! $height )
434 return $image;
435
436 // Expose arguments to a filter before passing to Photon
437 $photon_args = array(
438 'fit' => $width . ',' . $height
439 );
440
441 $photon_args = apply_filters( 'jetpack_photon_image_downsize_array', $photon_args, compact( 'width', 'height', 'image_url', 'attachment_id' ) );
442
443 // Generate Photon URL
444 $image = array(
445 jetpack_photon_url( $image_url, $photon_args ),
446 false,
447 false
448 );
449 }
450 }
451
452 return $image;
453 }
454
455 /**
456 ** GENERAL FUNCTIONS
457 **/
458
459 /**
460 * Ensure image URL is valid for Photon.
461 * Though Photon functions address some of the URL issues, we should avoid unnecessary processing if we know early on that the image isn't supported.
462 *
463 * @param string $url
464 * @uses wp_parse_args
465 * @return bool
466 */
467 protected static function validate_image_url( $url ) {
468 $parsed_url = @parse_url( $url );
469
470 if ( ! $parsed_url )
471 return false;
472
473 // Parse URL and ensure needed keys exist, since the array returned by `parse_url` only includes the URL components it finds.
474 $url_info = wp_parse_args( $parsed_url, array(
475 'scheme' => null,
476 'host' => null,
477 'port' => null,
478 'path' => null
479 ) );
480
481 // Bail if scheme isn't http or port is set that isn't port 80
482 if ( ( 'http' != $url_info['scheme'] || ! in_array( $url_info['port'], array( 80, null ) ) ) && apply_filters( 'jetpack_photon_reject_https', true ) )
483 return false;
484
485 // Bail if no host is found
486 if ( is_null( $url_info['host'] ) )
487 return false;
488
489 // Bail if the image alredy went through Photon
490 if ( preg_match( '#^i[\d]{1}.wp.com$#i', $url_info['host'] ) )
491 return false;
492
493 // Bail if no path is found
494 if ( is_null( $url_info['path'] ) )
495 return false;
496
497 // Ensure image extension is acceptable
498 if ( ! in_array( strtolower( pathinfo( $url_info['path'], PATHINFO_EXTENSION ) ), self::$extensions ) )
499 return false;
500
501 // If we got this far, we should have an acceptable image URL
502 // But let folks filter to decline if they prefer.
503 return apply_filters( 'photon_validate_image_url', true, $url, $parsed_url );
504 }
505
506 /**
507 * Checks if the file exists before it passes the file to photon
508 *
509 * @param string $src The image URL
510 * @return string
511 **/
512 protected static function strip_image_dimensions_maybe( $src ){
513 $stripped_src = $src;
514
515 // Build URL, first removing WP's resized string so we pass the original image to Photon
516 if ( preg_match( '#(-\d+x\d+)\.(' . implode('|', self::$extensions ) . '){1}$#i', $src, $src_parts ) ) {
517 $stripped_src = str_replace( $src_parts[1], '', $src );
518 $upload_dir = wp_upload_dir();
519
520 // Extracts the file path to the image minus the base url
521 $file_path = substr( $stripped_src, strlen ( $upload_dir['baseurl'] ) );
522
523 if( file_exists( $upload_dir["basedir"] . $file_path ) )
524 $src = $stripped_src;
525 }
526
527 return $src;
528 }
529
530 /**
531 * Provide an array of available image sizes and corresponding dimensions.
532 * Similar to get_intermediate_image_sizes() except that it includes image sizes' dimensions, not just their names.
533 *
534 * @global $wp_additional_image_sizes
535 * @uses get_option
536 * @return array
537 */
538 protected static function image_sizes() {
539 if ( null == self::$image_sizes ) {
540 global $_wp_additional_image_sizes;
541
542 // Populate an array matching the data structure of $_wp_additional_image_sizes so we have a consistent structure for image sizes
543 $images = array(
544 'thumb' => array(
545 'width' => intval( get_option( 'thumbnail_size_w' ) ),
546 'height' => intval( get_option( 'thumbnail_size_h' ) ),
547 'crop' => (bool) get_option( 'thumbnail_crop' )
548 ),
549 'medium' => array(
550 'width' => intval( get_option( 'medium_size_w' ) ),
551 'height' => intval( get_option( 'medium_size_h' ) ),
552 'crop' => false
553 ),
554 'large' => array(
555 'width' => intval( get_option( 'large_size_w' ) ),
556 'height' => intval( get_option( 'large_size_h' ) ),
557 'crop' => false
558 ),
559 'full' => array(
560 'width' => null,
561 'height' => null,
562 'crop' => false
563 )
564 );
565
566 // Compatibility mapping as found in wp-includes/media.php
567 $images['thumbnail'] = $images['thumb'];
568
569 // Update class variable, merging in $_wp_additional_image_sizes if any are set
570 if ( is_array( $_wp_additional_image_sizes ) && ! empty( $_wp_additional_image_sizes ) )
571 self::$image_sizes = array_merge( $images, $_wp_additional_image_sizes );
572 else
573 self::$image_sizes = $images;
574 }
575
576 return is_array( self::$image_sizes ) ? self::$image_sizes : array();
577 }
578
579 /**
580 * Pass og:image URLs through Photon
581 *
582 * @param array $tags
583 * @param array $parameters
584 * @uses jetpack_photon_url
585 * @return array
586 */
587 function filter_open_graph_tags( $tags, $parameters ) {
588 if ( empty( $tags['og:image'] ) ) {
589 return $tags;
590 }
591
592 $photon_args = array(
593 'fit' => sprintf( '%d,%d', 2 * $parameters['image_width'], 2 * $parameters['image_height'] ),
594 );
595
596 if ( is_array( $tags['og:image'] ) ) {
597 $images = array();
598 foreach ( $tags['og:image'] as $image ) {
599 $images[] = jetpack_photon_url( $image, $photon_args );
600 }
601 $tags['og:image'] = $images;
602 } else {
603 $tags['og:image'] = jetpack_photon_url( $tags['og:image'], $photon_args );
604 }
605
606 return $tags;
607 }
608
609 /**
610 * Enqueue Photon helper script
611 *
612 * @uses wp_enqueue_script, plugins_url
613 * @action wp_enqueue_script
614 * @return null
615 */
616 public function action_wp_enqueue_scripts() {
617 wp_enqueue_script( 'jetpack-photon', plugins_url( 'modules/photon/photon.js', JETPACK__PLUGIN_FILE ), array( 'jquery' ), 20130122, true );
618 }
619 }
620