summaryrefslogtreecommitdiff
blob: cdca685920e7a06a81843b284e4961ec0a835259 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
<?php
/**
 * Getty shortcode
 *
 * [getty src="82278805" width="$width" height="$height"]
 * <div class="getty embed image" style="background-color:#fff;display:inline-block;font-family:'Helvetica Neue',Helvetica,Arial,sans-serif;color:#a7a7a7;font-size:11px;width:100%;max-width:462px;"><div style="padding:0;margin:0;text-align:left;"><a href="http://www.gettyimages.com/detail/82278805" target="_blank" style="color:#a7a7a7;text-decoration:none;font-weight:normal !important;border:none;display:inline-block;">Embed from Getty Images</a></div><div style="overflow:hidden;position:relative;height:0;padding:80.086580% 0 0 0;width:100%;"><iframe src="//embed.gettyimages.com/embed/82278805?et=jGiu6FXXSpJDGf1SnwLV2g&sig=TFVNFtqghwNw5iJQ1MFWnI8f4Y40_sfogfZLhai6SfA=" width="462" height="370" scrolling="no" frameborder="0" style="display:inline-block;position:absolute;top:0;left:0;width:100%;height:100%;"></iframe></div><p style="margin:0;"></p></div>
 */

if ( defined( 'IS_WPCOM' ) && IS_WPCOM ) {
	add_action( 'init', 'jetpack_getty_enable_embeds' );
} else {
	jetpack_getty_enable_embeds();
}

/**
 * Register Getty as oembed provider. Add filter to reverse iframes to shortcode. Register [getty] shortcode.
 *
 * @since 4.5.0
 * @since 5.8.0 removed string parameter.
 */
function jetpack_getty_enable_embeds() {

	// Support their oEmbed Endpoint
	wp_oembed_add_provider( '#https?://www\.gettyimages\.com/detail/.*#i', "https://embed.gettyimages.com/oembed/", true );
	wp_oembed_add_provider( '#https?://(www\.)?gty\.im/.*#i',              "https://embed.gettyimages.com/oembed/", true );

	// Allow iframes to be filtered to short code (so direct copy+paste can be done)
	add_filter( 'pre_kses', 'wpcom_shortcodereverse_getty' );

	// Actually display the Getty Embed
	add_shortcode( 'getty', 'jetpack_getty_shortcode' );
}

/**
 * Filters the oEmbed provider URL for Getty URLs to include site URL host as
 * caller if available, falling back to "wordpress.com". Must be applied at
 * time of embed in case that `init` is too early (WP.com REST API).
 *
 * @module shortcodes
 *
 * @since 5.8.0
 *
 * @see WP_oEmbed::fetch
 *
 * @return string oEmbed provider URL
 */
add_filter( 'oembed_fetch_url', 'getty_add_oembed_endpoint_caller' );

function getty_add_oembed_endpoint_caller( $provider ) {
	// By time filter is called, original provider URL has had url, maxwidth,
	// maxheight query parameters added.
	if ( 0 !== strpos( $provider, 'https://embed.gettyimages.com/oembed/' ) ) {
		return $provider;
	}

	// Set the caller argument to pass to Getty's oembed provider.
	if ( defined( 'IS_WPCOM' ) && IS_WPCOM ) {

		// Only include caller for non-private sites
		if ( ! function_exists( 'is_private_blog' ) || ! is_private_blog() ) {
			$host = parse_url( get_bloginfo( 'url' ), PHP_URL_HOST );
		}

		// Fall back to WordPress.com
		if ( empty( $host ) ) {
			$host = 'wordpress.com';
		}
	} else {
		$host = parse_url( get_home_url(), PHP_URL_HOST );
	}

	return add_query_arg( 'caller', $host, $provider );
}

/**
 * Compose shortcode based on Getty iframes.
 *
 * @since 4.5.0
 *
 * @param string $content
 *
 * @return mixed
 */
