Completed
Push — v2/videopress ( 549e08...c1d5f0 )
by George
43:46 queued 26:27
created

VideoPress_Player::html_age_gate()   C

Complexity

Conditions 7
Paths 48

Size

Total Lines 68
Code Lines 40

Duplication

Lines 68
Ratio 100 %
Metric Value
dl 68
loc 68
rs 6.9654
cc 7
eloc 40
nc 48
nop 0

How to fix   Long Method   

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 View Code Duplication
class VideoPress_Player {
0 ignored issues
show
Duplication introduced by
This class seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
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
59
		self::$shown[ $guid ]++;
60
61
		$this->video_container_id = 'v-' . $guid . '-' . self::$shown[ $guid ];
62
		$this->video_id = $this->video_container_id . '-video';
63
64
		if ( is_array( $options ) ) {
65
			$this->options = $options;
66
		} else {
67
			$this->options = array();
68
		}
69
70
		// set up the video
71
		$cache_key = null;
72
73
		// disable cache in debug mode
74
		if ( defined('WP_DEBUG') && WP_DEBUG === true ) {
75
			$cached_video = null;
76
		} else {
77
			$cache_key_pieces = array( 'video' );
78
79
			if ( is_multisite() && is_subdomain_install() ) {
80
				$cache_key_pieces[] = get_current_blog_id();
81
			}
82
83
			$cache_key_pieces[] = $guid;
84
			if ( $maxwidth > 0 ) {
85
				$cache_key_pieces[] = $maxwidth;
86
			}
87
			if ( is_ssl() ) {
88
				$cache_key_pieces[] = 'ssl';
89
			}
90
			$cache_key = implode( '-', $cache_key_pieces );
91
			unset( $cache_key_pieces );
92
			$cached_video = wp_cache_get( $cache_key, 'video' );
93
		}
94
95
		if ( empty( $cached_video ) ) {
96
			$video = new VideoPress_Video( $guid, $maxwidth );
97
			if ( empty( $video ) ) {
98
				return;
99
			} elseif ( isset( $video->error ) ) {
100
				$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...
101
				return;
102
			} elseif ( is_wp_error( $video ) ) {
103
				$this->video = $video;
104
				return;
105
			}
106
107
			$this->video = $video;
108
			unset( $video );
109
110
			if ( ! defined( 'WP_DEBUG' ) || WP_DEBUG !== true ) {
111
				$expire = 3600;
112
				if ( isset( $video->expires ) && is_int( $video->expires ) ) {
113
					$expires_diff = time() - $video->expires;
114
					if ( $expires_diff > 0 && $expires_diff < 86400 ) { // allowed range: 1 second to 1 day
115
						$expire = $expires_diff;
116
					}
117
					unset( $expires_diff );
118
				}
119
120
				wp_cache_set( $cache_key, serialize( $this->video ), 'video', $expire );
121
				unset( $expire );
122
			}
123
		} else {
124
			$this->video = unserialize( $cached_video );
125
		}
126
		unset( $cache_key );
127
		unset( $cached_video );
128
	}
129
130
	/**
131
	 * Wrap output in a VideoPress player container
132
	 *
133
	 * @since 1.3
134
	 * @var string $content HTML string
135
	 * @return string HTML string or blank string if nothing to wrap
136
	 */
137
	private function html_wrapper( $content ) {
138
		if ( empty( $content ) ) {
139
			return '';
140
		} else {
141
			return '<div id="' . esc_attr( $this->video_container_id ) . '" class="video-player">' . $content . '</div>';
142
		}
143
	}
144
145
	/**
146
	 * Output content suitable for a feed reader displaying RSS or Atom feeds
147
	 * We do not display error messages in the feed view due to caching concerns.
148
	 * Flash content presented using <embed> markup for feed reader compatibility.
149
	 *
150
	 * @since 1.3
151
	 * @return string HTML string or empty string if error
152
	 */
153
	public function asXML() {
154
		if ( empty( $this->video ) || is_wp_error( $this->video ) ) {
155
			return '';
156
		}
157
158
		if ( isset( $this->options['freedom'] ) && $this->options['freedom'] === true ) {
159
			$content = $this->html5_static();
160
		} else {
161
			$content = $this->flash_embed();
162
		}
163
164
		return $this->html_wrapper( $content );
165
	}
166
167
	/**
168
	 * Video player markup for best matching the current request and publisher options
169
	 * @since 1.3
170
	 * @return string HTML markup string or empty string if no video property found
171
	 */
