Completed
Push — add/pwa ( fb0784...7de71e )
by
unknown
34:56 queued 26:22
created

Jetpack_Lazy_Images::process_image()   B

Complexity

Conditions 3
Paths 3

Size

Total Lines 24
Code Lines 14

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 3
eloc 14
nc 3
nop 1
dl 0
loc 24
rs 8.9713
c 0
b 0
f 0
1
<?php
2
/**
3
 * Plugin Name: Lazy Images
4
 * Description: Load images just before they scroll into view
5
 * Plugin URI: https://github.com/automattic/jetpack
6
 * Author: Automattic
7
 * Author URI: https://automattic.com
8
 * Version: 0.1.0
9
 * Text Domain: lazy-images
10
 * Domain Path: /languages/
11
 * License: GPLv2 or later
12
 */
13
14
/**
15
 * Props to batmoo for https://wordpress.org/plugins/lazy-load/
16
 * https://profiles.wordpress.org/batmoo
17
 */
18
class Jetpack_Lazy_Images {
19
	private static $__instance = null;
20
	/**
21
	 * Singleton implementation
22
	 *
23
	 * @return object
24
	 */
25
	public static function instance() {
26
		if ( ! is_a( self::$__instance, 'Jetpack_Lazy_Images' ) ) {
27
			self::$__instance = new Jetpack_Lazy_Images();
28
		}
29
30
		return self::$__instance;
31
	}
32
33
	/**
34
	 * Registers actions
35
	 */
36
	private function __construct() {
37
		// modify content
38
		add_action( 'wp_head', array( $this, 'setup_filters' ), 9999 ); // we don't really want to modify anything in <head> since it's mostly all metadata
39
40
		// js to do lazy loading
41
		add_action( 'init', array( $this, 'register_assets' ) );
42
		add_action( 'wp_enqueue_scripts', array( $this, 'enqueue_assets' ) );
43
	}
44
45
	public function setup_filters() {
46
		add_filter( 'the_content', array( $this, 'add_image_placeholders' ), 99 ); // run this later, so other content filters have run, including image_add_wh on WP.com
47
		add_filter( 'post_thumbnail_html', array( $this, 'add_image_placeholders' ), 11 );
48
		add_filter( 'get_avatar', array( $this, 'add_image_placeholders' ), 11 );
49
	}
50
51
	public function add_image_placeholders( $content ) {
52
		// Don't lazyload for feeds, previews
53
		if( is_feed() || is_preview() )
54
			return $content;
55
56
		// Don't lazy-load if the content has already been run through previously
57
		if ( false !== strpos( $content, 'data-lazy-src' ) )
58
			return $content;
59
60
		// This is a pretty simple regex, but it works
61
		$content = preg_replace_callback( '#<(img)([^>]+?)(>(.*?)</\\1>|[\/]?>)#si', array( __CLASS__, 'process_image' ), $content );
62
63
		return $content;
64
	}
65
66
 	function process_image( $matches ) {
67
		$old_attributes_str = $matches[2];
68
		$old_attributes = wp_kses_hair( $old_attributes_str, wp_allowed_protocols() );
69
70
		if ( empty( $old_attributes['src'] ) ) {
71
			return $matches[0];
72
		}
73
74
		$image_src = $old_attributes['src']['value'];
75
76
		if ( isset( $old_attributes['srcset'] ) ) {
77
			$image_srcset = $old_attributes['srcset']['value'];
78
		} else {
79
			$image_srcset = '';
80
		}
81
82
		// Remove src, lazy-src, srcset and lazy-srcset since we manually add them
83
		$new_attributes = $old_attributes;
84
		unset( $new_attributes['src'], $new_attributes['srcset'], $new_attributes['data-lazy-src'], $new_attributes['data-lazy-srcset'] );
85
86
		$new_attributes_str = $this->build_attributes_string( $new_attributes );
87
88
		return sprintf( '<img data-lazy-src="%1$s" data-lazy-srcset="%2$s" %3$s><noscript>%4$s</noscript>', esc_url( $image_src ), esc_attr( $image_srcset ), $new_attributes_str, $matches[0] );
89
	}
90
91
	private function build_attributes_string( $attributes ) {
92
		$string = array();
93
		foreach ( $attributes as $name => $attribute ) {
94
			$value = $attribute['value'];
95
			if ( '' === $value ) {
96
				$string[] = sprintf( '%s', $name );
97
			} else {
98
				$string[] = sprintf( '%s="%s"', $name, esc_attr( $value ) );
99
			}
100
		}
101
		return implode( ' ', $string );
102
	}
103
104
	public function register_assets() {
105
		wp_register_script( 'jetpack-lazy-images', plugins_url( 'assets/js/lazy-images.js', __FILE__ ), array('jquery'), '1.5', true );
106
		wp_register_script( 'jetpack-intersection-observer-polyfill', plugins_url( 'assets/js/intersection-observer.js', __FILE__ ), array('jquery'), '1.5' );
107
		wp_script_add_data( 'jetpack-intersection-observer-polyfill', 'conditional', 'IE' );
108
	}
109
110
	public function enqueue_assets() {
111
		wp_enqueue_script( 'jetpack-lazy-images' );
112
		wp_enqueue_script( 'jetpack-intersection-observer-polyfill' );
113
	}
114
}