/json-endpoints/class.wpcom-json-api-list-media-v1-1-endpoint.php

  1. <?php 
  2.  
  3. class WPCOM_JSON_API_List_Media_v1_1_Endpoint extends WPCOM_JSON_API_Endpoint { 
  4.  
  5. public $date_range = array(); 
  6. public $page_handle = array(); 
  7.  
  8. function callback( $path = '', $blog_id = 0 ) { 
  9. $blog_id = $this->api->switch_to_blog_and_validate_user( $this->api->get_blog_id( $blog_id ) ); 
  10. if ( is_wp_error( $blog_id ) ) { 
  11. return $blog_id; 
  12.  
  13. //upload_files can probably be used for other endpoints but we want contributors to be able to use media too 
  14. if ( ! current_user_can( 'edit_posts' ) ) { 
  15. return new WP_Error( 'unauthorized', 'User cannot view media', 403 ); 
  16.  
  17. $args = $this->query_args(); 
  18. $is_eligible_for_page_handle = true; 
  19.  
  20. if ( $args['number'] < 1 ) { 
  21. $args['number'] = 20; 
  22. } elseif ( 100 < $args['number'] ) { 
  23. return new WP_Error( 'invalid_number', 'The NUMBER parameter must be less than or equal to 100.', 400 ); 
  24.  
  25. if ( isset( $args['before'] ) ) { 
  26. $this->date_range['before'] = $args['before']; 
  27. if ( isset( $args['after'] ) ) { 
  28. $this->date_range['after'] = $args['after']; 
  29.  
  30. $query = array( 
  31. 'post_type' => 'attachment',  
  32. 'post_status' => 'inherit',  
  33. 'post_parent' => isset( $args['post_ID'] ) ? $args['post_ID'] : null,  
  34. 'offset' => isset( $args['offset'] ) ? $args['offset'] : null,  
  35. 'posts_per_page' => $args['number'],  
  36. 'post_mime_type' => isset( $args['mime_type'] ) ? $args['mime_type'] : null,  
  37. 'order' => isset( $args['order'] ) ? $args['order'] : 'DESC',  
  38. 'orderby' => isset( $args['order_by'] ) ? $args['order_by'] : 'date',  
  39. 's' => isset( $args['search'] ) ? $args['search'] : null,  
  40. ); 
  41.  
  42. if ( isset( $args['page'] ) ) { 
  43. if ( $args['page'] < 1 ) { 
  44. $args['page'] = 1; 
  45.  
  46. $query['paged'] = $args['page']; 
  47. if ( $query['paged'] !== 1 ) { 
  48. $is_eligible_for_page_handle = false; 
  49. } else { 
  50. if ( $args['offset'] < 0 ) { 
  51. $args['offset'] = 0; 
  52.  
  53. $query['offset'] = $args['offset']; 
  54. if ( $query['offset'] !== 0 ) { 
  55. $is_eligible_for_page_handle = false; 
  56.  
  57. if ( isset( $args['page_handle'] ) ) { 
  58. $page_handle = wp_parse_args( $args['page_handle'] ); 
  59. if ( isset( $page_handle['value'] ) && isset( $page_handle['id'] ) ) { 
  60. // we have a valid looking page handle 
  61. $this->page_handle = $page_handle; 
  62. add_filter( 'posts_where', array( $this, 'handle_where_for_page_handle' ) ); 
  63.  
  64. if ( $this->date_range ) { 
  65. add_filter( 'posts_where', array( $this, 'handle_date_range' ) ); 
  66.  
  67. $this->performed_query = $query; 
  68. add_filter( 'posts_orderby', array( $this, 'handle_orderby_for_page_handle' ) ); 
  69.  
  70. $media = new WP_Query( $query ); 
  71.  
  72. remove_filter( 'posts_orderby', array( $this, 'handle_orderby_for_page_handle' ) ); 
  73.  
  74. if ( $this->date_range ) { 
  75. remove_filter( 'posts_where', array( $this, 'handle_date_range' ) ); 
  76. $this->date_range = array(); 
  77.  
  78. if ( $this->page_handle ) { 
  79. remove_filter( 'posts_where', array( $this, 'handle_where_for_page_handle' ) ); 
  80.  
  81. $response = array(); 
  82. foreach ( $media->posts as $item ) { 
  83. $response[] = $this->get_media_item_v1_1( $item->ID ); 
  84.  
  85. $return = array( 
  86. 'found' => (int) $media->found_posts,  
  87. 'media' => $response 
  88. ); 
  89.  
  90. if ( $is_eligible_for_page_handle && $return['media'] ) { 
  91. $last_post = end( $return['media'] ); 
  92. reset( $return['media'] ); 
  93.  
  94. if ( ( $return['found'] > count( $return['media'] ) ) && $last_post ) { 
  95. $return['meta'] = array(); 
  96. $return['meta']['next_page'] = $this->build_page_handle( $last_post, $query ); 
  97.  
  98. return $return; 
  99.  
  100. function build_page_handle( $post, $query ) { 
  101. $column = $query['orderby']; 
  102. if ( ! $column ) { 
  103. $column = 'date'; 
  104. return build_query( array( 'value' => urlencode( $post->$column ), 'id' => $post->ID ) ); 
  105.  
  106. function handle_where_for_page_handle( $where ) { 
  107. global $wpdb; 
  108.  
  109. $column = $this->performed_query['orderby']; 
  110. if ( ! $column ) { 
  111. $column = 'date'; 
  112. $order = $this->performed_query['order']; 
  113. if ( ! $order ) { 
  114. $order = 'DESC'; 
  115.  
  116. if ( ! in_array( $column, array( 'ID', 'title', 'date', 'modified', 'comment_count' ) ) ) { 
  117. return $where; 
  118.  
  119. if ( ! in_array( $order, array( 'DESC', 'ASC' ) ) ) { 
  120. return $where; 
  121.  
  122. $db_column = ''; 
  123. $db_value = ''; 
  124. switch( $column ) { 
  125. case 'ID': 
  126. $db_column = 'ID'; 
  127. $db_value = '%d'; 
  128. break; 
  129. case 'title': 
  130. $db_column = 'post_title'; 
  131. $db_value = '%s'; 
  132. break; 
  133. case 'date': 
  134. $db_column = 'post_date'; 
  135. $db_value = 'CAST( %s as DATETIME )'; 
  136. break; 
  137. case 'modified': 
  138. $db_column = 'post_modified'; 
  139. $db_value = 'CAST( %s as DATETIME )'; 
  140. break; 
  141. case 'comment_count': 
  142. $db_column = 'comment_count'; 
  143. $db_value = '%d'; 
  144. break; 
  145.  
  146. if ( 'DESC'=== $order ) { 
  147. $db_order = '<'; 
  148. } else { 
  149. $db_order = '>'; 
  150.  
  151. // Add a clause that limits the results to items beyond the passed item, or equivalent to the passed item 
  152. // but with an ID beyond the passed item. When we're ordering by the ID already, we only ask for items 
  153. // beyond the passed item. 
  154. $where .= $wpdb->prepare( " AND ( ( `$wpdb->posts`.`$db_column` $db_order $db_value ) ", $this->page_handle['value'] ); 
  155. if ( $db_column !== 'ID' ) { 
  156. $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'] ); 
  157. $where .= ' )'; 
  158.  
  159. return $where; 
  160.  
  161. function handle_date_range( $where ) { 
  162. global $wpdb; 
  163.  
  164. switch ( count( $this->date_range ) ) { 
  165. case 2 : 
  166. $where .= $wpdb->prepare( 
  167. " AND `$wpdb->posts`.post_date BETWEEN CAST( %s AS DATETIME ) AND CAST( %s AS DATETIME ) ",  
  168. $this->date_range['after'],  
  169. $this->date_range['before'] 
  170. ); 
  171. break; 
  172. case 1 : 
  173. if ( isset( $this->date_range['before'] ) ) { 
  174. $where .= $wpdb->prepare( 
  175. " AND `$wpdb->posts`.post_date <= CAST( %s AS DATETIME ) ",  
  176. $this->date_range['before'] 
  177. ); 
  178. } else { 
  179. $where .= $wpdb->prepare( 
  180. " AND `$wpdb->posts`.post_date >= CAST( %s AS DATETIME ) ",  
  181. $this->date_range['after'] 
  182. ); 
  183. break; 
  184.  
  185. return $where; 
  186.  
  187. function handle_orderby_for_page_handle( $orderby ) { 
  188. global $wpdb; 
  189. if ( $this->performed_query['orderby'] === 'ID' ) { 
  190. // bail if we're already ordering by ID 
  191. return $orderby; 
  192.  
  193. if ( $orderby ) { 
  194. $orderby .= ' , '; 
  195. $order = $this->performed_query['order']; 
  196. if ( ! $order ) { 
  197. $order = 'DESC'; 
  198. $orderby .= " `$wpdb->posts`.ID $order"; 
  199. return $orderby; 
  200.  
.