PluginProbe
Jetpack – WP Security, Backup, Speed, & Growth / 16.2
Jetpack – WP Security, Backup, Speed, & Growth v16.2
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 13.7.2 13.8.3 All 506 releases
jetpack / jetpack_vendor / automattic / jetpack-videopress / src / class-data.php

class-data.php in Jetpack – WP Security, Backup, Speed, & Growth 16.2, at jetpack_vendor/automattic/jetpack-videopress/src/class-data.php

468 lines 14.2 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * The Data class.
4 * This class provides methods for data VideoPress access and manipulation.
5 *
6 * @package automattic/jetpack-videopress
7 */
8
9 namespace Automattic\Jetpack\VideoPress;
10
11 use Automattic\Jetpack\Connection\Manager as Connection_Manager;
12 use Automattic\Jetpack\Status\Host;
13 use WP_REST_Request;
14 /**
15 * The Data class.
16 */
17 class Data {
18
19 /**
20 * Gets the Jetpack blog ID
21 *
22 * @return int The blog ID
23 */
24 public static function get_blog_id() {
25 return VideoPressToken::blog_id();
26 }
27
28 /**
29 * Gets the VideoPress site privacy configuration.
30 *
31 * @return boolean If all the videos are private on the site
32 */
33 public static function get_videopress_videos_private_for_site() {
34 /**
35 * If it's a Simple site, returns the site privacy setting.
36 */
37 if ( defined( 'IS_WPCOM' ) && IS_WPCOM ) {
38 return video_is_private_wpcom_blog( get_current_blog_id() );
39 }
40 /**
41 * If it's a private Atomic site, the default setting is private as well.
42 */
43 if ( ( new Host() )->is_woa_site() ) {
44 if ( ( intval( get_option( 'blog_public', '' ) ) === -1 ) ) {
45 return true;
46 }
47 }
48
49 /* If it's a Jetpack site or a public Atomic site, check the settings */
50 return boolval( get_option( 'videopress_private_enabled_for_site', false ) );
51 }
52
53 /**
54 * Gets whether auto-generated subtitles are disabled for the site.
55 *
56 * Subtitles are generated by default, so this opt-out option defaults to false.
57 *
58 * @return boolean If auto-generated subtitles should be skipped for new videos.
59 */
60 public static function get_videopress_auto_subtitles_disabled() {
61 return boolval( get_option( 'videopress_auto_subtitles_disabled', false ) );
62 }
63
64 /**
65 * Gets whether player preloading is turned off for every embed on the site.
66 *
67 * Preloading is on by default, so this opt-out option defaults to false.
68 *
69 * @return boolean If embeds should wait for playback before fetching video data and player assets.
70 */
71 public static function get_videopress_player_preload_disabled() {
72 return boolval( get_option( 'videopress_player_preload_disabled', false ) );
73 }
74
75 /**
76 * Gets the VideoPress Settings.
77 *
78 * @return array The settings as an associative array.
79 */
80 public static function get_videopress_settings() {
81 $site_type = 'jetpack';
82 $site_is_private = false;
83
84 if ( defined( 'IS_WPCOM' ) && IS_WPCOM ) {
85 $site_type = 'simple';
86 $site_is_private = video_is_private_wpcom_blog( get_current_blog_id() );
87 } elseif ( ( new Host() )->is_woa_site() ) {
88 $site_type = 'atomic';
89 $site_is_private = intval( get_option( 'blog_public', '' ) ) === -1;
90 }
91
92 return array(
93 'videopress_videos_private_for_site' => self::get_videopress_videos_private_for_site(),
94 'videopress_auto_subtitles_disabled' => self::get_videopress_auto_subtitles_disabled(),
95 'videopress_player_preload_disabled' => self::get_videopress_player_preload_disabled(),
96 'site_is_private' => $site_is_private,
97 'site_type' => $site_type,
98 );
99 }
100
101 /**
102 * Gets the video data
103 *
104 * @param boolean $is_videopress - True when getting VideoPress data.
105 * @return array
106 */
107 public static function get_video_data( $is_videopress = true ) {
108 $video_data = array(
109 'videos' => array(),
110 'total' => 0,
111 'totalPages' => 0,
112 'query' => array(
113 'order' => 'desc',
114 'orderBy' => 'date',
115 'itemsPerPage' => 6,
116 'page' => 1,
117 ),
118 );
119
120 $args = array(
121 'order' => $video_data['query']['order'],
122 'orderby' => $video_data['query']['orderBy'],
123 'per_page' => $video_data['query']['itemsPerPage'],
124 'page' => $video_data['query']['page'],
125 );
126
127 if ( $is_videopress ) {
128 $args['mime_type'] = 'video/videopress';
129 } else {
130 $args['media_type'] = 'video';
131 $args['no_videopress'] = true;
132 }
133
134 // Do an internal request for the media list
135 $request = new WP_REST_Request( 'GET', '/wp/v2/media' );
136 $request->set_query_params( $args );
137 $response = rest_do_request( $request );
138
139 if ( $response->is_error() ) {
140 // @todo: error handling
141 return $video_data;
142 }
143
144 // load the real values
145 $video_data['videos'] = $response->get_data();
146 $headers = $response->get_headers();
147
148 if ( isset( $headers['X-WP-Total'] ) ) {
149 $video_data['total'] = $headers['X-WP-Total'];
150 }
151
152 if ( isset( $headers['X-WP-TotalPages'] ) ) {
153 $video_data['totalPages'] = $headers['X-WP-TotalPages'];
154 }
155
156 return $video_data;
157 }
158
159 /**
160 * Gets the user data
161 *
162 * @return array
163 */
164 public static function get_user_data() {
165 $user_data = array(
166 'items' => array(),
167 'pagination' => array(
168 'total' => 0,
169 'totalPages' => 1,
170 ),
171 'query' => array(
172 'order' => 'asc',
173 'orderBy' => 'name',
174 ),
175 '_meta' => array(
176 'relyOnInitialState' => true,
177 ),
178 );
179
180 $args = array(
181 'order' => $user_data['query']['order'],
182 'orderby' => $user_data['query']['orderBy'],
183 );
184
185 // Do an internal request for the user list
186 $request = new WP_REST_Request( 'GET', '/wp/v2/users' );
187 $request->set_query_params( $args );
188 $response = rest_do_request( $request );
189
190 if ( $response->is_error() ) {
191 // @todo: error handling
192 return $user_data;
193 }
194
195 // load the real values
196 $user_data['items'] = $response->get_data();
197 $headers = $response->get_headers();
198
199 if ( isset( $headers['X-WP-Total'] ) ) {
200 $user_data['pagination']['total'] = $headers['X-WP-Total'];
201 }
202
203 if ( isset( $headers['X-WP-TotalPages'] ) ) {
204 $user_data['pagination']['totalPages'] = $headers['X-WP-TotalPages'];
205 }
206
207 return $user_data;
208 }
209
210 /**
211 * Gets the VideoPress used storage space in bytes
212 *
213 * @return int the used storage space
214 */
215 public static function get_storage_used() {
216 $site_data = Site::get_site_info();
217 if ( is_wp_error( $site_data ) ) {
218 return 0;
219 }
220
221 if ( isset( $site_data['options'] ) && isset( $site_data['options']['videopress_storage_used'] ) ) {
222 return intval( round( $site_data['options']['videopress_storage_used'] * 1024 * 1024 ) );
223 } else {
224 return 0;
225 }
226 }
227
228 /**
229 * Return all the initial state that depends on a valid site connection
230 *
231 * @return array
232 */
233 public static function get_connected_initial_state() {
234 return array(
235 'videos' => array(
236 'storageUsed' => self::get_storage_used(),
237 ),
238 'purchases' => array(
239 'items' => Site::get_purchases(),
240 'isFetching' => false,
241 ),
242 );
243 }
244
245 /**
246 * Checks if the site has as connected owner
247 */
248 public static function has_connected_owner() {
249 if ( defined( 'IS_WPCOM' ) && IS_WPCOM ) {
250 return true;
251 }
252
253 if ( ( new Connection_Manager() )->has_connected_owner() ) {
254 return true;
255 }
256
257 return false;
258 }
259
260 /**
261 * Checks if the user is able to perform actions that modify data
262 */
263 public static function can_perform_action() {
264 if ( defined( 'IS_WPCOM' ) && IS_WPCOM ) {
265 return true;
266 }
267
268 $connection = new Connection_Manager();
269
270 return (
271 $connection->is_connected() &&
272 self::has_connected_owner() &&
273 $connection->is_user_connected()
274 );
275 }
276
277 /**
278 * Return the initial state of the VideoPress app,
279 * used to render initially the app in the frontend.
280 *
281 * @return array
282 */
283 public static function get_initial_state() {
284 $videopress_data = self::get_video_data();
285 $local_videos_data = self::get_video_data( false );
286
287 // Tweak local videos data.
288 $local_videos = array_map(
289 function ( $video ) {
290 $video = (array) $video;
291 $id = $video['id'];
292 $media_details = $video['media_details'];
293 $jetpack_videopress = $video['jetpack_videopress'];
294 $read_error = null;
295
296 // In malformed files, the media_details or jetpack_videopress properties are not arrays.
297 if ( ! is_array( $media_details ) || ! is_array( $jetpack_videopress ) ) {
298 $media_details = (array) $media_details;
299 $jetpack_videopress = (array) $jetpack_videopress;
300 $read_error = Upload_Exception::ERROR_MALFORMED_FILE;
301 }
302
303 // Check if video is already uploaded to VideoPress or has some error.
304 try {
305 $uploader = new Uploader( $id );
306 $is_uploaded_to_videopress = $uploader->is_uploaded();
307 } catch ( Upload_Exception $e ) {
308 $is_uploaded_to_videopress = false;
309 $read_error = $e->getCode();
310 }
311
312 $upload_date = $video['date'];
313 $url = $video['source_url'];
314
315 $title = $jetpack_videopress['title'];
316 $description = $jetpack_videopress['description'];
317 $caption = $jetpack_videopress['caption'];
318
319 $width = $media_details['width'] ?? null;
320 $height = $media_details['height'] ?? null;
321 $duration = $media_details['length'] ?? null;
322
323 return array(
324 'id' => $id,
325 'title' => $title,
326 'description' => $description,
327 'caption' => $caption,
328 'width' => $width,
329 'height' => $height,
330 'url' => $url,
331 'uploadDate' => $upload_date,
332 'duration' => $duration,
333 'isUploadedToVideoPress' => $is_uploaded_to_videopress,
334 'readError' => $read_error,
335 );
336 },
337 $local_videos_data['videos']
338 );
339
340 // Tweak VideoPress videos data.
341 $videos = array_map(
342 array( __CLASS__, 'prepare_videopress_video_data' ),
343 $videopress_data['videos']
344 );
345
346 $site_settings = self::get_videopress_settings();
347
348 $initial_state = array(
349 'users' => self::get_user_data(),
350 'siteSettings' => array(
351 'videoPressVideosPrivateForSite' => $site_settings['videopress_videos_private_for_site'],
352 'siteIsPrivate' => $site_settings['site_is_private'],
353 'siteType' => $site_settings['site_type'],
354 ),
355 'videos' => array(
356 'uploadedVideoCount' => $videopress_data['total'],
357 'items' => $videos,
358 'isFetching' => false,
359 'isFetchingUploadedVideoCount' => false,
360 'pagination' => array(
361 'totalPages' => $videopress_data['totalPages'],
362 'total' => $videopress_data['total'],
363 ),
364 'query' => $videopress_data['query'],
365 '_meta' => array(
366 'processedAllVideosBeingRemoved' => true,
367 'relyOnInitialState' => true,
368 ),
369 ),
370 'localVideos' => array(
371 'uploadedVideoCount' => $local_videos_data['total'],
372 'items' => $local_videos,
373 'isFetching' => false,
374 'isFetchingUploadedVideoCount' => false,
375 'pagination' => array(
376 'totalPages' => $local_videos_data['totalPages'],
377 'total' => $local_videos_data['total'],
378 ),
379 'query' => $local_videos_data['query'],
380 '_meta' => array(
381 'relyOnInitialState' => true,
382 ),
383 ),
384 );
385
386 if ( self::has_connected_owner() ) {
387 return array_merge_recursive( $initial_state, self::get_connected_initial_state() );
388 }
389
390 return $initial_state;
391 }
392
393 /**
394 * Maps a single VideoPress video, as returned by the media REST endpoint, to
395 * the shape consumed by the VideoPress dashboard app.
396 *
397 * Videos that are still processing (or otherwise have partial metadata) come
398 * back without `videopress`, `width` or `height` in their media_details, so
399 * every nested access is coalesced to avoid undefined-key and offset-on-null
400 * warnings.
401 *
402 * @param array|object $video A single video entry from the media REST endpoint.
403 * @return array The video data formatted for the dashboard app.
404 */
405 private static function prepare_videopress_video_data( $video ) {
406 $video = (array) $video;
407 $id = $video['id'];
408 $guid = $video['jetpack_videopress_guid'];
409 $media_details = (array) $video['media_details'];
410 $jetpack_videopress = (array) $video['jetpack_videopress'];
411
412 $videopress_media_details = $media_details['videopress'] ?? array();
413 $width = $media_details['width'] ?? null;
414 $height = $media_details['height'] ?? null;
415
416 $title = $jetpack_videopress['title'];
417 $description = $jetpack_videopress['description'];
418 $caption = $jetpack_videopress['caption'];
419 $rating = $jetpack_videopress['rating'];
420 $allow_download = $jetpack_videopress['allow_download'];
421 $display_embed = $jetpack_videopress['display_embed'];
422 $privacy_setting = $jetpack_videopress['privacy_setting'];
423 $needs_playback_token = $jetpack_videopress['needs_playback_token'];
424 $is_private = $jetpack_videopress['is_private'];
425
426 $original = $videopress_media_details['original'] ?? null;
427 $poster = ( ! $needs_playback_token ) ? ( $videopress_media_details['poster'] ?? null ) : null;
428 $upload_date = $videopress_media_details['upload_date'] ?? null;
429 $duration = $videopress_media_details['duration'] ?? null;
430 $file_url_base = $videopress_media_details['file_url_base'] ?? null;
431 $finished = $videopress_media_details['finished'] ?? null;
432 $files = $videopress_media_details['files'] ?? null;
433 $filename = $original !== null ? basename( $original ) : null;
434
435 if ( isset( $files['dvd']['original_img'] ) && isset( $file_url_base['https'] ) && $privacy_setting !== 1 ) {
436 $thumbnail = $file_url_base['https'] . $files['dvd']['original_img'];
437 } else {
438 $thumbnail = null;
439 }
440
441 return array(
442 'id' => $id,
443 'guid' => $guid,
444 'title' => $title,
445 'description' => $description,
446 'caption' => $caption,
447 'url' => $original,
448 'uploadDate' => $upload_date,
449 'duration' => $duration,
450 'isPrivate' => $is_private,
451 'posterImage' => $poster,
452 'allowDownload' => $allow_download,
453 'displayEmbed' => $display_embed,
454 'rating' => $rating,
455 'privacySetting' => $privacy_setting,
456 'needsPlaybackToken' => $needs_playback_token,
457 'width' => $width,
458 'height' => $height,
459 'poster' => array(
460 'src' => $poster,
461 ),
462 'thumbnail' => $thumbnail,
463 'finished' => $finished,
464 'filename' => $filename,
465 );
466 }
467 }
468