Created
March 8, 2017 22:36
-
-
Save nitishn/4b9f07668d4ec56ea713490618952a21 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Add cusom API routes if available | |
add_action( 'rest_api_init', 'setupCustomAPIRoutes' ); | |
// Define all custom API routes here. Use the Controller model documented here | |
// http://v2.wp-api.org/extending/adding/ | |
function setupCustomAPIRoutes() | |
{ | |
// If we have tribe events available, set up a custom route for events | |
if (class_exists('Tribe__Events__Main')) { | |
$newRoute = new \App\CustomRESTRoutes\WP_REST_Events_Controller( constant('Tribe__Events__Main::POSTTYPE') ); | |
$newRoute->register_routes(); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
namespace App\CustomRESTRoutes; | |
/** | |
* Add a custom route for Tribe Events because...Events are special. | |
* We can just extend the existing post controller and make changes to it | |
* to support Tribe Events. THere's no reason to create an entirely new route, | |
* we just override the constructor and get_items method to suit our needs. | |
*/ | |
class WP_REST_Events_Controller extends \WP_REST_Posts_Controller | |
{ | |
public function __construct( $post_type ) | |
{ | |
$post_type = $post_type; | |
$this->namespace = 'wp/v2'; | |
$this->post_type = $post_type; | |
$this->rest_base = 'events'; | |
$this->meta = new \WP_REST_Post_Meta_Fields( $this->post_type ); | |
} | |
// Only going to bother with the main root route (/) and ignore all others | |
public function register_routes() | |
{ | |
register_rest_route( $this->namespace, '/' . $this->rest_base, array( | |
array( | |
'methods' => \WP_REST_Server::READABLE, | |
'callback' => array( $this, 'get_items' ), | |
'permission_callback' => array( $this, 'get_items_permissions_check' ), | |
'args' => $this->get_collection_params(), | |
), | |
array( | |
'methods' => \WP_REST_Server::CREATABLE, | |
'callback' => array( $this, 'create_item' ), | |
'permission_callback' => array( $this, 'create_item_permissions_check' ), | |
'args' => $this->get_endpoint_args_for_item_schema( \WP_REST_Server::CREATABLE ), | |
), | |
'schema' => array( $this, 'get_public_item_schema' ), | |
) ); | |
} | |
/** | |
* Get a collection of posts. | |
* | |
* @param WP_REST_Request $request Full details about the request. | |
* @return WP_Error|WP_REST_Response | |
*/ | |
public function get_items( $request ) | |
{ | |
// Trimmed arguments list to cater events | |
$args = array(); | |
$args['menu_order'] = $request['menu_order']; | |
$args['offset'] = $request['offset']; | |
// $args['order'] = $request['order']; | |
$args['orderby'] = ''; | |
$args['paged'] = $request['page']; | |
$args['post__in'] = $request['include']; | |
$args['post__not_in'] = $request['exclude']; | |
$args['name'] = $request['slug']; | |
// $args['post_parent__in'] = $request['parent']; | |
// $args['post_parent__not_in'] = $request['parent_exclude']; | |
$args['s'] = $request['search']; | |
unset($args['ignore_sticky_posts']); | |
if ( is_array( $request['filter'] ) ) { | |
$args = array_merge( $args, $request['filter'] ); | |
unset( $args['filter'] ); | |
} | |
// Set the post type | |
$args['post_type'] = $this->post_type; | |
// Ensure our per_page parameter overrides filter. | |
$args['posts_per_page'] = $request['per_page']; | |
/** | |
* Filter the query arguments for a request. | |
* | |
* Enables adding extra arguments or setting defaults for a post | |
* collection request. | |
* | |
* @see https://developer.wordpress.org/reference/classes/wp_user_query/ | |
* | |
* @param array $args Key value array of query var to query value. | |
* @param WP_REST_Request $request The request used. | |
*/ | |
$args = apply_filters( "rest_{$this->post_type}_query", $args, $request ); | |
$query_args = $this->prepare_items_query( $args, $request ); | |
// Handle taxonomies | |
// Handle date filters | |
// Now let our Tribe Helper handle formatting events | |
$posts_query = new \WP_Query(); | |
$eventsHelper = new \App\TribeEventsHelper(); | |
$query_args = $eventsHelper->formatQueryArgs($query_args); | |
$query_result = $posts_query->query( $query_args ); | |
// Allow access to all password protected posts if the context is edit. | |
if ( 'edit' === $request['context'] ) { | |
add_filter( 'post_password_required', '__return_false' ); | |
} | |
$posts = array(); | |
foreach ( $query_result as $post ) { | |
if ( ! $this->check_read_permission( $post ) ) { | |
continue; | |
} | |
$data = $this->prepare_item_for_response( $post, $request ); | |
$posts[] = $this->prepare_response_for_collection( $data ); | |
} | |
// Reset filter. | |
if ( 'edit' === $request['context'] ) { | |
remove_filter( 'post_password_required', '__return_false' ); | |
} | |
$page = (int) $query_args['paged']; | |
$total_posts = $posts_query->found_posts; | |
if ( $total_posts < 1 ) { | |
// Out-of-bounds, run the query again without LIMIT for total count | |
unset( $query_args['paged'] ); | |
$count_query = new \WP_Query(); | |
$count_query->query( $query_args ); | |
$total_posts = $count_query->found_posts; | |
} | |
$max_pages = ceil( $total_posts / (int) $query_args['posts_per_page'] ); | |
$response = rest_ensure_response( $posts ); | |
$response->header( 'X-WP-Total', (int) $total_posts ); | |
$response->header( 'X-WP-TotalPages', (int) $max_pages ); | |
$request_params = $request->get_query_params(); | |
if ( ! empty( $request_params['filter'] ) ) { | |
// Normalize the pagination params. | |
unset( $request_params['filter']['posts_per_page'] ); | |
unset( $request_params['filter']['paged'] ); | |
} | |
$base = add_query_arg( $request_params, rest_url( sprintf( '%s/%s', $this->namespace, $this->rest_base ) ) ); | |
if ( $page > 1 ) { | |
$prev_page = $page - 1; | |
if ( $prev_page > $max_pages ) { | |
$prev_page = $max_pages; | |
} | |
$prev_link = add_query_arg( 'page', $prev_page, $base ); | |
$response->link_header( 'prev', $prev_link ); | |
} | |
if ( $max_pages > $page ) { | |
$next_page = $page + 1; | |
$next_link = add_query_arg( 'page', $next_page, $base ); | |
$response->link_header( 'next', $next_link ); | |
} | |
// if( $phpTimezone ) date_default_timezone_set($phpTimezone); | |
return $response; | |
} | |
/** | |
* Prepare a single event output for response. Override this funciton to | |
* trim unused data out! | |
* | |
* @param WP_Post $post Post object. | |
* @param WP_REST_Request $request Request object. | |
* @return WP_REST_Response $data | |
*/ | |
public function prepare_item_for_response( $post, $request ) | |
{ | |
$GLOBALS['post'] = $post; | |
setup_postdata( $post ); | |
$schema = $this->get_item_schema(); | |
// Base fields for every post. | |
$data = array(); | |
if ( ! empty( $schema['properties']['id'] ) ) { | |
$data['id'] = $post->ID; | |
} | |
if ( ! empty( $schema['properties']['slug'] ) ) { | |
$data['slug'] = $post->post_name; | |
} | |
if ( ! empty( $schema['properties']['status'] ) ) { | |
$data['status'] = $post->post_status; | |
} | |
if ( ! empty( $schema['properties']['type'] ) ) { | |
$data['type'] = $post->post_type; | |
} | |
if ( ! empty( $schema['properties']['link'] ) ) { | |
$data['link'] = get_permalink( $post->ID ); | |
} | |
if ( ! empty( $schema['properties']['title'] ) ) { | |
add_filter( 'protected_title_format', array( $this, 'protected_title_format' ) ); | |
$data['title'] = array( | |
'raw' => $post->post_title, | |
'rendered' => get_the_title( $post->ID ), | |
); | |
remove_filter( 'protected_title_format', array( $this, 'protected_title_format' ) ); | |
} | |
$has_password_filter = false; | |
if ( $this->can_access_password_content( $post, $request ) ) { | |
// Allow access to the post, permissions already checked before. | |
add_filter( 'post_password_required', '__return_false' ); | |
$has_password_filter = true; | |
} | |
if ( ! empty( $schema['properties']['content'] ) ) { | |
$data['content'] = array( | |
'raw' => $post->post_content, | |
/** This filter is documented in wp-includes/post-template.php */ | |
'rendered' => post_password_required( $post ) ? '' : apply_filters( 'the_content', $post->post_content ), | |
'protected' => (bool) $post->post_password, | |
); | |
} | |
if ( ! empty( $schema['properties']['excerpt'] ) ) { | |
/** This filter is documented in wp-includes/post-template.php */ | |
$excerpt = apply_filters( 'the_excerpt', apply_filters( 'get_the_excerpt', $post->post_excerpt, $post ) ); | |
$data['excerpt'] = array( | |
'raw' => $post->post_excerpt, | |
'rendered' => post_password_required( $post ) ? '' : $excerpt, | |
'protected' => (bool) $post->post_password, | |
); | |
} | |
if ( $has_password_filter ) { | |
// Reset filter. | |
remove_filter( 'post_password_required', '__return_false' ); | |
} | |
if ( ! empty( $schema['properties']['author'] ) ) { | |
$data['author'] = (int) $post->post_author; | |
} | |
if ( ! empty( $schema['properties']['featured_media'] ) ) { | |
$data['featured_media'] = (int) get_post_thumbnail_id( $post->ID ); | |
} | |
if ( ! empty( $schema['properties']['template'] ) ) { | |
if ( $template = get_page_template_slug( $post->ID ) ) { | |
$data['template'] = $template; | |
} else { | |
$data['template'] = ''; | |
} | |
} | |
if ( ! empty( $schema['properties']['format'] ) ) { | |
$data['format'] = get_post_format( $post->ID ); | |
// Fill in blank post format. | |
if ( empty( $data['format'] ) ) { | |
$data['format'] = 'standard'; | |
} | |
} | |
if ( ! empty( $schema['properties']['meta'] ) ) { | |
$data['meta'] = $this->meta->get_value( $post->ID, $request ); | |
} | |
$context = ! empty( $request['context'] ) ? $request['context'] : 'view'; | |
$data = $this->add_additional_fields_to_object( $data, $request ); | |
$data = $this->filter_response_by_context( $data, $context ); | |
// Wrap the data in a response object. | |
$response = rest_ensure_response( $data ); | |
/** | |
* Filter the post data for a response. | |
* | |
* The dynamic portion of the hook name, $this->post_type, refers to post_type of the post being | |
* prepared for the response. | |
* | |
* @param WP_REST_Response $response The response object. | |
* @param WP_Post $post Post object. | |
* @param WP_REST_Request $request Request object. | |
*/ | |
return apply_filters( "rest_prepare_{$this->post_type}", $response, $post, $request ); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment