Skip to content

Commit fe8516b

Browse files
authored
Allow future-scheduled posts in REST API export endpoint (#714)
* Allow future-scheduled posts in REST API export endpoint Includes future-dated posts/pages in the wporg_export content, allowing it to be sync'd to GitHub and local environments ahead of it's release. Draft and Pending-review content is not included. * Include the real post_status in the response.
1 parent eb02ef8 commit fe8516b

File tree

1 file changed

+58
-1
lines changed

1 file changed

+58
-1
lines changed

mu-plugins/rest-api/extras/class-wporg-export-context.php

Lines changed: 58 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,8 @@
2121
* ]);
2222
* })
2323
*
24+
* NOTE: This will also reveal future-scheduled post content! (ie. Release pages)
25+
*
2426
* ⚠️ Be careful to only expose public data!
2527
*/
2628

@@ -64,6 +66,7 @@ function register_raw_content_for_post_type( $post_type ) {
6466
);
6567

6668
add_filter( "rest_{$post_type}_item_schema", array( $this, 'add_export_context_to_schema' ) );
69+
add_filter( "rest_{$post_type}_query", array( $this, 'allow_scheduled_posts_in_export' ), 10, 2 );
6770
}
6871

6972
/**
@@ -77,6 +80,60 @@ public function add_export_context_to_schema( $schema ) {
7780
return $schema;
7881
}
7982

83+
/**
84+
* Allows future-scheduled posts to be visible in the rest-api.
85+
*
86+
* @param array $args The REST API query args.
87+
* @param \WP_REST_Request $request The REST API request.
88+
* @return array Modified REST API query args.
89+
*/
90+
public function allow_scheduled_posts_in_export( $args, $request ) {
91+
if (
92+
$this->context_name === $request->get_param( 'context' ) &&
93+
in_array( 'publish', (array) $args['post_status'], true )
94+
) {
95+
// Allow future posts to be visible in the export context.
96+
$args['post_status'][] = 'future';
97+
98+
/*
99+
* Pretend that the post_status is publish in the results.
100+
*
101+
* - the_posts: This is to pass WP_REST_Posts_Controller::check_read_permission().
102+
* - rest_prepare_*: This is so the resulting response shows the correct status.
103+
*/
104+
$args['_future_to_publish'] = true;
105+
add_filter( 'the_posts', static function( $posts, $wp_query ) use( $args ) {
106+
if (
107+
$wp_query->get( '_future_to_publish' ) &&
108+
$args['post_type'] === $wp_query->get( 'post_type' )
109+
) {
110+
foreach ( $posts as $post ) {
111+
if ( 'future' === $post->post_status ) {
112+
$post->post_status = 'publish';
113+
$post->real_post_status = 'future';
114+
}
115+
}
116+
}
117+
118+
return $posts;
119+
}, 10, 2 );
120+
add_filter( 'rest_prepare_' . $args['post_type'], static function( $response, $post ) {
121+
$prepared = $response->get_data();
122+
if (
123+
isset( $post->real_post_status ) &&
124+
$post->real_post_status !== $prepared['status']
125+
) {
126+
$prepared['status'] = $post->real_post_status;
127+
$response->set_data( $prepared );
128+
}
129+
130+
return $response;
131+
}, 10, 3 );
132+
}
133+
134+
return $args;
135+
}
136+
80137
/**
81138
* Find every item in the schema that has a 'view' context, and add an 'export' context to it.
82139
* Had to use a recursive function because array_walk_recursive only walks leaf nodes.
@@ -175,4 +232,4 @@ function show_post_content_raw( $object, $field_name, $request ) {
175232

176233
return $post->post_content;
177234
}
178-
}
235+
}

0 commit comments

Comments
 (0)