172
	public function asHTML() {
173
		if ( empty( $this->video ) ) {
174
			$content = '';
175
		} elseif ( is_wp_error( $this->video ) ) {
176
			$content = $this->error_message( $this->video );
177
		} elseif ( isset( $this->options['force_flash'] ) && $this->options['force_flash'] === true ) {
178
			$content = $this->flash_object();
179
		} elseif ( isset( $this->video->restricted_embed ) && $this->video->restricted_embed === true ) {
180
			if ( $this->options['forcestatic'] ) {
181
				$content = $this->flash_object();
182
			} else {
183
				$content = $this->html5_dynamic();
184
			}
185
		} elseif ( isset( $this->options['freedom'] ) && $this->options['freedom'] === true ) {
186
			$content = $this->html5_static();
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
207
		$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">';
208
		$html .= '<h1 style="font-size:180%;font-style:bold;line-height:130%;text-decoration:underline">' . esc_html( sprintf( __( '%s Error', 'jetpack' ), 'VideoPress' ) ) . '</h1>';
209
		foreach ( $error->get_error_messages() as $message ) {
210
			$html .= $message;
211
		}
212
		$html .= '</div>';
213
		return $html;
214
	}
215
216
	/**
217
	 * Rating agencies and industry associations require a potential viewer verify his or her age before a video or its poster frame are displayed.
218
	 * Content rated for audiences 17 years of age or older requires such verification across multiple rating agencies and industry associations
219
	 *
220
	 * @since 1.3
221
	 * @return bool true if video requires the viewer verify he or she is 17 years of age or older
222
	 */
223
	private function age_gate_required() {
224
		if ( isset( $this->video->age_rating ) && $this->video->age_rating >= 17 ) {
225
			return true;
226
		} else {
227
			return false;
228
		}
229
	}
230
231
	/**
232
	 * Select a date of birth using HTML form elements.
233
	 *
234
	 * @since 1.5
235
	 * @return string HTML markup
236
	 */
237
	private function html_age_gate() {
0 ignored issues
show
Unused Code introduced by
This method is not used, and could be removed.
Loading history...
238
		global $wp_locale;
239
		$text_align = 'left';
240
		if ( $this->video->text_direction === 'rtl' ) {
241
			$text_align = 'right';
242
		}
243
244
		$html = '<div class="videopress-age-gate" style="margin:0 60px">';
245
		$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>';
246
		$html .= '<fieldset id="birthday" style="border:0 none;text-align:' . $text_align . ';padding:0;">';
247
		$inputs_style = 'border:1px solid #444;margin-';
248
		if ( $this->video->text_direction === 'rtl' ) {
249
			$inputs_style .= 'left';
250
		} else {
251
			$inputs_style .= 'right';
252
		}
253
		$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';
254
255
		/**
256
		 * Display a list of months in the Gregorian calendar.
257
		 * Set values to 0-based to match JavaScript Date.
258
		 * @link https://developer.mozilla.org/en/JavaScript/Reference/global_objects/date Mozilla JavaScript Reference: Date
259
		 */
260
		$html .= '<select name="month" style="' . $inputs_style . '">';
261
262
		for ( $i=0; $i<12; $i++ ) {
263
			$html .= '<option value="' . esc_attr( $i ) . '">' . esc_html( $wp_locale->get_month( $i + 1 ) )  . '</option>';
264
		}
265
		$html .= '</select>';
266
267
		/**
268
		 * 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...
269
		 */
270
		$html .= '<select name="day" style="' . $inputs_style . '">';
271
		for ( $i = 1; $i < 32; $i++ ) {
272
			$html .= '<option>' . $i . '</option>';
273
		}
274
		$html .= '</select>';
275
276
		/**
277
		 * Current record for human life is 122. Go back 130 years and no one is left out.
278
		 * Don't ask infants younger than 2 for their birthday
279
		 * Default to 13
280
		 */
281
		$html .= '<select name="year" style="' . $inputs_style . '">';
282
		$start_year = date('Y') - 2;
283
		$default_year = $start_year - 11;
284
		$end_year = $start_year - 128;
285
		for ( $year=$start_year; $year>$end_year; $year-- ) {
286
			$html .= '<option';
287
			if ( $year === $default_year ) {
288
				$html .= ' selected="selected"';
289
			}
290
			$html .= '>' . $year . '</option>';
291
		}
292
		unset( $start_year );
293
		unset( $default_year );
294
		unset( $end_year );
295
		$html .= '</select>';
296
297
		$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" />';
298
299
		$html .= '</fieldset>';
300
		$html .= '<p style="padding-top:20px;padding-bottom:60px;text-align:' . $text_align . ';"><a rel="nofollow" href="http://videopress.com/" style="color:rgb(128,128,128);text-decoration:underline;font-size:15px">' . __( 'More information', 'jetpack' ) . '</a></p>';
301
302
		$html .= '</div>';
303
		return $html;
304
	}
305
306
	/**
307
	 * Return HTML5 video static markup for the given video parameters.
308
	 * Use default browser player controls.
309
	 * No Flash fallback.
310
	 *
311
	 * @since 1.2
312
	 * @link http://www.whatwg.org/specs/web-apps/current-work/multipage/video.html HTML5 video
313
	 * @return string HTML5 video element and children
314
	 */
315
	private function html5_static() {
316
		wp_enqueue_script( 'videopress' );
317
		$thumbnail = esc_url( $this->video->poster_frame_uri );
318
		$html = "<video id=\"{$this->video_id}\" width=\"{$this->video->calculated_width}\" height=\"{$this->video->calculated_height}\" poster=\"$thumbnail\" controls=\"true\"";
319
320
		if ( isset( $this->options['autoplay'] ) && $this->options['autoplay'] === true ) {
321
			$html .= ' autoplay="true"';
322
		} else {
323
			$html .= ' preload="metadata"';
324
		}
325
326
		if ( isset( $this->video->text_direction ) ) {
327
			$html .= ' dir="' . esc_attr( $this->video->text_direction ) . '"';
328
		}
329
		if ( isset( $this->video->language ) ) {
330
			$html .= ' lang="' . esc_attr( $this->video->language ) . '"';
331
		}
332
		$html .= '>';
333
		if ( ! isset( $this->options['freedom'] ) || $this->options['freedom'] === false ) {
334
			$mp4 = $this->video->videos->mp4->url;
335
			if ( ! empty( $mp4 ) ) {
336
				$html .= '<source src="' . esc_url( $mp4 ) . '" type="video/mp4; codecs=&quot;' . esc_attr( $this->video->videos->mp4->codecs ) . '&quot;" />';
337
			}
338
			unset( $mp4 );
339
		}
340
		$ogg = $this->video->videos->ogv->url;
341
		if ( ! empty( $ogg ) ) {
342
			$html .= '<source src="' . esc_url( $ogg ) . '" type="video/ogg; codecs=&quot;' . esc_attr( $this->video->videos->ogv->codecs ) . '&quot;" />';
343
		}
344
		unset( $ogg );
345
346
		$html .= '<div><img alt="';
347
		if ( isset( $this->video->title ) ) {
348
			$html .= esc_attr( $this->video->title );
349
		}
350
		$html .= '" src="' . $thumbnail . '" width="' . $this->video->calculated_width . '" height="' . $this->video->calculated_height . '" /></div>';
351
		if ( isset( $this->options['freedom'] ) && $this->options['freedom'] === true ) {
352
			$html .= '<p class="robots-nocontent">' . sprintf( __( 'You do not have sufficient <a rel="nofollow" href="%s">freedom levels</a> to view this video. Support free software and upgrade.', 'jetpack' ), 'http://www.gnu.org/philosophy/free-sw.html' ) . '</p>';
353
		} elseif ( isset( $this->video->title ) ) {
354
			$html .= '<p>' . esc_html( $this->video->title ) . '</p>';
355
		}
356
		$html .= '</video>';
357
		return $html;
358
	}
359
360
	/**
361
	 * Click to play dynamic HTML5-capable player.
362
	 * The player displays a video preview section including poster frame,
363
	 * video title, play button and watermark on the original page load
364
	 * and calculates the playback capabilities of the browser. The video player
365
	 * is loaded when the visitor clicks on the video preview area.
366
	 * If Flash Player 10 or above is available the browser will display
367
	 * the Flash version of the video. If HTML5 video appears to be supported
368
	 * and the browser may be capable of MP4 (H.264, AAC) or OGV (Theora, Vorbis)
369
	 * playback the browser will display its native HTML5 player.
370
	 *
371
	 * @since 1.5
372
	 * @return string HTML markup
373
	 */
374
	private function html5_dynamic() {
375
376
		/**
377
		 * Filter the VideoPress legacy player feature
378
		 *
379
		 * This filter allows you to control whether the legacy VideoPress player should be used
380
		 * instead of the improved one.
381
		 *
382
		 * @module videopress
383
		 *
384
		 * @since 3.7.0
385
		 *
386
		 * @param boolean $videopress_use_legacy_player
387
		 */
388
		if ( ! apply_filters( 'jetpack_videopress_use_legacy_player', false ) ) {
389
			return $this->html5_dynamic_next();
390
		}
391
392
		wp_enqueue_script( 'videopress' );
393
		$video_placeholder_id = $this->video_container_id . '-placeholder';
394
		$age_gate_required = $this->age_gate_required();
395
		$width = absint( $this->video->calculated_width );
396
		$height = absint( $this->video->calculated_height );
397
398
		$html = '<div id="' . $video_placeholder_id . '" class="videopress-placeholder" style="';
399
		if ( $age_gate_required ) {
400
			$html .= "min-width:{$width}px;min-height:{$height}px";
401
		} else {
402
			$html .= "width:{$width}px;height:{$height}px";
403
		}
404
		$html .= ';display:none;cursor:pointer !important;position:relative;';
405
		if ( isset( $this->video->skin ) && isset( $this->video->skin->background_color ) ) {
406
			$html .= 'background-color:' . esc_attr( $this->video->skin->background_color ) . ';';
407
		}
408
		$html .= 'font-family: \'Helvetica Neue\',Arial,Helvetica,\'Nimbus Sans L\',sans-serif;font-weight:bold;font-size:18px">' . PHP_EOL;
409
410
		/**
411
		 * Do not display a poster frame, title, or any other content hints for mature content.
412
		 */
413
		if ( ! $age_gate_required ) {
414
			if ( ! empty( $this->video->title ) ) {
415
				$html .= '<div class="videopress-title" style="display:inline;position:absolute;margin:20px 20px 0 20px;padding:4px 8px;vertical-align:top;text-align:';
416
				if ( $this->video->text_direction === 'rtl' ) {
417
					$html .= 'right" dir="rtl"';
418
				} else {
419
					$html .= 'left" dir="ltr"';
420
				}
421
				if ( isset( $this->video->language ) ) {
422
					$html .= ' lang="' . esc_attr( $this->video->language ) . '"';
423
				}
424
				$html .= '><span style="padding:3px 0;line-height:1.5em;';
425
				if ( isset( $this->video->skin ) && isset( $this->video->skin->background_color ) ) {
426
					$html .= 'background-color:';
427
					if ( $this->video->skin->background_color === 'rgb(0,0,0)' ) {
428
						$html .= 'rgba(0,0,0,0.8)';
429
					} else {
430
						$html .= esc_attr( $this->video->skin->background_color );
431
					}
432
					$html .= ';';
433
				}
434
				$html .= 'color:rgb(255,255,255)">' . esc_html( $this->video->title ) . '</span></div>';
435
			}
436
			$html .= '<img class="videopress-poster" alt="';
437
			if ( ! empty( $this->video->title ) ) {
438
				$html .= esc_attr( $this->video->title ) . '" title="' . esc_attr( sprintf( _x( 'Watch: %s', 'watch a video title', 'jetpack' ), $this->video->title ) );
439
			}
440
			$html .= '" src="' . esc_url( $this->video->poster_frame_uri, array( 'http', 'https' ) ) . '" width="' . $width . '" height="' . $height . '" />' . PHP_EOL;
441
442
			//style a play button hovered over the poster frame
443
			$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;
444
445
			// watermark
446
			if ( isset( $this->video->skin ) && isset( $this->video->skin->watermark ) ) {
447
				$html .= '<div style="position:relative;margin-top:-40px;height:25px;margin-bottom:35px;';
448
				if ( $this->video->text_direction === 'rtl' ) {
449
					$html .= 'margin-left:20px;text-align:left;';
450
				} else {
451
					$html .= 'margin-right:20px;text-align:right;';
452
				}
453
				$html .= 'vertical-align:bottom;z-index:3">';
454
				$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"/>';
455
				$html .= '</div>' . PHP_EOL;
456
			}
457
		}
458
459
		$data = array(
460
			'blog' => absint( $this->video->blog_id ),
461
			'post' => absint( $this->video->post_id ),
462
			'duration'=> absint( $this->video->duration ),
463
			'poster' => esc_url_raw( $this->video->poster_frame_uri, array( 'http', 'https' ) ),
464
			'hd' => (bool) $this->options['hd']
465
		);
466
		if ( isset( $this->video->videos ) ) {
467
			if ( isset( $this->video->videos->mp4 ) && isset( $this->video->videos->mp4->url ) ) {
468
				$data['mp4'] = array(
469
					'size' => $this->video->videos->mp4->format,
470
					'uri'  => esc_url_raw( $this->video->videos->mp4->url, array( 'http', 'https' ) )
471
				);
472
			}
473
			if ( isset( $this->video->videos->ogv ) && isset( $this->video->videos->ogv->url ) ) {
474
				$data['ogv'] = array(
475
					'size' => 'std',
476
					'uri'  => esc_url_raw( $this->video->videos->ogv->url, array( 'http', 'https' ) )
477
				);
478
			}
479
		}
480
		$locale = array( 'dir' => $this->video->text_direction );
481
		if ( isset( $this->video->language ) )
482
			$locale['lang'] = $this->video->language;
483
		$data['locale'] = $locale;
484
		unset( $locale );
485
486
		$guid = $this->video->guid;
487
		$guid_js = json_encode( $guid );
488
		$html .= '<script type="text/javascript">' . PHP_EOL;
489
		$html .= 'jQuery(document).ready(function() {';
490
491
		$html .= 'if ( !jQuery.VideoPress.data[' . json_encode($guid) . '] ) { jQuery.VideoPress.data[' . json_encode($guid) . '] = new Array(); }' . PHP_EOL;
492
		$html .= 'jQuery.VideoPress.data[' . json_encode( $guid ) . '][' . self::$shown[ $guid ] . ']=' . json_encode($data) . ';' . PHP_EOL;
493
		unset( $data );
494
495
		$jq_container = json_encode( '#' . $this->video_container_id );
496
		$jq_placeholder = json_encode( '#' . $video_placeholder_id );
497
		$player_config = "{width:{$width},height:{$height},";
498
		if ( isset( $this->options['freedom'] ) && $this->options['freedom'] === true ) {
499
			$player_config .= 'freedom:"true",';
500
		}
501
		$player_config .= 'container:jQuery(' . $jq_container . ')}';
502
503
		$html .= "jQuery({$jq_placeholder}).show(0,function(){jQuery.VideoPress.analytics.impression({$guid_js})});" . PHP_EOL;
504
505
		if ( $age_gate_required ) {
506
			$html .= 'if ( jQuery.VideoPress.support.flash() ) {' . PHP_EOL;
507
			/**
508
			 * @link http://code.google.com/p/swfobject/wiki/api#swfobject.embedSWF(swfUrlStr,_replaceElemIdStr,_widthStr,_height
509
			 */
510
			$html .= 'swfobject.embedSWF(' . implode( ',', array(
511
				'jQuery.VideoPress.video.flash.player_uri',
512
				json_encode( $this->video_container_id ),
513
				json_encode( $width ),
514
				json_encode( $height ),
515
				'jQuery.VideoPress.video.flash.min_version',
516
				'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
517
				'{guid:' . $guid_js . '}', // FlashVars
518
				'jQuery.VideoPress.video.flash.params',
519
				'null', // no attributes
520
				'jQuery.VideoPress.video.flash.embedCallback' // error fallback
521
			) ) . ');';
522
			$html .= '} else {' . PHP_EOL;
523
			$html .= "if ( jQuery.VideoPress.video.prepare({$guid_js},{$player_config}," . self::$shown[ $guid ] . ') ) {' . PHP_EOL;
524
			$html .= 'if ( jQuery(' . $jq_container . ').data( "player" ) === "flash" ){jQuery.VideoPress.video.play(jQuery(' . json_encode('#' . $this->video_container_id) . '));}else{';
525
			$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...
526
			$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;
527
			$html .= '}}}' . PHP_EOL;
528
		} else {
529
			$html .= "if ( jQuery.VideoPress.video.prepare({$guid_js}, {$player_config}," . self::$shown[ $guid ] . ') ) {' . PHP_EOL;
530
			if ( isset( $this->options['autoplay'] ) && $this->options['autoplay'] === true ) {
531
				$html .= "jQuery.VideoPress.video.play(jQuery({$jq_container}));";
532
			} else {
533
				$html .= 'jQuery(' . $jq_placeholder . ').one("click",function(){jQuery.VideoPress.video.play(jQuery(' . $jq_container . '))});';
534
			}
535
			$html .= '}';
536
537
			// close the jQuery(document).ready() function
538
			$html .= '});';
539
		}
540
		$html .= '</script>' . PHP_EOL;
541
		$html .= '</div>' . PHP_EOL;
542
543
		/*
544
		 * JavaScript required
545
		 */
546
		$noun = __( 'this video', 'jetpack' );
547
		if ( ! $age_gate_required ) {
548
			$vid_type = '';
549
			if ( ( isset( $this->options['freedom'] ) && $this->options['freedom'] === true ) && ( isset( $this->video->videos->ogv ) && isset( $this->video->videos->ogv->url ) ) ) {
550
				$vid_type = 'ogv';
551
			} elseif ( isset( $this->video->videos->mp4 ) && isset( $this->video->videos->mp4->url ) ) {
552
				$vid_type = 'mp4';
553
			} elseif ( isset( $this->video->videos->ogv ) && isset( $this->video->videos->ogv->url ) ) {
554
				$vid_type = 'ogv';
555
			}
556
557
			if ( $vid_type !== '' ) {
558
				$noun = '<a ';
559
				if ( isset( $this->video->language ) ) {
560
					$noun .= 'hreflang="' . esc_attr( $this->video->language ) . '" ';
561
				}
562
				if ( $vid_type === 'mp4' ) {
563
					$noun .= 'type="video/mp4" href="' . esc_url( $this->video->videos->mp4->url, array(
564
							'http',
565
							'https'
566
						) );
567
				} elseif ( $vid_type === 'ogv' ) {
568
					$noun .= 'type="video/ogv" href="' . esc_url( $this->video->videos->ogv->url, array(
569
							'http',
570
							'https'
571
						) );
572
				}
573
				$noun .= '">';
574
				if ( isset( $this->video->title ) ) {
575
					$noun .= esc_html( $this->video->title );
576
				} else {
577
					$noun .= __( 'this video', 'jetpack' );
578
				}
579
				$noun .= '</a>';
580
			} 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...
581
				$noun = esc_html( $this->title );
582
			}
583
			unset( $vid_type );
584
		}
585
		$html .= '<noscript><p>' . sprintf( _x( 'JavaScript required to play %s.', 'Play as in playback or view a movie', 'jetpack' ), $noun ) . '</p></noscript>';
586
587
		return $html;
588
	}
