Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
12.70% covered (danger)
12.70%
32 / 252
0.00% covered (danger)
0.00%
0 / 10
CRAP
0.00% covered (danger)
0.00%
0 / 1
Data
12.70% covered (danger)
12.70%
32 / 252
0.00% covered (danger)
0.00%
0 / 10
1159.50
0.00% covered (danger)
0.00%
0 / 1
 get_blog_id
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 get_videopress_videos_private_for_site
0.00% covered (danger)
0.00%
0 / 6
0.00% covered (danger)
0.00%
0 / 1
30
 get_videopress_settings
0.00% covered (danger)
0.00%
0 / 13
0.00% covered (danger)
0.00%
0 / 1
20
 get_video_data
96.97% covered (success)
96.97%
32 / 33
0.00% covered (danger)
0.00%
0 / 1
5
 get_user_data
0.00% covered (danger)
0.00%
0 / 30
0.00% covered (danger)
0.00%
0 / 1
20
 get_storage_used
0.00% covered (danger)
0.00%
0 / 6
0.00% covered (danger)
0.00%
0 / 1
20
 get_connected_initial_state
0.00% covered (danger)
0.00%
0 / 9
0.00% covered (danger)
0.00%
0 / 1
2
 has_connected_owner
0.00% covered (danger)
0.00%
0 / 5
0.00% covered (danger)
0.00%
0 / 1
20
 can_perform_action
0.00% covered (danger)
0.00%
0 / 8
0.00% covered (danger)
0.00%
0 / 1
30
 get_initial_state
0.00% covered (danger)
0.00%
0 / 141
0.00% covered (danger)
0.00%
0 / 1
72
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
9namespace Automattic\Jetpack\VideoPress;
10
11use Automattic\Jetpack\Connection\Manager as Connection_Manager;
12use Automattic\Jetpack\Status\Host;
13use WP_REST_Request;
14/**
15 * The Data class.
16 */
17class 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 the VideoPress Settings.
55     *
56     * @return array The settings as an associative array.
57     */
58    public static function get_videopress_settings() {
59        $site_type       = 'jetpack';
60        $site_is_private = false;
61
62        if ( defined( 'IS_WPCOM' ) && IS_WPCOM ) {
63            $site_type       = 'simple';
64            $site_is_private = video_is_private_wpcom_blog( get_current_blog_id() );
65        } elseif ( ( new Host() )->is_woa_site() ) {
66            $site_type       = 'atomic';
67            $site_is_private = intval( get_option( 'blog_public', '' ) ) === -1;
68        }
69
70        return array(
71            'videopress_videos_private_for_site' => self::get_videopress_videos_private_for_site(),
72            'site_is_private'                    => $site_is_private,
73            'site_type'                          => $site_type,
74        );
75    }
76
77    /**
78     * Gets the video data
79     *
80     * @param boolean $is_videopress - True when getting VideoPress data.
81     * @return array
82     */
83    public static function get_video_data( $is_videopress = true ) {
84        $video_data = array(
85            'videos'     => array(),
86            'total'      => 0,
87            'totalPages' => 0,
88            'query'      => array(
89                'order'        => 'desc',
90                'orderBy'      => 'date',
91                'itemsPerPage' => 6,
92                'page'         => 1,
93            ),
94        );
95
96        $args = array(
97            'order'    => $video_data['query']['order'],
98            'orderby'  => $video_data['query']['orderBy'],
99            'per_page' => $video_data['query']['itemsPerPage'],
100            'page'     => $video_data['query']['page'],
101        );
102
103        if ( $is_videopress ) {
104            $args['mime_type'] = 'video/videopress';
105        } else {
106            $args['media_type']    = 'video';
107            $args['no_videopress'] = true;
108        }
109
110        // Do an internal request for the media list
111        $request = new WP_REST_Request( 'GET', '/wp/v2/media' );
112        $request->set_query_params( $args );
113        $response = rest_do_request( $request );
114
115        if ( $response->is_error() ) {
116            // @todo: error handling
117            return $video_data;
118        }
119
120        // load the real values
121        $video_data['videos'] = $response->get_data();
122        $headers              = $response->get_headers();
123
124        if ( isset( $headers['X-WP-Total'] ) ) {
125            $video_data['total'] = $headers['X-WP-Total'];
126        }
127
128        if ( isset( $headers['X-WP-TotalPages'] ) ) {
129            $video_data['totalPages'] = $headers['X-WP-TotalPages'];
130        }
131
132        return $video_data;
133    }
134
135    /**
136     * Gets the user data
137     *
138     * @return array
139     */
140    public static function get_user_data() {
141        $user_data = array(
142            'items'      => array(),
143            'pagination' => array(
144                'total'      => 0,
145                'totalPages' => 1,
146            ),
147            'query'      => array(
148                'order'   => 'asc',
149                'orderBy' => 'name',
150            ),
151            '_meta'      => array(
152                'relyOnInitialState' => true,
153            ),
154        );
155
156        $args = array(
157            'order'   => $user_data['query']['order'],
158            'orderby' => $user_data['query']['orderBy'],
159        );
160
161        // Do an internal request for the user list
162        $request = new WP_REST_Request( 'GET', '/wp/v2/users' );
163        $request->set_query_params( $args );
164        $response = rest_do_request( $request );
165
166        if ( $response->is_error() ) {
167            // @todo: error handling
168            return $user_data;
169        }
170
171        // load the real values
172        $user_data['items'] = $response->get_data();
173        $headers            = $response->get_headers();
174
175        if ( isset( $headers['X-WP-Total'] ) ) {
176            $user_data['pagination']['total'] = $headers['X-WP-Total'];
177        }
178
179        if ( isset( $headers['X-WP-TotalPages'] ) ) {
180            $user_data['pagination']['totalPages'] = $headers['X-WP-TotalPages'];
181        }
182
183        return $user_data;
184    }
185
186    /**
187     * Gets the VideoPress used storage space in bytes
188     *
189     * @return int the used storage space
190     */
191    public static function get_storage_used() {
192        $site_data = Site::get_site_info();
193        if ( is_wp_error( $site_data ) ) {
194            return 0;
195        }
196
197        if ( isset( $site_data['options'] ) && isset( $site_data['options']['videopress_storage_used'] ) ) {
198            return intval( round( $site_data['options']['videopress_storage_used'] * 1024 * 1024 ) );
199        } else {
200            return 0;
201        }
202    }
203
204    /**
205     * Return all the initial state that depends on a valid site connection
206     *
207     * @return array
208     */
209    public static function get_connected_initial_state() {
210        return array(
211            'videos'    => array(
212                'storageUsed' => self::get_storage_used(),
213            ),
214            'purchases' => array(
215                'items'      => Site::get_purchases(),
216                'isFetching' => false,
217            ),
218        );
219    }
220
221    /**
222     * Checks if the site has as connected owner
223     */
224    public static function has_connected_owner() {
225        if ( defined( 'IS_WPCOM' ) && IS_WPCOM ) {
226            return true;
227        }
228
229        if ( ( new Connection_Manager() )->has_connected_owner() ) {
230            return true;
231        }
232
233        return false;
234    }
235
236    /**
237     * Checks if the user is able to perform actions that modify data
238     */
239    public static function can_perform_action() {
240        if ( defined( 'IS_WPCOM' ) && IS_WPCOM ) {
241            return true;
242        }
243
244        $connection = new Connection_Manager();
245
246        return (
247            $connection->is_connected() &&
248            self::has_connected_owner() &&
249            $connection->is_user_connected()
250        );
251    }
252
253    /**
254     * Return the initial state of the VideoPress app,
255     * used to render initially the app in the frontend.
256     *
257     * @return array
258     */
259    public static function get_initial_state() {
260        $videopress_data   = self::get_video_data();
261        $local_videos_data = self::get_video_data( false );
262
263        // Tweak local videos data.
264        $local_videos = array_map(
265            function ( $video ) {
266                $video              = (array) $video;
267                $id                 = $video['id'];
268                $media_details      = $video['media_details'];
269                $jetpack_videopress = $video['jetpack_videopress'];
270                $read_error         = null;
271
272                // In malformed files, the media_details or jetpack_videopress properties are not arrays.
273                if ( ! is_array( $media_details ) || ! is_array( $jetpack_videopress ) ) {
274                    $media_details      = (array) $media_details;
275                    $jetpack_videopress = (array) $jetpack_videopress;
276                    $read_error         = Upload_Exception::ERROR_MALFORMED_FILE;
277                }
278
279                // Check if video is already uploaded to VideoPress or has some error.
280                try {
281                    $uploader                  = new Uploader( $id );
282                    $is_uploaded_to_videopress = $uploader->is_uploaded();
283                } catch ( Upload_Exception $e ) {
284                    $is_uploaded_to_videopress = false;
285                    $read_error                = $e->getCode();
286                }
287
288                $upload_date = $video['date'];
289                $url         = $video['source_url'];
290
291                $title       = $jetpack_videopress['title'];
292                $description = $jetpack_videopress['description'];
293                $caption     = $jetpack_videopress['caption'];
294
295                $width    = $media_details['width'] ?? null;
296                $height   = $media_details['height'] ?? null;
297                $duration = $media_details['length'] ?? null;
298
299                return array(
300                    'id'                     => $id,
301                    'title'                  => $title,
302                    'description'            => $description,
303                    'caption'                => $caption,
304                    'width'                  => $width,
305                    'height'                 => $height,
306                    'url'                    => $url,
307                    'uploadDate'             => $upload_date,
308                    'duration'               => $duration,
309                    'isUploadedToVideoPress' => $is_uploaded_to_videopress,
310                    'readError'              => $read_error,
311                );
312            },
313            $local_videos_data['videos']
314        );
315
316        // Tweak VideoPress videos data.
317        $videos = array_map(
318            function ( $video ) {
319                $video              = (array) $video;
320                $id                 = $video['id'];
321                $guid               = $video['jetpack_videopress_guid'];
322                $media_details      = (array) $video['media_details'];
323                $jetpack_videopress = (array) $video['jetpack_videopress'];
324
325                $videopress_media_details = $media_details['videopress'];
326                $width                    = $media_details['width'];
327                $height                   = $media_details['height'];
328
329                $title                = $jetpack_videopress['title'];
330                $description          = $jetpack_videopress['description'];
331                $caption              = $jetpack_videopress['caption'];
332                $rating               = $jetpack_videopress['rating'];
333                $allow_download       = $jetpack_videopress['allow_download'];
334                $display_embed        = $jetpack_videopress['display_embed'];
335                $privacy_setting      = $jetpack_videopress['privacy_setting'];
336                $needs_playback_token = $jetpack_videopress['needs_playback_token'];
337                $is_private           = $jetpack_videopress['is_private'];
338
339                $original      = $videopress_media_details['original'];
340                $poster        = ( ! $needs_playback_token ) ? $videopress_media_details['poster'] : null;
341                $upload_date   = $videopress_media_details['upload_date'];
342                $duration      = $videopress_media_details['duration'];
343                $file_url_base = $videopress_media_details['file_url_base'];
344                $finished      = $videopress_media_details['finished'];
345                $files         = $videopress_media_details['files'];
346                $filename      = basename( $original );
347
348                if ( isset( $files['dvd']['original_img'] ) && $privacy_setting !== 1 ) {
349                    $thumbnail = $file_url_base['https'] . $files['dvd']['original_img'];
350                } else {
351                    $thumbnail = null;
352                }
353
354                return array(
355                    'id'                 => $id,
356                    'guid'               => $guid,
357                    'title'              => $title,
358                    'description'        => $description,
359                    'caption'            => $caption,
360                    'url'                => $original,
361                    'uploadDate'         => $upload_date,
362                    'duration'           => $duration,
363                    'isPrivate'          => $is_private,
364                    'posterImage'        => $poster,
365                    'allowDownload'      => $allow_download,
366                    'displayEmbed'       => $display_embed,
367                    'rating'             => $rating,
368                    'privacySetting'     => $privacy_setting,
369                    'needsPlaybackToken' => $needs_playback_token,
370                    'width'              => $width,
371                    'height'             => $height,
372                    'poster'             => array(
373                        'src' => $poster,
374                    ),
375                    'thumbnail'          => $thumbnail,
376                    'finished'           => $finished,
377                    'filename'           => $filename,
378                );
379            },
380            $videopress_data['videos']
381        );
382
383        $site_settings = self::get_videopress_settings();
384
385        $initial_state = array(
386            'users'        => self::get_user_data(),
387            'siteSettings' => array(
388                'videoPressVideosPrivateForSite' => $site_settings['videopress_videos_private_for_site'],
389                'siteIsPrivate'                  => $site_settings['site_is_private'],
390                'siteType'                       => $site_settings['site_type'],
391            ),
392            'videos'       => array(
393                'uploadedVideoCount'           => $videopress_data['total'],
394                'items'                        => $videos,
395                'isFetching'                   => false,
396                'isFetchingUploadedVideoCount' => false,
397                'pagination'                   => array(
398                    'totalPages' => $videopress_data['totalPages'],
399                    'total'      => $videopress_data['total'],
400                ),
401                'query'                        => $videopress_data['query'],
402                '_meta'                        => array(
403                    'processedAllVideosBeingRemoved' => true,
404                    'relyOnInitialState'             => true,
405                ),
406            ),
407            'localVideos'  => array(
408                'uploadedVideoCount'           => $local_videos_data['total'],
409                'items'                        => $local_videos,
410                'isFetching'                   => false,
411                'isFetchingUploadedVideoCount' => false,
412                'pagination'                   => array(
413                    'totalPages' => $local_videos_data['totalPages'],
414                    'total'      => $local_videos_data['total'],
415                ),
416                'query'                        => $local_videos_data['query'],
417                '_meta'                        => array(
418                    'relyOnInitialState' => true,
419                ),
420            ),
421        );
422
423        if ( self::has_connected_owner() ) {
424            return array_merge_recursive( $initial_state, self::get_connected_initial_state() );
425        }
426
427        return $initial_state;
428    }
429}