I built a custom endpoint for the WordPress REST API to get a post revision. The result is in the Wordpress Post syntax:
[ID] => 478
[post_author] => 1
[post_date] => 2017-11-20 17:22:11
[post_date_gmt] => 2017-11-20 16:22:11
[post_content] => My Post content
Whereas the Wordpress REST API would provide me something like this:
"author": 1,
"title": {
"rendered": "My title"
},
"content": {
"rendered": "",
"protected": false
},
(one is printed via php the other is in a JSON format, but what is important is that in the first example it says: post_content and in the second it's content which is then separated in rendered and protected for example.
I am pretty sure that it's almost the same thing as described here: https://wordpress.stackexchange.com/questions/236249/wp-api-v2-custom-endpoint-response-formatting?newreg=7edb54e1ae494e528e5e146982469664
But in my case I have revisions.
I tried to prepare the Post Object for the REST API.
I created a new instance of the WP_REST_Revisions_Controller and tried to use its method prepare_item_for_response. $request ist a WP_Rest_Request. (btw: why do I have to write new \WP_REST_Revisions_Controller with a backslash \ before).
$latest_revision = wp_get_post_revisions( $id, $args ); //WP Post Object
$postController = new \WP_REST_Revisions_Controller('revision');
$response = $postController->prepare_item_for_response( $latest_revision, $request );
print_r($response);
The problem is that I get Notices:
<b>Notice</b>: Trying to get property of non-object in <b>/Users/USER/Documents/my-api/wp/wp-includes/rest-api/endpoints/class-wp-rest-revisions-controller.php</b> on line <b>350</b>
<b>Notice</b>: Trying to get property of non-object in <b>/Users/USER/Documents/my-api/wp/wp-includes/rest-api/endpoints/class-wp-rest-revisions-controller.php</b> on line <b>354</b>
<b>Notice</b>: Trying to get property of non-object in <b>/Users/USER/Documents/my-api/wp/wp-includes/rest-api/endpoints/class-wp-rest-revisions-controller.php</b> on line <b>354</b>
....
Which must refer to these lines: https://developer.wordpress.org/reference/classes/wp_rest_revisions_controller/ (line 350 and following).
After the notices I print the $response and I get this:
WP_REST_Response Object
(
[links:protected] => Array
(
)
[matched_route:protected] =>
[matched_handler:protected] =>
[data] => Array
(
[author] => 0
[date] =>
[date_gmt] =>
[id] =>
[modified] =>
[modified_gmt] =>
[parent] => 0
[slug] =>
[guid] => Array
(
[rendered] =>
[raw] =>
)
)
[headers] => Array
(
)
[status] => 200
)
.. somehow the data is missing or something else went wrong.
And here is the whole php script to see what I am doing:
<?php
/**
* Add a new API route for a post or pages preview
*/
class Preview_To_REST_API_Controller extends WP_REST_Controller {
//The namespace and version for the REST SERVER
var $namespace = 'previews/v';
var $version = '1';
public function register_routes() {
$namespace = $this->namespace . $this->version;
$base = 'preview';
register_rest_route( $namespace, '/' . $base, array(
array(
'methods' => WP_REST_Server::READABLE,
'callback' => array( $this, 'get_preview' ),
'permission_callback' => array( $this, 'get_permission' )
)
) );
}
// Register our REST Server
public function hook_rest_server(){
add_action( 'rest_api_init', array( $this, 'register_routes' ) );
}
public function get_permission(){
if ( ! current_user_can( 'edit_posts' ) ) {
return new WP_Error( 'rest_forbidden', esc_html__( 'You do not have permissions to view this data.', 'my-text-domain' ), array( 'status' => 401 ) );
}
// This approach blocks the endpoint operation. You could alternatively do this by an un-blocking approach, by returning false here and changing the permissions check.
return true;
}
public function get_preview( WP_REST_Request $request ){
// use the helper methods to get the parameters
$id = $request->get_param( 'id' );
// Only return the newest
$args = array (
'order' => 'DESC',
'orderby' => 'date',
'posts_per_page' => '1'
);
// Preview version is saved in the latest revision of the page/post
$latest_revision = wp_get_post_revisions( $id, $args );
print_r($latest_revision);
$postController = new \WP_REST_Revisions_Controller('revision');
$response = $postController->prepare_item_for_response( $latest_revision, $request );
print_r($response);
if ($latest_revision) {
// Use the current method to get the only element in the revisions array
// [0] does not return anything, because the Array's value is saved
// as the ID key: Array[$id], but this ID we need to find out first
$revision_id = current($latest_revision) -> ID;
$acf_fields = get_fields($revision_id);
if ( empty($latest_revision) ) {
return null;
}
// Add acf fields to latest revision
$latest_revision[$revision_id] -> acf = $acf_fields;
return $latest_revision;
} else {
return null;
}
}
}
$preview_controller = new Preview_To_REST_API_Controller();
$preview_controller->hook_rest_server();
I would be really glad to receive any hints for solving this problem. Cheers
I haven't seen the result of your
print_rbut I'm going to guess that it's an array ofWP_Postobjects.prepare_item_for_responserequires a singleWP_Postas the first argument and you're passing it an array.Try this, after you set
$latest_revision:The
array_valuescall is a quick and easy way to re-index your array.This should give you a single post and not an array.
Update: per your own answer to your question and the questions you asked.
prepare_item_for_responserewrites aWP_Postobject as something that can be serialized uniformly by the REST controller to output. For instance, it handles attachments rather than simply ignoring them. If you simply returned aWP_Postobject over, say, JSON, you'd miss out on a lot of the post content. You can think ofprepare_response_for_collectionas the array version of the same thing. Really, it's more like theWP_Queryversion of the same thing so the WP rest controller can act as one-stop shopping to return lists ofWP_Postobjects to a REST consumer.rest_ensure_responsedoes something similar for any REST response. It hides the loose typing of PHP (and WP), where actions like function calls can return nothing or indeterminate things, from REST, where every request must have an appropriate response. It's not much more than a wrapper that is aware ofWP_Error.