589
590
	function html5_dynamic_next() {
591
		$video_container_id = 'v-' . $this->video->guid;
592
593
		// Must not use iframes for IE11 due to a fullscreen bug
594
		if ( isset( $_SERVER['HTTP_USER_AGENT'] ) && stristr( $_SERVER['HTTP_USER_AGENT'], 'Trident/7.0; rv:11.0' ) ) {
595
			$iframe_embed = false;
596
		} else {
597
598
			/**
599
			 * Filter the VideoPress iframe embed
600
			 *
601
			 * This filter allows you to control whether the videos will be embedded using an iframe.
602
			 * Set this to false in order to use an in-page embed rather than an iframe.
603
			 *
604
			 * @module videopress
605
			 *
606
			 * @since 3.7.0
607
			 *
608
			 * @param boolean $videopress_player_use_iframe
609
			 */
610
			$iframe_embed = apply_filters( 'jetpack_videopress_player_use_iframe', true );
611
		}
612
613
		if ( ! array_key_exists( 'hd', $this->options ) ) {
614
			$this->options['hd'] = (bool) get_option( 'video_player_high_quality', false );
615
		}
616
617
		$videopress_options = array(
618
			'width' => absint( $this->video->calculated_width ),
619
			'height' => absint( $this->video->calculated_height ),
620
		);
621
		foreach ( $this->options as $option => $value ) {
622
			switch ( $option ) {
623
				case 'at':
624
					if ( intval( $value ) ) {
625
						$videopress_options[ $option ] = intval( $value );
626
					}
627
					break;
628
				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...
629
					$option = 'autoPlay';
630
				case 'hd':
631
				case 'loop':
632
				case 'permalink':
633
					if ( in_array( $value, array( 1, 'true' ) ) ) {
634
						$videopress_options[ $option ] = true;
635
					} elseif ( in_array( $value, array( 0, 'false' ) ) ) {
636
						$videopress_options[ $option ] = false;
637
					}
638
					break;
639
				case 'defaultlangcode':
640
					$option = 'defaultLangCode';
641
					if ( $value ) {
642
						$videopress_options[ $option ] = $value;
643
					}
644
					break;
645
			}
646
		}
647
648
		if ( $iframe_embed ) {
649
			$iframe_url = "https://videopress.com/embed/{$this->video->guid}";
650
651
			foreach ( $videopress_options as $option => $value ) {
652
				if ( ! in_array( $option, array( 'width', 'height' ) ) ) {
653
654
					// add_query_arg ignores false as a value, so replacing it with 0
655
					$iframe_url = add_query_arg( $option, ( false === $value ) ? 0 : $value, $iframe_url );
656
				}
657
			}
658
659
			$js_url = 'https://s0.wp.com/wp-content/plugins/video/assets/js/next/videopress-iframe.js';
660
			$js_url = add_query_arg( 'jetpack_version', JETPACK__VERSION, $js_url );
661
662
			return "<iframe width='" . esc_attr( $videopress_options['width'] )
663
				. "' height='" . esc_attr( $videopress_options['height'] )
664
				. "' src='" . esc_attr( $iframe_url )
665
				. "' frameborder='0' allowfullscreen></iframe>"
666
				. "<script src='" . esc_attr( $js_url ) . "'></script>";
667
668
		} else {
669
			$videopress_options = json_encode( $videopress_options );
670
			$js_url = 'https://s0.wp.com/wp-content/plugins/video/assets/js/next/videopress.js';
671
			$js_url = add_query_arg( 'jetpack_version', JETPACK__VERSION, $js_url );
672
673
			return "<div id='{$video_container_id}'></div>
674
				<script src='{$js_url}'></script>
675
				<script>
676
					videopress('{$this->video->guid}', document.querySelector('#{$video_container_id}'), {$videopress_options});
677
				</script>";
678
		}
679
	}
