Completed
Push — update/add-single-purpose-jetp... ( 28d890...705f7e )
by
unknown
09:19
created

vimeo.php ➔ vimeo_shortcode()   C

Complexity

Conditions 13
Paths 18

Size

Total Lines 81

Duplication

Lines 14
Ratio 17.28 %

Importance

Changes 0
Metric Value
cc 13
nc 18
nop 1
dl 14
loc 81
rs 5.7078
c 0
b 0
f 0

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

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 id=141358 width=350 height=500]
10
 *
11
 * <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>
12
 *
13
 * @package Jetpack
14
 */
15
16
/**
17
 * Extract Vimeo ID from shortcode.
18
 *
19
 * @param array $atts Shortcode attributes.
20
 */
21
function jetpack_shortcode_get_vimeo_id( $atts ) {
22
	if ( isset( $atts[0] ) ) {
23
		$atts[0] = trim( $atts[0], '=' );
24
		$id      = false;
25
		if ( is_numeric( $atts[0] ) ) {
26
			$id = (int) $atts[0];
27
		} elseif ( preg_match( '|vimeo\.com/(\d+)/?$|i', $atts[0], $match ) ) {
28
			$id = (int) $match[1];
29
		} elseif ( preg_match( '|player\.vimeo\.com/video/(\d+)/?$|i', $atts[0], $match ) ) {
30
			$id = (int) $match[1];
31
		}
32
33
		return $id;
34
	}
35
36
	return 0;
37
}
38
39
/**
40
 * Get video dimensions.
41
 *
42
 * @since 8.0.0
43
 *
44
 * @param array $attr     The attributes of the shortcode.
45
 * @param array $old_attr Optional array of attributes from the old shortcode format.
46
 *
47
 * @return array Width and height.
48
 */
49
function jetpack_shortcode_get_vimeo_dimensions( $attr, $old_attr = array() ) {
50
	global $content_width;
51
52
	$default_width  = 600;
53
	$default_height = 338;
54
	$aspect_ratio   = $default_height / $default_width;
55
	$width          = ( ! empty( $attr['width'] ) ? absint( $attr['width'] ) : $default_width );
56
	$height         = ( ! empty( $attr['height'] ) ? absint( $attr['height'] ) : $default_height );
57
58
	/*
59
	 * Support w and h argument as fallbacks.
60
	 */
61 View Code Duplication
	if (
62
		$default_width === $width
63
		&& ! empty( $old_attr['w'] )
64
	) {
65
		$width = absint( $old_attr['w'] );
66
67
		if (
68
			$default_width === $width
69
			&& empty( $old_attr['h'] )
70
		) {
71
			$height = round( $width * $aspect_ratio );
72
		}
73
	}
74
75 View Code Duplication
	if (
76
		$default_height === $height
77
		&& ! empty( $old_attr['h'] )
78
	) {
79
		$height = absint( $old_attr['h'] );
80
81
		if ( empty( $old_attr['w'] ) ) {
82
			$width = round( $height * $aspect_ratio );
83
		}
84
	}
85
86
	/*
87
	 * If we have a content width defined, let it be the new default.
88
	 */
89
	if (
90
		$default_width === $width
91
		&& ! empty( $content_width )
92
	) {
93
		$width = absint( $content_width );
94
	}
95
96
	/*
97
	 * If we have a custom width, we need a custom height as well
98
	 * to maintain aspect ratio.
99
	 */
100
	if (
101
		$default_width !== $width
102
		&& $default_height === $height
103
	) {
104
		$height = round( ( $width / 640 ) * 360 );
105
	}
106
107
	/**
108
	 * Filter the Vimeo player width.
109
	 *
110
	 * @module shortcodes
111
	 *
112
	 * @since 3.4.0
113
	 *
114
	 * @param int $width Width of the Vimeo player in pixels.
115
	 */
116
	$width = (int) apply_filters( 'vimeo_width', $width );
117
118
	/**
119
	 * Filter the Vimeo player height.
120
	 *
121
	 * @module shortcodes
122
	 *
123
	 * @since 3.4.0
124
	 *
125
	 * @param int $height Height of the Vimeo player in pixels.
126
	 */
127
	$height = (int) apply_filters( 'vimeo_height', $height );
128
129
	return array( $width, $height );
130
}
131
132
/**
133
 * Convert a Vimeo shortcode into an embed code.
134
 *
135
 * @param array $atts An array of shortcode attributes.
136
 *
137
 * @return string The embed code for the Vimeo video.
138
 */
