PluginProbe
Jetpack – WP Security, Backup, Speed, & Growth / 16.3-beta
Jetpack – WP Security, Backup, Speed, & Growth v16.3-beta
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 13.7.2 All 507 releases
jetpack / jetpack_vendor / automattic / jetpack-videopress / src / class-rest-controller.php

class-rest-controller.php in Jetpack – WP Security, Backup, Speed, & Growth 16.3-beta, at jetpack_vendor/automattic/jetpack-videopress/src/class-rest-controller.php

176 lines 5.2 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * The VideoPress REST Controller.
4 *
5 * Registers the `/jetpack/v4/videopress/*` routes backing the
6 * modernized wp-build dashboard. Currently exposes one route — a
7 * user-signed proxy to the WPCOM `sites/{id}/stats/video-plays`
8 * endpoint — needed by the Overview screen's KPI / trends / top-N
9 * cards.
10 *
11 * @package automattic/jetpack-videopress
12 */
13
14 namespace Automattic\Jetpack\VideoPress;
15
16 use Automattic\Jetpack\Connection\Client;
17 use Jetpack_Options;
18 use WP_Error;
19 use WP_REST_Request;
20 use WP_REST_Server;
21
22 /**
23 * REST routes for the modernized VideoPress admin UI.
24 */
25 class Rest_Controller {
26
27 /**
28 * REST namespace used by this package's modernization routes.
29 *
30 * @var string
31 */
32 const REST_NAMESPACE = 'jetpack/v4/videopress';
33
34 /**
35 * Hook the route registration on `rest_api_init`.
36 *
37 * @return void
38 */
39 public static function init() {
40 add_action( 'rest_api_init', array( __CLASS__, 'register_rest_routes' ) );
41 }
42
43 /**
44 * Register the VideoPress REST routes.
45 *
46 * @return void
47 */
48 public static function register_rest_routes() {
49 register_rest_route(
50 self::REST_NAMESPACE,
51 '/stats/video-plays',
52 array(
53 'methods' => WP_REST_Server::READABLE,
54 'callback' => array( __CLASS__, 'get_stats_video_plays' ),
55 'permission_callback' => array( __CLASS__, 'permissions_callback' ),
56 'args' => self::stats_video_plays_args(),
57 )
58 );
59 }
60
61 /**
62 * Query params accepted by the video-plays proxy. Forwarded verbatim
63 * to WPCOM after permission and shape validation. `complete_stats` and
64 * `check_stats_module` are always forced by the callback and are
65 * therefore not exposed as incoming params.
66 *
67 * @return array
68 */
69 private static function stats_video_plays_args() {
70 return array(
71 'period' => array(
72 'description' => __( 'Period unit: day, week, month, or year.', 'jetpack-videopress-pkg' ),
73 'type' => 'string',
74 'enum' => array( 'day', 'week', 'month', 'year' ),
75 ),
76 'num' => array(
77 'description' => __( 'Number of periods to include.', 'jetpack-videopress-pkg' ),
78 'type' => 'integer',
79 'minimum' => 1,
80 'maximum' => 365,
81 ),
82 'date' => array(
83 'description' => __( 'Most recent day to include in results (YYYY-MM-DD).', 'jetpack-videopress-pkg' ),
84 'type' => 'string',
85 'format' => 'date',
86 ),
87 'start_date' => array(
88 'description' => __( 'Starting date for range queries (YYYY-MM-DD).', 'jetpack-videopress-pkg' ),
89 'type' => 'string',
90 'format' => 'date',
91 ),
92 );
93 }
94
95 /**
96 * Permission callback. Admin-gated. The upstream call is blog-signed,
97 * matching the existing `Stats::fetch_video_plays` path; no user-level
98 * WPCOM connection is required.
99 *
100 * @return bool
101 */
102 public static function permissions_callback() {
103 return current_user_can( 'manage_options' );
104 }
105
106 /**
107 * Proxy the video-plays stats endpoint.
108 *
109 * Forwards the allowed query params to WPCOM (REST v1.1, blog-signed
110 * — matching the existing `Stats::fetch_video_plays` path) and forces
111 * `complete_stats=true`. `check_stats_module=false` is also forced so the
112 * report loads for standalone VideoPress sites without the Jetpack Stats
113 * module active, matching `Stats::fetch_video_plays`. In complete-stats
114 * mode, each day entry carries
115 * `total.views`, `total.impressions`, and `total.watch_time` (in hours)
116 * plus a per-video `data[]` array whose entries have `post_id`, `title`,
117 * `views`, `impressions`, `watch_time` (hours), and `retention_rate`.
118 * The `plays` field is NOT returned in complete-stats mode.
119 *
120 * @param WP_REST_Request $request Incoming request.
121 * @return mixed Decoded JSON response from WPCOM, or WP_Error on failure.
122 */
123 public static function get_stats_video_plays( WP_REST_Request $request ) {
124 $blog_id = (int) Jetpack_Options::get_option( 'id' );
125 if ( ! $blog_id ) {
126 return new WP_Error(
127 'videopress_stats_not_connected',
128 esc_html__( 'This site is not connected to WordPress.com.', 'jetpack-videopress-pkg' ),
129 array( 'status' => 400 )
130 );
131 }
132
133 $params = array(
134 'complete_stats' => 'true',
135 'check_stats_module' => 'false',
136 );
137 foreach ( array_keys( self::stats_video_plays_args() ) as $key ) {
138 $value = $request->get_param( $key );
139 if ( $value !== null && $value !== '' ) {
140 $params[ $key ] = $value;
141 }
142 }
143
144 $path = sprintf(
145 'sites/%d/stats/video-plays?%s',
146 $blog_id,
147 http_build_query( $params )
148 );
149 $response = Client::wpcom_json_api_request_as_blog( $path );
150
151 if ( is_wp_error( $response ) ) {
152 return new WP_Error(
153 'videopress_stats_request_failed',
154 $response->get_error_message(),
155 array( 'status' => 500 )
156 );
157 }
158
159 $status = (int) wp_remote_retrieve_response_code( $response );
160 $body = json_decode( wp_remote_retrieve_body( $response ), true );
161
162 if ( 200 !== $status ) {
163 $message = is_array( $body ) && isset( $body['message'] )
164 ? (string) $body['message']
165 : esc_html__( 'Unable to fetch VideoPress stats.', 'jetpack-videopress-pkg' );
166 return new WP_Error(
167 'videopress_stats_request_failed',
168 $message,
169 array( 'status' => $status ? $status : 500 )
170 );
171 }
172
173 return rest_ensure_response( $body );
174 }
175 }
176