680
681
	/**
682
	 * Only allow legitimate Flash parameters and their values
683
	 *
684
	 * @since 1.2
685
	 * @link http://kb2.adobe.com/cps/127/tn_12701.html Flash object and embed attributes
686
	 * @link http://kb2.adobe.com/cps/133/tn_13331.html devicefont
687
	 * @link http://kb2.adobe.com/cps/164/tn_16494.html allowscriptaccess
688
	 * @link http://www.adobe.com/devnet/flashplayer/articles/full_screen_mode.html full screen mode
689
	 * @link http://livedocs.adobe.com/flash/9.0/main/wwhelp/wwhimpl/common/html/wwhelp.htm?context=LiveDocs_Parts&file=00001079.html allownetworking
690
	 * @param array $flash_params Flash parameters expressed in key-value form
691
	 * @return array validated Flash parameters
692
	 */
693
	public static function esc_flash_params( $flash_params ) {
694
		$allowed_params = array(
695
			'swliveconnect' => array('true', 'false'),
696
			'play' => array('true', 'false'),
697
			'loop' => array('true', 'false'),
698
			'menu' => array('true', 'false'),
699
			'quality' => array('low', 'autolow', 'autohigh', 'medium', 'high', 'best'),
700
			'scale' => array('default', 'noborder', 'exactfit', 'noscale'),
701
			'align' => array('l', 'r', 't'),
702
			'salign' => array('l', 'r', 't', 'tl', 'tr', 'bl', 'br'),
703
			'wmode' => array('window', 'opaque', 'transparent','direct','gpu'),
704
			'devicefont' => array('_sans', '_serif', '_typewriter'),
705
			'allowscriptaccess' => array('always', 'samedomain', 'never'),
706
			'allownetworking' => array('all','internal', 'none'),
707
			'seamlesstabbing' => array('true', 'false'),
708
			'allowfullscreen' => array('true', 'false'),
709
			'fullScreenAspectRatio' => array('portrait', 'landscape'),
710
			'base',
711
			'bgcolor',
712
			'flashvars'
713
		);
714
715
		$allowed_params_keys = array_keys( $allowed_params );
716
717
		$filtered_params = array();
718
		foreach( $flash_params as $param => $value ) {
719
			if ( empty( $param ) || empty( $value ) )
720
				continue;
721
			$param = strtolower( $param );
722
			if ( in_array( $param, $allowed_params_keys ) ) {
723
				if ( isset( $allowed_params[ $param ] ) && is_array( $allowed_params[ $param ] ) ) {
724
					$value = strtolower($value);
725
					if ( in_array( $value, $allowed_params[ $param ] ) ) {
726
						$filtered_params[ $param ] = $value;
727
					}
728
				} else {
729
					$filtered_params[ $param ] = $value;
730
				}
731
			}
732
		}
733
		unset( $allowed_params_keys );
734
735
		/**
736
		 * Flash specifies sameDomain, not samedomain. change from lowercase value for preciseness
737
		 */
738
		if ( isset( $filtered_params['allowscriptaccess'] ) && $filtered_params['allowscriptaccess'] === 'samedomain' ) {
739
			$filtered_params['allowscriptaccess'] = 'sameDomain';
740
		}
741
742
		return $filtered_params;
743
	}
