function ( $param, $request, $key ) { return( is_string( $param ) ); } , ]; $post_slug_arg = array_merge( $slug_arg, [ 'description' => 'String representing a valid WordPress post slug', ] ); $page_slug_arg = array_merge( $slug_arg, [ 'description' => 'String representing a valid WordPress page slug', ] ); // Register routes register_rest_route( 'api/v1', '/post', [ 'methods' => 'GET', 'callback' => 'rest_get_post', 'args' => [ 'slug' => array_merge( $post_slug_arg, [ 'required' => true, ] ), ], ] ); register_rest_route( 'api/v1', '/page', [ 'methods' => 'GET', 'callback' => 'rest_get_page', 'args' => [ 'slug' => array_merge( $page_slug_arg, [ 'required' => true, ] ), ], ] ); register_rest_route('api/v1', '/post/preview', [ 'methods' => 'GET', 'callback' => 'rest_get_post_preview', 'args' => [ 'id' => [ 'validate_callback' => function ( $param, $request, $key ) { return ( is_numeric( $param ) ); } , 'required' => true, 'description' => 'Valid WordPress post ID', ], ], 'permission_callback' => function () { return current_user_can( 'edit_posts' ); } , ] ); } ); /** * Respond to a REST API request to get post data. * * @param WP_REST_Request $request Request. * @return WP_REST_Response */ function rest_get_post( WP_REST_Request $request ) { return rest_get_content( $request, 'post', __FUNCTION__ ); } /** * Respond to a REST API request to get page data. * * @param WP_REST_Request $request Request. * @return WP_REST_Response */ function rest_get_page( WP_REST_Request $request ) { return rest_get_content( $request, 'page', __FUNCTION__ ); } /** * Respond to a REST API request to get post or page data. * * Handles changed slugs * * Doesn't return posts whose status isn't published * * Redirects to the admin when an edit parameter is present * * @param WP_REST_Request $request Request * @param str $type Type * @param str $function_name Function name * @return WP_REST_Response */ function rest_get_content( WP_REST_Request $request, $type, $function_name ) { $content_in_array = in_array( $type, [ 'post', 'page', ], true ); if ( ! $content_in_array ) { $type = 'post'; } $slug = $request->get_param( 'slug' ); $post = get_content_by_slug( $slug, $type ); if ( ! $post ) { return new WP_Error( $function_name, $slug . ' ' . $type . ' does not exist', [ 'status' => 404, ] ); } ; // Shortcut to WP admin page editor $edit = $request->get_param( 'edit' ); if ( 'true' === $edit ) { header( 'Location: /wp-admin/post.php?post=' . $post->ID . '&action=edit' ); exit; } $controller = new WP_REST_Posts_Controller( 'post' ); $data = $controller->prepare_item_for_response( $post, $request ); $response = $controller->prepare_response_for_collection( $data ); return new WP_REST_Response( $response ); } /** * Returns a post or page given a slug. Returns false if no post matches. * * @param str $slug Slug * @param str $type Valid values are 'post' or 'page' * @return Post */ function get_content_by_slug( $slug, $type = 'post' ) { $content_in_array = in_array( $type, [ 'post', 'page', ], true ); if ( ! $content_in_array ) { $type = 'post'; } $args = [ 'name' => $slug, 'post_type' => $type, 'post_status' => 'publish', 'numberposts' => 1, ]; // phpcs:ignore WordPress.VIP.RestrictedFunctions.get_posts_get_posts $post_search_results = get_posts( $args ); if ( !$post_search_results ) { // Maybe the slug changed // check wp_postmeta table for old slug $args = [ // phpcs:ignore WordPress.VIP.SlowDBQuery.slow_db_query_meta_query 'meta_query' => [ [ 'key' => '_wp_old_slug', 'value' => $post_slug, 'compare' => '=', ], ], ]; $query = new WP_Query( $args ); $post_search_results = $query->posts; } if ( isset( $post_search_results[0] ) ) { return $post_search_results[0]; } return false; } /** * Respond to a REST API request to get a post's latest revision. * * Requires a valid _wpnonce on the query string * * User must have 'edit_posts' rights * * Will return draft revisions of even published posts * * @param WP_REST_Request $request Rest request. * @return WP_REST_Response */ function rest_get_post_preview( WP_REST_Request $request ) { $post_id = $request->get_param( 'id' ); // Revisions are drafts so here we remove the default 'publish' status remove_action( 'pre_get_posts', 'set_default_status_to_publish' ); $check_enabled = [ 'check_enabled' => false, ]; if ( $revisions = wp_get_post_revisions( $post_id, $check_enabled ) ) { $last_revision = reset( $revisions ); $rev_post = wp_get_post_revision( $last_revision->ID ); $controller = new WP_REST_Posts_Controller( 'post' ); $data = $controller->prepare_item_for_response( $rev_post, $request ); } elseif ( $post = get_post( $post_id ) ) { // There are no revisions, just return the saved parent post $controller = new WP_REST_Posts_Controller( 'post' ); $data = $controller->prepare_item_for_response( $post, $request ); } else { $not_found = [ 'status' => 404, ]; $error = new WP_Error( 'rest_get_post_preview', 'Post ' . $post_id . ' does not exist', $not_found ); return $error; } $response = $controller->prepare_response_for_collection( $data ); return new WP_REST_Response( $response ); }