Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
54.55% covered (warning)
54.55%
42 / 77
81.25% covered (warning)
81.25%
13 / 16
CRAP
0.00% covered (danger)
0.00%
0 / 1
Videopress
54.67% covered (warning)
54.67%
41 / 75
81.25% covered (warning)
81.25%
13 / 16
107.35
0.00% covered (danger)
0.00%
0 / 1
 register_endpoints
100.00% covered (success)
100.00%
10 / 10
100.00% covered (success)
100.00%
1 / 1
1
 permissions_callback
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 get_name
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 get_title
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 get_description
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 get_long_description
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 get_features
100.00% covered (success)
100.00%
6 / 6
100.00% covered (success)
100.00%
1 / 1
1
 get_pricing_for_ui
100.00% covered (success)
100.00%
7 / 7
100.00% covered (success)
100.00%
1 / 1
1
 get_post_checkout_url
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 get_wpcom_product_slug
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 get_post_activation_url
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 get_manage_url
100.00% covered (success)
100.00%
5 / 5
100.00% covered (success)
100.00%
1 / 1
4
 get_paid_plan_product_slugs
100.00% covered (success)
100.00%
5 / 5
100.00% covered (success)
100.00%
1 / 1
1
 is_upgradable_by_bundle
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 get_videopress_stats
0.00% covered (danger)
0.00%
0 / 31
0.00% covered (danger)
0.00%
0 / 1
132
 get_site_videopress_data
0.00% covered (danger)
0.00%
0 / 2
0.00% covered (danger)
0.00%
0 / 1
2
1<?php
2/**
3 * VideoPress product
4 *
5 * @package my-jetpack
6 */
7
8namespace Automattic\Jetpack\My_Jetpack\Products;
9
10use Automattic\Jetpack\Feature_Flags\Feature_Flags;
11use Automattic\Jetpack\My_Jetpack\Hybrid_Product;
12use Automattic\Jetpack\My_Jetpack\Wpcom_Products;
13use Automattic\Jetpack\VideoPress\Stats as VideoPress_Stats;
14use WP_Error;
15use WP_REST_Response;
16
17if ( ! defined( 'ABSPATH' ) ) {
18    exit( 0 );
19}
20
21/**
22 * Class responsible for handling the VideoPress product
23 */
24class Videopress extends Hybrid_Product {
25    private const VIDEOPRESS_STATS_KEY  = 'my-jetpack-videopress-stats';
26    private const VIDEOPRESS_PERIOD_KEY = 'my-jetpack-videopress-period';
27
28    /**
29     * The product slug
30     *
31     * @var string
32     */
33    public static $slug = 'videopress';
34
35    /**
36     * The Jetpack module name
37     *
38     * @var string
39     */
40    public static $module_name = 'videopress';
41
42    /**
43     * The slug of the plugin associated with this product.
44     *
45     * @var string
46     */
47    public static $plugin_slug = 'jetpack-videopress';
48
49    /**
50     * The category of the product
51     *
52     * @var string
53     */
54    public static $category = 'performance';
55
56    /**
57     * The filename (id) of the plugin associated with this product.
58     *
59     * @var string
60     */
61    public static $plugin_filename = array(
62        'jetpack-videopress/jetpack-videopress.php',
63        'videopress/jetpack-videopress.php',
64        'jetpack-videopress-dev/jetpack-videopress.php',
65    );
66
67    /**
68     * Search only requires site connection
69     *
70     * @var boolean
71     */
72    public static $requires_user_connection = true;
73
74    /**
75     * VideoPress has a standalone plugin
76     *
77     * @var bool
78     */
79    public static $has_standalone_plugin = true;
80
81    /**
82     * Whether this product has a free offering
83     *
84     * @var bool
85     */
86    public static $has_free_offering = true;
87
88    /**
89     * The feature slug that identifies the paid plan
90     *
91     * @var string
92     */
93    public static $feature_identifying_paid_plan = 'videopress';
94
95        /**
96         * Setup VideoPress REST API endpoints
97         *
98         * @return void
99         */
100    public static function register_endpoints(): void {
101        parent::register_endpoints();
102        // Get Jetpack VideoPress data.
103        register_rest_route(
104            'my-jetpack/v1',
105            '/site/videopress/data',
106            array(
107                'methods'             => \WP_REST_Server::READABLE,
108                'callback'            => __CLASS__ . '::get_site_videopress_data',
109                'permission_callback' => __CLASS__ . '::permissions_callback',
110            )
111        );
112    }
113
114    /**
115     * Checks if the user has the correct permissions
116     */
117    public static function permissions_callback() {
118        return current_user_can( 'edit_posts' );
119    }
120
121    /**
122     * Get the product name
123     *
124     * @return string
125     */
126    public static function get_name() {
127        return 'VideoPress';
128    }
129
130    /**
131     * Get the product title
132     *
133     * @return string
134     */
135    public static function get_title() {
136        return 'Jetpack VideoPress';
137    }
138
139    /**
140     * Get the internationalized product description
141     *
142     * @return string
143     */
144    public static function get_description() {
145        return __( 'Powerful and flexible video hosting.', 'jetpack-my-jetpack' );
146    }
147
148    /**
149     * Get the internationalized product long description
150     *
151     * @return string
152     */
153    public static function get_long_description() {
154        return __( 'Stunning-quality, ad-free video in the WordPress Editor', 'jetpack-my-jetpack' );
155    }
156
157    /**
158     * Get the internationalized features list
159     *
160     * @return array Boost features list
161     */
162    public static function get_features() {
163        return array(
164            _x( '1TB of storage', 'VideoPress Product Feature', 'jetpack-my-jetpack' ),
165            _x( 'Built into WordPress editor', 'VideoPress Product Feature', 'jetpack-my-jetpack' ),
166            _x( 'Ad-free and customizable player', 'VideoPress Product Feature', 'jetpack-my-jetpack' ),
167            _x( 'Unlimited users', 'VideoPress Product Feature', 'jetpack-my-jetpack' ),
168        );
169    }
170
171    /**
172     * Get the product princing details
173     *
174     * @return array Pricing details
175     */
176    public static function get_pricing_for_ui() {
177        return array_merge(
178            array(
179                'available'          => true,
180                'wpcom_product_slug' => static::get_wpcom_product_slug(),
181            ),
182            Wpcom_Products::get_product_pricing( static::get_wpcom_product_slug() )
183        );
184    }
185
186    /**
187     * Get the URL the user is taken after purchasing the product through the checkout
188     *
189     * @return ?string
190     */
191    public static function get_post_checkout_url() {
192        return self::get_manage_url();
193    }
194
195    /**
196     * Get the WPCOM product slug used to make the purchase
197     *
198     * @return ?string
199     */
200    public static function get_wpcom_product_slug() {
201        return 'jetpack_videopress';
202    }
203
204    /**
205     * Get the URL the user is taken after activating the product
206     *
207     * @return ?string
208     */
209    public static function get_post_activation_url() {
210        return ''; // stay in My Jetpack page.
211    }
212
213    /**
214     * Get the URL where the user manages the product
215     *
216     * @return ?string
217     */
218    public static function get_manage_url() {
219        if ( method_exists( 'Automattic\Jetpack\VideoPress\Initializer', 'should_initialize_admin_ui' ) && \Automattic\Jetpack\VideoPress\Initializer::should_initialize_admin_ui() ) {
220            return \Automattic\Jetpack\VideoPress\Admin_UI::get_admin_page_url();
221        } elseif ( Feature_Flags::is_enabled( \Automattic\Jetpack\My_Jetpack\Initializer::SETTINGS_CONSOLIDATION_FLAG ) ) {
222            return admin_url( 'admin.php?page=my-jetpack#/features?search=videopress' );
223        } else {
224            return admin_url( 'admin.php?page=jetpack#/settings?term=videopress' );
225        }
226    }
227
228    /**
229     * Get the product-slugs of the paid plans for this product (not including bundles)
230     *
231     * @return array
232     */
233    public static function get_paid_plan_product_slugs() {
234        return array(
235            'jetpack_videopress',
236            'jetpack_videopress_monthly',
237            'jetpack_videopress_bi_yearly',
238        );
239    }
240
241    /**
242     * Return product bundles list
243     * that supports the product.
244     *
245     * @return boolean|array Products bundle list.
246     */
247    public static function is_upgradable_by_bundle() {
248        return array( 'complete' );
249    }
250
251    /**
252     * Get stats for VideoPress
253     *
254     * @return array|WP_Error
255     */
256    private static function get_videopress_stats() {
257        $video_count = array_sum( (array) wp_count_attachments( 'video' ) );
258
259        if ( ! class_exists( 'Automattic\Jetpack\VideoPress\Stats' ) ) {
260            return array(
261                'videoCount' => $video_count,
262            );
263        }
264
265        $featured_stats = get_transient( self::VIDEOPRESS_STATS_KEY );
266
267        if ( $featured_stats ) {
268            return array(
269                'featuredStats' => $featured_stats,
270                'videoCount'    => $video_count,
271            );
272        }
273
274        $stats_period     = get_transient( self::VIDEOPRESS_PERIOD_KEY );
275        $videopress_stats = new VideoPress_Stats();
276
277        // If the stats period exists, retrieve that information without checking the view count.
278        // If it does not, check the view count of monthly stats and determine if we want to show yearly or monthly stats.
279        if ( $stats_period ) {
280            if ( $stats_period === 'day' ) {
281                $featured_stats = $videopress_stats->get_featured_stats( 60, 'day' );
282            } else {
283                $featured_stats = $videopress_stats->get_featured_stats( 2, 'year' );
284            }
285        } else {
286            $featured_stats = $videopress_stats->get_featured_stats( 60, 'day' );
287
288            if (
289                ! is_wp_error( $featured_stats ) &&
290                $featured_stats &&
291                ( $featured_stats['data']['views']['current'] < 500 || $featured_stats['data']['views']['previous'] < 500 )
292            ) {
293                $featured_stats = $videopress_stats->get_featured_stats( 2, 'year' );
294            }
295        }
296
297        if ( is_wp_error( $featured_stats ) || ! $featured_stats ) {
298            return array(
299                'videoCount' => $video_count,
300            );
301        }
302
303        set_transient( self::VIDEOPRESS_PERIOD_KEY, $featured_stats['period'], WEEK_IN_SECONDS );
304        set_transient( self::VIDEOPRESS_STATS_KEY, $featured_stats, DAY_IN_SECONDS );
305
306        return array(
307            'featuredStats' => $featured_stats,
308            'videoCount'    => $video_count,
309        );
310    }
311
312    /**
313     * Get VideoPress data for the REST API
314     *
315     * @return WP_REST_Response|WP_Error
316     */
317    public static function get_site_videopress_data() {
318        $videopress_stats = self::get_videopress_stats();
319
320        return rest_ensure_response( $videopress_stats );
321    }
322}