744
745
	/**
746
	 * Filter Flash variables from the response, taking into consideration player options.
747
	 *
748
	 * @since 1.3
749
	 * @return array Flash variable key value pairs
750
	 */
751
	private function get_flash_variables() {
752
		if ( ! isset( $this->video->players->swf->vars ) ) {
753
			return array();
754
		}
755
756
		$flashvars = (array) $this->video->players->swf->vars;
757
		if ( isset( $this->options['autoplay'] ) && $this->options['autoplay'] === true ) {
758
			$flashvars['autoPlay'] = 'true';
759
		}
760
		return $flashvars;
761
	}
762
763
	/**
764
	 * Validate and filter Flash parameters
765
	 *
766
	 * @since 1.3
767
	 * @return array Flash parameters passed through key and value validation
768
	 */
769
	private function get_flash_parameters() {
770
		if ( ! isset( $this->video->players->swf->params ) ) {
771
			return array();
772
		} else {
773
			return self::esc_flash_params(
774
				/**
775
				 * Filters the Flash parameters of the VideoPress player.
776
				 *
777
				 * @module videopress
778
				 *
779
				 * @since 1.2.0
780
				 *
781
				 * @param array $this ->video->players->swf->params Array of swf parameters for the VideoPress flash player.
782
				 */
783
				apply_filters( 'video_flash_params', (array) $this->video->players->swf->params, 10, 1 )
784
			);
785
		}
786
	}