139
function vimeo_shortcode( $atts ) {
140
	$attr = array_map(
141
		'intval',
142
		shortcode_atts(
143
			array(
144
				'id'       => 0,
145
				'width'    => 0,
146
				'height'   => 0,
147
				'autoplay' => 0,
148
				'loop'     => 0,
149
			),
150
			$atts
151
		)
152
	);
153
154
	if ( isset( $atts[0] ) ) {
155
		$attr['id'] = jetpack_shortcode_get_vimeo_id( $atts );
156
	}
157
158
	if ( ! $attr['id'] ) {
159
		return '<!-- vimeo error: not a vimeo video -->';
160
	}
161
162
	// Handle old shortcode params such as h=500&w=350.
163
	$params = shortcode_new_to_old_params( $atts );
164
	$params = str_replace( array( '&amp;', '&#038;' ), '&', $params );
165
	parse_str( $params, $args );
166
167
	list( $width, $height ) = jetpack_shortcode_get_vimeo_dimensions( $attr, $args );
0 ignored issues
show
Bug introduced by
It seems like $args can also be of type null; however, jetpack_shortcode_get_vimeo_dimensions() does only seem to accept array, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
168
169
	$url = esc_url( 'https://player.vimeo.com/video/' . $attr['id'] );
170
171
	// Handle autoplay and loop arguments.
172 View Code Duplication
	if (
173
		isset( $args['autoplay'] ) && '1' === $args['autoplay'] // Parsed from the embedded URL.
174
		|| $attr['autoplay']                                    // Parsed from shortcode arguments.
175
		|| in_array( 'autoplay', $atts, true )                  // Catch the argument passed without a value.
176
	) {
177
		$url = add_query_arg( 'autoplay', 1, $url );
178
	}
179
180 View Code Duplication
	if (
181
		isset( $args['loop'] ) && '1' === $args['loop'] // Parsed from the embedded URL.
182
		|| $attr['loop']                                // Parsed from shortcode arguments.
183
		|| in_array( 'loop', $atts, true )              // Catch the argument passed without a value.
184
	) {
185
		$url = add_query_arg( 'loop', 1, $url );
186
	}
187
188
	if (
189
		class_exists( 'Jetpack_AMP_Support' )
190
		&& Jetpack_AMP_Support::is_amp_request()
191
	) {
192
		$html = sprintf(
193
			'<amp-vimeo data-videoid="%1$s" layout="responsive" width="%2$d" height="%3$d"></amp-vimeo>',
194
			esc_attr( $attr['id'] ),
195
			absint( $width ),
196
			absint( $height )
197
		);
198
	} else {
199
		$html = sprintf(
200
			'<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>',
201
			esc_url( $url ),
202
			esc_attr( $width ),
203
			esc_attr( $height )
204
		);
205
	}
206
207
	/**
208
	 * Filter the Vimeo player HTML.
209
	 *
210
	 * @module shortcodes
211
	 *
212
	 * @since 1.2.3
213
	 *
214
	 * @param string $html Embedded Vimeo player HTML.
215
	 */
216
	$html = apply_filters( 'video_embed_html', $html );
217
218
	return $html;
219
}
220
add_shortcode( 'vimeo', 'vimeo_shortcode' );
221
222
/**
223
 * Callback to modify output of embedded Vimeo video using Jetpack's shortcode.
224
 *
225
 * @since 3.9
226
 *
227
 * @param array $matches Regex partial matches against the URL passed.
228
 * @param array $attr    Attributes received in embed response.
229
 * @param array $url     Requested URL to be embedded.
230
 *
231
 * @return string Return output of Vimeo shortcode with the proper markup.
232
 */
233
function wpcom_vimeo_embed_url( $matches, $attr, $url ) {
234
	return vimeo_shortcode( array( $url ) );
235
}
236
237
/**
238
 * For bare URLs on their own line of the form
239
 * http://vimeo.com/12345
240
 *
241
 * @since 3.9
242
 *
243
 * @uses wpcom_vimeo_embed_url
244
 */
245
function wpcom_vimeo_embed_url_init() {
246
	wp_embed_register_handler( 'wpcom_vimeo_embed_url', '#https?://(.+\.)?vimeo\.com/#i', 'wpcom_vimeo_embed_url' );
247
}
248
249
/*
250
 * Register handler to modify Vimeo embeds using Jetpack's shortcode output.
251
 * This does not happen on WordPress.com, since embeds are handled by core there.
252
 */
253
if ( ! defined( 'IS_WPCOM' ) || ! IS_WPCOM ) {
254
	add_action( 'init', 'wpcom_vimeo_embed_url_init' );
255
}
256
257
/**
258
 * Transform a Vimeo embed iFrame into a Vimeo shortcode.
259
 *
260
 * @param string $content Post content.
261
 */
