WordPress JSON API (http://wordpress.org/plugins/json-api/) is a powerful plugin that allows RESTful API for WordPress.
However, I needed specific post query such as “Get posts since 1999/01/01 11:00:00”, which JSON API did not support. After doing hours research to do so, I couldn’t find relavant answers.
Since JSON API uses WP_Query in WordPress, I thought I could use Time Parameters. (http://codex.wordpress.org/Class_Reference/WP_Query#Time_Parameters)
However, Time Parameters only support exact date/time. In the class reference, it guides to use add_filter function to add custom query like below:
// Create a new filtering function that will add our where clause to the query function filter_where( $where = '' ) { // posts in the last 30 days $where .= " AND post_date > '" . date('Y-m-d', strtotime('-30 days')) . "'"; return $where; } add_filter( 'posts_where', 'filter_where' ); $query = new WP_Query( $query_string ); remove_filter( 'posts_where', 'filter_where' );
In my knowledge, there was only one way to do what I wanted to do – modifying JSON API code, even if this way is so not recommended.
JSON API Version: 1.1.1
{"status":"ok","json_api_version":"1.1.1","controllers":["posts","core"]}
Modified file: /wp-content/plugins/json-api/singletons/introspector.php
<?php class JSON_API_Introspector { public function get_posts($query = false, $wp_posts = false) { global $post, $wp_query; $this->set_posts_query($query); $output = array(); while (have_posts()) { the_post(); if ($wp_posts) { $new_post = $post; } else { $new_post = new JSON_API_Post($post); } $output[] = $new_post; } return $output; } public function get_date_archive_permalinks() { $archives = wp_get_archives('echo=0'); preg_match_all("/href='([^']+)'/", $archives, $matches); return $matches[1]; } public function get_date_archive_tree($permalinks) { $tree = array(); foreach ($permalinks as $url) { if (preg_match('#(\d{4})/(\d{2})#', $url, $date)) { $year = $date[1]; $month = $date[2]; } else if (preg_match('/(\d{4})(\d{2})/', $url, $date)) { $year = $date[1]; $month = $date[2]; } else { continue; } $count = $this->get_date_archive_count($year, $month); if (empty($tree[$year])) { $tree[$year] = array( $month => $count ); } else { $tree[$year][$month] = $count; } } return $tree; } public function get_date_archive_count($year, $month) { if (!isset($this->month_archives)) { global $wpdb; $post_counts = $wpdb->get_results(" SELECT DATE_FORMAT(post_date, '%Y%m') AS month, COUNT(ID) AS post_count FROM $wpdb->posts WHERE post_status = 'publish' AND post_type = 'post' GROUP BY month "); $this->month_archives = array(); foreach ($post_counts as $post_count) { $this->month_archives[$post_count->month] = $post_count->post_count; } } return $this->month_archives["$year$month"]; } public function get_categories($args = null) { $wp_categories = get_categories($args); $categories = array(); foreach ($wp_categories as $wp_category) { if ($wp_category->term_id == 1 && $wp_category->slug == 'uncategorized') { continue; } $categories[] = $this->get_category_object($wp_category); } return $categories; } public function get_current_post() { global $json_api; extract($json_api->query->get(array('id', 'slug', 'post_id', 'post_slug'))); if ($id || $post_id) { if (!$id) { $id = $post_id; } $posts = $this->get_posts(array( 'p' => $id ), true); } else if ($slug || $post_slug) { if (!$slug) { $slug = $post_slug; } $posts = $this->get_posts(array( 'name' => $slug ), true); } else { $json_api->error("Include 'id' or 'slug' var in your request."); } if (!empty($posts)) { return $posts[0]; } else { return null; } } public function get_current_category() { global $json_api; extract($json_api->query->get(array('id', 'slug', 'category_id', 'category_slug'))); if ($id || $category_id) { if (!$id) { $id = $category_id; } return $this->get_category_by_id($id); } else if ($slug || $category_slug) { if (!$slug) { $slug = $category_slug; } return $this->get_category_by_slug($slug); } else { $json_api->error("Include 'id' or 'slug' var in your request."); } return null; } public function get_category_by_id($category_id) { $wp_category = get_term_by('id', $category_id, 'category'); return $this->get_category_object($wp_category); } public function get_category_by_slug($category_slug) { $wp_category = get_term_by('slug', $category_slug, 'category'); return $this->get_category_object($wp_category); } public function get_tags() { $wp_tags = get_tags(); return array_map(array(&$this, 'get_tag_object'), $wp_tags); } public function get_current_tag() { global $json_api; extract($json_api->query->get(array('id', 'slug', 'tag_id', 'tag_slug'))); if ($id || $tag_id) { if (!$id) { $id = $tag_id; } return $this->get_tag_by_id($id); } else if ($slug || $tag_slug) { if (!$slug) { $slug = $tag_slug; } return $this->get_tag_by_slug($slug); } else { $json_api->error("Include 'id' or 'slug' var in your request."); } return null; } public function get_tag_by_id($tag_id) { $wp_tag = get_term_by('id', $tag_id, 'post_tag'); return $this->get_tag_object($wp_tag); } public function get_tag_by_slug($tag_slug) { $wp_tag = get_term_by('slug', $tag_slug, 'post_tag'); return $this->get_tag_object($wp_tag); } public function get_authors() { global $wpdb; $author_ids = $wpdb->get_col(" SELECT u.ID, m.meta_value AS last_name FROM $wpdb->users AS u, $wpdb->usermeta AS m WHERE m.user_id = u.ID AND m.meta_key = 'last_name' ORDER BY last_name "); $all_authors = array_map(array(&$this, 'get_author_by_id'), $author_ids); $active_authors = array_filter($all_authors, array(&$this, 'is_active_author')); return $active_authors; } public function get_current_author() { global $json_api; extract($json_api->query->get(array('id', 'slug', 'author_id', 'author_slug'))); if ($id || $author_id) { if (!$id) { $id = $author_id; } return $this->get_author_by_id($id); } else if ($slug || $author_slug) { if (!$slug) { $slug = $author_slug; } return $this->get_author_by_login($slug); } else { $json_api->error("Include 'id' or 'slug' var in your request."); } return null; } public function get_author_by_id($id) { $id = get_the_author_meta('ID', $id); if (!$id) { return null; } return new JSON_API_Author($id); } public function get_author_by_login($login) { global $wpdb; $id = $wpdb->get_var($wpdb->prepare(" SELECT ID FROM $wpdb->users WHERE user_nicename = %s ", $login)); return $this->get_author_by_id($id); } public function get_comments($post_id) { global $wpdb; $wp_comments = $wpdb->get_results($wpdb->prepare(" SELECT * FROM $wpdb->comments WHERE comment_post_ID = %d AND comment_approved = 1 AND comment_type = '' ORDER BY comment_date ", $post_id)); $comments = array(); foreach ($wp_comments as $wp_comment) { $comments[] = new JSON_API_Comment($wp_comment); } return $comments; } public function get_attachments($post_id) { $wp_attachments = get_children(array( 'post_type' => 'attachment', 'post_parent' => $post_id, 'orderby' => 'menu_order', 'order' => 'ASC', 'suppress_filters' => false )); $attachments = array(); if (!empty($wp_attachments)) { foreach ($wp_attachments as $wp_attachment) { $attachments[] = new JSON_API_Attachment($wp_attachment); } } return $attachments; } public function get_attachment($attachment_id) { global $wpdb; $wp_attachment = $wpdb->get_row( $wpdb->prepare(" SELECT * FROM $wpdb->posts WHERE ID = %d ", $attachment_id) ); return new JSON_API_Attachment($wp_attachment); } public function attach_child_posts(&$post) { $post->children = array(); $wp_children = get_posts(array( 'post_type' => $post->type, 'post_parent' => $post->id, 'order' => 'ASC', 'orderby' => 'menu_order', 'numberposts' => -1, 'suppress_filters' => false )); foreach ($wp_children as $wp_post) { $new_post = new JSON_API_Post($wp_post); $new_post->parent = $post->id; $post->children[] = $new_post; } foreach ($post->children as $child) { $this->attach_child_posts($child); } } protected function get_category_object($wp_category) { if (!$wp_category) { return null; } return new JSON_API_Category($wp_category); } protected function get_tag_object($wp_tag) { if (!$wp_tag) { return null; } return new JSON_API_Tag($wp_tag); } protected function is_active_author($author) { if (!isset($this->active_authors)) { $this->active_authors = explode(',', wp_list_authors(array( 'html' => false, 'echo' => false, 'exclude_admin' => false ))); $this->active_authors = array_map('trim', $this->active_authors); } return in_array($author->name, $this->active_authors); } protected function set_posts_query($query = false) { global $json_api, $wp_query; if (!$query) { $query = array(); } $query = array_merge($query, $wp_query->query); if ($json_api->query->page) { $query['paged'] = $json_api->query->page; } if ($json_api->query->count) { $query['posts_per_page'] = $json_api->query->count; } if ($json_api->query->post_type) { $query['post_type'] = $json_api->query->post_type; } // ADDED START: Handle parameter for since if(isset($query['since']) && strtotime($query['since']) !== false) { $since = $query['since']; add_filter( 'posts_where', 'filter_where' ); } // ADDED: FINISH: Handle parameter for since if (!empty($query)) { query_posts($query); do_action('json_api_query', $wp_query); // ADDED START: Handle parameter for since remove_filter( 'posts_where', 'filter_where' ); // ADDED: FINISH: Handle parameter for since } } } // ADDED START: Handle parameter for since function filter_where( $where = '' ) { if(isset($_GET['since']) && strtotime($_GET['since']) !== false) { $where .= " AND post_date > '".date("Y/m/d H:i:s", strtotime($_GET['since']))."'"; } return $where; } // ADDED: FINISH: Handle parameter for since ?>
Use: http://{your domain}/api/get_posts/?post_type=topic&since=2013-06-28%2010:01:00&orderby=date&order=ASC
NOTE: This is a bad way to accomplish what I wanted to do because it means I should modify the file every update. Should find a better way to do so.
Thanks so much for this. I am taking this and extending it for modified_since. I am also added support for multiple post types in the form post_type=post;events
Thanks again.