787
788
	/**
789
	 * Flash player markup in a HTML embed element.
790
	 *
791
	 * @since 1.1
792
	 * @link http://www.whatwg.org/specs/web-apps/current-work/multipage/the-iframe-element.html#the-embed-element embed element
793
	 * @link http://www.google.com/support/reader/bin/answer.py?answer=70664 Google Reader markup support
794
	 * @return string HTML markup. Embed element with no children
795
	 */
796
	private function flash_embed() {
797
		wp_enqueue_script( 'videopress' );
798
		if ( ! isset( $this->video->players->swf ) || ! isset( $this->video->players->swf->url ) ) {
799
			return '';
800
		}
801
802
		$embed = array(
803
			'id' => $this->video_id,
804
			'src' => esc_url_raw( $this->video->players->swf->url . '&' . http_build_query( $this->get_flash_variables(), null, '&' ) , array( 'http', 'https' ) ),
805
			'type' => 'application/x-shockwave-flash',
806
			'width' => $this->video->calculated_width,
807
			'height' => $this->video->calculated_height
808
		);
809
		if ( isset( $this->video->title ) ) {
810
			$embed['title'] = $this->video->title;
811
		}
812
		$embed = array_merge( $embed, $this->get_flash_parameters() );
813
814
		$html = '<embed';
815
		foreach ( $embed as $attribute => $value ) {
816
			$html .= ' ' . esc_html( $attribute ) . '="' . esc_attr( $value ) . '"';
817
		}
818
		unset( $embed );
819
		$html .= '></embed>';
820
		return $html;
821
	}