262
function vimeo_embed_to_shortcode( $content ) {
263
	if ( ! is_string( $content ) || false === stripos( $content, 'player.vimeo.com/video/' ) ) {
264
		return $content;
265
	}
266
267
	$regexp     = '!<iframe\s+src=[\'"](https?:)?//player\.vimeo\.com/video/(\d+)[\w=&;?]*[\'"]((?:\s+\w+=[\'"][^\'"]*[\'"])*)((?:[\s\w]*))></iframe>!i';
268
	$regexp_ent = str_replace( '&amp;#0*58;', '&amp;#0*58;|&#0*58;', htmlspecialchars( $regexp, ENT_NOQUOTES ) );
269
270
	foreach ( compact( 'regexp', 'regexp_ent' ) as $reg => $regexp ) {
271
		if ( ! preg_match_all( $regexp, $content, $matches, PREG_SET_ORDER ) ) {
272
			continue;
273
		}
274
275
		foreach ( $matches as $match ) {
276
			$id = (int) $match[2];
277
278
			$params = $match[3];
279
280
			if ( 'regexp_ent' === $reg ) {
281
				$params = html_entity_decode( $params );
282
			}
283
284
			$params = wp_kses_hair( $params, array( 'http' ) );
285
286
			$width  = isset( $params['width'] ) ? (int) $params['width']['value'] : 0;
287
			$height = isset( $params['height'] ) ? (int) $params['height']['value'] : 0;
288
289
			$wh = '';
290
			if ( $width && $height ) {
291
				$wh = ' w=' . $width . ' h=' . $height;
292
			}
293
294
			$shortcode = '[vimeo ' . $id . $wh . ']';
295
			$content   = str_replace( $match[0], $shortcode, $content );
296
		}
297
	}
298
299
	return $content;
300
}
301
add_filter( 'pre_kses', 'vimeo_embed_to_shortcode' );
302
303
/**
304
 * Replaces shortcodes and plain-text URLs to Vimeo videos with Vimeo embeds.
305
 * Covers shortcode usage [vimeo 1234] | [vimeo https://vimeo.com/1234] | [vimeo http://vimeo.com/1234]
306
 * Or plain text URLs https://vimeo.com/1234 | vimeo.com/1234 | //vimeo.com/1234
307
 * Links are left intact.
308
 *
309
 * @since 3.7.0
310
 * @since 3.9.5 One regular expression matches shortcodes and plain URLs.
311
 *
312
 * @param string $content HTML content.
313
 *
314
 * @return string The content with embeds instead of URLs
315
 */
316
function vimeo_link( $content ) {
317
	/**
318
	 *  [vimeo 12345]
319
	 *  [vimeo http://vimeo.com/12345]
320
	 */
321
	$shortcode = '(?:\[vimeo\s+[^0-9]*)([0-9]+)(?:\])';
322
323
	/**
324
	 * Regex to look for a Vimeo link.
325
	 *
326
	 * - http://vimeo.com/12345
327
	 * - https://vimeo.com/12345
328
	 * - //vimeo.com/12345
329
	 * - vimeo.com/some/descender/12345
330
	 *
331
	 *  Should not capture inside HTML attributes
332
	 *  [Not] <a href="vimeo.com/12345">Cool Video</a>
333
	 *  [Not] <a href="https://vimeo.com/12345">vimeo.com/12345</a>
334
	 *
335
	 *  Could erroneously capture:
336
	 *  <a href="some.link/maybe/even/vimeo">This video (vimeo.com/12345) is teh cat's meow!</a>
337
	 */
338
	$plain_url = "(?:[^'\">]?\/?(?:https?:\/\/)?vimeo\.com[^0-9]+)([0-9]+)(?:[^'\"0-9<]|$)";
339
340
	return jetpack_preg_replace_callback_outside_tags(
341
		sprintf( '#%s|%s#i', $shortcode, $plain_url ),
342
		'vimeo_link_callback',
343
		$content,
344
		'vimeo'
345
	);
346
}
347
348
/**
349
 * Callback function for the regex that replaces Vimeo URLs with Vimeo embeds.
350
 *
351
 * @since 3.7.0
352
 *
353
 * @param array $matches An array containing a Vimeo URL.
354
 * @return string The Vimeo HTML embed code.
355
 */
356
function vimeo_link_callback( $matches ) {
357
	$id = isset( $matches[2] ) ? $matches[2] : $matches[1];
358
	if ( isset( $id ) && ctype_digit( $id ) ) {
359
		return "\n" . vimeo_shortcode( array( 'id' => $id ) ) . "\n";
360
	}
361
	return $matches[0];
362
}
363
364
if (
365
	! is_admin()
366
	/** This filter is documented in modules/shortcodes/youtube.php */
367
	&& apply_filters( 'jetpack_comments_allow_oembed', true )
368
	// No need for this on WordPress.com, this is done for multiple shortcodes at a time there.
369
	&& ( ! defined( 'IS_WPCOM' ) || ! IS_WPCOM )
370
) {
371
	/*
372
	 * We attach wp_kses_post to comment_text in default-filters.php with priority of 10 anyway,
373
	 * so the iframe gets filtered out.
374
	 * Higher priority because we need it before auto-link and autop get to it
375
	 */
376
	add_filter( 'comment_text', 'vimeo_link', 1 );
377
}
378