Automattic /
jetpack
These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more
| 1 | <?php |
||
| 2 | |||
| 3 | new WPCOM_JSON_API_List_Media_v1_1_Endpoint( array( |
||
| 4 | 'description' => 'Get a list of items in the media library.', |
||
| 5 | 'group' => 'media', |
||
| 6 | 'stat' => 'media', |
||
| 7 | 'min_version' => '1.1', |
||
| 8 | 'max_version' => '1.1', |
||
| 9 | 'method' => 'GET', |
||
| 10 | 'path' => '/sites/%s/media/', |
||
| 11 | 'path_labels' => array( |
||
| 12 | '$site' => '(int|string) Site ID or domain', |
||
| 13 | ), |
||
| 14 | |||
| 15 | 'query_parameters' => array( |
||
| 16 | 'number' => '(int=20) The number of media items to return. Limit: 100.', |
||
| 17 | 'offset' => '(int=0) 0-indexed offset.', |
||
| 18 | 'page' => '(int) Return the Nth 1-indexed page of posts. Takes precedence over the <code>offset</code> parameter.', |
||
| 19 | 'page_handle' => '(string) A page handle, returned from a previous API call as a <code>meta.next_page</code> property. This is the most efficient way to fetch the next page of results.', |
||
| 20 | 'order' => array( |
||
| 21 | 'DESC' => 'Return files in descending order. For dates, that means newest to oldest.', |
||
| 22 | 'ASC' => 'Return files in ascending order. For dates, that means oldest to newest.', |
||
| 23 | ), |
||
| 24 | 'order_by' => array( |
||
| 25 | 'date' => 'Order by the uploaded time of each file.', |
||
| 26 | 'title' => "Order lexicographically by file titles.", |
||
| 27 | 'ID' => 'Order by media ID.', |
||
| 28 | ), |
||
| 29 | 'search' => '(string) Search query.', |
||
| 30 | 'post_ID' => '(int) Default is showing all items. The post where the media item is attached. 0 shows unattached media items.', |
||
| 31 | 'mime_type' => "(string) Default is empty. Filter by mime type (e.g., 'image/jpeg', 'application/pdf'). Partial searches also work (e.g. passing 'image' will search for all image files).", |
||
| 32 | 'after' => '(ISO 8601 datetime) Return media items uploaded after the specified datetime.', |
||
| 33 | 'before' => '(ISO 8601 datetime) Return media items uploaded before the specified datetime.', |
||
| 34 | ), |
||
| 35 | |||
| 36 | 'response_format' => array( |
||
| 37 | 'media' => '(array) Array of media objects', |
||
| 38 | 'found' => '(int) The number of total results found', |
||
| 39 | 'meta' => '(object) Meta data', |
||
| 40 | ), |
||
| 41 | |||
| 42 | 'example_request' => 'https://public-api.wordpress.com/rest/v1.1/sites/82974409/media', |
||
| 43 | 'example_request_data' => array( |
||
| 44 | 'headers' => array( |
||
| 45 | 'authorization' => 'Bearer YOUR_API_TOKEN' |
||
| 46 | ) |
||
| 47 | ) |
||
| 48 | ) ); |
||
| 49 | |||
| 50 | class WPCOM_JSON_API_List_Media_v1_1_Endpoint extends WPCOM_JSON_API_Endpoint { |
||
| 51 | |||
| 52 | public $date_range = array(); |
||
| 53 | public $page_handle = array(); |
||
| 54 | |||
| 55 | function callback( $path = '', $blog_id = 0 ) { |
||
| 56 | $blog_id = $this->api->switch_to_blog_and_validate_user( $this->api->get_blog_id( $blog_id ) ); |
||
| 57 | if ( is_wp_error( $blog_id ) ) { |
||
| 58 | return $blog_id; |
||
| 59 | } |
||
| 60 | |||
| 61 | //upload_files can probably be used for other endpoints but we want contributors to be able to use media too |
||
| 62 | if ( ! current_user_can( 'edit_posts' ) ) { |
||
| 63 | return new WP_Error( 'unauthorized', 'User cannot view media', 403 ); |
||
|
0 ignored issues
–
show
|
|||
| 64 | } |
||
| 65 | |||
| 66 | $args = $this->query_args(); |
||
| 67 | $is_eligible_for_page_handle = true; |
||
| 68 | |||
| 69 | if ( $args['number'] < 1 ) { |
||
| 70 | $args['number'] = 20; |
||
| 71 | } elseif ( 100 < $args['number'] ) { |
||
| 72 | return new WP_Error( 'invalid_number', 'The NUMBER parameter must be less than or equal to 100.', 400 ); |
||
|
0 ignored issues
–
show
The call to
WP_Error::__construct() has too many arguments starting with 'invalid_number'.
This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue. If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress. In this case you can add the Loading history...
|
|||
| 73 | } |
||
| 74 | |||
| 75 | if ( defined( 'IS_WPCOM' ) && IS_WPCOM ) { |
||
| 76 | $this->load_theme_functions(); |
||
| 77 | } |
||
| 78 | |||
| 79 | if ( isset( $args['before'] ) ) { |
||
| 80 | $this->date_range['before'] = $args['before']; |
||
| 81 | } |
||
| 82 | if ( isset( $args['after'] ) ) { |
||
| 83 | $this->date_range['after'] = $args['after']; |
||
| 84 | } |
||
| 85 | |||
| 86 | $query = array( |
||
| 87 | 'post_type' => 'attachment', |
||
| 88 | 'post_status' => 'inherit', |
||
| 89 | 'post_parent' => isset( $args['post_ID'] ) ? $args['post_ID'] : null, |
||
| 90 | 'posts_per_page' => $args['number'], |
||
| 91 | 'post_mime_type' => isset( $args['mime_type'] ) ? $args['mime_type'] : null, |
||
| 92 | 'order' => isset( $args['order'] ) ? $args['order'] : 'DESC', |
||
| 93 | 'orderby' => isset( $args['order_by'] ) ? $args['order_by'] : 'date', |
||
| 94 | 's' => isset( $args['search'] ) ? $args['search'] : null, |
||
| 95 | ); |
||
| 96 | |||
| 97 | View Code Duplication | if ( isset( $args['page'] ) ) { |
|
| 98 | if ( $args['page'] < 1 ) { |
||
| 99 | $args['page'] = 1; |
||
| 100 | } |
||
| 101 | |||
| 102 | $query['paged'] = $args['page']; |
||
| 103 | if ( $query['paged'] !== 1 ) { |
||
| 104 | $is_eligible_for_page_handle = false; |
||
| 105 | } |
||
| 106 | } else { |
||
| 107 | if ( $args['offset'] < 0 ) { |
||
| 108 | $args['offset'] = 0; |
||
| 109 | } |
||
| 110 | |||
| 111 | $query['offset'] = $args['offset']; |
||
| 112 | if ( $query['offset'] !== 0 ) { |
||
| 113 | $is_eligible_for_page_handle = false; |
||
| 114 | } |
||
| 115 | } |
||
| 116 | |||
| 117 | View Code Duplication | if ( isset( $args['page_handle'] ) ) { |
|
| 118 | $page_handle = wp_parse_args( $args['page_handle'] ); |
||
| 119 | if ( isset( $page_handle['value'] ) && isset( $page_handle['id'] ) ) { |
||
| 120 | // we have a valid looking page handle |
||
| 121 | $this->page_handle = $page_handle; |
||
| 122 | add_filter( 'posts_where', array( $this, 'handle_where_for_page_handle' ) ); |
||
| 123 | } |
||
| 124 | } |
||
| 125 | |||
| 126 | if ( $this->date_range ) { |
||
| 127 | add_filter( 'posts_where', array( $this, 'handle_date_range' ) ); |
||
| 128 | } |
||
| 129 | |||
| 130 | $this->performed_query = $query; |
||
| 131 | add_filter( 'posts_orderby', array( $this, 'handle_orderby_for_page_handle' ) ); |
||
| 132 | |||
| 133 | $media = new WP_Query( $query ); |
||
| 134 | |||
| 135 | remove_filter( 'posts_orderby', array( $this, 'handle_orderby_for_page_handle' ) ); |
||
| 136 | |||
| 137 | if ( $this->date_range ) { |
||
| 138 | remove_filter( 'posts_where', array( $this, 'handle_date_range' ) ); |
||
| 139 | $this->date_range = array(); |
||
| 140 | } |
||
| 141 | |||
| 142 | if ( $this->page_handle ) { |
||
| 143 | remove_filter( 'posts_where', array( $this, 'handle_where_for_page_handle' ) ); |
||
| 144 | } |
||
| 145 | |||
| 146 | $response = array(); |
||
| 147 | |||
| 148 | foreach ( $media->posts as $item ) { |
||
| 149 | $response[] = $this->get_media_item_v1_1( $item->ID ); |
||
| 150 | } |
||
| 151 | |||
| 152 | $return = array( |
||
| 153 | 'found' => (int) $media->found_posts, |
||
| 154 | 'media' => $response |
||
| 155 | ); |
||
| 156 | |||
| 157 | if ( $is_eligible_for_page_handle && $return['media'] ) { |
||
| 158 | $last_post = end( $return['media'] ); |
||
| 159 | reset( $return['media'] ); |
||
| 160 | |||
| 161 | if ( ( $return['found'] > count( $return['media'] ) ) && $last_post ) { |
||
| 162 | $return['meta'] = array(); |
||
| 163 | $return['meta']['next_page'] = $this->build_page_handle( $last_post, $query ); |
||
| 164 | } |
||
| 165 | } |
||
| 166 | |||
| 167 | return $return; |
||
| 168 | } |
||
| 169 | |||
| 170 | View Code Duplication | function build_page_handle( $post, $query ) { |
|
| 171 | $column = $query['orderby']; |
||
| 172 | if ( ! $column ) { |
||
| 173 | $column = 'date'; |
||
| 174 | } |
||
| 175 | return build_query( array( 'value' => urlencode( $post->$column ), 'id' => $post->ID ) ); |
||
| 176 | } |
||
| 177 | |||
| 178 | View Code Duplication | function handle_where_for_page_handle( $where ) { |
|
| 179 | global $wpdb; |
||
| 180 | |||
| 181 | $column = $this->performed_query['orderby']; |
||
| 182 | if ( ! $column ) { |
||
| 183 | $column = 'date'; |
||
| 184 | } |
||
| 185 | $order = $this->performed_query['order']; |
||
| 186 | if ( ! $order ) { |
||
| 187 | $order = 'DESC'; |
||
| 188 | } |
||
| 189 | |||
| 190 | if ( ! in_array( $column, array( 'ID', 'title', 'date', 'modified', 'comment_count' ) ) ) { |
||
| 191 | return $where; |
||
| 192 | } |
||
| 193 | |||
| 194 | if ( ! in_array( $order, array( 'DESC', 'ASC' ) ) ) { |
||
| 195 | return $where; |
||
| 196 | } |
||
| 197 | |||
| 198 | $db_column = ''; |
||
| 199 | $db_value = ''; |
||
| 200 | switch( $column ) { |
||
| 201 | case 'ID': |
||
| 202 | $db_column = 'ID'; |
||
| 203 | $db_value = '%d'; |
||
| 204 | break; |
||
| 205 | case 'title': |
||
| 206 | $db_column = 'post_title'; |
||
| 207 | $db_value = '%s'; |
||
| 208 | break; |
||
| 209 | case 'date': |
||
| 210 | $db_column = 'post_date'; |
||
| 211 | $db_value = 'CAST( %s as DATETIME )'; |
||
| 212 | break; |
||
| 213 | case 'modified': |
||
| 214 | $db_column = 'post_modified'; |
||
| 215 | $db_value = 'CAST( %s as DATETIME )'; |
||
| 216 | break; |
||
| 217 | case 'comment_count': |
||
| 218 | $db_column = 'comment_count'; |
||
| 219 | $db_value = '%d'; |
||
| 220 | break; |
||
| 221 | } |
||
| 222 | |||
| 223 | if ( 'DESC'=== $order ) { |
||
| 224 | $db_order = '<'; |
||
| 225 | } else { |
||
| 226 | $db_order = '>'; |
||
| 227 | } |
||
| 228 | |||
| 229 | // Add a clause that limits the results to items beyond the passed item, or equivalent to the passed item |
||
| 230 | // but with an ID beyond the passed item. When we're ordering by the ID already, we only ask for items |
||
| 231 | // beyond the passed item. |
||
| 232 | $where .= $wpdb->prepare( " AND ( ( `$wpdb->posts`.`$db_column` $db_order $db_value ) ", $this->page_handle['value'] ); |
||
| 233 | if ( $db_column !== 'ID' ) { |
||
| 234 | $where .= $wpdb->prepare( "OR ( `$wpdb->posts`.`$db_column` = $db_value AND `$wpdb->posts`.ID $db_order %d )", $this->page_handle['value'], $this->page_handle['id'] ); |
||
| 235 | } |
||
| 236 | $where .= ' )'; |
||
| 237 | |||
| 238 | return $where; |
||
| 239 | } |
||
| 240 | |||
| 241 | View Code Duplication | function handle_date_range( $where ) { |
|
| 242 | global $wpdb; |
||
| 243 | |||
| 244 | switch ( count( $this->date_range ) ) { |
||
| 245 | case 2 : |
||
| 246 | $where .= $wpdb->prepare( |
||
| 247 | " AND `$wpdb->posts`.post_date BETWEEN CAST( %s AS DATETIME ) AND CAST( %s AS DATETIME ) ", |
||
| 248 | $this->date_range['after'], |
||
| 249 | $this->date_range['before'] |
||
| 250 | ); |
||
| 251 | break; |
||
| 252 | case 1 : |
||
| 253 | if ( isset( $this->date_range['before'] ) ) { |
||
| 254 | $where .= $wpdb->prepare( |
||
| 255 | " AND `$wpdb->posts`.post_date <= CAST( %s AS DATETIME ) ", |
||
| 256 | $this->date_range['before'] |
||
| 257 | ); |
||
| 258 | } else { |
||
| 259 | $where .= $wpdb->prepare( |
||
| 260 | " AND `$wpdb->posts`.post_date >= CAST( %s AS DATETIME ) ", |
||
| 261 | $this->date_range['after'] |
||
| 262 | ); |
||
| 263 | } |
||
| 264 | break; |
||
| 265 | } |
||
| 266 | |||
| 267 | return $where; |
||
| 268 | } |
||
| 269 | |||
| 270 | View Code Duplication | function handle_orderby_for_page_handle( $orderby ) { |
|
| 271 | global $wpdb; |
||
| 272 | if ( $this->performed_query['orderby'] === 'ID' ) { |
||
| 273 | // bail if we're already ordering by ID |
||
| 274 | return $orderby; |
||
| 275 | } |
||
| 276 | |||
| 277 | if ( $orderby ) { |
||
| 278 | $orderby .= ' ,'; |
||
| 279 | } |
||
| 280 | $order = $this->performed_query['order']; |
||
| 281 | if ( ! $order ) { |
||
| 282 | $order = 'DESC'; |
||
| 283 | } |
||
| 284 | $orderby .= " `$wpdb->posts`.ID $order"; |
||
| 285 | return $orderby; |
||
| 286 | } |
||
| 287 | |||
| 288 | } |
||
| 289 |
This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.
If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress.
In this case you can add the
@ignorePhpDoc annotation to the duplicate definition and it will be ignored.