Completed
Push — add/pathinfo-sitemap ( eb9d33...02fba8 )
by Jeremy
14:23 queued 04:10
created

VideoPress_Player::html_wrapper()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 6
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Importance

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