Completed
Push — prepare/4.1 ( 0b4dc2...26fe0a )
by Jeremy
279:11 queued 269:16
created

VideoPress_Player::esc_flash_params()   C

Complexity

Conditions 10
Paths 12

Size

Total Lines 49
Code Lines 37

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 10
eloc 37
nc 12
nop 1
dl 0
loc 49
rs 5.5471
c 0
b 0
f 0

How to fix   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
 * VideoPress playback module markup generator.
4
 *
5
 * @since 1.3
6
 */
7
class VideoPress_Player {
8
	/**
9
	 * Video data for the requested guid and maximum width
10
	 *
11
	 * @since 1.3
12
	 * @var VideoPress_Video
13
	 */
14
	protected $video;
15
16
	/**
17
	 * DOM identifier of the video container
18
	 *
19
	 * @var string
20
	 * @since 1.3
21
	 */
22
	protected $video_container_id;
23
24
	/**
25
	 * DOM identifier of the video element (video, object, embed)
26
	 *
27
	 * @var string
28
	 * @since 1.3
29
	 */
30
	protected $video_id;
31
32
	/**
33
	 * Array of playback options: force_flash or freedom
34
	 *
35
	 * @var array
36
	 * @since 1.3
37
	 */
38
	protected $options;
39
40
	/**
41
	 * Array of video GUIDs shown and their counts,
42
	 * moved from the old VideoPress class.
43
	 */
44
	public static $shown = array();
45
46
	/**
47
	 * Initiate a player object based on shortcode values and possible blog-level option overrides
48
	 *
49
	 * @since 1.3
50
	 * @var string $guid VideoPress unique identifier
51
	 * @var int $maxwidth maximum desired width of the video player if specified
52
	 * @var array $options player customizations
53
	 */
54
	public function __construct( $guid, $maxwidth = 0, $options = array() ) {
55
		if ( empty( self::$shown[ $guid ] ) )
56
			self::$shown[ $guid ] = 0;
57
58
		self::$shown[ $guid ]++;
59
60
		$this->video_container_id = 'v-' . $guid . '-' . self::$shown[ $guid ];
61
		$this->video_id = $this->video_container_id . '-video';
62
63
		if ( is_array( $options ) )
64
			$this->options = $options;
65
		else
66
			$this->options = array();
67
68
		// set up the video
69
		$cache_key = null;
70
71
		// disable cache in debug mode
72
		if ( defined('WP_DEBUG') && WP_DEBUG === true ) {
73
			$cached_video = null;
74
		} else {
75
			$cache_key_pieces = array( 'video' );
76
77
			if ( is_multisite() && is_subdomain_install() )
78
				$cache_key_pieces[] = get_current_blog_id();
79
80
			$cache_key_pieces[] = $guid;
81
			if ( $maxwidth > 0 )
82
				$cache_key_pieces[] = $maxwidth;
83
			if ( is_ssl() )
84
				$cache_key_pieces[] = 'ssl';
85
			$cache_key = implode( '-', $cache_key_pieces );
86
			unset( $cache_key_pieces );
87
			$cached_video = wp_cache_get( $cache_key, 'video' );
88
		}
89
		if ( empty( $cached_video ) ) {
90
			$video = new VideoPress_Video( $guid, $maxwidth );
91
			if ( empty( $video ) ) {
92
				return;
93
			} elseif ( isset( $video->error ) ) {
94
				$this->video = $video->error;
0 ignored issues
show
Bug introduced by
The property error does not seem to exist in VideoPress_Video.

An attempt at access to an undefined property has been detected. This may either be a typographical error or the property has been renamed but there are still references to its old name.

If you really want to allow access to undefined properties, you can define magic methods to allow access. See the php core documentation on Overloading.

Loading history...
95
				return;
96
			} elseif ( is_wp_error( $video ) ) {
97
				$this->video = $video;
98
				return;
99
			}
100
101
			$this->video = $video;
102
			unset( $video );
103
104
			if ( ! defined( 'WP_DEBUG' ) || WP_DEBUG !== true ) {
105
				$expire = 3600;
106
				if ( isset( $video->expires ) && is_int( $video->expires ) ) {
107
					$expires_diff = time() - $video->expires;
108
					if ( $expires_diff > 0 && $expires_diff < 86400 ) // allowed range: 1 second to 1 day
109
						$expire = $expires_diff;
110
					unset( $expires_diff );
111
				}
112
113
				wp_cache_set( $cache_key, serialize( $this->video ), 'video', $expire );
114
				unset( $expire );
115
			}
116
		} else {
117
			$this->video = unserialize( $cached_video );
118
		}
119
		unset( $cache_key );
120
		unset( $cached_video );
121
	}
122
123
	/**
124
	 * Wrap output in a VideoPress player container
125
	 *
126
	 * @since 1.3
127
	 * @var string $content HTML string
128
	 * @return string HTML string or blank string if nothing to wrap
129
	 */
130
	private function html_wrapper( $content ) {
131
		if ( empty( $content ) )
132
			return '';
133
		else
134
			return '<div id="' . esc_attr( $this->video_container_id ) . '" class="video-player">' . $content . '</div>';
135
	}
136
137
	/**
138
	 * Output content suitable for a feed reader displaying RSS or Atom feeds
139
	 * We do not display error messages in the feed view due to caching concerns.
140
	 * Flash content presented using <embed> markup for feed reader compatibility.
141
	 *
142
	 * @since 1.3
143
	 * @return string HTML string or empty string if error
144
	 */
145
	public function asXML() {
146
		if ( empty( $this->video ) || is_wp_error( $this->video ) ) {
147
			return '';
148
		}
149
150
		if ( isset( $this->options['force_flash'] ) && true === $this->options['force_flash'] ) {
151
			$content = $this->flash_embed();
152
153
		} else {
154
			$content = $this->html5_static();
155
		}
156
157
		return $this->html_wrapper( $content );
158
	}
159
160
	/**
161
	 * Video player markup for best matching the current request and publisher options
162
	 * @since 1.3
163
	 * @return string HTML markup string or empty string if no video property found
164
	 */
165
	public function asHTML() {
166
		if ( empty( $this->video ) ) {
167
			$content = '';
168
169
		} elseif ( is_wp_error( $this->video ) ) {
170
			$content = $this->error_message( $this->video );
171
172
		} elseif ( isset( $this->options['force_flash'] ) && true === $this->options['force_flash'] ) {
173
			$content = $this->flash_object();
174
175
		} elseif ( isset( $this->video->restricted_embed ) && true === $this->video->restricted_embed ) {
176
177
			if ( $this->options['forcestatic'] ) {
178
				$content = $this->flash_object();
179
180
			} else {
181
				$content = $this->html5_dynamic();
182
			}
183
184
		} elseif ( isset( $this->options['freedom'] ) && true === $this->options['freedom'] ) {
185
			$content = $this->html5_static();
186
187
		} else {
188
			$content = $this->html5_dynamic();
189
		}
190
191
		return $this->html_wrapper( $content );
192
	}
193
194
	/**
195
	 * Display an error message to users capable of doing something about the error
196
	 *
197
	 * @since 1.3
198
	 * @uses current_user_can() to test if current user has edit_posts capability
199
	 * @var WP_Error $error WordPress error
200
	 * @return string HTML string
201
	 */
202
	private function error_message( $error ) {
203
		if ( ! current_user_can( 'edit_posts' ) || empty( $error ) )
204
			return '';
205
206
		$html = '<div class="videopress-error" style="background-color:rgb(255,0,0);color:rgb(255,255,255);font-family:font-family:\'Helvetica Neue\',Arial,Helvetica,\'Nimbus Sans L\',sans-serif;font-size:140%;min-height:10em;padding-top:1.5em;padding-bottom:1.5em">';
207
		$html .= '<h1 style="font-size:180%;font-style:bold;line-height:130%;text-decoration:underline">' . esc_html( sprintf( __( '%s Error', 'jetpack' ), 'VideoPress' ) ) . '</h1>';
208
		foreach( $error->get_error_messages() as $message ) {
209
			$html .= $message;
210
		}
211
		$html .= '</div>';
212
		return $html;
213
	}
214
215
	/**
216
	 * Rating agencies and industry associations require a potential viewer verify his or her age before a video or its poster frame are displayed.
217
	 * Content rated for audiences 17 years of age or older requires such verification across multiple rating agencies and industry associations
218
	 *
219
	 * @since 1.3
220
	 * @return bool true if video requires the viewer verify he or she is 17 years of age or older
221
	 */
222
	private function age_gate_required() {
223
		if ( isset( $this->video->age_rating ) && $this->video->age_rating >= 17 )
224
			return true;
225
		else
226
			return false;
227
	}
228
229
	/**
230
	 * Select a date of birth using HTML form elements.
231
	 *
232
	 * @since 1.5
233
	 * @return string HTML markup
234
	 */
235
	private function html_age_gate() {
0 ignored issues
show
Unused Code introduced by
This method is not used, and could be removed.
Loading history...
236
		global $wp_locale;
237
		$text_align = 'left';
238
		if ( $this->video->text_direction === 'rtl' )
239
			$text_align = 'right';
240
241
		$html = '<div class="videopress-age-gate" style="margin:0 60px">';
242
		$html .= '<p class="instructions" style="color:rgb(255, 255, 255);font-size:21px;padding-top:60px;padding-bottom:20px;text-align:' . $text_align . '">' . esc_html( __( 'This video is intended for mature audiences.', 'jetpack' ) ) . '<br />' . esc_html( __( 'Please verify your birthday.', 'jetpack' ) ) . '</p>';
243
		$html .= '<fieldset id="birthday" style="border:0 none;text-align:' . $text_align . ';padding:0;">';
244
		$inputs_style = 'border:1px solid #444;margin-';
245
		if ( $this->video->text_direction === 'rtl' )
246
			$inputs_style .= 'left';
247
		else
248
			$inputs_style .= 'right';
249
		$inputs_style .= ':10px;background-color:rgb(0, 0, 0);font-size:14px;color:rgb(255,255,255);padding:4px 6px;line-height: 2em;vertical-align: middle';
250
251
		/**
252
		 * Display a list of months in the Gregorian calendar.
253
		 * Set values to 0-based to match JavaScript Date.
254
		 * @link https://developer.mozilla.org/en/JavaScript/Reference/global_objects/date Mozilla JavaScript Reference: Date
255
		 */
256
		$html .= '<select name="month" style="' . $inputs_style . '">';
257
258
		for( $i=0; $i<12; $i++ ) {
259
			$html .= '<option value="' . esc_attr( $i ) . '">' . esc_html( $wp_locale->get_month( $i + 1 ) )  . '</option>';
260
		}
261
		$html .= '</select>';
262
263
		/**
264
		 * todo: numdays variance by month
0 ignored issues
show
Coding Style Best Practice introduced by
Comments for TODO tasks are often forgotten in the code; it might be better to use a dedicated issue tracker.
Loading history...
265
		 */
266
		$html .= '<select name="day" style="' . $inputs_style . '">';
267
		for ( $i=1; $i<32; $i++ ) {
268
			$html .= '<option>' . $i . '</option>';
269
		}
270
		$html .= '</select>';
271
272
		/**
273
		 * Current record for human life is 122. Go back 130 years and no one is left out.
274
		 * Don't ask infants younger than 2 for their birthday
275
		 * Default to 13
276
		 */
277
		$html .= '<select name="year" style="' . $inputs_style . '">';
278
		$start_year = date('Y') - 2;
279
		$default_year = $start_year - 11;
280
		$end_year = $start_year - 128;
281
		for ( $year=$start_year; $year>$end_year; $year-- ) {
282
			$html .= '<option';
283
			if ( $year === $default_year )
284
				$html .= ' selected="selected"';
285
			$html .= '>' . $year . '</option>';
286
		}
287
		unset( $start_year );
288
		unset( $default_year );
289
		unset( $end_year );
290
		$html .= '</select>';
291
292
		$html .= '<input type="submit" value="' . __( 'Submit', 'jetpack' ) . '" style="cursor:pointer;border-radius: 1em;border:1px solid #333;background-color:#333;background:-webkit-gradient( linear, left top, left bottom, color-stop(0.0, #444), color-stop(1, #111) );background:-moz-linear-gradient(center top, #444 0%, #111 100%);font-size:13px;padding:4px 10px 5px;line-height:1em;vertical-align:top;color:white;text-decoration:none;margin:0" />';
293
294
		$html .= '</fieldset>';
295
		$html .= '<p style="padding-top:20px;padding-bottom:60px;text-align:' . $text_align . ';"><a rel="nofollow" href="http://videopress.com/" target="_blank" style="color:rgb(128,128,128);text-decoration:underline;font-size:15px">' . __( 'More information', 'jetpack' ) . '</a></p>';
296
297
		$html .= '</div>';
298
		return $html;
299
	}
300
301
	/**
302
	 * Return HTML5 video static markup for the given video parameters.
303
	 * Use default browser player controls.
304
	 * No Flash fallback.
305
	 *
306
	 * @since 1.2
307
	 * @link http://www.whatwg.org/specs/web-apps/current-work/multipage/video.html HTML5 video
308
	 * @return string HTML5 video element and children
309
	 */
310
	private function html5_static() {
311
		wp_enqueue_script( 'videopress' );
312
		$thumbnail = esc_url( $this->video->poster_frame_uri );
313
		$html = "<video id=\"{$this->video_id}\" width=\"{$this->video->calculated_width}\" height=\"{$this->video->calculated_height}\" poster=\"$thumbnail\" controls=\"true\"";
314 View Code Duplication
		if ( isset( $this->options['autoplay'] ) && $this->options['autoplay'] === true )
315
			$html .= ' autoplay="true"';
316
		else
317
			$html .= ' preload="metadata"';
318
		if ( isset( $this->video->text_direction ) )
319
			$html .= ' dir="' . esc_attr( $this->video->text_direction ) . '"';
320 View Code Duplication
		if ( isset( $this->video->language ) )
321
			$html .= ' lang="' . esc_attr( $this->video->language ) . '"';
322
		$html .= '>';
323
		if ( ! isset( $this->options['freedom'] ) || $this->options['freedom'] === false ) {
324
			$mp4 = $this->video->videos->mp4->url;
325 View Code Duplication
			if ( ! empty( $mp4 ) )
326
				$html .= '<source src="' . esc_url( $mp4 ) . '" type="video/mp4; codecs=&quot;' . esc_attr( $this->video->videos->mp4->codecs ) . '&quot;" />';
327
			unset( $mp4 );
328
		}
329
		$ogg = $this->video->videos->ogv->url;
330 View Code Duplication
		if ( ! empty( $ogg ) )
331
			$html .= '<source src="' . esc_url( $ogg ) . '" type="video/ogg; codecs=&quot;' . esc_attr( $this->video->videos->ogv->codecs ) . '&quot;" />';
332
		unset( $ogg );
333
334
		$html .= '<div><img alt="';
335
		if ( isset( $this->video->title ) )
336
			$html .= esc_attr( $this->video->title );
337
		$html .= '" src="' . $thumbnail . '" width="' . $this->video->calculated_width . '" height="' . $this->video->calculated_height . '" /></div>';
338
		if ( isset( $this->options['freedom'] ) && $this->options['freedom'] === true )
339
			$html .= '<p class="robots-nocontent">' . sprintf( __( 'You do not have sufficient <a rel="nofollow" href="%s" target="_blank">freedom levels</a> to view this video. Support free software and upgrade.', 'jetpack' ), 'http://www.gnu.org/philosophy/free-sw.html' ) . '</p>';
340
		elseif ( isset( $this->video->title ) )
341
			$html .= '<p>' . esc_html( $this->video->title ) . '</p>';
342
		$html .= '</video>';
343
		return $html;
344
	}
345
346
	/**
347
	 * Click to play dynamic HTML5-capable player.
348
	 * The player displays a video preview section including poster frame,
349
	 * video title, play button and watermark on the original page load
350
	 * and calculates the playback capabilities of the browser. The video player
351
	 * is loaded when the visitor clicks on the video preview area.
352
	 * If Flash Player 10 or above is available the browser will display
353
	 * the Flash version of the video. If HTML5 video appears to be supported
354
	 * and the browser may be capable of MP4 (H.264, AAC) or OGV (Theora, Vorbis)
355
	 * playback the browser will display its native HTML5 player.
356
	 *
357
	 * @since 1.5
358
	 * @return string HTML markup
359
	 */
360
	private function html5_dynamic() {
361
362
		/**
363
		 * Filter the VideoPress legacy player feature
364
		 *
365
		 * This filter allows you to control whether the legacy VideoPress player should be used
366
		 * instead of the improved one.
367
		 *
368
		 * @module videopress
369
		 *
370
		 * @since 3.7.0
371
		 *
372
		 * @param boolean $videopress_use_legacy_player
373
		 */
374
		if ( ! apply_filters( 'jetpack_videopress_use_legacy_player', false ) ) {
375
			return $this->html5_dynamic_next();
376
		}
377
378
		wp_enqueue_script( 'videopress' );
379
		$video_placeholder_id = $this->video_container_id . '-placeholder';
380
		$age_gate_required = $this->age_gate_required();
381
		$width = absint( $this->video->calculated_width );
382
		$height = absint( $this->video->calculated_height );
383
384
		$html = '<div id="' . $video_placeholder_id . '" class="videopress-placeholder" style="';
385
		if ( $age_gate_required )
386
			$html .= "min-width:{$width}px;min-height:{$height}px";
387
		else
388
			$html .= "width:{$width}px;height:{$height}px";
389
		$html .= ';display:none;cursor:pointer !important;position:relative;';
390
		if ( isset( $this->video->skin ) && isset( $this->video->skin->background_color ) )
391
			$html .= 'background-color:' . esc_attr( $this->video->skin->background_color ) . ';';
392
		$html .= 'font-family: \'Helvetica Neue\',Arial,Helvetica,\'Nimbus Sans L\',sans-serif;font-weight:bold;font-size:18px">' . PHP_EOL;
393
394
		/**
395
		 * Do not display a poster frame, title, or any other content hints for mature content.
396
		 */
397
		if ( ! $age_gate_required ) {
398
			if ( ! empty( $this->video->title ) ) {
399
				$html .= '<div class="videopress-title" style="display:inline;position:absolute;margin:20px 20px 0 20px;padding:4px 8px;vertical-align:top;text-align:';
400
				if ( $this->video->text_direction === 'rtl' )
401
					$html .= 'right" dir="rtl"';
402
				else
403
					$html .= 'left" dir="ltr"';
404 View Code Duplication
				if ( isset( $this->video->language ) )
405
					$html .= ' lang="' . esc_attr( $this->video->language ) . '"';
406
				$html .= '><span style="padding:3px 0;line-height:1.5em;';
407
				if ( isset( $this->video->skin ) && isset( $this->video->skin->background_color ) ) {
408
					$html .= 'background-color:';
409
					if ( $this->video->skin->background_color === 'rgb(0,0,0)' )
410
						$html .= 'rgba(0,0,0,0.8)';
411
					else
412
						$html .= esc_attr( $this->video->skin->background_color );
413
					$html .= ';';
414
				}
415
				$html .= 'color:rgb(255,255,255)">' . esc_html( $this->video->title ) . '</span></div>';
416
			}
417
			$html .= '<img class="videopress-poster" alt="';
418
			if ( ! empty( $this->video->title ) )
419
				$html .= esc_attr( $this->video->title ) . '" title="' . esc_attr( sprintf( _x( 'Watch: %s', 'watch a video title', 'jetpack' ), $this->video->title ) );
420
			$html .= '" src="' . esc_url( $this->video->poster_frame_uri, array( 'http', 'https' ) ) . '" width="' . $width . '" height="' . $height . '" />' . PHP_EOL;
421
422
			//style a play button hovered over the poster frame
423
			$html .= '<div class="play-button"><span style="z-index:2;display:block;position:absolute;top:50%;left:50%;text-align:center;vertical-align:middle;color:rgb(255,255,255);opacity:0.9;margin:0 0 0 -0.45em;padding:0;line-height:0;font-size:500%;text-shadow:0 0 40px rgba(0,0,0,0.5)">&#9654;</span></div>' . PHP_EOL;
424
425
			// watermark
426
			if ( isset( $this->video->skin ) && isset( $this->video->skin->watermark ) ) {
427
				$html .= '<div style="position:relative;margin-top:-40px;height:25px;margin-bottom:35px;';
428
				if ( $this->video->text_direction === 'rtl' )
429
					$html .= 'margin-left:20px;text-align:left;';
430
				else
431
					$html .= 'margin-right:20px;text-align:right;';
432
				$html .= 'vertical-align:bottom;z-index:3">';
433
				$html .= '<img alt="" src="' . esc_url( $this->video->skin->watermark, array( 'http', 'https' ) ) . '" width="90" height="13" style="background-color:transparent;background-image:none;background-repeat:no-repeat;border:none;margin:0;padding:0"/>';
434
				$html .= '</div>' . PHP_EOL;
435
			}
436
		}
437
438
		$data = array(
439
			'blog' => absint( $this->video->blog_id ),
440
			'post' => absint( $this->video->post_id ),
441
			'duration'=> absint( $this->video->duration ),
442
			'poster' => esc_url_raw( $this->video->poster_frame_uri, array( 'http', 'https' ) ),
443
			'hd' => (bool) $this->options['hd']
444
		);
445
		if ( isset( $this->video->videos ) ) {
446
			if ( isset( $this->video->videos->mp4 ) && isset( $this->video->videos->mp4->url ) )
447
				$data['mp4'] = array( 'size' => $this->video->videos->mp4->format, 'uri' => esc_url_raw( $this->video->videos->mp4->url, array( 'http', 'https' ) ) );
448
			if ( isset( $this->video->videos->ogv ) && isset( $this->video->videos->ogv->url ) )
449
				$data['ogv'] = array( 'size' => 'std', 'uri' => esc_url_raw( $this->video->videos->ogv->url, array( 'http', 'https' ) ) );
450
		}
451
		$locale = array( 'dir' => $this->video->text_direction );
452
		if ( isset( $this->video->language ) )
453
			$locale['lang'] = $this->video->language;
454
		$data['locale'] = $locale;
455
		unset( $locale );
456
457
		$guid = $this->video->guid;
458
		$guid_js = json_encode( $guid );
459
		$html .= '<script type="text/javascript">' . PHP_EOL;
460
		$html .= 'jQuery(document).ready(function() {';
461
462
		$html .= 'if ( !jQuery.VideoPress.data[' . json_encode($guid) . '] ) { jQuery.VideoPress.data[' . json_encode($guid) . '] = new Array(); }' . PHP_EOL;
463
		$html .= 'jQuery.VideoPress.data[' . json_encode( $guid ) . '][' . self::$shown[ $guid ] . ']=' . json_encode($data) . ';' . PHP_EOL;
464
		unset( $data );
465
466
		$jq_container = json_encode( '#' . $this->video_container_id );
467
		$jq_placeholder = json_encode( '#' . $video_placeholder_id );
468
		$player_config = "{width:{$width},height:{$height},";
469
		if ( isset( $this->options['freedom'] ) && $this->options['freedom'] === true )
470
			$player_config .= 'freedom:"true",';
471
		$player_config .= 'container:jQuery(' . $jq_container . ')}';
472
473
		$html .= "jQuery({$jq_placeholder}).show(0,function(){jQuery.VideoPress.analytics.impression({$guid_js})});" . PHP_EOL;
474
475
		if ( $age_gate_required ) {
476
			$html .= 'if ( jQuery.VideoPress.support.flash() ) {' . PHP_EOL;
477
			/**
478
			 * @link http://code.google.com/p/swfobject/wiki/api#swfobject.embedSWF(swfUrlStr,_replaceElemIdStr,_widthStr,_height
479
			 */
480
			$html .= 'swfobject.embedSWF(' . implode( ',', array(
481
				'jQuery.VideoPress.video.flash.player_uri',
482
				json_encode( $this->video_container_id ),
483
				json_encode( $width ),
484
				json_encode( $height ),
485
				'jQuery.VideoPress.video.flash.min_version',
486
				'jQuery.VideoPress.video.flash.expressinstall', // attempt to upgrade the Flash player if less than min_version. requires a 310x137 container or larger but we will always try to include
487
				'{guid:' . $guid_js . '}', // FlashVars
488
				'jQuery.VideoPress.video.flash.params',
489
				'null', // no attributes
490
				'jQuery.VideoPress.video.flash.embedCallback' // error fallback
491
			) ) . ');';
492
			$html .= '} else {' . PHP_EOL;
493
			$html .= "if ( jQuery.VideoPress.video.prepare({$guid_js},{$player_config}," . self::$shown[ $guid ] . ') ) {' . PHP_EOL;
494
			$html .= 'if ( jQuery(' . $jq_container . ').data( "player" ) === "flash" ){jQuery.VideoPress.video.play(jQuery(' . json_encode('#' . $this->video_container_id) . '));}else{';
495
			$html .= 'jQuery(' . $jq_placeholder . ').html(' . json_encode( $this->html_age_date() ) . ');' . PHP_EOL;
0 ignored issues
show
Bug introduced by
The method html_age_date() does not exist on VideoPress_Player. Did you maybe mean html_age_gate()?

This check marks calls to methods that do not seem to exist on an object.

This is most likely the result of a method being renamed without all references to it being renamed likewise.

Loading history...
496
			$html .= 'jQuery(' . json_encode( '#' . $video_placeholder_id . ' input[type=submit]' ) . ').one("click", function(event){jQuery.VideoPress.requirements.isSufficientAge(jQuery(' . $jq_container . '),' . absint( $this->video->age_rating ) . ')});' . PHP_EOL;
497
			$html .= '}}}' . PHP_EOL;
498
		} else {
499
			$html .= "if ( jQuery.VideoPress.video.prepare({$guid_js}, {$player_config}," . self::$shown[ $guid ] . ') ) {' . PHP_EOL;
500
			if ( isset( $this->options['autoplay'] ) && $this->options['autoplay'] === true )
501
				$html .= "jQuery.VideoPress.video.play(jQuery({$jq_container}));";
502
			else
503
				$html .= 'jQuery(' . $jq_placeholder .  ').one("click",function(){jQuery.VideoPress.video.play(jQuery(' . $jq_container . '))});';
504
			$html .= '}';
505
506
			// close the jQuery(document).ready() function
507
			$html .= '});';
508
		}
509
		$html .= '</script>' . PHP_EOL;
510
		$html .= '</div>' . PHP_EOL;
511
512
		/*
513
		 * JavaScript required
514
		 */
515
		$noun = __( 'this video', 'jetpack' );
516
		if ( ! $age_gate_required ) {
517
			$vid_type = '';
518
			if ( ( isset( $this->options['freedom'] ) && $this->options['freedom'] === true ) && ( isset( $this->video->videos->ogv ) && isset( $this->video->videos->ogv->url ) ) )
519
				$vid_type = 'ogv';
520 View Code Duplication
			elseif ( isset( $this->video->videos->mp4 ) && isset( $this->video->videos->mp4->url ) )
521
				$vid_type = 'mp4';
522 View Code Duplication
			elseif ( isset( $this->video->videos->ogv ) && isset( $this->video->videos->ogv->url ) )
523
				$vid_type = 'ogv';
524
525
			if ( $vid_type !== '' ) {
526
				$noun = '<a ';
527 View Code Duplication
				if ( isset( $this->video->language ) )
528
					$noun .= 'hreflang="' . esc_attr( $this->video->language ) . '" ';
529
				if ( $vid_type === 'mp4' )
530
					$noun .= 'type="video/mp4" href="' . esc_url( $this->video->videos->mp4->url, array( 'http', 'https' ) );
531
				elseif ( $vid_type === 'ogv' )
532
					$noun .= 'type="video/ogv" href="' . esc_url( $this->video->videos->ogv->url, array( 'http', 'https' ) );
533
				$noun .= '">';
534
				if ( isset( $this->video->title ) )
535
					$noun .= esc_html( $this->video->title );
536
				else
537
					$noun .= __( 'this video', 'jetpack' );
538
				$noun .= '</a>';
539
			} elseif ( ! empty( $this->title ) ) {
0 ignored issues
show
Bug introduced by
The property title does not exist. Did you maybe forget to declare it?

In PHP it is possible to write to properties without declaring them. For example, the following is perfectly valid PHP code:

class MyClass { }

$x = new MyClass();
$x->foo = true;

Generally, it is a good practice to explictly declare properties to avoid accidental typos and provide IDE auto-completion:

class MyClass {
    public $foo;
}

$x = new MyClass();
$x->foo = true;
Loading history...
540
				$noun = esc_html( $this->title );
541
			}
542
			unset( $vid_type );
543
		}
544
		$html .= '<noscript><p>' . sprintf( _x( 'JavaScript required to play %s.', 'Play as in playback or view a movie', 'jetpack' ), $noun ) . '</p></noscript>';
545
546
		return $html;
547
	}
548
549
	function html5_dynamic_next() {
550
		$video_container_id = 'v-' . $this->video->guid;
551
552
		// Must not use iframes for IE11 due to a fullscreen bug
553
		if ( isset( $_SERVER['HTTP_USER_AGENT'] ) && stristr( $_SERVER['HTTP_USER_AGENT'], 'Trident/7.0; rv:11.0' ) ) {
554
			$iframe_embed = false;
555
		} else {
556
557
			/**
558
			 * Filter the VideoPress iframe embed
559
			 *
560
			 * This filter allows you to control whether the videos will be embedded using an iframe.
561
			 * Set this to false in order to use an in-page embed rather than an iframe.
562
			 *
563
			 * @module videopress
564
			 *
565
			 * @since 3.7.0
566
			 *
567
			 * @param boolean $videopress_player_use_iframe
568
			 */
569
			$iframe_embed = apply_filters( 'jetpack_videopress_player_use_iframe', true );
570
		}
571
572
		if ( ! array_key_exists( 'hd', $this->options ) ) {
573
			$this->options['hd'] = (bool) get_option( 'video_player_high_quality', false );
574
		}
575
576
		$videopress_options = array(
577
			'width' => absint( $this->video->calculated_width ),
578
			'height' => absint( $this->video->calculated_height ),
579
		);
580
		foreach ( $this->options as $option => $value ) {
581
			switch ( $option ) {
582
				case 'at':
583
					if ( intval( $value ) ) {
584
						$videopress_options[ $option ] = intval( $value );
585
					}
586
					break;
587
				case 'autoplay':
0 ignored issues
show
Coding Style introduced by
There must be a comment when fall-through is intentional in a non-empty case body
Loading history...
588
					$option = 'autoPlay';
589
				case 'hd':
590
				case 'loop':
591
				case 'permalink':
592
					if ( in_array( $value, array( 1, 'true' ) ) ) {
593
						$videopress_options[ $option ] = true;
594
					} elseif ( in_array( $value, array( 0, 'false' ) ) ) {
595
						$videopress_options[ $option ] = false;
596
					}
597
					break;
598
				case 'defaultlangcode':
599
					$option = 'defaultLangCode';
600
					if ( $value ) {
601
						$videopress_options[ $option ] = $value;
602
					}
603
					break;
604
			}
605
		}
606
607
		if ( $iframe_embed ) {
608
			$iframe_url = "https://videopress.com/embed/{$this->video->guid}";
609
610
			foreach ( $videopress_options as $option => $value ) {
611
				if ( ! in_array( $option, array( 'width', 'height' ) ) ) {
612
613
					// add_query_arg ignores false as a value, so replacing it with 0
614
					$iframe_url = add_query_arg( $option, ( false === $value ) ? 0 : $value, $iframe_url );
615
				}
616
			}
617
618
			$js_url = 'https://s0.wp.com/wp-content/plugins/video/assets/js/next/videopress-iframe.js';
619
			$js_url = add_query_arg( 'jetpack_version', JETPACK__VERSION, $js_url );
620
621
			return "<iframe width='" . esc_attr( $videopress_options['width'] )
622
				. "' height='" . esc_attr( $videopress_options['height'] )
623
				. "' src='" . esc_attr( $iframe_url )
624
				. "' frameborder='0' allowfullscreen></iframe>"
625
				. "<script src='" . esc_attr( $js_url ) . "'></script>";
626
627
		} else {
628
			$videopress_options = json_encode( $videopress_options );
629
			$js_url = 'https://s0.wp.com/wp-content/plugins/video/assets/js/next/videopress.js';
630
			$js_url = add_query_arg( 'jetpack_version', JETPACK__VERSION, $js_url );
631
632
			return "<div id='{$video_container_id}'></div>
633
				<script src='{$js_url}'></script>
634
				<script>
635
					videopress('{$this->video->guid}', document.querySelector('#{$video_container_id}'), {$videopress_options});
636
				</script>";
637
		}
638
	}
639
640
	/**
641
	 * Only allow legitimate Flash parameters and their values
642
	 *
643
	 * @since 1.2
644
	 * @link http://kb2.adobe.com/cps/127/tn_12701.html Flash object and embed attributes
645
	 * @link http://kb2.adobe.com/cps/133/tn_13331.html devicefont
646
	 * @link http://kb2.adobe.com/cps/164/tn_16494.html allowscriptaccess
647
	 * @link http://www.adobe.com/devnet/flashplayer/articles/full_screen_mode.html full screen mode
648
	 * @link http://livedocs.adobe.com/flash/9.0/main/wwhelp/wwhimpl/common/html/wwhelp.htm?context=LiveDocs_Parts&file=00001079.html allownetworking
649
	 * @param array $flash_params Flash parameters expressed in key-value form
650
	 * @return array validated Flash parameters
651
	 */
652
	public static function esc_flash_params( $flash_params ) {
653
		$allowed_params = array(
654
			'swliveconnect' => array('true', 'false'),
655
			'play' => array('true', 'false'),
656
			'loop' => array('true', 'false'),
657
			'menu' => array('true', 'false'),
658
			'quality' => array('low', 'autolow', 'autohigh', 'medium', 'high', 'best'),
659
			'scale' => array('default', 'noborder', 'exactfit', 'noscale'),
660
			'align' => array('l', 'r', 't'),
661
			'salign' => array('l', 'r', 't', 'tl', 'tr', 'bl', 'br'),
662
			'wmode' => array('window', 'opaque', 'transparent','direct','gpu'),
663
			'devicefont' => array('_sans', '_serif', '_typewriter'),
664
			'allowscriptaccess' => array('always', 'samedomain', 'never'),
665
			'allownetworking' => array('all','internal', 'none'),
666
			'seamlesstabbing' => array('true', 'false'),
667
			'allowfullscreen' => array('true', 'false'),
668
			'fullScreenAspectRatio' => array('portrait', 'landscape'),
669
			'base',
670
			'bgcolor',
671
			'flashvars'
672
		);
673
674
		$allowed_params_keys = array_keys( $allowed_params );
675
676
		$filtered_params = array();
677
		foreach( $flash_params as $param=>$value ) {
678
			if ( empty($param) || empty($value) )
679
				continue;
680
			$param = strtolower($param);
681
			if ( in_array($param, $allowed_params_keys) ) {
682
				if ( isset( $allowed_params[$param] ) && is_array( $allowed_params[$param] ) ) {
683
					$value = strtolower($value);
684
					if ( in_array( $value, $allowed_params[$param] ) )
685
						$filtered_params[$param] = $value;
686
				} else {
687
					$filtered_params[$param] = $value;
688
				}
689
			}
690
		}
691
		unset( $allowed_params_keys );
692
693
		/**
694
		 * Flash specifies sameDomain, not samedomain. change from lowercase value for preciseness
695
		 */
696
		if ( isset( $filtered_params['allowscriptaccess'] ) && $filtered_params['allowscriptaccess'] === 'samedomain' )
697
			$filtered_params['allowscriptaccess'] = 'sameDomain';
698
699
		return $filtered_params;
700
	}
701
702
	/**
703
	 * Filter Flash variables from the response, taking into consideration player options.
704
	 *
705
	 * @since 1.3
706
	 * @return array Flash variable key value pairs
707
	 */
708
	private function get_flash_variables() {
709
		if ( ! isset( $this->video->players->swf->vars ) )
710
			return array();
711
712
		$flashvars = (array) $this->video->players->swf->vars;
713 View Code Duplication
		if ( isset( $this->options['autoplay'] ) && $this->options['autoplay'] === true )
714
			$flashvars['autoPlay'] = 'true';
715
		return $flashvars;
716
	}
717
718
	/**
719
	 * Validate and filter Flash parameters
720
	 *
721
	 * @since 1.3
722
	 * @return array Flash parameters passed through key and value validation
723
	 */
724
	private function get_flash_parameters() {
725
		if ( ! isset( $this->video->players->swf->params ) )
726
			return array();
727
		else
728
			return self::esc_flash_params(
729
				/**
730
				 * Filters the Flash parameters of the VideoPress player.
731
				 *
732
				 * @module videopress
733
				 *
734
				 * @since 1.2.0
735
				 *
736
				 * @param array $this->video->players->swf->params Array of swf parameters for the VideoPress flash player.
737
				 */
738
				apply_filters( 'video_flash_params', (array) $this->video->players->swf->params, 10, 1 )
739
			);
740
	}
741
742
	/**
743
	 * Flash player markup in a HTML embed element.
744
	 *
745
	 * @since 1.1
746
	 * @link http://www.whatwg.org/specs/web-apps/current-work/multipage/the-iframe-element.html#the-embed-element embed element
747
	 * @link http://www.google.com/support/reader/bin/answer.py?answer=70664 Google Reader markup support
748
	 * @return string HTML markup. Embed element with no children
749
	 */
750
	private function flash_embed() {
751
		wp_enqueue_script( 'videopress' );
752 View Code Duplication
		if ( ! isset( $this->video->players->swf ) || ! isset( $this->video->players->swf->url ) )
753
			return '';
754
755
		$embed = array(
756
			'id' => $this->video_id,
757
			'src' => esc_url_raw( $this->video->players->swf->url . '&' . http_build_query( $this->get_flash_variables(), null, '&' ) , array( 'http', 'https' ) ),
758
			'type' => 'application/x-shockwave-flash',
759
			'width' => $this->video->calculated_width,
760
			'height' => $this->video->calculated_height
761
		);
762
		if ( isset( $this->video->title ) )
763
			$embed['title'] = $this->video->title;
764
		$embed = array_merge( $embed, $this->get_flash_parameters() );
765
766
		$html = '<embed';
767
		foreach ( $embed as $attribute => $value ) {
768
			$html .= ' ' . esc_html( $attribute ) . '="' . esc_attr( $value ) . '"';
769
		}
770
		unset( $embed );
771
		$html .= '></embed>';
772
		return $html;
773
	}
774
775
	/**
776
	 * Double-baked Flash object markup for Internet Explorer and more standards-friendly consuming agents.
777
	 *
778
	 * @since 1.1
779
	 * @return HTML markup. Object and children.
780
	 */
781
	private function flash_object() {
782
		wp_enqueue_script( 'videopress' );
783 View Code Duplication
		if ( ! isset( $this->video->players->swf ) || ! isset( $this->video->players->swf->url ) )
784
			return '';
785
786
		$thumbnail_html = '<img alt="';
787
		if ( isset( $this->video->title ) )
788
			$thumbnail_html .= esc_attr( $this->video->title );
789
		$thumbnail_html .= '" src="' . esc_url( $this->video->poster_frame_uri, array( 'http', 'https' ) ) . '" width="' . $this->video->calculated_width . '" height="' . $this->video->calculated_height . '" />';
790
		$flash_vars = esc_attr( http_build_query( $this->get_flash_variables(), null, '&' ) );
791
		$flash_params = '';
792
		foreach ( $this->get_flash_parameters() as $attribute => $value ) {
793
			$flash_params .= '<param name="' . esc_attr( $attribute ) . '" value="' . esc_attr( $value ) . '" />';
794
		}
795
		$flash_help = sprintf( __( 'This video requires <a rel="nofollow" href="%s" target="_blank">Adobe Flash</a> for playback.', 'jetpack' ), 'http://www.adobe.com/go/getflashplayer');
796
		$flash_player_url = esc_url( $this->video->players->swf->url, array( 'http', 'https' ) );
797
		$description = '';
798
		if ( isset( $this->video->title ) ) {
799
			$standby = $this->video->title;
800
			$description = '<p><strong>' . esc_html( $this->video->title ) . '</strong></p>';
801
		} else {
802
			$standby = __( 'Loading video...', 'jetpack' );
803
		}
804
		$standby = ' standby="' . esc_attr( $standby ) . '"';
805
		return <<<OBJECT
806
<script type="text/javascript">if(typeof swfobject!=="undefined"){swfobject.registerObject("{$this->video_id}", "{$this->video->players->swf->version}");}</script>
807
<object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" width="{$this->video->calculated_width}" height="{$this->video->calculated_height}" id="{$this->video_id}"{$standby}>
808
	<param name="movie" value="{$flash_player_url}" />
809
	{$flash_params}
810
	<param name="flashvars" value="{$flash_vars}" />
811
	<!--[if !IE]>-->
812
	<object type="application/x-shockwave-flash" data="{$flash_player_url}" width="{$this->video->calculated_width}" height="{$this->video->calculated_height}"{$standby}>
813
		{$flash_params}
814
		<param name="flashvars" value="{$flash_vars}" />
815
	<!--<![endif]-->
816
	{$thumbnail_html}{$description}<p class="robots-nocontent">{$flash_help}</p>
817
	<!--[if !IE]>-->
818
	</object>
819
	<!--<![endif]-->
820
</object>
821
OBJECT;
822
	}
823
}
824