PluginProbe
Gutenberg / 4.7.0
Gutenberg v4.7.0
24.0.0 23.9.1 23.9.0 23.8.0 23.7.2 23.7.1 23.7.0 23.6.1 23.6.2 23.6.0 23.5.3 23.5.2 23.5.1 23.5.0 23.4.0 23.3.2 23.3.1 23.3.0 23.2.0 23.2.1 23.2.2 23.1.1 23.1.0 23.0.1 12.6.0 All 403 releases
← All changes | lib/rest-api.php +326 -21 24.0.04.7.0 View file →
@@ -10,38 +10,343 @@
10 10 die( 'Silence is golden.' );
11 11 }
12 12
13 13 /**
14 - * Overrides the REST controller for the `wp_global_styles` post type.
14 + * Registers the REST API routes needed by the Gutenberg editor.
15 15 *
16 - * @param array $args Array of arguments for registering a post type.
17 - * See the register_post_type() function for accepted arguments.
16 + * @since 2.8.0
17 + */
18 +function gutenberg_register_rest_routes() {
19 + $controller = new WP_REST_Block_Renderer_Controller();
20 + $controller->register_routes();
21 +
22 + /**
23 + * Filters the search handlers to use in the REST search controller.
24 + *
25 + * @since 3.3.0
26 + *
27 + * @param array $search_handlers List of search handlers to use in the controller. Each search
28 + * handler instance must extend the `WP_REST_Search_Handler` class.
29 + * Default is only a handler for posts.
30 + */
31 + $search_handlers = apply_filters( 'wp_rest_search_handlers', array( new WP_REST_Post_Search_Handler() ) );
32 +
33 + $controller = new WP_REST_Search_Controller( $search_handlers );
34 + $controller->register_routes();
35 +
36 + foreach ( get_post_types( array( 'show_in_rest' => true ), 'objects' ) as $post_type ) {
37 + $class = ! empty( $post_type->rest_controller_class ) ? $post_type->rest_controller_class : 'WP_REST_Posts_Controller';
38 +
39 + // Check if the class exists and is a subclass of WP_REST_Controller.
40 + if ( ! is_subclass_of( $class, 'WP_REST_Controller' ) ) {
41 + continue;
42 + }
43 +
44 + // Initialize the Autosaves controller.
45 + $autosaves_controller = new WP_REST_Autosaves_Controller( $post_type->name );
46 + $autosaves_controller->register_routes();
47 + }
48 +
49 + $themes_controller = new WP_REST_Themes_Controller();
50 + $themes_controller->register_routes();
51 +}
52 +add_action( 'rest_api_init', 'gutenberg_register_rest_routes' );
53 +
54 +/**
55 + * Make sure oEmbed REST Requests apply the WP Embed security mechanism for WordPress embeds.
18 56 *
19 - * @return array Array of arguments for registering a post type.
57 + * @see https://core.trac.wordpress.org/ticket/32522
58 + *
59 + * TODO: This is a temporary solution. Next step would be to edit the WP_oEmbed_Controller,
60 + * once merged into Core.
61 + *
62 + * @since 2.3.0
63 + *
64 + * @param WP_HTTP_Response|WP_Error $response The REST Request response.
65 + * @param WP_REST_Server $handler ResponseHandler instance (usually WP_REST_Server).
66 + * @param WP_REST_Request $request Request used to generate the response.
67 + * @return WP_HTTP_Response|object|WP_Error The REST Request response.
20 68 */
21 -function gutenberg_override_global_styles_endpoint( array $args ): array {
22 - $args['rest_controller_class'] = 'WP_REST_Global_Styles_Controller_Gutenberg';
23 - $args['late_route_registration'] = true;
24 - $args['show_in_rest'] = true;
25 - $args['rest_base'] = 'global-styles';
69 +function gutenberg_filter_oembed_result( $response, $handler, $request ) {
70 + if ( 'GET' !== $request->get_method() ) {
71 + return $response;
72 + }
26 73
27 - return $args;
74 + if ( is_wp_error( $response ) && 'oembed_invalid_url' !== $response->get_error_code() ) {
75 + return $response;
76 + }
77 +
78 + // External embeds.
79 + if ( '/oembed/1.0/proxy' === $request->get_route() ) {
80 + if ( is_wp_error( $response ) ) {
81 + // It's possibly a local post, so lets try and retrieve it that way.
82 + $post_id = url_to_postid( $_GET['url'] );
83 + $data = get_oembed_response_data( $post_id, apply_filters( 'oembed_default_width', 600 ) );
84 +
85 + if ( $data ) {
86 + // It's a local post!
87 + $response = (object) $data;
88 + } else {
89 + // Try using a classic embed, instead.
90 + global $wp_embed;
91 + $html = $wp_embed->shortcode( array(), $_GET['url'] );
92 + if ( $html ) {
93 + global $wp_scripts;
94 + // Check if any scripts were enqueued by the shortcode, and
95 + // include them in the response.
96 + $enqueued_scripts = array();
97 + foreach ( $wp_scripts->queue as $script ) {
98 + $enqueued_scripts[] = $wp_scripts->registered[ $script ]->src;
99 + }
100 + return array(
101 + 'provider_name' => __( 'Embed Handler', 'gutenberg' ),
102 + 'html' => $html,
103 + 'scripts' => $enqueued_scripts,
104 + );
105 + }
106 + }
107 + }
108 +
109 + // Make sure the HTML is run through the oembed sanitisation routines.
110 + $response->html = wp_oembed_get( $_GET['url'], $_GET );
111 + }
112 +
113 + return $response;
28 114 }
29 -add_filter( 'register_wp_global_styles_post_type_args', 'gutenberg_override_global_styles_endpoint' );
115 +add_filter( 'rest_request_after_callbacks', 'gutenberg_filter_oembed_result', 10, 3 );
30 116
31 117 /**
32 - * Registers the Edit Site Export REST API routes.
118 + * Add additional 'visibility' rest api field to taxonomies.
119 + *
120 + * Used so private taxonomies are not displayed in the UI.
121 + *
122 + * @see https://core.trac.wordpress.org/ticket/42707
33 123 */
34 -function gutenberg_register_edit_site_export_controller_endpoints() {
35 - $edit_site_export_controller = new WP_REST_Edit_Site_Export_Controller_Gutenberg();
36 - $edit_site_export_controller->register_routes();
124 +function gutenberg_add_taxonomy_visibility_field() {
125 + register_rest_field(
126 + 'taxonomy',
127 + 'visibility',
128 + array(
129 + 'get_callback' => 'gutenberg_get_taxonomy_visibility_data',
130 + 'schema' => array(
131 + 'description' => __( 'The visibility settings for the taxonomy.', 'gutenberg' ),
132 + 'type' => 'object',
133 + 'context' => array( 'edit' ),
134 + 'readonly' => true,
135 + 'properties' => array(
136 + 'public' => array(
137 + 'description' => __( 'Whether a taxonomy is intended for use publicly either via the admin interface or by front-end users.', 'gutenberg' ),
138 + 'type' => 'boolean',
139 + ),
140 + 'publicly_queryable' => array(
141 + 'description' => __( 'Whether the taxonomy is publicly queryable.', 'gutenberg' ),
142 + 'type' => 'boolean',
143 + ),
144 + 'show_ui' => array(
145 + 'description' => __( 'Whether to generate a default UI for managing this taxonomy.', 'gutenberg' ),
146 + 'type' => 'boolean',
147 + ),
148 + 'show_admin_column' => array(
149 + 'description' => __( 'Whether to allow automatic creation of taxonomy columns on associated post-types table.', 'gutenberg' ),
150 + 'type' => 'boolean',
151 + ),
152 + 'show_in_nav_menus' => array(
153 + 'description' => __( 'Whether to make the taxonomy available for selection in navigation menus.', 'gutenberg' ),
154 + 'type' => 'boolean',
155 + ),
156 + 'show_in_quick_edit' => array(
157 + 'description' => __( 'Whether to show the taxonomy in the quick/bulk edit panel.', 'gutenberg' ),
158 + 'type' => 'boolean',
159 + ),
160 + ),
161 + ),
162 + )
163 + );
37 164 }
38 -add_action( 'rest_api_init', 'gutenberg_register_edit_site_export_controller_endpoints' );
39 165
40 166 /**
41 - * Registers the Icons Registry REST API routes.
167 + * Gets taxonomy visibility property data.
168 + *
169 + * @see https://core.trac.wordpress.org/ticket/42707
170 + *
171 + * @param array $object Taxonomy data from REST API.
172 + * @return array Array of taxonomy visibility data.
42 173 */
43 -function gutenberg_register_icon_controller_endpoints() {
44 - $icons_controller = new WP_REST_Icons_Controller_Gutenberg();
45 - $icons_controller->register_routes();
174 +function gutenberg_get_taxonomy_visibility_data( $object ) {
175 + // Just return existing data for up-to-date Core.
176 + if ( isset( $object['visibility'] ) ) {
177 + return $object['visibility'];
178 + }
179 +
180 + $taxonomy = get_taxonomy( $object['slug'] );
181 +
182 + return array(
183 + 'public' => $taxonomy->public,
184 + 'publicly_queryable' => $taxonomy->publicly_queryable,
185 + 'show_ui' => $taxonomy->show_ui,
186 + 'show_admin_column' => $taxonomy->show_admin_column,
187 + 'show_in_nav_menus' => $taxonomy->show_in_nav_menus,
188 + 'show_in_quick_edit' => $taxonomy->show_ui,
189 + );
46 190 }
47 -add_action( 'rest_api_init', 'gutenberg_register_icon_controller_endpoints' );
191 +
192 +add_action( 'rest_api_init', 'gutenberg_add_taxonomy_visibility_field' );
193 +
194 +/**
195 + * Add a permalink template to posts in the post REST API response.
196 + *
197 + * @see https://core.trac.wordpress.org/ticket/45017
198 + *
199 + * @param WP_REST_Response $response WP REST API response of a post.
200 + * @param WP_Post $post The post being returned.
201 + * @param WP_REST_Request $request WP REST API request.
202 + * @return WP_REST_Response Response containing the permalink_template.
203 + */
204 +function gutenberg_add_permalink_template_to_posts( $response, $post, $request ) {
205 + if ( 'edit' !== $request['context'] ) {
206 + return $response;
207 + }
208 +
209 + $post_type_obj = get_post_type_object( $post->post_type );
210 + if ( ! is_post_type_viewable( $post_type_obj ) || ! $post_type_obj->public ) {
211 + return $response;
212 + }
213 +
214 + if ( ! function_exists( 'get_sample_permalink' ) ) {
215 + require_once ABSPATH . '/wp-admin/includes/post.php';
216 + }
217 +
218 + $sample_permalink = get_sample_permalink( $post->ID, $post->post_title, '' );
219 +
220 + $response->data['permalink_template'] = $sample_permalink[0];
221 + $response->data['generated_slug'] = $sample_permalink[1];
222 +
223 + return $response;
224 +}
225 +
226 +/**
227 + * Add the block format version to post content in the post REST API response.
228 + *
229 + * @todo This will need to be registered to the schema too.
230 + *
231 + * @see https://core.trac.wordpress.org/ticket/43887
232 + *
233 + * @param WP_REST_Response $response WP REST API response of a post.
234 + * @param WP_Post $post The post being returned.
235 + * @param WP_REST_Request $request WP REST API request.
236 + * @return WP_REST_Response Response containing the block_format.
237 + */
238 +function gutenberg_add_block_format_to_post_content( $response, $post, $request ) {
239 + if ( 'edit' !== $request['context'] ) {
240 + return $response;
241 + }
242 +
243 + $response_data = $response->get_data();
244 + if ( isset( $response_data['content'] ) && is_array( $response_data['content'] ) && isset( $response_data['content']['raw'] ) ) {
245 + $response_data['content']['block_format'] = gutenberg_content_block_version( $response_data['content']['raw'] );
246 + $response->set_data( $response_data );
247 + }
248 +
249 + return $response;
250 +}
251 +
252 +/**
253 + * Include target schema attributes to links, based on whether the user can.
254 + *
255 + * @see https://core.trac.wordpress.org/ticket/45014
256 + *
257 + * @param WP_REST_Response $response WP REST API response of a post.
258 + * @param WP_Post $post The post being returned.
259 + * @param WP_REST_Request $request WP REST API request.
260 + * @return WP_REST_Response Response containing the new links.
261 + */
262 +function gutenberg_add_target_schema_to_links( $response, $post, $request ) {
263 + $new_links = array();
264 + $orig_links = $response->get_links();
265 + $post_type = get_post_type_object( $post->post_type );
266 + $orig_href = ! empty( $orig_links['self'][0]['href'] ) ? $orig_links['self'][0]['href'] : null;
267 + if ( 'edit' === $request['context'] && current_user_can( 'unfiltered_html' ) ) {
268 + $new_links['https://api.w.org/action-unfiltered-html'] = array(
269 + array(
270 + 'title' => __( 'The current user can post HTML markup and JavaScript.', 'gutenberg' ),
271 + 'href' => $orig_href,
272 + 'targetSchema' => array(
273 + 'type' => 'object',
274 + 'properties' => array(
275 + 'unfiltered_html' => array(
276 + 'type' => 'boolean',
277 + ),
278 + ),
279 + ),
280 + ),
281 + );
282 + }
283 +
284 + $response->add_links( $new_links );
285 + return $response;
286 +}
287 +
288 +/**
289 + * Whenever a post type is registered, ensure we're hooked into it's WP REST API response.
290 + *
291 + * @param string $post_type The newly registered post type.
292 + * @return string That same post type.
293 + */
294 +function gutenberg_register_post_prepare_functions( $post_type ) {
295 + add_filter( "rest_prepare_{$post_type}", 'gutenberg_add_permalink_template_to_posts', 10, 3 );
296 + add_filter( "rest_prepare_{$post_type}", 'gutenberg_add_block_format_to_post_content', 10, 3 );
297 + add_filter( "rest_prepare_{$post_type}", 'gutenberg_add_target_schema_to_links', 10, 3 );
298 + return $post_type;
299 +}
300 +add_filter( 'registered_post_type', 'gutenberg_register_post_prepare_functions' );
301 +
302 +
303 +/**
304 + * Silence PHP Warnings and Errors in JSON requests
305 + *
306 + * @todo This is a temporary measure until errors are properly silenced in REST API responses in core
307 + *
308 + * @see https://core.trac.wordpress.org/ticket/44534
309 + */
310 +function gutenberg_silence_rest_errors() {
311 +
312 + if ( ( isset( $_SERVER['CONTENT_TYPE'] ) && 'application/json' === $_SERVER['CONTENT_TYPE'] ) ||
313 + ( isset( $_SERVER['HTTP_ACCEPT'] ) && strpos( $_SERVER['HTTP_ACCEPT'], 'application/json' ) !== false ) ) {
314 + // @codingStandardsIgnoreStart
315 + @ini_set( 'display_errors', 0 );
316 + // @codingStandardsIgnoreEnd
317 + }
318 +
319 +}
320 +
321 +/**
322 + * Include additional labels for registered post types
323 + *
324 + * @see https://core.trac.wordpress.org/ticket/45101
325 + *
326 + * @param array $args Arguments supplied to register_post_type().
327 + * @param string $post_type Post type key.
328 + * @return array Arguments supplied to register_post_type()
329 + */
330 +function gutenberg_filter_post_type_labels( $args, $post_type ) {
331 + $registered_labels = ( empty( $args['labels'] ) ) ? array() : $args['labels'];
332 + if ( is_post_type_hierarchical( $post_type ) ) {
333 + $labels = array(
334 + 'item_published' => __( 'Page published.', 'gutenberg' ),
335 + 'item_published_privately' => __( 'Page published privately.', 'gutenberg' ),
336 + 'item_reverted_to_draft' => __( 'Page reverted to draft.', 'gutenberg' ),
337 + 'item_scheduled' => __( 'Page scheduled.', 'gutenberg' ),
338 + 'item_updated' => __( 'Page updated.', 'gutenberg' ),
339 + );
340 + } else {
341 + $labels = array(
342 + 'item_published' => __( 'Post published.', 'gutenberg' ),
343 + 'item_published_privately' => __( 'Post published privately.', 'gutenberg' ),
344 + 'item_reverted_to_draft' => __( 'Post reverted to draft.', 'gutenberg' ),
345 + 'item_scheduled' => __( 'Post scheduled.', 'gutenberg' ),
346 + 'item_updated' => __( 'Post updated.', 'gutenberg' ),
347 + );
348 + }
349 + $args['labels'] = array_merge( $labels, $registered_labels );
350 + return $args;
351 +}
352 +add_filter( 'register_post_type_args', 'gutenberg_filter_post_type_labels', 10, 2 );