PluginProbe
Jetpack – WP Security, Backup, Speed, & Growth / 14.8
Jetpack – WP Security, Backup, Speed, & Growth v14.8
16.2-beta 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 All 501 releases
jetpack / modules / shortcodes / vimeo.php

vimeo.php in Jetpack – WP Security, Backup, Speed, & Growth 14.8, at modules/shortcodes/vimeo.php

422 lines 11.5 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Vimeo Shortcode.
4 *
5 * Examples:
6 * [vimeo 141358]
7 * [vimeo http://vimeo.com/141358]
8 * [vimeo 141358 h=500&w=350]
9 * [vimeo 141358 h=500 w=350]
10 * [vimeo id=141358 width=350 height=500]
11 *
12 * <iframe src="http://player.vimeo.com/video/18427511" width="400" height="225" frameborder="0"></iframe><p><a href="http://vimeo.com/18427511">Eskmo 'We Got More' (Official Video)</a> from <a href="http://vimeo.com/ninjatune">Ninja Tune</a> on <a href="http://vimeo.com">Vimeo</a>.</p>
13 *
14 * @package automattic/jetpack
15 */
16
17 /**
18 * Extract Vimeo ID from shortcode.
19 *
20 * @param array $atts Shortcode attributes.
21 */
22 function jetpack_shortcode_get_vimeo_id( $atts ) {
23 if ( isset( $atts[0] ) ) {
24 $atts[0] = trim( $atts[0], '=' );
25 if ( is_numeric( $atts[0] ) ) {
26 return (int) $atts[0];
27 }
28
29 /**
30 * Extract Vimeo ID from the URL. For examples:
31 * https://vimeo.com/12345
32 * https://vimeo.com/289091934/cd1f466bcc
33 * https://vimeo.com/album/2838732/video/6342264
34 * https://vimeo.com/groups/758728/videos/897094040
35 * https://vimeo.com/channels/staffpicks/123456789
36 * https://vimeo.com/album/1234567/video/7654321
37 * https://player.vimeo.com/video/18427511
38 */
39 $pattern = '/(?:https?:\/\/)?vimeo\.com\/(?:groups\/\d+\/videos\/|album\/\d+\/video\/|video\/|channels\/[^\/]+\/videos\/|[^\/]+\/)?([0-9]+)(?:[^\'\"0-9<]|$)/i';
40 $match = array();
41 if ( preg_match( $pattern, $atts[0], $match ) ) {
42 return (int) $match[1];
43 }
44 }
45
46 return 0;
47 }
48
49 /**
50 * Get video dimensions.
51 *
52 * @since 8.0.0
53 *
54 * @param array $attr The attributes of the shortcode.
55 * @param array $old_attr Optional array of attributes from the old shortcode format.
56 *
57 * @return array Width and height.
58 */
59 function jetpack_shortcode_get_vimeo_dimensions( $attr, $old_attr = array() ) {
60 global $content_width;
61
62 $default_width = 600;
63 $default_height = 338;
64 $aspect_ratio = $default_height / $default_width;
65
66 /*
67 * For width and height, we want to support both formats
68 * that can be provided in the new shortcode format:
69 * - for width: width or w
70 * - for height: height or h
71 *
72 * For each variation, the full word takes priority.
73 *
74 * If no variation is set, we default to the default width and height values set above.
75 */
76 if ( ! empty( $attr['width'] ) ) {
77 $width = absint( $attr['width'] );
78 } elseif ( ! empty( $attr['w'] ) ) {
79 $width = absint( $attr['w'] );
80 } else {
81 $width = $default_width;
82 }
83
84 if ( ! empty( $attr['height'] ) ) {
85 $height = absint( $attr['height'] );
86 } elseif ( ! empty( $attr['h'] ) ) {
87 $height = absint( $attr['h'] );
88 } else {
89 $height = $default_height;
90 }
91
92 /*
93 * Support w and h argument as fallbacks in old shortcode format.
94 */
95 if (
96 $default_width === $width
97 && ! empty( $old_attr['w'] )
98 ) {
99 $width = absint( $old_attr['w'] );
100
101 if (
102 $default_width === $width
103 && empty( $old_attr['h'] )
104 ) {
105 $height = round( $width * $aspect_ratio );
106 }
107 }
108
109 if (
110 $default_height === $height
111 && ! empty( $old_attr['h'] )
112 ) {
113 $height = absint( $old_attr['h'] );
114
115 if ( empty( $old_attr['w'] ) ) {
116 $width = round( $height * $aspect_ratio );
117 }
118 }
119
120 /*
121 * If we have a content width defined, let it be the new default.
122 */
123 if (
124 $default_width === $width
125 && ! empty( $content_width )
126 ) {
127 $width = absint( $content_width );
128 }
129
130 /*
131 * If we have a custom width, we need a custom height as well
132 * to maintain aspect ratio.
133 */
134 if (
135 $default_width !== $width
136 && $default_height === $height
137 ) {
138 $height = round( ( $width / 640 ) * 360 );
139 }
140
141 /**
142 * Filter the Vimeo player width.
143 *
144 * @module shortcodes
145 *
146 * @since 3.4.0
147 *
148 * @param int $width Width of the Vimeo player in pixels.
149 */
150 $width = (int) apply_filters( 'vimeo_width', $width );
151
152 /**
153 * Filter the Vimeo player height.
154 *
155 * @module shortcodes
156 *
157 * @since 3.4.0
158 *
159 * @param int $height Height of the Vimeo player in pixels.
160 */
161 $height = (int) apply_filters( 'vimeo_height', $height );
162
163 return array( $width, $height );
164 }
165
166 /**
167 * Convert a Vimeo shortcode into an embed code.
168 *
169 * @param array $atts An array of shortcode attributes.
170 *
171 * @return string The embed code for the Vimeo video.
172 */
173 function vimeo_shortcode( $atts ) {
174 $attr = array_map(
175 'intval',
176 shortcode_atts(
177 array(
178 'id' => 0,
179 'width' => 0,
180 'height' => 0,
181 'autoplay' => 0,
182 'loop' => 0,
183 'w' => 0,
184 'h' => 0,
185 ),
186 $atts
187 )
188 );
189
190 if ( isset( $atts[0] ) ) {
191 $attr['id'] = jetpack_shortcode_get_vimeo_id( $atts );
192 }
193
194 if ( ! $attr['id'] ) {
195 return '<!-- vimeo error: not a vimeo video -->';
196 }
197
198 // Handle old shortcode params such as h=500&w=350.
199 $params = shortcode_new_to_old_params( $atts );
200 $params = str_replace( array( '&amp;', '&#038;' ), '&', $params );
201 parse_str( $params, $args );
202
203 list( $width, $height ) = jetpack_shortcode_get_vimeo_dimensions( $attr, $args );
204
205 $url = esc_url( 'https://player.vimeo.com/video/' . $attr['id'] );
206
207 // Handle autoplay and loop arguments.
208 if (
209 isset( $args['autoplay'] ) && '1' === $args['autoplay'] // Parsed from the embedded URL.
210 || $attr['autoplay'] // Parsed from shortcode arguments.
211 || in_array( 'autoplay', $atts, true ) // Catch the argument passed without a value.
212 ) {
213 $url = add_query_arg( 'autoplay', 1, $url );
214 }
215
216 if (
217 isset( $args['loop'] ) && '1' === $args['loop'] // Parsed from the embedded URL.
218 || $attr['loop'] // Parsed from shortcode arguments.
219 || in_array( 'loop', $atts, true ) // Catch the argument passed without a value.
220 ) {
221 $url = add_query_arg( 'loop', 1, $url );
222 }
223
224 if (
225 class_exists( 'Jetpack_AMP_Support' )
226 && Jetpack_AMP_Support::is_amp_request()
227 ) {
228 $html = sprintf(
229 '<amp-vimeo data-videoid="%1$s" layout="responsive" width="%2$d" height="%3$d"></amp-vimeo>',
230 esc_attr( $attr['id'] ),
231 absint( $width ),
232 absint( $height )
233 );
234 } else {
235 $html = sprintf(
236 '<div class="embed-vimeo" style="text-align: center;"><iframe src="%1$s" width="%2$u" height="%3$u" frameborder="0" webkitallowfullscreen mozallowfullscreen allowfullscreen></iframe></div>',
237 esc_url( $url ),
238 esc_attr( $width ),
239 esc_attr( $height )
240 );
241 }
242
243 /**
244 * Filter the Vimeo player HTML.
245 *
246 * @module shortcodes
247 *
248 * @since 1.2.3
249 *
250 * @param string $html Embedded Vimeo player HTML.
251 */
252 $html = apply_filters( 'video_embed_html', $html );
253
254 return $html;
255 }
256 add_shortcode( 'vimeo', 'vimeo_shortcode' );
257
258 /**
259 * Callback to modify output of embedded Vimeo video using Jetpack's shortcode.
260 *
261 * @since 3.9
262 * @deprecated since 13.8
263 *
264 * @param array $matches Regex partial matches against the URL passed.
265 * @param array $attr Attributes received in embed response.
266 * @param array $url Requested URL to be embedded.
267 *
268 * @return string Return output of Vimeo shortcode with the proper markup.
269 */
270 function wpcom_vimeo_embed_url( $matches, $attr, $url ) {
271 _deprecated_function( __FUNCTION__, 'jetpack-13.8' );
272 $vimeo_info = array( $url );
273
274 // If we are able to extract a video ID, use it in the shortcode instead of the full URL.
275 if ( ! empty( $matches['video_id'] ) ) {
276 $vimeo_info = array( 'id' => $matches['video_id'] );
277 }
278
279 return vimeo_shortcode( $vimeo_info );
280 }
281
282 /**
283 * For bare URLs on their own line of the form.
284 *
285 * Accepted formats:
286 * https://vimeo.com/289091934/cd1f466bcc
287 * https://vimeo.com/album/2838732/video/6342264
288 * https://vimeo.com/6342264
289 * http://player.vimeo.com/video/18427511
290 *
291 * @since 3.9
292 * @deprecated since 13.8
293 *
294 * @uses wpcom_vimeo_embed_url
295 */
296 function wpcom_vimeo_embed_url_init() {
297 _deprecated_function( __FUNCTION__, 'jetpack-13.8' );
298 wp_embed_register_handler( 'wpcom_vimeo_embed_url', '#https?://(?:[^/]+\.)?vimeo\.com/(?:album/(?<album_id>\d+)/)?(?:video/)?(?<video_id>\d+)(?:/.*)?$#i', 'wpcom_vimeo_embed_url' );
299 }
300
301 /**
302 * Transform a Vimeo embed iFrame into a Vimeo shortcode.
303 *
304 * @param string $content Post content.
305 */
306 function vimeo_embed_to_shortcode( $content ) {
307 if ( ! is_string( $content ) || false === stripos( $content, 'player.vimeo.com/video/' ) ) {
308 return $content;
309 }
310
311 $regexp = '!<iframe\s+src=[\'"](https?:)?//player\.vimeo\.com/video/(\d+)[\w=&;?]*[\'"]((?:\s+\w+=[\'"][^\'"]*[\'"])*)((?:[\s\w]*))></iframe>!i';
312 $regexp_ent = str_replace( '&amp;#0*58;', '&amp;#0*58;|&#0*58;', htmlspecialchars( $regexp, ENT_NOQUOTES ) );
313
314 foreach ( compact( 'regexp', 'regexp_ent' ) as $reg => $regexp ) {
315 if ( ! preg_match_all( $regexp, $content, $matches, PREG_SET_ORDER ) ) {
316 continue;
317 }
318
319 foreach ( $matches as $match ) {
320 $id = (int) $match[2];
321
322 $params = $match[3];
323
324 if ( 'regexp_ent' === $reg ) {
325 $params = html_entity_decode( $params, ENT_QUOTES | ENT_SUBSTITUTE | ENT_HTML401 );
326 }
327
328 $params = wp_kses_hair( $params, array( 'http' ) );
329
330 $width = isset( $params['width'] ) ? (int) $params['width']['value'] : 0;
331 $height = isset( $params['height'] ) ? (int) $params['height']['value'] : 0;
332
333 $wh = '';
334 if ( $width && $height ) {
335 $wh = ' w=' . $width . ' h=' . $height;
336 }
337
338 $shortcode = '[vimeo ' . $id . $wh . ']';
339 $content = str_replace( $match[0], $shortcode, $content );
340 }
341 }
342
343 return $content;
344 }
345 add_filter( 'pre_kses', 'vimeo_embed_to_shortcode' );
346
347 /**
348 * Replaces shortcodes and plain-text URLs to Vimeo videos with Vimeo embeds.
349 * Covers shortcode usage [vimeo 1234] | [vimeo https://vimeo.com/1234] | [vimeo http://vimeo.com/1234]
350 * Or plain text URLs https://vimeo.com/1234 | vimeo.com/1234 | //vimeo.com/1234
351 * Links are left intact.
352 *
353 * @since 3.7.0
354 * @since 3.9.5 One regular expression matches shortcodes and plain URLs.
355 *
356 * @param string $content HTML content.
357 *
358 * @return string The content with embeds instead of URLs
359 */
360 function vimeo_link( $content ) {
361 /**
362 * [vimeo 12345]
363 * [vimeo http://vimeo.com/12345]
364 */
365 $shortcode = '(?:\[vimeo\s+[^0-9]*)([0-9]+)(?:\])';
366
367 /**
368 * Regex to look for a Vimeo link.
369 *
370 * - http://vimeo.com/12345
371 * - https://vimeo.com/12345
372 * - //vimeo.com/12345
373 * - vimeo.com/some/descender/12345
374 *
375 * Should not capture inside HTML attributes
376 * [Not] <a href="vimeo.com/12345">Cool Video</a>
377 * [Not] <a href="https://vimeo.com/12345">vimeo.com/12345</a>
378 *
379 * Could erroneously capture:
380 * <a href="some.link/maybe/even/vimeo">This video (vimeo.com/12345) is teh cat's meow!</a>
381 */
382 $plain_url = "(?:[^'\">]?\/?(?:https?:\/\/)?vimeo\.com\/(?:groups\/\d+\/videos\/|album\/\d+\/video\/|video\/|channels\/[^\/]+\/videos\/|[^\/]+\/)?)([0-9]+)(?:[^'\"0-9<]|$)";
383
384 return jetpack_preg_replace_callback_outside_tags(
385 sprintf( '#%s|%s#i', $shortcode, $plain_url ),
386 'vimeo_link_callback',
387 $content,
388 'vimeo'
389 );
390 }
391
392 /**
393 * Callback function for the regex that replaces Vimeo URLs with Vimeo embeds.
394 *
395 * @since 3.7.0
396 *
397 * @param array $matches An array containing a Vimeo URL.
398 * @return string The Vimeo HTML embed code.
399 */
400 function vimeo_link_callback( $matches ) {
401 $id = isset( $matches[2] ) ? $matches[2] : $matches[1];
402 if ( isset( $id ) && ctype_digit( $id ) ) {
403 return "\n" . vimeo_shortcode( array( 'id' => $id ) ) . "\n";
404 }
405 return $matches[0];
406 }
407
408 if (
409 ! is_admin()
410 /** This filter is documented in modules/shortcodes/youtube.php */
411 && apply_filters( 'jetpack_comments_allow_oembed', true )
412 // No need for this on WordPress.com, this is done for multiple shortcodes at a time there.
413 && ( ! defined( 'IS_WPCOM' ) || ! IS_WPCOM )
414 ) {
415 /*
416 * We attach wp_kses_post to comment_text in default-filters.php with priority of 10 anyway,
417 * so the iframe gets filtered out.
418 * Higher priority because we need it before auto-link and autop get to it
419 */
420 add_filter( 'comment_text', 'vimeo_link', 1 );
421 }
422