PluginProbe
Jetpack – WP Security, Backup, Speed, & Growth / 16.3
Jetpack – WP Security, Backup, Speed, & Growth v16.3
16.3 16.3-beta 16.3-a.5 16.3-a.7 16.3-a.3 16.3-a.1 16.2 16.2-beta 12.0.3 12.1.3 12.2.3 12.3.2 12.4.2 12.5.2 12.6.4 12.7.3 12.8.3 12.9.5 13.0.2 13.1.5 13.2.4 13.3.3 13.4.5 13.5.2 13.6.2 All 508 releases
← All changes | modules/videopress/class.videopress-video.php +383 -0 16.2-beta → 16.3 View file →
@@ -1,0 +1,383 @@
1 +<?php // phpcs:ignore WordPress.Files.FileName.InvalidClassFileName
2 +
3 +if ( ! defined( 'ABSPATH' ) ) {
4 + exit( 0 );
5 +}
6 +
7 +/**
8 + * VideoPress video object retrieved from VideoPress servers and parsed.
9 + *
10 + * @since 1.3
11 + */
12 +class VideoPress_Video {
13 + /**
14 + * VideoPress version.
15 + *
16 + * @var int
17 + */
18 + public $version = 3;
19 +
20 + /**
21 + * Manifest version returned by remote service.
22 + *
23 + * @var string
24 + * @since 1.3
25 + */
26 + const manifest_version = '1.5'; // phpcs:ignore Generic.NamingConventions.UpperCaseConstantName.ClassConstantNotUpperCase
27 +
28 + /**
29 + * Expiration of the video expressed in Unix time
30 + *
31 + * @var int
32 + * @since 1.3
33 + */
34 + public $expires;
35 +
36 + /**
37 + * VideoPress unique identifier
38 + *
39 + * @var string
40 + * @since 1.3
41 + */
42 + public $guid;
43 +
44 + /**
45 + * WordPress.com blog identifier
46 + *
47 + * @var int
48 + * @since 1.5
49 + */
50 + public $blog_id;
51 +
52 + /**
53 + * Remote blog attachment identifier
54 + *
55 + * @var int
56 + * @since 1.5
57 + */
58 + public $post_id;
59 +
60 + /**
61 + * Maximum desired width.
62 + *
63 + * @var int
64 + * @since 1.3
65 + */
66 + public $maxwidth;
67 +
68 + /**
69 + * Video width calculated based on original video dimensions and the requested maxwidth
70 + *
71 + * @var int
72 + * @since 1.3
73 + */
74 + public $calculated_width;
75 +
76 + /**
77 + * Video height calculated based on original video dimensions and the requested maxwidth
78 + *
79 + * @var int
80 + * @since 1.3
81 + */
82 + public $calculated_height;
83 +
84 + /**
85 + * Video title
86 + *
87 + * @var string
88 + * @since 1.3
89 + */
90 + public $title;
91 +
92 + /**
93 + * Video description
94 + *
95 + * @var string
96 + * @since 4.4
97 + */
98 + public $description;
99 +
100 + /**
101 + * Directionality of title text. ltr or rtl
102 + *
103 + * @var string
104 + * @since 1.3
105 + */
106 + public $text_direction;
107 +
108 + /**
109 + * Text and audio language as ISO 639-2 language code
110 + *
111 + * @var string
112 + * @since 1.3
113 + */
114 + public $language;
115 +
116 + /**
117 + * Video duration in whole seconds
118 + *
119 + * @var int
120 + * @since 1.3
121 + */
122 + public $duration;
123 +
124 + /**
125 + * Recommended minimum age of the viewer.
126 + *
127 + * @var int
128 + * @since 1.3
129 + */
130 + public $age_rating;
131 +
132 + /**
133 + * Video author has restricted video embedding or sharing
134 + *
135 + * @var bool
136 + * @since 1.3
137 + */
138 + public $restricted_embed;
139 +
140 + /**
141 + * Poster frame image URI for the given video guid and calculated dimensions.
142 + *
143 + * @var string
144 + * @since 1.3
145 + */
146 + public $poster_frame_uri;
147 +
148 + /**
149 + * Video files associated with the given guid for the calculated dimensions.
150 + *
151 + * @var stdClass
152 + * @since 1.3
153 + */
154 + public $videos;
155 +
156 + /**
157 + * Video player information
158 + *
159 + * @var stdClass
160 + * @since 1.3
161 + */
162 + public $players;
163 +
164 + /**
165 + * Video player skinning preferences including background color and watermark
166 + *
167 + * @var array
168 + * @since 1.5
169 + */
170 + public $skin;
171 +
172 + /**
173 + * Closed captions if available for the given video. Associative array of ISO 639-2 language code and a WebVTT URI
174 + *
175 + * @var array
176 + * @since 1.5
177 + */
178 + public $captions;
179 +
180 + /**
181 + * Error data.
182 + *
183 + * @var mixed
184 + */
185 + public $error;
186 +
187 + /**
188 + * Setup the object.
189 + * Request video information from VideoPress servers and process the response.
190 + *
191 + * @since 1.3
192 + * @param string $guid VideoPress unique identifier.
193 + * @param int $maxwidth maximum requested video width. final width and height are calculated on VideoPress servers based on the aspect ratio of the original video upload.
194 + */
195 + public function __construct( $guid, $maxwidth = 640 ) {
196 + $this->guid = $guid;
197 +
198 + $maxwidth = absint( $maxwidth );
199 + if ( $maxwidth > 0 ) {
200 + $this->maxwidth = $maxwidth;
201 + }
202 +
203 + $data = $this->get_data();
204 + if ( is_wp_error( $data ) || empty( $data ) ) {
205 + /** This filter is documented in modules/videopress/class.videopress-player.php */
206 + if ( ! apply_filters( 'jetpack_videopress_use_legacy_player', false ) ) {
207 + // Unlike the Flash player, the new player does it's own error checking, age gate, etc.
208 + $data = (object) array(
209 + 'guid' => $guid,
210 + 'width' => $maxwidth,
211 + 'height' => $maxwidth / 16 * 9,
212 + );
213 + } else {
214 + $this->error = $data;
215 + return;
216 + }
217 + }
218 +
219 + if ( isset( $data->blog_id ) ) {
220 + $this->blog_id = absint( $data->blog_id );
221 + }
222 +
223 + if ( isset( $data->post_id ) ) {
224 + $this->post_id = absint( $data->post_id );
225 + }
226 +
227 + if ( isset( $data->title ) && $data->title !== '' ) {
228 + $this->title = trim( str_replace( '&nbsp;', ' ', $data->title ) );
229 + }
230 +
231 + if ( isset( $data->description ) && $data->description !== '' ) {
232 + $this->description = trim( $data->description );
233 + }
234 +
235 + if ( isset( $data->text_direction ) && $data->text_direction === 'rtl' ) {
236 + $this->text_direction = 'rtl';
237 + } else {
238 + $this->text_direction = 'ltr';
239 + }
240 +
241 + if ( isset( $data->language ) ) {
242 + $this->language = $data->language;
243 + }
244 +
245 + if ( isset( $data->duration ) && $data->duration > 0 ) {
246 + $this->duration = absint( $data->duration );
247 + }
248 +
249 + if ( isset( $data->width ) && $data->width > 0 ) {
250 + $this->calculated_width = absint( $data->width );
251 + }
252 +
253 + if ( isset( $data->height ) && $data->height > 0 ) {
254 + $this->calculated_height = absint( $data->height );
255 + }
256 +
257 + if ( isset( $data->age_rating ) ) {
258 + $this->age_rating = absint( $this->age_rating );
259 + }
260 +
261 + if ( isset( $data->restricted_embed ) && $data->restricted_embed === true ) {
262 + $this->restricted_embed = true;
263 + } else {
264 + $this->restricted_embed = false;
265 + }
266 +
267 + if ( isset( $data->posterframe ) && $data->posterframe !== '' ) {
268 + $this->poster_frame_uri = esc_url_raw( $data->posterframe, array( 'http', 'https' ) );
269 + }
270 +
271 + if ( isset( $data->mp4 ) || isset( $data->ogv ) ) {
272 + $this->videos = new stdClass();
273 + if ( isset( $data->mp4 ) ) {
274 + $this->videos->mp4 = $data->mp4;
275 + }
276 + if ( isset( $data->ogv ) ) {
277 + $this->videos->ogv = $data->ogv;
278 + }
279 + }
280 +
281 + if ( isset( $data->swf ) ) {
282 + if ( ! isset( $this->players ) ) {
283 + $this->players = new stdClass();
284 + }
285 + $this->players->swf = $data->swf;
286 + }
287 +
288 + if ( isset( $data->skin ) ) {
289 + $this->skin = $data->skin;
290 + }
291 +
292 + if ( isset( $data->captions ) ) {
293 + $this->captions = (array) $data->captions;
294 + }
295 + }
296 +
297 + /**
298 + * Convert an Expires HTTP header value into Unix time for use in WP Cache.
299 + *
300 + * @since 1.3
301 + * @param string $expires_header Expires header value.
302 + * @return int|bool Unix time or false
303 + */
304 + public static function calculate_expiration( $expires_header ) {
305 + if ( empty( $expires_header ) || ! is_string( $expires_header ) ) {
306 + return false;
307 + }
308 +
309 + $expires_date = DateTime::createFromFormat( 'D, d M Y H:i:s T', $expires_header, new DateTimeZone( 'UTC' ) );
310 + if ( $expires_date instanceof DateTime ) {
311 + return date_format( $expires_date, 'U' );
312 + }
313 + return false;
314 + }
315 +
316 + /**
317 + * Extract the site's host domain for statistics and comparison against an allowed site list in the case of restricted embeds.
318 + *
319 + * @since 1.2
320 + * @param string $url absolute URL.
321 + * @return bool|string host component of the URL, or false if none found.
322 + */
323 + public static function hostname( $url ) {
324 + return wp_parse_url( esc_url_raw( $url ), PHP_URL_HOST );
325 + }
326 +
327 + /**
328 + * Request data from WordPress.com for the given guid, maxwidth, and calculated blog hostname.
329 + *
330 + * @since 1.3
331 + * @return stdClass|WP_Error parsed JSON response or WP_Error if request unsuccessful
332 + */
333 + private function get_data() {
334 + global $wp_version;
335 +
336 + $domain = self::hostname( home_url() );
337 + $request_params = array(
338 + 'guid' => $this->guid,
339 + 'domain' => $domain,
340 + );
341 + if ( isset( $this->maxwidth ) && $this->maxwidth > 0 ) {
342 + $request_params['maxwidth'] = $this->maxwidth;
343 + }
344 +
345 + $url = 'https://v.wordpress.com/data/wordpress.json';
346 +
347 + $response = wp_remote_get(
348 + add_query_arg( $request_params, $url ),
349 + array(
350 + 'redirection' => 1,
351 + 'user-agent' => 'VideoPress plugin ' . $this->version . '; WordPress ' . $wp_version . ' (' . home_url( '/' ) . ')',
352 + )
353 + );
354 +
355 + unset( $request_params );
356 + unset( $url );
357 + $response_body = wp_remote_retrieve_body( $response );
358 + $response_code = absint( wp_remote_retrieve_response_code( $response ) );
359 +
360 + if ( is_wp_error( $response ) ) {
361 + return $response;
362 + } elseif ( $response_code === 400 ) {
363 + return new WP_Error( 'bad_config', __( 'The VideoPress plugin could not communicate with the VideoPress servers. This error is most likely caused by a misconfigured plugin. Please reinstall or upgrade.', 'jetpack' ) );
364 + } elseif ( $response_code === 403 ) {
365 + /* translators: %s URL of site trying to embed a VideoPress video */
366 + return new WP_Error( 'http_forbidden', '<p>' . sprintf( __( '<strong>%s</strong> is not an allowed embed site.', 'jetpack' ), esc_html( $domain ) ) . '</p><p>' . __( 'Publisher limits playback of video embeds.', 'jetpack' ) . '</p>' );
367 + } elseif ( $response_code === 404 ) {
368 + /* translators: %s VideoPress object identifier */
369 + return new WP_Error( 'http_not_found', '<p>' . sprintf( __( 'No data found for VideoPress identifier: <strong>%s</strong>.', 'jetpack' ), $this->guid ) . '</p>' );
370 + } elseif ( $response_code !== 200 || empty( $response_body ) ) {
371 + return;
372 + } else {
373 + $expires_header = wp_remote_retrieve_header( $response, 'Expires' );
374 + if ( ! empty( $expires_header ) ) {
375 + $expires = self::calculate_expiration( $expires_header );
376 + if ( ! empty( $expires ) ) {
377 + $this->expires = $expires;
378 + }
379 + }
380 + return json_decode( $response_body );
381 + }
382 + }
383 +}