Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
34.44% covered (danger)
34.44%
31 / 90
11.11% covered (danger)
11.11%
1 / 9
CRAP
0.00% covered (danger)
0.00%
0 / 1
WPCOM_REST_API_V2_Endpoint_App_Media
35.63% covered (danger)
35.63%
31 / 87
11.11% covered (danger)
11.11%
1 / 9
75.01
0.00% covered (danger)
0.00%
0 / 1
 __construct
0.00% covered (danger)
0.00%
0 / 3
0.00% covered (danger)
0.00%
0 / 1
2
 register_routes
100.00% covered (success)
100.00%
31 / 31
100.00% covered (success)
100.00%
1 / 1
1
 permission_callback
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 sanitize_media
0.00% covered (danger)
0.00%
0 / 2
0.00% covered (danger)
0.00%
0 / 1
2
 validate_media
0.00% covered (danger)
0.00%
0 / 2
0.00% covered (danger)
0.00%
0 / 1
2
 prepare_media_param
0.00% covered (danger)
0.00%
0 / 8
0.00% covered (danger)
0.00%
0 / 1
30
 get_media
0.00% covered (danger)
0.00%
0 / 16
0.00% covered (danger)
0.00%
0 / 1
2
 format_response
0.00% covered (danger)
0.00%
0 / 9
0.00% covered (danger)
0.00%
0 / 1
12
 format_item
0.00% covered (danger)
0.00%
0 / 15
0.00% covered (danger)
0.00%
0 / 1
2
1<?php
2/**
3 * REST API endpoint for the media uploaded by the Jetpack app.
4 *
5 * @package automattic/jetpack
6 * @since 13.1
7 */
8
9if ( ! defined( 'ABSPATH' ) ) {
10    exit( 0 );
11}
12
13/**
14 * Media uploaded by the Jetpack app helper API.
15 *
16 * @since 13.1
17 */
18class WPCOM_REST_API_V2_Endpoint_App_Media extends WP_REST_Controller {
19
20    /**
21     * Constructor.
22     */
23    public function __construct() {
24        $this->namespace = 'wpcom/v2';
25        $this->rest_base = 'app-media';
26
27        add_action( 'rest_api_init', array( $this, 'register_routes' ) );
28    }
29
30    /**
31     * Registers the routes for external media.
32     */
33    public function register_routes() {
34        register_rest_route(
35            $this->namespace,
36            $this->rest_base,
37            array(
38                'methods'             => WP_REST_Server::READABLE,
39                'callback'            => array( $this, 'get_media' ),
40                'permission_callback' => array( $this, 'permission_callback' ),
41                'args'                => array(
42                    'number'      => array(
43                        'description'       => __( 'Number of media items in the request', 'jetpack' ),
44                        'type'              => 'number',
45                        'default'           => 20,
46                        'required'          => false,
47                        'sanitize_callback' => 'absint',
48
49                    ),
50                    'page_handle' => array(
51                        'type'              => 'number',
52                        'default'           => 1,
53                        'required'          => false,
54                        'sanitize_callback' => 'absint',
55
56                    ),
57                    'after'       => array(
58                        'description'       => __( 'Timestamp since the media was uploaded', 'jetpack' ),
59                        'type'              => 'number',
60                        'default'           => 0,
61                        'required'          => true,
62                        'sanitize_callback' => 'absint',
63                    ),
64                ),
65            )
66        );
67    }
68
69    /**
70     * Checks if a given request has access to external media libraries.
71     */
72    public function permission_callback() {
73        return current_user_can( 'upload_files' );
74    }
75
76    /**
77     * Sanitization callback for media parameter.
78     *
79     * @param array $param Media parameter.
80     * @return true|\WP_Error
81     */
82    public function sanitize_media( $param ) {
83        $param = $this->prepare_media_param( $param );
84
85        return rest_sanitize_value_from_schema( $param, $this->media_schema );
86    }
87
88    /**
89     * Validation callback for media parameter.
90     *
91     * @param array $param Media parameter.
92     * @return true|\WP_Error
93     */
94    public function validate_media( $param ) {
95        $param = $this->prepare_media_param( $param );
96        return rest_validate_value_from_schema( $param, $this->media_schema, 'media' );
97    }
98
99    /**
100     * Decodes guid json and sets parameter defaults.
101     *
102     * @param array $param Media parameter.
103     * @return array
104     */
105    private function prepare_media_param( $param ) {
106        foreach ( $param as $key => $item ) {
107            if ( ! empty( $item['guid'] ) ) {
108                $param[ $key ]['guid'] = json_decode( $item['guid'], true );
109            }
110
111            if ( empty( $param[ $key ]['caption'] ) ) {
112                $param[ $key ]['caption'] = '';
113            }
114            if ( empty( $param[ $key ]['title'] ) ) {
115                $param[ $key ]['title'] = '';
116            }
117        }
118
119        return $param;
120    }
121
122    /**
123     * Retrieves media items from external libraries.
124     *
125     * @param \WP_REST_Request $request Full details about the request.
126     * @return array|\WP_Error|mixed
127     */
128    public function get_media( \WP_REST_Request $request ) {
129        $params = $request->get_params();
130
131        $query_args = array(
132            'post_type'   => 'attachment',
133            'post_status' => 'inherit',
134            'number'      => $params['number'],
135            'date_query'  => array(
136                'after' => gmdate( DATE_RSS, intval( $params['after'] ) ),
137            ),
138            'paged'       => $params['page_handle'],
139            'author'      => get_current_user_id(),
140            'orderby'     => 'date',
141        );
142
143        $media_query = new WP_Query( $query_args );
144        $response    = $this->format_response( $media_query );
145
146        wp_reset_postdata();
147        return $response;
148    }
149    /**
150     * Formats api the response.
151     *
152     * @param \WP_Query $media_query Media query.
153     */
154    private function format_response( $media_query ) {
155        $response          = array();
156        $response['media'] = array();
157        while ( $media_query->have_posts() ) {
158            $media_query->the_post();
159            // only include images.
160            if ( wp_attachment_is_image( $media_query->post->ID ) ) {
161                $response['media'][] = $this->format_item( $media_query->post );
162            }
163        }
164        $response['found'] = $media_query->found_posts;
165        $response['meta']  = array( 'next_page' => $media_query->paged + 1 );
166        return $response;
167    }
168    /**
169     * Formats a single item.
170     *
171     * @param \WP_Post $item Media item.
172     */
173    private function format_item( $item ) {
174        return array(
175            'ID'         => $item->ID,
176            'url'        => wp_get_attachment_image_url( $item->ID, 'full', true ),
177            'date'       => get_date_from_gmt( $item->post_date_gmt ),
178            'name'       => get_the_title( $item ),
179            'file'       => basename( wp_get_attachment_url( $item->ID ) ),
180            'title'      => get_the_title( $item ),
181            'guid'       => get_the_guid( $item ),
182            'type'       => get_post_mime_type( $item ),
183            'caption'    => '',
184            'thumbnails' => array(
185                'thumbnail' => wp_get_attachment_image_url( $item->ID, 'thumbnail' ),
186                'large'     => wp_get_attachment_image_url( $item->ID, 'large' ),
187            ),
188        );
189    }
190}
191
192wpcom_rest_api_v2_load_plugin( 'WPCOM_REST_API_V2_Endpoint_App_Media' );