822
823
	/**
824
	 * Double-baked Flash object markup for Internet Explorer and more standards-friendly consuming agents.
825
	 *
826
	 * @since 1.1
827
	 * @return HTML markup. Object and children.
828
	 */
829
	private function flash_object() {
830
		wp_enqueue_script( 'videopress' );
831
		if ( ! isset( $this->video->players->swf ) || ! isset( $this->video->players->swf->url ) ) {
832
			return '';
833
		}
834
835
		$thumbnail_html = '<img alt="';
836
		if ( isset( $this->video->title ) ) {
837
			$thumbnail_html .= esc_attr( $this->video->title );
838
		}
839
		$thumbnail_html .= '" src="' . esc_url( $this->video->poster_frame_uri, array( 'http', 'https' ) ) . '" width="' . $this->video->calculated_width . '" height="' . $this->video->calculated_height . '" />';
840
		$flash_vars = esc_attr( http_build_query( $this->get_flash_variables(), null, '&' ) );
841
		$flash_params = '';
842
		foreach ( $this->get_flash_parameters() as $attribute => $value ) {
843
			$flash_params .= '<param name="' . esc_attr( $attribute ) . '" value="' . esc_attr( $value ) . '" />';
844
		}
845
		$flash_help = sprintf( __( 'This video requires <a rel="nofollow" href="%s">Adobe Flash</a> for playback.', 'jetpack' ), 'http://www.adobe.com/go/getflashplayer');
846
		$flash_player_url = esc_url( $this->video->players->swf->url, array( 'http', 'https' ) );
847
		$description = '';
848
		if ( isset( $this->video->title ) ) {
849
			$standby = $this->video->title;
850
			$description = '<p><strong>' . esc_html( $this->video->title ) . '</strong></p>';
851
		} else {
852
			$standby = __( 'Loading video...', 'jetpack' );
853
		}
854
		$standby = ' standby="' . esc_attr( $standby ) . '"';
855
		return <<<OBJECT
856
<script type="text/javascript">if(typeof swfobject!=="undefined"){swfobject.registerObject("{$this->video_id}", "{$this->video->players->swf->version}");}</script>
857
<object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" width="{$this->video->calculated_width}" height="{$this->video->calculated_height}" id="{$this->video_id}"{$standby}>
858
	<param name="movie" value="{$flash_player_url}" />
859
	{$flash_params}
860
	<param name="flashvars" value="{$flash_vars}" />
861
	<!--[if !IE]>-->
862
	<object type="application/x-shockwave-flash" data="{$flash_player_url}" width="{$this->video->calculated_width}" height="{$this->video->calculated_height}"{$standby}>
863
		{$flash_params}
864
		<param name="flashvars" value="{$flash_vars}" />
865
	<!--<![endif]-->
866
	{$thumbnail_html}{$description}<p class="robots-nocontent">{$flash_help}</p>
867
	<!--[if !IE]>-->
868
	</object>
869
	<!--<![endif]-->
870
</object>
871
OBJECT;
872
	}
873
}
874