function wpcom_shortcodereverse_getty( $content ) {
	if ( ! is_string( $content ) || false === stripos( $content, '.gettyimages.com/' ) ) {
		return $content;
	}

	$regexp = '!<iframe\s+src=[\'"](https?:)?//embed\.gettyimages\.com/embed(/|/?\?assets=)([a-z0-9_-]+(,[a-z0-9_-]+)*)[^\'"]*?[\'"]((?:\s+\w+=[\'"][^\'"]*[\'"])*)((?:[\s\w]*))></iframe>!i';
	$regexp_ent = str_replace( '&amp;#0*58;', '&amp;#0*58;|&#0*58;', htmlspecialchars( $regexp, ENT_NOQUOTES ) );


	// Markup pattern for 2017 embed syntax with significant differences from
	// the prior pattern:
	$regexp_2017 = '!<a.+?class=\'gie-(single|slideshow)\'.+?gie\.widgets\.load\({([^}]+)}\).+?embed-cdn\.gettyimages\.com/widgets\.js.+?</script>!';
	$regexp_2017_ent = str_replace( '&amp;#0*58;', '&amp;#0*58;|&#0*58;', htmlspecialchars( $regexp_2017, ENT_NOQUOTES ) );

	foreach ( array( 'regexp_2017', 'regexp_2017_ent', 'regexp', 'regexp_ent' ) as $reg ) {
		if ( ! preg_match_all( $$reg, $content, $matches, PREG_SET_ORDER ) ) {
			continue;
		}

		foreach ( $matches as $match ) {
			if ( 'regexp_2017' === $reg || 'regexp_2017_ent' === $reg ) {
				// Extract individual keys from the matched JavaScript object
				$params = $match[2];
				if ( ! preg_match_all( '!(?P<key>\w+)\s*:\s*([\'"](?P<value>[^\'"]*?)(px)?[\'"])!', $params, $key_matches, PREG_SET_ORDER ) ) {
					continue;
				}

				foreach ( $key_matches as $key_match ) {
					switch ( $key_match['key'] ) {
						case 'items': $ids = $key_match['value']; break;
						case 'w': $width = (int) $key_match['value']; break;
						case 'h': $height = (int) $key_match['value']; break;
						case 'tld': $tld = $key_match['value']; break;
					}
				}
			} else {
				$params = $match[5];
				if ( 'regexp_ent' === $reg ) {
					$params = html_entity_decode( $params );
				}
				$params = wp_kses_hair( $params, array( 'http' ) );

				$ids = esc_html( $match[3] );
				$width = isset( $params['width'] ) ? (int) $params['width']['value'] : 0;
				$height = isset( $params['height'] ) ? (int) $params['height']['value'] : 0;
			}

			if ( empty( $ids ) ) {
				continue;
			}

			$shortcode = '[getty src="' . esc_attr( $ids ) . '"';
			if ( ! empty( $width ) ) {
				$shortcode .= ' width="' . esc_attr( $width ) . '"';
			}
			if ( ! empty( $height ) ) {
				$shortcode .= ' height="' . esc_attr( $height ) . '"';
			}
			// While it does not appear to have any practical impact, Getty has
			// requested that we include TLD in the embed request
			if ( ! empty( $tld ) ) {
				$shortcode .= ' tld="' . esc_attr( $tld ). '"';
			}
			$shortcode .= ']';

			$content = str_replace( $match[0], $shortcode, $content );
		}
	}

	// strip out enclosing div and any other markup
	$regexp = '%<div class="getty\s[^>]*+>.*?<div[^>]*+>(\[getty[^\]]*+\])\s*</div>.*?</div>%is';
	$regexp_ent = str_replace( array( '&amp;#0*58;', '[^&gt;]' ), array( '&amp;#0*58;|&#0*58;', '[^&]' ), htmlspecialchars( $regexp, ENT_NOQUOTES ) );

	foreach ( array( 'regexp', 'regexp_ent' ) as $reg ) {
		if ( ! preg_match_all( $$reg, $content, $matches, PREG_SET_ORDER ) ) {
			continue;
		}

		foreach ( $matches as $match ) {
			$content = str_replace( $match[0], $match[1], $content );
		}
	}

	/** This action is documented in modules/widgets/social-media-icons.php */
	do_action( 'jetpack_bump_stats_extras', 'html_to_shortcode', 'getty' );

	return $content;
}

/**
 * Parse shortcode arguments and render its output.
 *
 * @since 4.5.0
 *
 * @param array  $atts    Shortcode parameters.
 * @param string $content Content enclosed by shortcode tags.
 *
 * @return string
 */
function jetpack_getty_shortcode( $atts, $content = '' ) {

	if ( ! empty( $content ) ) {
		$src = $content;
	} elseif ( ! empty( $atts['src'] ) ) {
		$src = $atts['src'];
	} elseif ( ! empty( $atts[0] ) ) {
		$src = $atts[0];
	} else {
		return '<!-- Missing Getty Source ID -->';
	}

	$src = preg_replace( '/^([\da-z-]+(,[\da-z-]+)*).*$/', '$1', $src );

	$params = array(
		'width'  => isset( $atts['width'] ) ? (int) $atts['width'] : null,
		'height' => isset( $atts['height'] ) ? (int) $atts['height'] : null
	);

	if ( ! empty( $atts['tld'] ) ) {
		$params['tld'] = $atts['tld'];
	}

	return wp_oembed_get( 'https://gty.im/' . $src, array_filter( $params ) );
}