From d45e15c2427e4edf4d28ff2e74654069bb2881af Mon Sep 17 00:00:00 2001 From: Adam Silverstein Date: Thu, 31 Aug 2017 23:44:23 -0400 Subject: [PATCH 01/44] first pass --- gutenberg.php | 1 + 1 file changed, 1 insertion(+) diff --git a/gutenberg.php b/gutenberg.php index 41b7af888b802..12d7e2288593e 100644 --- a/gutenberg.php +++ b/gutenberg.php @@ -19,6 +19,7 @@ require_once dirname( __FILE__ ) . '/lib/class-wp-block-type.php'; require_once dirname( __FILE__ ) . '/lib/class-wp-block-type-registry.php'; require_once dirname( __FILE__ ) . '/lib/blocks.php'; + require_once dirname( __FILE__ ) . '/lib/class-wp-rest-gutenberg-blocks.php'; require_once dirname( __FILE__ ) . '/lib/client-assets.php'; require_once dirname( __FILE__ ) . '/lib/compat.php'; require_once dirname( __FILE__ ) . '/lib/i18n.php'; From 09a8e51a4dba6fee0d9845d6d8fc2aea9b611cb4 Mon Sep 17 00:00:00 2001 From: Adam Silverstein Date: Fri, 1 Sep 2017 13:13:18 -0400 Subject: [PATCH 02/44] it works, second pass --- lib/register.php | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/lib/register.php b/lib/register.php index 86f0b44e20f47..208e066259b46 100644 --- a/lib/register.php +++ b/lib/register.php @@ -73,8 +73,16 @@ function gutenberg_add_edit_links_filters() { add_filter( 'page_row_actions', 'gutenberg_add_edit_links', 10, 2 ); // For non-hierarchical post types. add_filter( 'post_row_actions', 'gutenberg_add_edit_links', 10, 2 ); + +} +add_action( 'init', 'gutenberg_add_edit_links_filters' ); + +function load_blocks_rest_api() { + error_log('load_blocks_rest_api'); + $controller = new WP_Gutenberg_Block_Controller; + $controller->register_routes(); } -add_action( 'admin_init', 'gutenberg_add_edit_links_filters' ); +add_action( 'init', 'load_blocks_rest_api' ); /** * Registers additional links in the post/page screens to edit any post/page in From f70f6bb9c146f15087423497fd156d68ccf8de86 Mon Sep 17 00:00:00 2001 From: Adam Silverstein Date: Fri, 1 Sep 2017 13:32:35 -0400 Subject: [PATCH 03/44] add gutenburg block class --- lib/class-wp-rest-gutenberg-blocks.php | 433 +++++++++++++++++++++++++ 1 file changed, 433 insertions(+) create mode 100644 lib/class-wp-rest-gutenberg-blocks.php diff --git a/lib/class-wp-rest-gutenberg-blocks.php b/lib/class-wp-rest-gutenberg-blocks.php new file mode 100644 index 0000000000000..4d764664a0556 --- /dev/null +++ b/lib/class-wp-rest-gutenberg-blocks.php @@ -0,0 +1,433 @@ +namespace = 'wp/v2'; + $this->rest_base = 'blocks'; + } + + /** + * Registers the routes for the objects of the controller. + * + * @since 1.1.0 + * + * @see register_rest_route() + */ + 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(), + ), + 'schema' => array( $this, 'get_public_item_schema' ), + ) ); + + $schema = $this->get_item_schema(); + $get_item_args = array( + 'context' => $this->get_context_param( array( 'default' => 'view' ) ), + ); + + + register_rest_route( $this->namespace, '/' . $this->rest_base . '/(?P[\d]+)', array( + 'args' => array( + 'id' => array( + 'description' => __( 'Unique identifier for the post.' ), + 'type' => 'integer', + ), + ), + array( + 'methods' => WP_REST_Server::READABLE, + 'callback' => array( $this, 'get_item' ), + 'permission_callback' => array( $this, 'get_item_permissions_check' ), + 'args' => $get_item_args, + ), + 'schema' => array( $this, 'get_public_item_schema' ), + ) ); + } + + /** + * Checks if a given request has access to read posts. + * + * @since 1.1.0 + * + * @param WP_REST_Request $request Full details about the request. + * + * @return true|WP_Error True if the request has read access, WP_Error object otherwise. + */ + public function get_items_permissions_check( $request ) { + + return true; + } + + /** + * Retrieves a collection of posts. + * + * @since 1.1.0 + * + * @param WP_REST_Request $request Full details about the request. + * + * @return WP_REST_Response|WP_Error Response object on success, or WP_Error object on failure. + */ + public function get_items( $request ) { +error_log('get_items'); + // Retrieve the list of registered collection query parameters. + $registered = $this->get_collection_params(); + $args = array(); + + /* + * This array defines mappings between public API query parameters whose + * values are accepted as-passed, and their internal WP_Query parameter + * name equivalents (some are the same). Only values which are also + * present in $registered will be set. + */ + $parameter_mappings = array(); + + /* + * For each known parameter which is both registered and present in the request, + * set the parameter's value on the query $args. + */ + foreach ( $parameter_mappings as $api_param => $wp_param ) { + if ( isset( $registered[ $api_param ], $request[ $api_param ] ) ) { + $args[ $wp_param ] = $request[ $api_param ]; + } + } + + /** + * Filters the query arguments for a request. + * + * Enables adding extra arguments or setting defaults for a post collection request. + * + * @since 1.1.0 + * + * @link https://developer.wordpress.org/reference/classes/wp_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_blocks_query", $args, $request ); + $query_args = $this->prepare_items_query( $args, $request ); + + $posts_query = new WP_Query(); + $query_result = $posts_query->query( $query_args ); + foreach ( $query_result as $post ) { + if ( ! $this->check_read_permission( $post ) ) { + continue; + } + $content = $post->post_content; + $data = gutenberg_parse_blocks( $content ); + $posts[] = $data; + } + $response = rest_ensure_response( $posts ); + + return $response; + } + + /** + * Get the blocks for a post, if the ID is valid. + * + * @since 1.1.0 + * + * @param int $id Supplied ID. + * @return WP_Post|WP_Error Post object if ID is valid, WP_Error otherwise. + */ + protected function get_post( $id ) { + $error = new WP_Error( 'rest_post_invalid_id', __( 'Invalid post ID.' ), array( 'status' => 404 ) ); + + if ( (int) $id <= 0 ) { + return $error; + } + + $post = get_post( (int) $id ); + if ( empty( $post ) || empty( $post->ID ) ) { + return $error; + } + + return $post; + } + + /** + * Checks if a given request has access to read a post. + * + * @since 1.1.0 + * + * @param WP_REST_Request $request Full details about the request. + * @return bool|WP_Error True if the request has read access for the item, WP_Error object otherwise. + */ + public function get_item_permissions_check( $request ) { + $post = $this->get_post( $request['id'] ); + if ( is_wp_error( $post ) ) { + return $post; + } + + if ( $post ) { + return $this->check_read_permission( $post ); + } + + return true; + } + + /** + * Retrieves a single post's blocks. + * + * @since 1.1.0 + * + * @param WP_REST_Request $request Full details about the request. + * @return WP_REST_Response|WP_Error Response object on success, or WP_Error object on failure. + */ + public function get_item( $request ) { + $post = $this->get_post( $request['id'] ); + if ( is_wp_error( $post ) ) { + return $post; + } + + $data = $this->prepare_item_for_response( $post, $request ); + $response = rest_ensure_response( $data ); + + if ( is_post_type_viewable( get_post_type_object( $post->post_type ) ) ) { + $response->link_header( 'alternate', get_permalink( $post->ID ), array( 'type' => 'text/html' ) ); + } + + return $response; + } + + /** + * Determines the allowed query_vars for a get_items() response and prepares + * them for WP_Query. + * + * @since 1.1.0 + * + * @param array $prepared_args Optional. Prepared WP_Query arguments. Default empty array. + * @param WP_REST_Request $request Optional. Full details about the request. + * @return array Items query arguments. + */ + protected function prepare_items_query( $prepared_args = array(), $request = null ) { + $query_args = array(); + + foreach ( $prepared_args as $key => $value ) { + /** + * Filters the query_vars used in get_items() for the constructed query. + * + * The dynamic portion of the hook name, `$key`, refers to the query_var key. + * + * @since 1.1.0 + * + * @param string $value The query_var value. + */ + $query_args[ $key ] = apply_filters( "rest_query_var-{$key}", $value ); + } + + // Map to proper WP_Query orderby param. + if ( isset( $query_args['orderby'] ) && isset( $request['orderby'] ) ) { + $orderby_mappings = array( + 'id' => 'ID', + ); + + } + + return $query_args; + } + + /** + * Checks if a given post type can be viewed or managed. + * + * @since 1.1.0 + * + * @param object|string $post_type Post type name or object. + * @return bool Whether the post type is allowed in REST. + */ + protected function check_is_post_type_allowed( $post_type ) { + if ( ! is_object( $post_type ) ) { + $post_type = get_post_type_object( $post_type ); + } + + if ( ! empty( $post_type ) && ! empty( $post_type->show_in_rest ) ) { + return true; + } + + return false; + } + + /** + * Checks if a post's blocks can be read. + * + * @since 1.1.0 + * + * @param object $post Post object. + * @return bool Whether the post can be read. + */ + public function check_read_permission( $post ) { + $post_type = get_post_type_object( $post->post_type ); + if ( ! $this->check_is_post_type_allowed( $post_type ) ) { + return false; + } + + // Is the post readable? + if ( 'publish' === $post->post_status || current_user_can( $post_type->cap->read_post, $post->ID ) ) { + return true; + } + + $post_status_obj = get_post_status_object( $post->post_status ); + if ( $post_status_obj && $post_status_obj->public ) { + return true; + } + + return false; + } + + /** + * Prepares a single post output for response. + * + * @since 1.1.0 + * + * @param WP_Post $post Post object. + * @param WP_REST_Request $request Request object. + * @return WP_REST_Response Response object. + */ + 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; + } + + $content = $post->post_content; + $data = gutenberg_parse_blocks( $content ); + + // Wrap the data in a response object. + $response = rest_ensure_response( $data ); + + /** + * Filters the post data for a response. + * + * The dynamic portion of the hook name, `$this->post_type`, refers to the post type slug. + * + * @since 1.1.0 + * + * @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_blocks", $response, $post, $request ); + } + + /** + * Retrieves the post's schema, conforming to JSON Schema. + * + * @since 1.1.0 + * + * @return array Item schema data. + */ + public function get_item_schema() { + + $schema = array( + '$schema' => 'http://json-schema.org/schema#', + 'title' => 'blocks', + 'type' => 'object', + // Base properties for every Block. + 'properties' => array( + 'name' => array( + 'description' => __( "The name of the block." ), + 'type' => 'string', + 'context' => array( 'view', 'edit', 'embed' ), + ), + + 'id' => array( + 'description' => __( 'The id of the post containing the block.' ), + 'type' => 'integer', + 'context' => array( 'view', 'edit', 'embed' ), + 'readonly' => true, + ), + 'slug' => array( + 'description' => __( 'An alphanumeric identifier for the object unique to its type.' ), + 'type' => 'string', + 'context' => array( 'view', 'edit', 'embed' ), + 'arg_options' => array( + 'sanitize_callback' => array( $this, 'sanitize_slug' ), + ), + ), + 'data' => array( + 'description' => __( 'The data underlying the block.' ), + 'type' => 'string', + 'enum' => array_keys( get_post_stati( array( 'internal' => false ) ) ), + 'context' => array( 'view', 'edit' ), + ), + 'rendered' => array( + 'description' => __( 'The rendered block content.' ), + 'type' => 'string', + 'context' => array( 'view', 'edit', 'embed' ), + 'readonly' => true, + ), + ), + ); + + $post_type_obj = get_post_type_object( $this->post_type ); + + + return $this->add_additional_fields_schema( $schema ); + } + + /** + * Retrieves the query params for the posts collection. + * + * @since 1.1.0 + * + * @return array Collection parameters. + */ + public function get_collection_params() { + $query_params = parent::get_collection_params(); + + + /** + * Filter collection parameters for the posts controller. + * + * The dynamic part of the filter `$this->post_type` refers to the post + * type slug for the controller. + * + * This filter registers the collection parameter, but does not map the + * collection parameter to an internal WP_Query parameter. Use the + * `rest_{$this->post_type}_query` filter to set WP_Query parameters. + * + * @since 1.1.0 + * + * @param array $query_params JSON Schema-formatted collection parameters. + * @param WP_Post_Type $post_type Post type object. + */ + return apply_filters( "rest_blocks_collection_params", $query_params, $post_type ); + } + +} From 6f73d88eb801f41350f6ff42ae8377be948a1218 Mon Sep 17 00:00:00 2001 From: Adam Silverstein Date: Sat, 2 Sep 2017 00:27:05 -0400 Subject: [PATCH 04/44] remove logging, add inline docs, clean up --- lib/class-wp-rest-gutenberg-blocks.php | 114 +++++++------------------ 1 file changed, 33 insertions(+), 81 deletions(-) diff --git a/lib/class-wp-rest-gutenberg-blocks.php b/lib/class-wp-rest-gutenberg-blocks.php index 4d764664a0556..acb75f23e2e03 100644 --- a/lib/class-wp-rest-gutenberg-blocks.php +++ b/lib/class-wp-rest-gutenberg-blocks.php @@ -4,22 +4,6 @@ */ class WP_Gutenberg_Block_Controller extends WP_REST_Controller { - /** - * Post type. - * - * @since 1.1.0 - * @var string - */ - protected $block_type; - - /** - * Instance of a post meta fields object. - * - * @since 1.1.0 - * @var WP_REST_Post_Meta_Fields - */ - protected $meta; - /** * Constructor. * @@ -32,7 +16,7 @@ public function __construct() { } /** - * Registers the routes for the objects of the controller. + * Register the block routes. * * @since 1.1.0 * @@ -40,6 +24,7 @@ public function __construct() { */ public function register_routes() { + // Add a post collection block route. register_rest_route( $this->namespace, '/' . $this->rest_base, array( array( 'methods' => WP_REST_Server::READABLE, @@ -55,7 +40,7 @@ public function register_routes() { 'context' => $this->get_context_param( array( 'default' => 'view' ) ), ); - + // Add a single post block route. register_rest_route( $this->namespace, '/' . $this->rest_base . '/(?P[\d]+)', array( 'args' => array( 'id' => array( @@ -74,7 +59,7 @@ public function register_routes() { } /** - * Checks if a given request has access to read posts. + * Checks if a given request has access to read posts and their blocks. * * @since 1.1.0 * @@ -88,7 +73,7 @@ public function get_items_permissions_check( $request ) { } /** - * Retrieves a collection of posts. + * Retrieves a collection of posts blocks. * * @since 1.1.0 * @@ -97,33 +82,15 @@ public function get_items_permissions_check( $request ) { * @return WP_REST_Response|WP_Error Response object on success, or WP_Error object on failure. */ public function get_items( $request ) { -error_log('get_items'); + // Retrieve the list of registered collection query parameters. $registered = $this->get_collection_params(); $args = array(); - /* - * This array defines mappings between public API query parameters whose - * values are accepted as-passed, and their internal WP_Query parameter - * name equivalents (some are the same). Only values which are also - * present in $registered will be set. - */ - $parameter_mappings = array(); - - /* - * For each known parameter which is both registered and present in the request, - * set the parameter's value on the query $args. - */ - foreach ( $parameter_mappings as $api_param => $wp_param ) { - if ( isset( $registered[ $api_param ], $request[ $api_param ] ) ) { - $args[ $wp_param ] = $request[ $api_param ]; - } - } - /** * Filters the query arguments for a request. * - * Enables adding extra arguments or setting defaults for a post collection request. + * Enables adding extra arguments or setting defaults for a post blocks collection request. * * @since 1.1.0 * @@ -141,6 +108,8 @@ public function get_items( $request ) { if ( ! $this->check_read_permission( $post ) ) { continue; } + + // Parse the blocks from post content. $content = $post->post_content; $data = gutenberg_parse_blocks( $content ); $posts[] = $data; @@ -156,6 +125,7 @@ public function get_items( $request ) { * @since 1.1.0 * * @param int $id Supplied ID. + * * @return WP_Post|WP_Error Post object if ID is valid, WP_Error otherwise. */ protected function get_post( $id ) { @@ -174,15 +144,16 @@ protected function get_post( $id ) { } /** - * Checks if a given request has access to read a post. + * Checks if a given request has access to read a post and its blocks. * * @since 1.1.0 * * @param WP_REST_Request $request Full details about the request. + * * @return bool|WP_Error True if the request has read access for the item, WP_Error object otherwise. */ public function get_item_permissions_check( $request ) { - $post = $this->get_post( $request['id'] ); + $post = $this->get_post( (int) $request['id'] ); if ( is_wp_error( $post ) ) { return $post; } @@ -191,7 +162,8 @@ public function get_item_permissions_check( $request ) { return $this->check_read_permission( $post ); } - return true; + $error = new WP_Error( 'rest_post_invalid', __( 'Invalid post.' ), array( 'status' => 404 ) ) + return $error; } /** @@ -200,6 +172,7 @@ public function get_item_permissions_check( $request ) { * @since 1.1.0 * * @param WP_REST_Request $request Full details about the request. + * * @return WP_REST_Response|WP_Error Response object on success, or WP_Error object on failure. */ public function get_item( $request ) { @@ -211,10 +184,6 @@ public function get_item( $request ) { $data = $this->prepare_item_for_response( $post, $request ); $response = rest_ensure_response( $data ); - if ( is_post_type_viewable( get_post_type_object( $post->post_type ) ) ) { - $response->link_header( 'alternate', get_permalink( $post->ID ), array( 'type' => 'text/html' ) ); - } - return $response; } @@ -226,12 +195,14 @@ public function get_item( $request ) { * * @param array $prepared_args Optional. Prepared WP_Query arguments. Default empty array. * @param WP_REST_Request $request Optional. Full details about the request. + * * @return array Items query arguments. */ protected function prepare_items_query( $prepared_args = array(), $request = null ) { $query_args = array(); foreach ( $prepared_args as $key => $value ) { + /** * Filters the query_vars used in get_items() for the constructed query. * @@ -244,14 +215,6 @@ protected function prepare_items_query( $prepared_args = array(), $request = nul $query_args[ $key ] = apply_filters( "rest_query_var-{$key}", $value ); } - // Map to proper WP_Query orderby param. - if ( isset( $query_args['orderby'] ) && isset( $request['orderby'] ) ) { - $orderby_mappings = array( - 'id' => 'ID', - ); - - } - return $query_args; } @@ -261,6 +224,7 @@ protected function prepare_items_query( $prepared_args = array(), $request = nul * @since 1.1.0 * * @param object|string $post_type Post type name or object. + * * @return bool Whether the post type is allowed in REST. */ protected function check_is_post_type_allowed( $post_type ) { @@ -281,6 +245,7 @@ protected function check_is_post_type_allowed( $post_type ) { * @since 1.1.0 * * @param object $post Post object. + * * @return bool Whether the post can be read. */ public function check_read_permission( $post ) { @@ -309,6 +274,7 @@ public function check_read_permission( $post ) { * * @param WP_Post $post Post object. * @param WP_REST_Request $request Request object. + * * @return WP_REST_Response Response object. */ public function prepare_item_for_response( $post, $request ) { @@ -325,6 +291,7 @@ public function prepare_item_for_response( $post, $request ) { $data['id'] = $post->ID; } + // Parse the blocks from post content. $content = $post->post_content; $data = gutenberg_parse_blocks( $content ); @@ -334,8 +301,6 @@ public function prepare_item_for_response( $post, $request ) { /** * Filters the post data for a response. * - * The dynamic portion of the hook name, `$this->post_type`, refers to the post type slug. - * * @since 1.1.0 * * @param WP_REST_Response $response The response object. @@ -358,46 +323,34 @@ public function get_item_schema() { '$schema' => 'http://json-schema.org/schema#', 'title' => 'blocks', 'type' => 'object', + // Base properties for every Block. 'properties' => array( - 'name' => array( + 'blockName' => array( 'description' => __( "The name of the block." ), 'type' => 'string', - 'context' => array( 'view', 'edit', 'embed' ), + 'context' => array( 'view' ), + 'readonly' => true, ), - - 'id' => array( - 'description' => __( 'The id of the post containing the block.' ), - 'type' => 'integer', - 'context' => array( 'view', 'edit', 'embed' ), + 'attrs' => array( + 'description' => __( 'The block data attributes.' ), + 'type' => 'array', + 'context' => array( 'view' ), 'readonly' => true, ), - 'slug' => array( - 'description' => __( 'An alphanumeric identifier for the object unique to its type.' ), + 'rawContent' => array( + 'description' => __( 'The raw block content.' ), 'type' => 'string', - 'context' => array( 'view', 'edit', 'embed' ), + 'context' => array( 'view' ), 'arg_options' => array( 'sanitize_callback' => array( $this, 'sanitize_slug' ), ), ), - 'data' => array( - 'description' => __( 'The data underlying the block.' ), - 'type' => 'string', - 'enum' => array_keys( get_post_stati( array( 'internal' => false ) ) ), - 'context' => array( 'view', 'edit' ), - ), - 'rendered' => array( - 'description' => __( 'The rendered block content.' ), - 'type' => 'string', - 'context' => array( 'view', 'edit', 'embed' ), - 'readonly' => true, - ), ), ); $post_type_obj = get_post_type_object( $this->post_type ); - return $this->add_additional_fields_schema( $schema ); } @@ -429,5 +382,4 @@ public function get_collection_params() { */ return apply_filters( "rest_blocks_collection_params", $query_params, $post_type ); } - } From 97d282b6ae17b182dd82304ef863cbc8088cbe03 Mon Sep 17 00:00:00 2001 From: Adam Silverstein Date: Sat, 2 Sep 2017 01:04:33 -0400 Subject: [PATCH 05/44] add rendered block content when available --- gutenberg.php | 2 +- lib/class-wp-rest-gutenberg-blocks.php | 37 +++++++++++++++++++++++--- lib/register.php | 1 - 3 files changed, 35 insertions(+), 5 deletions(-) diff --git a/gutenberg.php b/gutenberg.php index 12d7e2288593e..ec4e890d949e3 100644 --- a/gutenberg.php +++ b/gutenberg.php @@ -19,12 +19,12 @@ require_once dirname( __FILE__ ) . '/lib/class-wp-block-type.php'; require_once dirname( __FILE__ ) . '/lib/class-wp-block-type-registry.php'; require_once dirname( __FILE__ ) . '/lib/blocks.php'; - require_once dirname( __FILE__ ) . '/lib/class-wp-rest-gutenberg-blocks.php'; require_once dirname( __FILE__ ) . '/lib/client-assets.php'; require_once dirname( __FILE__ ) . '/lib/compat.php'; require_once dirname( __FILE__ ) . '/lib/i18n.php'; require_once dirname( __FILE__ ) . '/lib/parser.php'; require_once dirname( __FILE__ ) . '/lib/register.php'; + require_once dirname( __FILE__ ) . '/lib/class-wp-rest-gutenberg-blocks.php'; // Register server-side code for individual blocks. foreach ( glob( dirname( __FILE__ ) . '/blocks/library/*/index.php' ) as $block_logic ) { diff --git a/lib/class-wp-rest-gutenberg-blocks.php b/lib/class-wp-rest-gutenberg-blocks.php index acb75f23e2e03..9e017f87e98c6 100644 --- a/lib/class-wp-rest-gutenberg-blocks.php +++ b/lib/class-wp-rest-gutenberg-blocks.php @@ -104,6 +104,7 @@ public function get_items( $request ) { $posts_query = new WP_Query(); $query_result = $posts_query->query( $query_args ); + $registry = WP_Block_Type_Registry::get_instance(); foreach ( $query_result as $post ) { if ( ! $this->check_read_permission( $post ) ) { continue; @@ -111,7 +112,21 @@ public function get_items( $request ) { // Parse the blocks from post content. $content = $post->post_content; - $data = gutenberg_parse_blocks( $content ); + $blocks = gutenberg_parse_blocks( $content ); + + $data = array(); + foreach ( $blocks->data as $block ) { + $block_name = isset( $block['blockName'] ) ? $block['blockName'] : null; + $attributes = is_array( $block['attrs'] ) ? $block['attrs'] : array(); + $raw_content = isset( $block['rawContent'] ) ? $block['rawContent'] : null; + if ( $block_name ) { + $block_type = $registry->get_registered( $block_name ); + if ( null !== $block_type ) { + $block['renderedContent'] = $block_type->render( $attributes, $raw_content ); + } + } + $data[] = $block; + } $posts[] = $data; } $response = rest_ensure_response( $posts ); @@ -162,7 +177,7 @@ public function get_item_permissions_check( $request ) { return $this->check_read_permission( $post ); } - $error = new WP_Error( 'rest_post_invalid', __( 'Invalid post.' ), array( 'status' => 404 ) ) + $error = new WP_Error( 'rest_post_invalid', __( 'Invalid post.' ), array( 'status' => 404 ) ); return $error; } @@ -181,7 +196,23 @@ public function get_item( $request ) { return $post; } - $data = $this->prepare_item_for_response( $post, $request ); + $blocks = $this->prepare_item_for_response( $post, $request ); + $registry = WP_Block_Type_Registry::get_instance(); + + $data = array(); + foreach ( $blocks->data as $block ) { + $block_name = isset( $block['blockName'] ) ? $block['blockName'] : null; + $attributes = is_array( $block['attrs'] ) ? $block['attrs'] : array(); + $raw_content = isset( $block['rawContent'] ) ? $block['rawContent'] : null; + if ( $block_name ) { + $block_type = $registry->get_registered( $block_name ); + if ( null !== $block_type ) { + $block['renderedContent'] = $block_type->render( $attributes, $raw_content ); + } + } + $data[] = $block; + } + $response = rest_ensure_response( $data ); return $response; diff --git a/lib/register.php b/lib/register.php index 208e066259b46..7d7b67175d830 100644 --- a/lib/register.php +++ b/lib/register.php @@ -78,7 +78,6 @@ function gutenberg_add_edit_links_filters() { add_action( 'init', 'gutenberg_add_edit_links_filters' ); function load_blocks_rest_api() { - error_log('load_blocks_rest_api'); $controller = new WP_Gutenberg_Block_Controller; $controller->register_routes(); } From 30d12b96b5ca9016f4f7bb33c6f4853ad4c9617f Mon Sep 17 00:00:00 2001 From: Adam Silverstein Date: Sat, 2 Sep 2017 01:15:39 -0400 Subject: [PATCH 06/44] restore register.php --- lib/register.php | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/lib/register.php b/lib/register.php index 7d7b67175d830..86f0b44e20f47 100644 --- a/lib/register.php +++ b/lib/register.php @@ -73,15 +73,8 @@ function gutenberg_add_edit_links_filters() { add_filter( 'page_row_actions', 'gutenberg_add_edit_links', 10, 2 ); // For non-hierarchical post types. add_filter( 'post_row_actions', 'gutenberg_add_edit_links', 10, 2 ); - -} -add_action( 'init', 'gutenberg_add_edit_links_filters' ); - -function load_blocks_rest_api() { - $controller = new WP_Gutenberg_Block_Controller; - $controller->register_routes(); } -add_action( 'init', 'load_blocks_rest_api' ); +add_action( 'admin_init', 'gutenberg_add_edit_links_filters' ); /** * Registers additional links in the post/page screens to edit any post/page in From 488690d99a581a7dd8d826b437f7804b447d28cb Mon Sep 17 00:00:00 2001 From: Adam Silverstein Date: Sat, 2 Sep 2017 01:18:40 -0400 Subject: [PATCH 07/44] restore register.php --- lib/register.php | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/lib/register.php b/lib/register.php index 86f0b44e20f47..6f235c4663643 100644 --- a/lib/register.php +++ b/lib/register.php @@ -73,9 +73,16 @@ function gutenberg_add_edit_links_filters() { add_filter( 'page_row_actions', 'gutenberg_add_edit_links', 10, 2 ); // For non-hierarchical post types. add_filter( 'post_row_actions', 'gutenberg_add_edit_links', 10, 2 ); + } add_action( 'admin_init', 'gutenberg_add_edit_links_filters' ); +function load_blocks_rest_api() { + $controller = new WP_Gutenberg_Block_Controller; + $controller->register_routes(); +} +add_action( 'init', 'load_blocks_rest_api' ); + /** * Registers additional links in the post/page screens to edit any post/page in * the Gutenberg editor. @@ -90,9 +97,8 @@ function gutenberg_add_edit_links_filters() { function gutenberg_add_edit_links( $actions, $post ) { $can_edit_post = current_user_can( 'edit_post', $post->ID ); $title = _draft_or_post_title( $post->ID ); - $post_type = get_post_type( $post ); - if ( $can_edit_post && 'trash' !== $post->post_status && apply_filters( 'gutenberg_add_edit_link_for_post_type', true, $post_type, $post ) ) { + if ( $can_edit_post && 'trash' !== $post->post_status ) { // Build the Gutenberg edit action. See also: WP_Posts_List_Table::handle_row_actions(). $gutenberg_url = menu_page_url( 'gutenberg', false ); $gutenberg_action = sprintf( From 632a07d9e92fbe193f4e099aa21c8a77131b964d Mon Sep 17 00:00:00 2001 From: Adam Silverstein Date: Sat, 2 Sep 2017 01:21:33 -0400 Subject: [PATCH 08/44] restore register.php --- lib/register.php | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/lib/register.php b/lib/register.php index 6f235c4663643..1bba3782ea54b 100644 --- a/lib/register.php +++ b/lib/register.php @@ -73,7 +73,6 @@ function gutenberg_add_edit_links_filters() { add_filter( 'page_row_actions', 'gutenberg_add_edit_links', 10, 2 ); // For non-hierarchical post types. add_filter( 'post_row_actions', 'gutenberg_add_edit_links', 10, 2 ); - } add_action( 'admin_init', 'gutenberg_add_edit_links_filters' ); @@ -83,6 +82,7 @@ function load_blocks_rest_api() { } add_action( 'init', 'load_blocks_rest_api' ); + /** * Registers additional links in the post/page screens to edit any post/page in * the Gutenberg editor. @@ -97,8 +97,9 @@ function load_blocks_rest_api() { function gutenberg_add_edit_links( $actions, $post ) { $can_edit_post = current_user_can( 'edit_post', $post->ID ); $title = _draft_or_post_title( $post->ID ); + $post_type = get_post_type( $post ); - if ( $can_edit_post && 'trash' !== $post->post_status ) { + if ( $can_edit_post && 'trash' !== $post->post_status && apply_filters( 'gutenberg_add_edit_link_for_post_type', true, $post_type, $post ) ) { // Build the Gutenberg edit action. See also: WP_Posts_List_Table::handle_row_actions(). $gutenberg_url = menu_page_url( 'gutenberg', false ); $gutenberg_action = sprintf( From 9ce9ca49cc3496123982ed90861a7bc7522d28a3 Mon Sep 17 00:00:00 2001 From: Adam Silverstein Date: Sat, 2 Sep 2017 11:40:29 -0400 Subject: [PATCH 09/44] dry out block parsing code, remove unused prepare_item_for_response --- lib/class-wp-rest-gutenberg-blocks.php | 108 ++++++++----------------- 1 file changed, 33 insertions(+), 75 deletions(-) diff --git a/lib/class-wp-rest-gutenberg-blocks.php b/lib/class-wp-rest-gutenberg-blocks.php index 9e017f87e98c6..4cba1335a39fe 100644 --- a/lib/class-wp-rest-gutenberg-blocks.php +++ b/lib/class-wp-rest-gutenberg-blocks.php @@ -111,22 +111,8 @@ public function get_items( $request ) { } // Parse the blocks from post content. - $content = $post->post_content; - $blocks = gutenberg_parse_blocks( $content ); - - $data = array(); - foreach ( $blocks->data as $block ) { - $block_name = isset( $block['blockName'] ) ? $block['blockName'] : null; - $attributes = is_array( $block['attrs'] ) ? $block['attrs'] : array(); - $raw_content = isset( $block['rawContent'] ) ? $block['rawContent'] : null; - if ( $block_name ) { - $block_type = $registry->get_registered( $block_name ); - if ( null !== $block_type ) { - $block['renderedContent'] = $block_type->render( $attributes, $raw_content ); - } - } - $data[] = $block; - } + $data = $this->get_block_data_from_content( $post->post_content ); + $posts[] = $data; } $response = rest_ensure_response( $posts ); @@ -196,22 +182,7 @@ public function get_item( $request ) { return $post; } - $blocks = $this->prepare_item_for_response( $post, $request ); - $registry = WP_Block_Type_Registry::get_instance(); - - $data = array(); - foreach ( $blocks->data as $block ) { - $block_name = isset( $block['blockName'] ) ? $block['blockName'] : null; - $attributes = is_array( $block['attrs'] ) ? $block['attrs'] : array(); - $raw_content = isset( $block['rawContent'] ) ? $block['rawContent'] : null; - if ( $block_name ) { - $block_type = $registry->get_registered( $block_name ); - if ( null !== $block_type ) { - $block['renderedContent'] = $block_type->render( $attributes, $raw_content ); - } - } - $data[] = $block; - } + $data = $this->get_block_data_from_content( $post->post_content ); $response = rest_ensure_response( $data ); @@ -298,49 +269,6 @@ public function check_read_permission( $post ) { return false; } - /** - * Prepares a single post output for response. - * - * @since 1.1.0 - * - * @param WP_Post $post Post object. - * @param WP_REST_Request $request Request object. - * - * @return WP_REST_Response Response object. - */ - 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; - } - - // Parse the blocks from post content. - $content = $post->post_content; - $data = gutenberg_parse_blocks( $content ); - - // Wrap the data in a response object. - $response = rest_ensure_response( $data ); - - /** - * Filters the post data for a response. - * - * @since 1.1.0 - * - * @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_blocks", $response, $post, $request ); - } - /** * Retrieves the post's schema, conforming to JSON Schema. * @@ -413,4 +341,34 @@ public function get_collection_params() { */ return apply_filters( "rest_blocks_collection_params", $query_params, $post_type ); } + + /** + * Extract the blocks from post content. + * + * @since 1.1.0 + * + * @param string The post content. + * + * @return array Array of block data. + */ + public function get_block_data_from_content( $content ) { + $registry = WP_Block_Type_Registry::get_instance(); + $blocks = gutenberg_parse_blocks( $content ); + $data = array(); + + // Loop thru the blocks, adding rendered content when available. + foreach ( $blocks as $block ) { + $block_name = isset( $block['blockName'] ) ? $block['blockName'] : null; + $attributes = is_array( $block['attrs'] ) ? $block['attrs'] : array(); + $raw_content = isset( $block['rawContent'] ) ? $block['rawContent'] : null; + if ( $block_name ) { + $block_type = $registry->get_registered( $block_name ); + if ( null !== $block_type ) { + $block['renderedContent'] = $block_type->render( $attributes, $raw_content ); + } + } + $data[] = $block; + } + return $data; + } } From 148469e861d2d3b602f0b2ac6847d35f5a728809 Mon Sep 17 00:00:00 2001 From: Adam Silverstein Date: Mon, 4 Sep 2017 15:35:20 -0400 Subject: [PATCH 10/44] Remap response fields to match #2503 --- lib/class-wp-rest-gutenberg-blocks.php | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/lib/class-wp-rest-gutenberg-blocks.php b/lib/class-wp-rest-gutenberg-blocks.php index 4cba1335a39fe..106ea802b599a 100644 --- a/lib/class-wp-rest-gutenberg-blocks.php +++ b/lib/class-wp-rest-gutenberg-blocks.php @@ -355,20 +355,32 @@ public function get_block_data_from_content( $content ) { $registry = WP_Block_Type_Registry::get_instance(); $blocks = gutenberg_parse_blocks( $content ); $data = array(); + $data_pre = array(); // Loop thru the blocks, adding rendered content when available. foreach ( $blocks as $block ) { $block_name = isset( $block['blockName'] ) ? $block['blockName'] : null; $attributes = is_array( $block['attrs'] ) ? $block['attrs'] : array(); $raw_content = isset( $block['rawContent'] ) ? $block['rawContent'] : null; - if ( $block_name ) { + if ( null !== $block_name ) { $block_type = $registry->get_registered( $block_name ); if ( null !== $block_type ) { $block['renderedContent'] = $block_type->render( $attributes, $raw_content ); } + $data_pre[] = $block; } - $data[] = $block; } + + // Remap the block fields for the response. + foreach ( $data_pre as $block ) { + $data[] = array( + 'type' => $block['blockName'], + 'attributes' => $block['attrs'], + 'content' => $block['rawContent'], + 'rendered' => isset( $block['renderedContent'] ) ? $block['renderedContent'] : null, + ); + } + return $data; } } From 96f1fa21bcc68bf867a260d1fff3dd3a13d042ba Mon Sep 17 00:00:00 2001 From: Adam Silverstein Date: Mon, 4 Sep 2017 16:00:04 -0400 Subject: [PATCH 11/44] Remove WP_Gutenberg_Block_Controller class --- gutenberg.php | 1 - lib/class-wp-rest-gutenberg-blocks.php | 386 ------------------------- lib/register.php | 7 - 3 files changed, 394 deletions(-) delete mode 100644 lib/class-wp-rest-gutenberg-blocks.php diff --git a/gutenberg.php b/gutenberg.php index ec4e890d949e3..41b7af888b802 100644 --- a/gutenberg.php +++ b/gutenberg.php @@ -24,7 +24,6 @@ require_once dirname( __FILE__ ) . '/lib/i18n.php'; require_once dirname( __FILE__ ) . '/lib/parser.php'; require_once dirname( __FILE__ ) . '/lib/register.php'; - require_once dirname( __FILE__ ) . '/lib/class-wp-rest-gutenberg-blocks.php'; // Register server-side code for individual blocks. foreach ( glob( dirname( __FILE__ ) . '/blocks/library/*/index.php' ) as $block_logic ) { diff --git a/lib/class-wp-rest-gutenberg-blocks.php b/lib/class-wp-rest-gutenberg-blocks.php deleted file mode 100644 index 106ea802b599a..0000000000000 --- a/lib/class-wp-rest-gutenberg-blocks.php +++ /dev/null @@ -1,386 +0,0 @@ -namespace = 'wp/v2'; - $this->rest_base = 'blocks'; - } - - /** - * Register the block routes. - * - * @since 1.1.0 - * - * @see register_rest_route() - */ - public function register_routes() { - - // Add a post collection block route. - 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(), - ), - 'schema' => array( $this, 'get_public_item_schema' ), - ) ); - - $schema = $this->get_item_schema(); - $get_item_args = array( - 'context' => $this->get_context_param( array( 'default' => 'view' ) ), - ); - - // Add a single post block route. - register_rest_route( $this->namespace, '/' . $this->rest_base . '/(?P[\d]+)', array( - 'args' => array( - 'id' => array( - 'description' => __( 'Unique identifier for the post.' ), - 'type' => 'integer', - ), - ), - array( - 'methods' => WP_REST_Server::READABLE, - 'callback' => array( $this, 'get_item' ), - 'permission_callback' => array( $this, 'get_item_permissions_check' ), - 'args' => $get_item_args, - ), - 'schema' => array( $this, 'get_public_item_schema' ), - ) ); - } - - /** - * Checks if a given request has access to read posts and their blocks. - * - * @since 1.1.0 - * - * @param WP_REST_Request $request Full details about the request. - * - * @return true|WP_Error True if the request has read access, WP_Error object otherwise. - */ - public function get_items_permissions_check( $request ) { - - return true; - } - - /** - * Retrieves a collection of posts blocks. - * - * @since 1.1.0 - * - * @param WP_REST_Request $request Full details about the request. - * - * @return WP_REST_Response|WP_Error Response object on success, or WP_Error object on failure. - */ - public function get_items( $request ) { - - // Retrieve the list of registered collection query parameters. - $registered = $this->get_collection_params(); - $args = array(); - - /** - * Filters the query arguments for a request. - * - * Enables adding extra arguments or setting defaults for a post blocks collection request. - * - * @since 1.1.0 - * - * @link https://developer.wordpress.org/reference/classes/wp_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_blocks_query", $args, $request ); - $query_args = $this->prepare_items_query( $args, $request ); - - $posts_query = new WP_Query(); - $query_result = $posts_query->query( $query_args ); - $registry = WP_Block_Type_Registry::get_instance(); - foreach ( $query_result as $post ) { - if ( ! $this->check_read_permission( $post ) ) { - continue; - } - - // Parse the blocks from post content. - $data = $this->get_block_data_from_content( $post->post_content ); - - $posts[] = $data; - } - $response = rest_ensure_response( $posts ); - - return $response; - } - - /** - * Get the blocks for a post, if the ID is valid. - * - * @since 1.1.0 - * - * @param int $id Supplied ID. - * - * @return WP_Post|WP_Error Post object if ID is valid, WP_Error otherwise. - */ - protected function get_post( $id ) { - $error = new WP_Error( 'rest_post_invalid_id', __( 'Invalid post ID.' ), array( 'status' => 404 ) ); - - if ( (int) $id <= 0 ) { - return $error; - } - - $post = get_post( (int) $id ); - if ( empty( $post ) || empty( $post->ID ) ) { - return $error; - } - - return $post; - } - - /** - * Checks if a given request has access to read a post and its blocks. - * - * @since 1.1.0 - * - * @param WP_REST_Request $request Full details about the request. - * - * @return bool|WP_Error True if the request has read access for the item, WP_Error object otherwise. - */ - public function get_item_permissions_check( $request ) { - $post = $this->get_post( (int) $request['id'] ); - if ( is_wp_error( $post ) ) { - return $post; - } - - if ( $post ) { - return $this->check_read_permission( $post ); - } - - $error = new WP_Error( 'rest_post_invalid', __( 'Invalid post.' ), array( 'status' => 404 ) ); - return $error; - } - - /** - * Retrieves a single post's blocks. - * - * @since 1.1.0 - * - * @param WP_REST_Request $request Full details about the request. - * - * @return WP_REST_Response|WP_Error Response object on success, or WP_Error object on failure. - */ - public function get_item( $request ) { - $post = $this->get_post( $request['id'] ); - if ( is_wp_error( $post ) ) { - return $post; - } - - $data = $this->get_block_data_from_content( $post->post_content ); - - $response = rest_ensure_response( $data ); - - return $response; - } - - /** - * Determines the allowed query_vars for a get_items() response and prepares - * them for WP_Query. - * - * @since 1.1.0 - * - * @param array $prepared_args Optional. Prepared WP_Query arguments. Default empty array. - * @param WP_REST_Request $request Optional. Full details about the request. - * - * @return array Items query arguments. - */ - protected function prepare_items_query( $prepared_args = array(), $request = null ) { - $query_args = array(); - - foreach ( $prepared_args as $key => $value ) { - - /** - * Filters the query_vars used in get_items() for the constructed query. - * - * The dynamic portion of the hook name, `$key`, refers to the query_var key. - * - * @since 1.1.0 - * - * @param string $value The query_var value. - */ - $query_args[ $key ] = apply_filters( "rest_query_var-{$key}", $value ); - } - - return $query_args; - } - - /** - * Checks if a given post type can be viewed or managed. - * - * @since 1.1.0 - * - * @param object|string $post_type Post type name or object. - * - * @return bool Whether the post type is allowed in REST. - */ - protected function check_is_post_type_allowed( $post_type ) { - if ( ! is_object( $post_type ) ) { - $post_type = get_post_type_object( $post_type ); - } - - if ( ! empty( $post_type ) && ! empty( $post_type->show_in_rest ) ) { - return true; - } - - return false; - } - - /** - * Checks if a post's blocks can be read. - * - * @since 1.1.0 - * - * @param object $post Post object. - * - * @return bool Whether the post can be read. - */ - public function check_read_permission( $post ) { - $post_type = get_post_type_object( $post->post_type ); - if ( ! $this->check_is_post_type_allowed( $post_type ) ) { - return false; - } - - // Is the post readable? - if ( 'publish' === $post->post_status || current_user_can( $post_type->cap->read_post, $post->ID ) ) { - return true; - } - - $post_status_obj = get_post_status_object( $post->post_status ); - if ( $post_status_obj && $post_status_obj->public ) { - return true; - } - - return false; - } - - /** - * Retrieves the post's schema, conforming to JSON Schema. - * - * @since 1.1.0 - * - * @return array Item schema data. - */ - public function get_item_schema() { - - $schema = array( - '$schema' => 'http://json-schema.org/schema#', - 'title' => 'blocks', - 'type' => 'object', - - // Base properties for every Block. - 'properties' => array( - 'blockName' => array( - 'description' => __( "The name of the block." ), - 'type' => 'string', - 'context' => array( 'view' ), - 'readonly' => true, - ), - 'attrs' => array( - 'description' => __( 'The block data attributes.' ), - 'type' => 'array', - 'context' => array( 'view' ), - 'readonly' => true, - ), - 'rawContent' => array( - 'description' => __( 'The raw block content.' ), - 'type' => 'string', - 'context' => array( 'view' ), - 'arg_options' => array( - 'sanitize_callback' => array( $this, 'sanitize_slug' ), - ), - ), - ), - ); - - $post_type_obj = get_post_type_object( $this->post_type ); - - return $this->add_additional_fields_schema( $schema ); - } - - /** - * Retrieves the query params for the posts collection. - * - * @since 1.1.0 - * - * @return array Collection parameters. - */ - public function get_collection_params() { - $query_params = parent::get_collection_params(); - - - /** - * Filter collection parameters for the posts controller. - * - * The dynamic part of the filter `$this->post_type` refers to the post - * type slug for the controller. - * - * This filter registers the collection parameter, but does not map the - * collection parameter to an internal WP_Query parameter. Use the - * `rest_{$this->post_type}_query` filter to set WP_Query parameters. - * - * @since 1.1.0 - * - * @param array $query_params JSON Schema-formatted collection parameters. - * @param WP_Post_Type $post_type Post type object. - */ - return apply_filters( "rest_blocks_collection_params", $query_params, $post_type ); - } - - /** - * Extract the blocks from post content. - * - * @since 1.1.0 - * - * @param string The post content. - * - * @return array Array of block data. - */ - public function get_block_data_from_content( $content ) { - $registry = WP_Block_Type_Registry::get_instance(); - $blocks = gutenberg_parse_blocks( $content ); - $data = array(); - $data_pre = array(); - - // Loop thru the blocks, adding rendered content when available. - foreach ( $blocks as $block ) { - $block_name = isset( $block['blockName'] ) ? $block['blockName'] : null; - $attributes = is_array( $block['attrs'] ) ? $block['attrs'] : array(); - $raw_content = isset( $block['rawContent'] ) ? $block['rawContent'] : null; - if ( null !== $block_name ) { - $block_type = $registry->get_registered( $block_name ); - if ( null !== $block_type ) { - $block['renderedContent'] = $block_type->render( $attributes, $raw_content ); - } - $data_pre[] = $block; - } - } - - // Remap the block fields for the response. - foreach ( $data_pre as $block ) { - $data[] = array( - 'type' => $block['blockName'], - 'attributes' => $block['attrs'], - 'content' => $block['rawContent'], - 'rendered' => isset( $block['renderedContent'] ) ? $block['renderedContent'] : null, - ); - } - - return $data; - } -} diff --git a/lib/register.php b/lib/register.php index 1bba3782ea54b..86f0b44e20f47 100644 --- a/lib/register.php +++ b/lib/register.php @@ -76,13 +76,6 @@ function gutenberg_add_edit_links_filters() { } add_action( 'admin_init', 'gutenberg_add_edit_links_filters' ); -function load_blocks_rest_api() { - $controller = new WP_Gutenberg_Block_Controller; - $controller->register_routes(); -} -add_action( 'init', 'load_blocks_rest_api' ); - - /** * Registers additional links in the post/page screens to edit any post/page in * the Gutenberg editor. From 202390109a209d577870ea196dc10252d5c652d0 Mon Sep 17 00:00:00 2001 From: Adam Silverstein Date: Mon, 4 Sep 2017 16:01:50 -0400 Subject: [PATCH 12/44] Attach the block data to the rest api post response --- lib/blocks.php | 82 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 82 insertions(+) diff --git a/lib/blocks.php b/lib/blocks.php index dc329e94ef6f5..c3e9f5b6d60f3 100644 --- a/lib/blocks.php +++ b/lib/blocks.php @@ -93,3 +93,85 @@ function do_blocks( $content ) { return $content_after_blocks; } add_filter( 'the_content', 'do_blocks', 9 ); // BEFORE do_shortcode() and wpautop(). + + +/** + * Extract the blocks from post content for the REST API post response. + * + * @since 1.1.0 + * + * @param string The post content. + * + * @return array Array of block data. + */ +function get_block_data_for_api_from_post_content( $content ) { + $registry = WP_Block_Type_Registry::get_instance(); + $blocks = gutenberg_parse_blocks( $content ); + $data = array(); + $data_pre = array(); + + // Loop thru the blocks, adding rendered content when available. + foreach ( $blocks as $block ) { + $block_name = isset( $block['blockName'] ) ? $block['blockName'] : null; + $attributes = is_array( $block['attrs'] ) ? $block['attrs'] : array(); + $raw_content = isset( $block['rawContent'] ) ? $block['rawContent'] : null; + if ( null !== $block_name ) { + $block_type = $registry->get_registered( $block_name ); + if ( null !== $block_type ) { + $block['renderedContent'] = $block_type->render( $attributes, $raw_content ); + } + $data_pre[] = $block; + } + } + + // Remap the block fields for the response. + foreach ( $data_pre as $block ) { + $data[] = array( + 'type' => $block['blockName'], + 'attributes' => $block['attrs'], + 'content' => $block['rawContent'], + 'rendered' => isset( $block['renderedContent'] ) ? $block['renderedContent'] : null, + ); + } + + return $data; +} + +/** + * Attach a post's block data callback to the REST API response. + * + * @since 1.1.0 + * + * @param string | array $post_type Post type, or array of post types. + */ +function attach_block_response_callback( $post_type ) { + if ( empty( $post_type ) ) { + $post_type = 'post'; + } + if ( is_array( $post_type ) ) { + foreach ( $post_type as $type ) { + add_filter( 'rest_prepare_' . $type, 'attach_block_data_to_post_response', 10, 3 ); + } + } else { + add_filter( 'rest_prepare_' . $post_type, 'attach_block_data_to_post_response', 10, 3 ); + } +} +attach_block_response_callback( 'post' ); + +/** + * Attach a post's block data to the REST API response. + * + * @since 1.1.0 + * + * @param string $post_type Post type. + */ +function attach_block_data_to_post_response( $response, $post, $request ) { + if ( ! $post ) { + return $response; + } + $blocks = get_block_data_for_api_from_post_content( $post->post_content ); + if ( $blocks ) { + $response->data['content']['blocks'] = $blocks; + } + return $response; +} From b4a3a92f5aae7af50cd22d5eab8f57ecc6d5fd59 Mon Sep 17 00:00:00 2001 From: Adam Silverstein Date: Mon, 4 Sep 2017 16:07:48 -0400 Subject: [PATCH 13/44] remove unused $request parameter from callback --- lib/blocks.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/blocks.php b/lib/blocks.php index c3e9f5b6d60f3..227fefce9b816 100644 --- a/lib/blocks.php +++ b/lib/blocks.php @@ -150,10 +150,10 @@ function attach_block_response_callback( $post_type ) { } if ( is_array( $post_type ) ) { foreach ( $post_type as $type ) { - add_filter( 'rest_prepare_' . $type, 'attach_block_data_to_post_response', 10, 3 ); + add_filter( 'rest_prepare_' . $type, 'attach_block_data_to_post_response', 10, 2 ); } } else { - add_filter( 'rest_prepare_' . $post_type, 'attach_block_data_to_post_response', 10, 3 ); + add_filter( 'rest_prepare_' . $post_type, 'attach_block_data_to_post_response', 10, 2 ); } } attach_block_response_callback( 'post' ); @@ -165,7 +165,7 @@ function attach_block_response_callback( $post_type ) { * * @param string $post_type Post type. */ -function attach_block_data_to_post_response( $response, $post, $request ) { +function attach_block_data_to_post_response( $response, $post ) { if ( ! $post ) { return $response; } From 4c0093119ac66378ddfbd0a0b57c151ebdeb5d63 Mon Sep 17 00:00:00 2001 From: Adam Silverstein Date: Mon, 4 Sep 2017 16:09:13 -0400 Subject: [PATCH 14/44] whitespace cleanup --- lib/blocks.php | 1 - 1 file changed, 1 deletion(-) diff --git a/lib/blocks.php b/lib/blocks.php index 227fefce9b816..9bceb27ba5b72 100644 --- a/lib/blocks.php +++ b/lib/blocks.php @@ -94,7 +94,6 @@ function do_blocks( $content ) { } add_filter( 'the_content', 'do_blocks', 9 ); // BEFORE do_shortcode() and wpautop(). - /** * Extract the blocks from post content for the REST API post response. * From 5a17b339129fd509648dc56999ce4aa487366142 Mon Sep 17 00:00:00 2001 From: Adam Silverstein Date: Mon, 4 Sep 2017 16:11:20 -0400 Subject: [PATCH 15/44] remove extraneous extra loop --- lib/blocks.php | 20 ++++++++------------ 1 file changed, 8 insertions(+), 12 deletions(-) diff --git a/lib/blocks.php b/lib/blocks.php index 9bceb27ba5b72..4eee36004965f 100644 --- a/lib/blocks.php +++ b/lib/blocks.php @@ -107,7 +107,6 @@ function get_block_data_for_api_from_post_content( $content ) { $registry = WP_Block_Type_Registry::get_instance(); $blocks = gutenberg_parse_blocks( $content ); $data = array(); - $data_pre = array(); // Loop thru the blocks, adding rendered content when available. foreach ( $blocks as $block ) { @@ -119,18 +118,15 @@ function get_block_data_for_api_from_post_content( $content ) { if ( null !== $block_type ) { $block['renderedContent'] = $block_type->render( $attributes, $raw_content ); } - $data_pre[] = $block; - } - } - // Remap the block fields for the response. - foreach ( $data_pre as $block ) { - $data[] = array( - 'type' => $block['blockName'], - 'attributes' => $block['attrs'], - 'content' => $block['rawContent'], - 'rendered' => isset( $block['renderedContent'] ) ? $block['renderedContent'] : null, - ); + // Remap the block fields for the response. + $data[] = array( + 'type' => $block['blockName'], + 'attributes' => $block['attrs'], + 'content' => $block['rawContent'], + 'rendered' => isset( $block['renderedContent'] ) ? $block['renderedContent'] : null, + ); + } } return $data; From dff3f0b8f44102996d73cceed1222bf1cd873329 Mon Sep 17 00:00:00 2001 From: Adam Silverstein Date: Mon, 4 Sep 2017 16:28:51 -0400 Subject: [PATCH 16/44] Clean up data response --- lib/blocks.php | 21 +++++++++++++-------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/lib/blocks.php b/lib/blocks.php index 4eee36004965f..c1e2eede9320e 100644 --- a/lib/blocks.php +++ b/lib/blocks.php @@ -111,7 +111,7 @@ function get_block_data_for_api_from_post_content( $content ) { // Loop thru the blocks, adding rendered content when available. foreach ( $blocks as $block ) { $block_name = isset( $block['blockName'] ) ? $block['blockName'] : null; - $attributes = is_array( $block['attrs'] ) ? $block['attrs'] : array(); + $attributes = is_array( $block['attrs'] ) ? $block['attrs'] : null; $raw_content = isset( $block['rawContent'] ) ? $block['rawContent'] : null; if ( null !== $block_name ) { $block_type = $registry->get_registered( $block_name ); @@ -119,13 +119,18 @@ function get_block_data_for_api_from_post_content( $content ) { $block['renderedContent'] = $block_type->render( $attributes, $raw_content ); } - // Remap the block fields for the response. - $data[] = array( - 'type' => $block['blockName'], - 'attributes' => $block['attrs'], - 'content' => $block['rawContent'], - 'rendered' => isset( $block['renderedContent'] ) ? $block['renderedContent'] : null, - ); + // Set up the item data. + $item_data = array(); + $item_data['type'] = $block['blockName']; + if ( null !== $attributes ) { + $item_data['attributes'] = $block['attrs']; + } + $item_data['content'] = $block['rawContent']; + if ( null !== $raw_content ) { + $item_data['rendered'] = $raw_content ; + } + + $data[] = $item_data; } } From cfd2f5e1b8921a9f12c592a8f547b7802721b5f5 Mon Sep 17 00:00:00 2001 From: Adam Silverstein Date: Mon, 4 Sep 2017 16:32:15 -0400 Subject: [PATCH 17/44] fix rendered data setup --- lib/blocks.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/blocks.php b/lib/blocks.php index c1e2eede9320e..c4e6bff194743 100644 --- a/lib/blocks.php +++ b/lib/blocks.php @@ -126,8 +126,8 @@ function get_block_data_for_api_from_post_content( $content ) { $item_data['attributes'] = $block['attrs']; } $item_data['content'] = $block['rawContent']; - if ( null !== $raw_content ) { - $item_data['rendered'] = $raw_content ; + if ( null !== $block['renderedContent'] ) { + $item_data['rendered'] = $block['renderedContent'] ; } $data[] = $item_data; From 36f1000ffa6dab2edd7ee65bf58aa8906f117a85 Mon Sep 17 00:00:00 2001 From: Adam Silverstein Date: Thu, 7 Sep 2017 10:35:24 -0400 Subject: [PATCH 18/44] rename get_block_data_for_api_from_post_content -> get_block_data_for_api_from_post_content --- lib/blocks.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/blocks.php b/lib/blocks.php index c4e6bff194743..c9a670ffa1d95 100644 --- a/lib/blocks.php +++ b/lib/blocks.php @@ -103,7 +103,7 @@ function do_blocks( $content ) { * * @return array Array of block data. */ -function get_block_data_for_api_from_post_content( $content ) { +function gutenberg_add_blocks_to_post_resource( $content ) { $registry = WP_Block_Type_Registry::get_instance(); $blocks = gutenberg_parse_blocks( $content ); $data = array(); @@ -169,7 +169,7 @@ function attach_block_data_to_post_response( $response, $post ) { if ( ! $post ) { return $response; } - $blocks = get_block_data_for_api_from_post_content( $post->post_content ); + $blocks = gutenberg_add_blocks_to_post_resource( $post->post_content ); if ( $blocks ) { $response->data['content']['blocks'] = $blocks; } From d990979593eef33875cc321a3273f0b4db10bcf5 Mon Sep 17 00:00:00 2001 From: Adam Silverstein Date: Thu, 7 Sep 2017 10:39:09 -0400 Subject: [PATCH 19/44] =?UTF-8?q?Skip=20block=20if=20we=20didn=E2=80=99t?= =?UTF-8?q?=20get=20a=20valid=20block=20name.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/blocks.php | 34 ++++++++++++++++++---------------- 1 file changed, 18 insertions(+), 16 deletions(-) diff --git a/lib/blocks.php b/lib/blocks.php index c9a670ffa1d95..6de88c7ad0d8e 100644 --- a/lib/blocks.php +++ b/lib/blocks.php @@ -113,25 +113,27 @@ function gutenberg_add_blocks_to_post_resource( $content ) { $block_name = isset( $block['blockName'] ) ? $block['blockName'] : null; $attributes = is_array( $block['attrs'] ) ? $block['attrs'] : null; $raw_content = isset( $block['rawContent'] ) ? $block['rawContent'] : null; - if ( null !== $block_name ) { - $block_type = $registry->get_registered( $block_name ); - if ( null !== $block_type ) { - $block['renderedContent'] = $block_type->render( $attributes, $raw_content ); - } - // Set up the item data. - $item_data = array(); - $item_data['type'] = $block['blockName']; - if ( null !== $attributes ) { - $item_data['attributes'] = $block['attrs']; - } - $item_data['content'] = $block['rawContent']; - if ( null !== $block['renderedContent'] ) { - $item_data['rendered'] = $block['renderedContent'] ; - } + // Skip block if we didn’t get a valid block name. + if ( null === $block_name ) { + continue; + } + $block_type = $registry->get_registered( $block_name ); + if ( null !== $block_type ) { + $block['renderedContent'] = $block_type->render( $attributes, $raw_content ); + } - $data[] = $item_data; + // Set up and add the item data. + $item_data = array(); + $item_data['type'] = $block['blockName']; + if ( null !== $attributes ) { + $item_data['attributes'] = $block['attrs']; + } + $item_data['content'] = $block['rawContent']; + if ( null !== $block['renderedContent'] ) { + $item_data['rendered'] = $block['renderedContent'] ; } + $data[] = $item_data; } return $data; From 5937d1a51dbaec4facf81591e10bb6037e56c08e Mon Sep 17 00:00:00 2001 From: Adam Silverstein Date: Thu, 7 Sep 2017 10:43:18 -0400 Subject: [PATCH 20/44] use already set up $block_name --- lib/blocks.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/blocks.php b/lib/blocks.php index 6de88c7ad0d8e..836b622323265 100644 --- a/lib/blocks.php +++ b/lib/blocks.php @@ -125,7 +125,7 @@ function gutenberg_add_blocks_to_post_resource( $content ) { // Set up and add the item data. $item_data = array(); - $item_data['type'] = $block['blockName']; + $item_data['type'] = $block_name; if ( null !== $attributes ) { $item_data['attributes'] = $block['attrs']; } From 862bccc206c87695ca751059578a7d69ec5dfb89 Mon Sep 17 00:00:00 2001 From: Adam Silverstein Date: Thu, 7 Sep 2017 10:44:59 -0400 Subject: [PATCH 21/44] attributes: use $attributes and return even if null --- lib/blocks.php | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/lib/blocks.php b/lib/blocks.php index 836b622323265..19cddcb49039c 100644 --- a/lib/blocks.php +++ b/lib/blocks.php @@ -126,9 +126,7 @@ function gutenberg_add_blocks_to_post_resource( $content ) { // Set up and add the item data. $item_data = array(); $item_data['type'] = $block_name; - if ( null !== $attributes ) { - $item_data['attributes'] = $block['attrs']; - } + $item_data['attributes'] = $attributes; $item_data['content'] = $block['rawContent']; if ( null !== $block['renderedContent'] ) { $item_data['rendered'] = $block['renderedContent'] ; From a5756f5c287185d56f6f4cebb21ec95562781d3d Mon Sep 17 00:00:00 2001 From: Adam Silverstein Date: Thu, 7 Sep 2017 11:07:01 -0400 Subject: [PATCH 22/44] return `rendered`, even if null --- lib/blocks.php | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/lib/blocks.php b/lib/blocks.php index 19cddcb49039c..db73af9e88f39 100644 --- a/lib/blocks.php +++ b/lib/blocks.php @@ -118,6 +118,9 @@ function gutenberg_add_blocks_to_post_resource( $content ) { if ( null === $block_name ) { continue; } + + // Set up rendered content, if available. + $block['renderedContent'] = null; $block_type = $registry->get_registered( $block_name ); if ( null !== $block_type ) { $block['renderedContent'] = $block_type->render( $attributes, $raw_content ); @@ -128,9 +131,7 @@ function gutenberg_add_blocks_to_post_resource( $content ) { $item_data['type'] = $block_name; $item_data['attributes'] = $attributes; $item_data['content'] = $block['rawContent']; - if ( null !== $block['renderedContent'] ) { - $item_data['rendered'] = $block['renderedContent'] ; - } + $item_data['rendered'] = $block['renderedContent'] ; $data[] = $item_data; } From 8340341c7257a975d8895a3c85f78979d833280c Mon Sep 17 00:00:00 2001 From: Adam Silverstein Date: Thu, 7 Sep 2017 11:07:21 -0400 Subject: [PATCH 23/44] ensure $post_type IS an array --- lib/blocks.php | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/lib/blocks.php b/lib/blocks.php index db73af9e88f39..8d95d4a8f25be 100644 --- a/lib/blocks.php +++ b/lib/blocks.php @@ -149,12 +149,11 @@ function attach_block_response_callback( $post_type ) { if ( empty( $post_type ) ) { $post_type = 'post'; } - if ( is_array( $post_type ) ) { - foreach ( $post_type as $type ) { - add_filter( 'rest_prepare_' . $type, 'attach_block_data_to_post_response', 10, 2 ); - } - } else { - add_filter( 'rest_prepare_' . $post_type, 'attach_block_data_to_post_response', 10, 2 ); + if ( ! is_array( $post_type ) ) { + $post_type = array( $post_type ); + } + foreach ( $post_type as $type ) { + add_filter( 'rest_prepare_' . $type, 'attach_block_data_to_post_response', 10, 3 ); } } attach_block_response_callback( 'post' ); From 957dc7e5e8d2ee8dc8e459986b6c3df500ffde54 Mon Sep 17 00:00:00 2001 From: Adam Silverstein Date: Thu, 7 Sep 2017 11:11:18 -0400 Subject: [PATCH 24/44] Always attach blocks, even if null. --- lib/blocks.php | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/lib/blocks.php b/lib/blocks.php index 8d95d4a8f25be..b124357ffbb40 100644 --- a/lib/blocks.php +++ b/lib/blocks.php @@ -170,8 +170,6 @@ function attach_block_data_to_post_response( $response, $post ) { return $response; } $blocks = gutenberg_add_blocks_to_post_resource( $post->post_content ); - if ( $blocks ) { - $response->data['content']['blocks'] = $blocks; - } + $response->data['content']['blocks'] = $blocks; return $response; } From bc5f31e8710020e581537d4c86ee5ac400d3a75a Mon Sep 17 00:00:00 2001 From: Adam Silverstein Date: Thu, 7 Sep 2017 11:17:14 -0400 Subject: [PATCH 25/44] use get_data/set_data to adjust response --- lib/blocks.php | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/lib/blocks.php b/lib/blocks.php index b124357ffbb40..372121682adbb 100644 --- a/lib/blocks.php +++ b/lib/blocks.php @@ -170,6 +170,8 @@ function attach_block_data_to_post_response( $response, $post ) { return $response; } $blocks = gutenberg_add_blocks_to_post_resource( $post->post_content ); - $response->data['content']['blocks'] = $blocks; + $content = $response->get_data( 'content' ); + $content['blocks'] = $blocks; + $response->set_data( array( 'content'=> $content ) ); return $response; } From 5509c1b15863c364bfc074315a3fd90805688f36 Mon Sep 17 00:00:00 2001 From: Adam Silverstein Date: Thu, 7 Sep 2017 11:22:57 -0400 Subject: [PATCH 26/44] Code clean up, improve documentation blocks --- lib/blocks.php | 26 +++++++++++++++++--------- 1 file changed, 17 insertions(+), 9 deletions(-) diff --git a/lib/blocks.php b/lib/blocks.php index 372121682adbb..4073e24c9b179 100644 --- a/lib/blocks.php +++ b/lib/blocks.php @@ -73,8 +73,8 @@ function do_blocks( $content ) { $content_after_blocks = ''; foreach ( $blocks as $block ) { - $block_name = isset( $block['blockName'] ) ? $block['blockName'] : null; - $attributes = is_array( $block['attrs'] ) ? $block['attrs'] : array(); + $block_name = isset( $block['blockName'] ) ? $block['blockName'] : null; + $attributes = is_array( $block['attrs'] ) ? $block['attrs'] : array(); $raw_content = isset( $block['rawContent'] ) ? $block['rawContent'] : null; if ( $block_name ) { @@ -127,12 +127,12 @@ function gutenberg_add_blocks_to_post_resource( $content ) { } // Set up and add the item data. - $item_data = array(); - $item_data['type'] = $block_name; + $item_data = array(); + $item_data['type'] = $block_name; $item_data['attributes'] = $attributes; - $item_data['content'] = $block['rawContent']; - $item_data['rendered'] = $block['renderedContent'] ; - $data[] = $item_data; + $item_data['content'] = $block['rawContent']; + $item_data['rendered'] = $block['renderedContent'] ; + $data[] = $item_data; } return $data; @@ -163,15 +163,23 @@ function attach_block_response_callback( $post_type ) { * * @since 1.1.0 * - * @param string $post_type Post type. + * @param WP_REST_Response $response The response object. + * @param WP_Post $post The Post object. + * + * @return WP_REST_Response $response The filtered response object. */ function attach_block_data_to_post_response( $response, $post ) { if ( ! $post ) { return $response; } + + // Extract the block data from the post content. $blocks = gutenberg_add_blocks_to_post_resource( $post->post_content ); - $content = $response->get_data( 'content' ); + + // Add block data to the response as part of 'content'. + $content = $response->get_data( 'content' ); $content['blocks'] = $blocks; $response->set_data( array( 'content'=> $content ) ); + return $response; } From 822ffe276b0093711e77fbaa2c342fcfca298ab1 Mon Sep 17 00:00:00 2001 From: Adam Silverstein Date: Thu, 7 Sep 2017 13:45:20 -0400 Subject: [PATCH 27/44] Fixes for phpcs --- lib/blocks.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/blocks.php b/lib/blocks.php index 4073e24c9b179..9abb9191d97c0 100644 --- a/lib/blocks.php +++ b/lib/blocks.php @@ -92,14 +92,14 @@ function do_blocks( $content ) { return $content_after_blocks; } -add_filter( 'the_content', 'do_blocks', 9 ); // BEFORE do_shortcode() and wpautop(). +add_filter( 'the_content', 'do_blocks', 9 ); // BEFORE do_shortcode and wpautop. /** * Extract the blocks from post content for the REST API post response. * * @since 1.1.0 * - * @param string The post content. + * @param string $content The post content. * * @return array Array of block data. */ @@ -179,7 +179,7 @@ function attach_block_data_to_post_response( $response, $post ) { // Add block data to the response as part of 'content'. $content = $response->get_data( 'content' ); $content['blocks'] = $blocks; - $response->set_data( array( 'content'=> $content ) ); + $response->set_data( array( 'content' => $content ) ); return $response; } From 6cf7a5f2134dcf664360b88df94e7681ddd0fc4a Mon Sep 17 00:00:00 2001 From: Adam Silverstein Date: Fri, 8 Sep 2017 13:55:54 -0400 Subject: [PATCH 28/44] Clean up data setup --- lib/blocks.php | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/lib/blocks.php b/lib/blocks.php index 9abb9191d97c0..88117d08cf884 100644 --- a/lib/blocks.php +++ b/lib/blocks.php @@ -126,13 +126,13 @@ function gutenberg_add_blocks_to_post_resource( $content ) { $block['renderedContent'] = $block_type->render( $attributes, $raw_content ); } - // Set up and add the item data. - $item_data = array(); - $item_data['type'] = $block_name; - $item_data['attributes'] = $attributes; - $item_data['content'] = $block['rawContent']; - $item_data['rendered'] = $block['renderedContent'] ; - $data[] = $item_data; + // Add the item data. + $data[] = array( + 'type' => $block_name, + 'attributes' => $attributes, + 'content' => $block['rawContent'], + 'rendered' => $block['renderedContent'], + );; } return $data; From 23a556535bdd68519db0d95a72d03b9c8a8d1002 Mon Sep 17 00:00:00 2001 From: Adam Silverstein Date: Fri, 8 Sep 2017 13:59:53 -0400 Subject: [PATCH 29/44] revert unreleated changes --- lib/blocks.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/blocks.php b/lib/blocks.php index 88117d08cf884..279fcab776059 100644 --- a/lib/blocks.php +++ b/lib/blocks.php @@ -73,8 +73,8 @@ function do_blocks( $content ) { $content_after_blocks = ''; foreach ( $blocks as $block ) { - $block_name = isset( $block['blockName'] ) ? $block['blockName'] : null; - $attributes = is_array( $block['attrs'] ) ? $block['attrs'] : array(); + $block_name = isset( $block['blockName'] ) ? $block['blockName'] : null; + $attributes = is_array( $block['attrs'] ) ? $block['attrs'] : array(); $raw_content = isset( $block['rawContent'] ) ? $block['rawContent'] : null; if ( $block_name ) { @@ -92,7 +92,7 @@ function do_blocks( $content ) { return $content_after_blocks; } -add_filter( 'the_content', 'do_blocks', 9 ); // BEFORE do_shortcode and wpautop. +add_filter( 'the_content', 'do_blocks', 9 ); // BEFORE do_shortcode() and wpautop(). /** * Extract the blocks from post content for the REST API post response. From 36f5df1618780cb12d45599fd4ddddd6ba7edbd7 Mon Sep 17 00:00:00 2001 From: Adam Silverstein Date: Sun, 10 Sep 2017 09:38:03 -0400 Subject: [PATCH 30/44] Add tests for the rest api block data in posts->content --- phpunit/class-rest-blocks-api-test.php | 101 +++++++++++++++++++++++++ 1 file changed, 101 insertions(+) create mode 100644 phpunit/class-rest-blocks-api-test.php diff --git a/phpunit/class-rest-blocks-api-test.php b/phpunit/class-rest-blocks-api-test.php new file mode 100644 index 0000000000000..972485fb9bb3a --- /dev/null +++ b/phpunit/class-rest-blocks-api-test.php @@ -0,0 +1,101 @@ + 'post', + 'post_status' => 'publish', + 'post_name' => 'gutenberg-block-test', + 'post_title' => 'My cool block', + 'post_content' => self::$demo_post_content, + ) ); + + self::$editor_id = $factory->user->create( array( + 'role' => 'editor', + ) ); + } + + /** + * Delete our fake data after our tests run. + */ + public static function wpTearDownAfterClass() { + wp_delete_post( self::$test_block_post_id ); + + self::delete_user( self::$editor_id ); + } + + /** + * Check that we can GET blocks from a post request. + */ + public function test_get_items() { + wp_set_current_user( self::$editor_id ); + + $request = new WP_REST_Request( 'GET', '/wp/v2/posts/' . self::$test_block_post_id ); + $this->assertNotEquals( null, $request ); + + $response = self::$server->dispatch( $request ); + + $this->assertEquals( 200, $response->get_status() ); + $response->get_data(); + + $blocks = isset( $response->data['content']['blocks'] ) ? $response->data['content']['blocks'] : false; + + $first_block_url_attribute = wp_unslash( $blocks[0]['attributes']['url'] ); + $first_block_type = wp_unslash( $blocks[0]['type'] ); + + $this->assertEquals( count( $blocks ), 43, 'The demo post content api call should contain 43 blocks.' ); + $this->assertEquals( 'https://cldup.com/GCwahb3aOb.jpg', $first_block_url_attribute, 'Block attributes should be returned correctly.' ); + $this->assertEquals( 'core/cover-image', $first_block_type, 'Block type should be returned correctly.' ); + } + +} From 37513d1466f6e606c08835e6bb7f6f1e787642e7 Mon Sep 17 00:00:00 2001 From: Adam Silverstein Date: Sun, 10 Sep 2017 09:53:27 -0400 Subject: [PATCH 31/44] attach block data to pages and posts --- lib/blocks.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/blocks.php b/lib/blocks.php index 279fcab776059..6e7ff4d723fe5 100644 --- a/lib/blocks.php +++ b/lib/blocks.php @@ -145,9 +145,9 @@ function gutenberg_add_blocks_to_post_resource( $content ) { * * @param string | array $post_type Post type, or array of post types. */ -function attach_block_response_callback( $post_type ) { if ( empty( $post_type ) ) { $post_type = 'post'; +function gutenberg_attach_block_response_callback( $post_types ) { } if ( ! is_array( $post_type ) ) { $post_type = array( $post_type ); @@ -156,7 +156,7 @@ function attach_block_response_callback( $post_type ) { add_filter( 'rest_prepare_' . $type, 'attach_block_data_to_post_response', 10, 3 ); } } -attach_block_response_callback( 'post' ); +gutenberg_attach_block_response_callback( array( 'post', 'page' ) ); /** * Attach a post's block data to the REST API response. From daece40ed35a192bfbb8b4cf238b480d8c658c51 Mon Sep 17 00:00:00 2001 From: Adam Silverstein Date: Sun, 10 Sep 2017 09:53:56 -0400 Subject: [PATCH 32/44] Add a filter for whether to add block data to api response: gutenberg_add_blocks_to_rest_for_post_type --- lib/blocks.php | 28 ++++++++++++++++++++-------- 1 file changed, 20 insertions(+), 8 deletions(-) diff --git a/lib/blocks.php b/lib/blocks.php index 6e7ff4d723fe5..f4b03b0d518b6 100644 --- a/lib/blocks.php +++ b/lib/blocks.php @@ -143,17 +143,29 @@ function gutenberg_add_blocks_to_post_resource( $content ) { * * @since 1.1.0 * - * @param string | array $post_type Post type, or array of post types. + * @param string | array $post_types Post type, or array of post types. */ - if ( empty( $post_type ) ) { - $post_type = 'post'; function gutenberg_attach_block_response_callback( $post_types ) { + if ( empty( $post_types ) ) { + $post_types = 'post'; } - if ( ! is_array( $post_type ) ) { - $post_type = array( $post_type ); + if ( ! is_array( $post_types ) ) { + $post_types = array( $post_types ); } - foreach ( $post_type as $type ) { - add_filter( 'rest_prepare_' . $type, 'attach_block_data_to_post_response', 10, 3 ); + foreach ( $post_types as $post_type ) { + + /** + * Filter whether a post type has its blocks data added the REST API response content. + * + * @since 1.1.0 + * + * @param bool $blocks_show_in_rest Whether to show blocks in the REST API response. + * @param string $post_type The post type. + * + */ + if ( apply_filters( "gutenberg_add_blocks_to_rest_for_post_type", true, $post_type ) ) { + add_filter( 'rest_prepare_' . $post_type, 'gutenberg_extract_blocks_from_post_content', 10, 3 ); + } } } gutenberg_attach_block_response_callback( array( 'post', 'page' ) ); @@ -168,7 +180,7 @@ function gutenberg_attach_block_response_callback( $post_types ) { * * @return WP_REST_Response $response The filtered response object. */ -function attach_block_data_to_post_response( $response, $post ) { +function gutenberg_extract_blocks_from_post_content( $response, $post ) { if ( ! $post ) { return $response; } From 1eb5331d7a7929cbde4ca3d0727521a62342beb8 Mon Sep 17 00:00:00 2001 From: Adam Silverstein Date: Sun, 10 Sep 2017 10:09:39 -0400 Subject: [PATCH 33/44] fixes for phpcs --- lib/blocks.php | 5 ++--- phpunit/class-rest-blocks-api-test.php | 12 +++--------- 2 files changed, 5 insertions(+), 12 deletions(-) diff --git a/lib/blocks.php b/lib/blocks.php index f4b03b0d518b6..7cc0aff4717ce 100644 --- a/lib/blocks.php +++ b/lib/blocks.php @@ -132,7 +132,7 @@ function gutenberg_add_blocks_to_post_resource( $content ) { 'attributes' => $attributes, 'content' => $block['rawContent'], 'rendered' => $block['renderedContent'], - );; + ); } return $data; @@ -161,9 +161,8 @@ function gutenberg_attach_block_response_callback( $post_types ) { * * @param bool $blocks_show_in_rest Whether to show blocks in the REST API response. * @param string $post_type The post type. - * */ - if ( apply_filters( "gutenberg_add_blocks_to_rest_for_post_type", true, $post_type ) ) { + if ( apply_filters( 'gutenberg_add_blocks_to_rest_for_post_type', true, $post_type ) ) { add_filter( 'rest_prepare_' . $post_type, 'gutenberg_extract_blocks_from_post_content', 10, 3 ); } } diff --git a/phpunit/class-rest-blocks-api-test.php b/phpunit/class-rest-blocks-api-test.php index 972485fb9bb3a..1a15970cd1197 100644 --- a/phpunit/class-rest-blocks-api-test.php +++ b/phpunit/class-rest-blocks-api-test.php @@ -10,13 +10,6 @@ */ class WP_REST_BlockAPI_Test extends WP_UnitTestCase { - /** - * The WP Rest server. - * - * @var int - */ - protected static $server; - /** * Our fake reusable block's post ID. * @@ -45,7 +38,7 @@ class WP_REST_BlockAPI_Test extends WP_UnitTestCase { */ public static function wpSetUpBeforeClass( $factory ) { global $wp_rest_server; - self::$server = $wp_rest_server = new \WP_REST_Server; + $wp_rest_server = new WP_REST_Server; do_action( 'rest_api_init' ); self::$demo_post_content = file_get_contents( @@ -78,12 +71,13 @@ public static function wpTearDownAfterClass() { * Check that we can GET blocks from a post request. */ public function test_get_items() { + global $wp_rest_server; wp_set_current_user( self::$editor_id ); $request = new WP_REST_Request( 'GET', '/wp/v2/posts/' . self::$test_block_post_id ); $this->assertNotEquals( null, $request ); - $response = self::$server->dispatch( $request ); + $response = $wp_rest_server->dispatch( $request ); $this->assertEquals( 200, $response->get_status() ); $response->get_data(); From d395197eaaf381d285c7afdc540e384712b71ba0 Mon Sep 17 00:00:00 2001 From: Adam Silverstein Date: Thu, 28 Sep 2017 14:31:08 -0400 Subject: [PATCH 34/44] Fix data return setup for blocks data --- lib/blocks.php | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/lib/blocks.php b/lib/blocks.php index 7cc0aff4717ce..1eaa659684f2d 100644 --- a/lib/blocks.php +++ b/lib/blocks.php @@ -186,11 +186,7 @@ function gutenberg_extract_blocks_from_post_content( $response, $post ) { // Extract the block data from the post content. $blocks = gutenberg_add_blocks_to_post_resource( $post->post_content ); - - // Add block data to the response as part of 'content'. - $content = $response->get_data( 'content' ); - $content['blocks'] = $blocks; - $response->set_data( array( 'content' => $content ) ); + $response->data['content']['blocks'] = $blocks; return $response; } From f0355f093bb6661cbba1be89e2aa9bf26e7daf07 Mon Sep 17 00:00:00 2001 From: Adam Silverstein Date: Tue, 2 Jan 2018 14:32:43 -0500 Subject: [PATCH 35/44] restore api code after merge --- lib/blocks.php | 53 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 53 insertions(+) diff --git a/lib/blocks.php b/lib/blocks.php index 863e857d2429c..413f9c2c4c198 100644 --- a/lib/blocks.php +++ b/lib/blocks.php @@ -256,3 +256,56 @@ function gutenberg_wpautop_insert_post_data( $data ) { return $data; } add_filter( 'wp_insert_post_data', 'gutenberg_wpautop_insert_post_data' ); + +/** + * Attach a post's block data callback to the REST API response. + * + * @since 1.1.0 + * + * @param string | array $post_types Post type, or array of post types. + */ +function gutenberg_attach_block_response_callback( $post_types ) { + if ( empty( $post_types ) ) { + $post_types = 'post'; + } + if ( ! is_array( $post_types ) ) { + $post_types = array( $post_types ); + } + foreach ( $post_types as $post_type ) { + + /** + * Filter whether a post type has its blocks data added the REST API response content. + * + * @since 1.1.0 + * + * @param bool $blocks_show_in_rest Whether to show blocks in the REST API response. + * @param string $post_type The post type. + */ + if ( apply_filters( 'gutenberg_add_blocks_to_rest_for_post_type', true, $post_type ) ) { + add_filter( 'rest_prepare_' . $post_type, 'gutenberg_extract_blocks_from_post_content', 10, 3 ); + } + } +} +gutenberg_attach_block_response_callback( array( 'post', 'page' ) ); + +/** + * Attach a post's block data to the REST API response. + * + * @since 1.1.0 + * + * @param WP_REST_Response $response The response object. + * @param WP_Post $post The Post object. + * + * @return WP_REST_Response $response The filtered response object. + */ +function gutenberg_extract_blocks_from_post_content( $response, $post ) { + if ( ! $post ) { + return $response; + } + + // Extract the block data from the post content. + $blocks = gutenberg_add_blocks_to_post_resource( $post->post_content ); + $response->data['content']['blocks'] = $blocks; + + return $response; +} From 55732b8bc5a56959abb5215bb3df50ac4d4cd4eb Mon Sep 17 00:00:00 2001 From: Adam Silverstein Date: Tue, 2 Jan 2018 14:41:08 -0500 Subject: [PATCH 36/44] readd gutenberg_add_blocks_to_post_resource after merge --- lib/blocks.php | 44 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 44 insertions(+) diff --git a/lib/blocks.php b/lib/blocks.php index 413f9c2c4c198..31138e77414ae 100644 --- a/lib/blocks.php +++ b/lib/blocks.php @@ -257,6 +257,50 @@ function gutenberg_wpautop_insert_post_data( $data ) { } add_filter( 'wp_insert_post_data', 'gutenberg_wpautop_insert_post_data' ); +/** + * Extract the blocks from post content for the REST API post response. + * + * @since 1.1.0 + * + * @param string $content The post content. + * + * @return array Array of block data. + */ +function gutenberg_add_blocks_to_post_resource( $content ) { + $registry = WP_Block_Type_Registry::get_instance(); + $blocks = gutenberg_parse_blocks( $content ); + $data = array(); + + // Loop thru the blocks, adding rendered content when available. + foreach ( $blocks as $block ) { + $block_name = isset( $block['blockName'] ) ? $block['blockName'] : null; + $attributes = is_array( $block['attrs'] ) ? $block['attrs'] : null; + $raw_content = isset( $block['rawContent'] ) ? $block['rawContent'] : null; + + // Skip block if we didn’t get a valid block name. + if ( null === $block_name ) { + continue; + } + + // Set up rendered content, if available. + $block['renderedContent'] = null; + $block_type = $registry->get_registered( $block_name ); + if ( null !== $block_type ) { + $block['renderedContent'] = $block_type->render( $attributes, $raw_content ); + } + + // Add the item data. + $data[] = array( + 'type' => $block_name, + 'attributes' => $attributes, + 'content' => $raw_content, + 'rendered' => $block['renderedContent'], + ); + } + + return $data; +} + /** * Attach a post's block data callback to the REST API response. * From 5e4db00b06b0d681a62a5a0c410b6a95cd521e6a Mon Sep 17 00:00:00 2001 From: Adam Silverstein Date: Tue, 2 Jan 2018 14:56:53 -0500 Subject: [PATCH 37/44] alignment for phpcs --- lib/blocks.php | 4 ++-- phpunit/class-rest-blocks-api-test.php | 10 +++++----- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/lib/blocks.php b/lib/blocks.php index 31138e77414ae..6d7dba8cc4a14 100644 --- a/lib/blocks.php +++ b/lib/blocks.php @@ -284,7 +284,7 @@ function gutenberg_add_blocks_to_post_resource( $content ) { // Set up rendered content, if available. $block['renderedContent'] = null; - $block_type = $registry->get_registered( $block_name ); + $block_type = $registry->get_registered( $block_name ); if ( null !== $block_type ) { $block['renderedContent'] = $block_type->render( $attributes, $raw_content ); } @@ -348,7 +348,7 @@ function gutenberg_extract_blocks_from_post_content( $response, $post ) { } // Extract the block data from the post content. - $blocks = gutenberg_add_blocks_to_post_resource( $post->post_content ); + $blocks = gutenberg_add_blocks_to_post_resource( $post->post_content ); $response->data['content']['blocks'] = $blocks; return $response; diff --git a/phpunit/class-rest-blocks-api-test.php b/phpunit/class-rest-blocks-api-test.php index 1a15970cd1197..62651cd84807b 100644 --- a/phpunit/class-rest-blocks-api-test.php +++ b/phpunit/class-rest-blocks-api-test.php @@ -46,10 +46,10 @@ public static function wpSetUpBeforeClass( $factory ) { ); self::$test_block_post_id = wp_insert_post( array( - 'post_type' => 'post', - 'post_status' => 'publish', - 'post_name' => 'gutenberg-block-test', - 'post_title' => 'My cool block', + 'post_type' => 'post', + 'post_status' => 'publish', + 'post_name' => 'gutenberg-block-test', + 'post_title' => 'My cool block', 'post_content' => self::$demo_post_content, ) ); @@ -85,7 +85,7 @@ public function test_get_items() { $blocks = isset( $response->data['content']['blocks'] ) ? $response->data['content']['blocks'] : false; $first_block_url_attribute = wp_unslash( $blocks[0]['attributes']['url'] ); - $first_block_type = wp_unslash( $blocks[0]['type'] ); + $first_block_type = wp_unslash( $blocks[0]['type'] ); $this->assertEquals( count( $blocks ), 43, 'The demo post content api call should contain 43 blocks.' ); $this->assertEquals( 'https://cldup.com/GCwahb3aOb.jpg', $first_block_url_attribute, 'Block attributes should be returned correctly.' ); From bd638d1cc576cb6f6e78b20d2634472581b4fc8d Mon Sep 17 00:00:00 2001 From: Adam Silverstein Date: Tue, 2 Jan 2018 16:48:21 -0500 Subject: [PATCH 38/44] update tests for new demo data --- phpunit/class-rest-blocks-api-test.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/phpunit/class-rest-blocks-api-test.php b/phpunit/class-rest-blocks-api-test.php index 62651cd84807b..cb0e1c13ac2f3 100644 --- a/phpunit/class-rest-blocks-api-test.php +++ b/phpunit/class-rest-blocks-api-test.php @@ -87,8 +87,8 @@ public function test_get_items() { $first_block_url_attribute = wp_unslash( $blocks[0]['attributes']['url'] ); $first_block_type = wp_unslash( $blocks[0]['type'] ); - $this->assertEquals( count( $blocks ), 43, 'The demo post content api call should contain 43 blocks.' ); - $this->assertEquals( 'https://cldup.com/GCwahb3aOb.jpg', $first_block_url_attribute, 'Block attributes should be returned correctly.' ); + $this->assertEquals( count( $blocks ), 36, 'The demo post content api call should contain 36 blocks.' ); + $this->assertEquals( 'https://cldup.com/Fz-ASbo2s3.jpg', $first_block_url_attribute, 'Block attributes should be returned correctly.' ); $this->assertEquals( 'core/cover-image', $first_block_type, 'Block type should be returned correctly.' ); } From 0098344237e1a6591acada8dd7606b2c6765205c Mon Sep 17 00:00:00 2001 From: Adam Silverstein Date: Tue, 2 Jan 2018 17:09:35 -0500 Subject: [PATCH 39/44] fix test_delete_item expected --- phpunit/class-rest-blocks-controller-test.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/phpunit/class-rest-blocks-controller-test.php b/phpunit/class-rest-blocks-controller-test.php index bf317ce670bd9..9f278859977eb 100644 --- a/phpunit/class-rest-blocks-controller-test.php +++ b/phpunit/class-rest-blocks-controller-test.php @@ -174,7 +174,7 @@ public function test_delete_item() { array( 'deleted' => true, 'previous' => array( - 'id' => 8, + 'id' => 9, 'title' => 'My cool block', 'content' => '

Hello!

', ), From 63de8afed663e57ad81667447e3dc593ea7d971e Mon Sep 17 00:00:00 2001 From: Adam Silverstein Date: Thu, 11 Apr 2019 11:27:14 -0600 Subject: [PATCH 40/44] restore after merge conflict resolution --- lib/blocks.php | 94 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 94 insertions(+) diff --git a/lib/blocks.php b/lib/blocks.php index fc3adb8a09efa..e9386ec7c3558 100644 --- a/lib/blocks.php +++ b/lib/blocks.php @@ -45,3 +45,97 @@ function gutenberg_reregister_core_block_types() { } } add_action( 'init', 'gutenberg_reregister_core_block_types' ); + +/** + * Extract the blocks from post content for the REST API post response. + * + * @since 1.1.0 + * + * @param string $content The post content. + * + * @return array Array of block data. + */ +function gutenberg_add_blocks_to_post_resource( $content ) { + $registry = WP_Block_Type_Registry::get_instance(); + $blocks = gutenberg_parse_blocks( $content ); + $data = array(); + + // Loop thru the blocks, adding rendered content when available. + foreach ( $blocks as $block ) { + $block_name = isset( $block['blockName'] ) ? $block['blockName'] : null; + $attributes = is_array( $block['attrs'] ) ? $block['attrs'] : null; + $raw_content = isset( $block['rawContent'] ) ? $block['rawContent'] : null; + + // Skip block if we didn’t get a valid block name. + if ( null === $block_name ) { + continue; + } + + // Set up rendered content, if available. + $block['renderedContent'] = null; + $block_type = $registry->get_registered( $block_name ); + if ( null !== $block_type ) { + $block['renderedContent'] = $block_type->render( $attributes, $raw_content ); + } + + // Add the item data. + $data[] = array( + 'type' => $block_name, + 'attributes' => $attributes, + 'content' => $raw_content, + 'rendered' => $block['renderedContent'], + ); + } + + return $data; +} + +/** + * Attach a post's block data callback to the REST API response. + * + * @since 1.1.0 + * + * @param string | array $post_types Post type, or array of post types. + */ +function gutenberg_attach_block_response_callback( $post_types ) { + if ( ! is_array( $post_types ) ) { + $post_types = array( $post_types ); + } + foreach ( $post_types as $post_type ) { + + /** + * Filter whether a post type has its blocks data added the REST API response content. + * + * @since 1.1.0 + * + * @param bool $blocks_show_in_rest Whether to show blocks in the REST API response. + * @param string $post_type The post type. + */ + if ( apply_filters( 'gutenberg_add_blocks_to_rest_for_post_type', true, $post_type ) ) { + add_filter( 'rest_prepare_' . $post_type, 'gutenberg_extract_blocks_from_post_content', 10, 3 ); + } + } +} +gutenberg_attach_block_response_callback( array( 'post', 'page' ) ); + +/** + * Attach a post's block data to the REST API response. + * + * @since 1.1.0 + * + * @param WP_REST_Response $response The response object. + * @param WP_Post $post The Post object. + * + * @return WP_REST_Response $response The filtered response object. + */ +function gutenberg_extract_blocks_from_post_content( $response, $post ) { + if ( ! $post ) { + return $response; + } + + // Extract the block data from the post content. + $blocks = gutenberg_add_blocks_to_post_resource( $post->post_content ); + $response->data['content']['blocks'] = $blocks; + + return $response; +} From 131dd902f0b43009c59c4cc4a1ebdc9a2bdb8548 Mon Sep 17 00:00:00 2001 From: Adam Silverstein Date: Thu, 11 Apr 2019 11:34:06 -0600 Subject: [PATCH 41/44] Update parser use --- lib/blocks.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/blocks.php b/lib/blocks.php index e9386ec7c3558..cd739e4e6e1ff 100644 --- a/lib/blocks.php +++ b/lib/blocks.php @@ -57,7 +57,8 @@ function gutenberg_reregister_core_block_types() { */ function gutenberg_add_blocks_to_post_resource( $content ) { $registry = WP_Block_Type_Registry::get_instance(); - $blocks = gutenberg_parse_blocks( $content ); + $parser = new WP_Block_Parser(); + $blocks = $parser->parse( $content ); $data = array(); // Loop thru the blocks, adding rendered content when available. From 546fb81ee4d51453c6fee3acc8e0a0dd39a9bbfe Mon Sep 17 00:00:00 2001 From: Adam Silverstein Date: Thu, 5 Nov 2020 13:54:52 -0700 Subject: [PATCH 42/44] Cleanup for PHPCS. --- phpunit/class-rest-blocks-api-test.php | 26 +++++++++++-------- phpunit/class-rest-blocks-controller-test.php | 15 +++++++---- 2 files changed, 25 insertions(+), 16 deletions(-) diff --git a/phpunit/class-rest-blocks-api-test.php b/phpunit/class-rest-blocks-api-test.php index cb0e1c13ac2f3..64c18df1b8e16 100644 --- a/phpunit/class-rest-blocks-api-test.php +++ b/phpunit/class-rest-blocks-api-test.php @@ -45,17 +45,21 @@ public static function wpSetUpBeforeClass( $factory ) { dirname( __FILE__ ) . '/fixtures/long-content.html' ); - self::$test_block_post_id = wp_insert_post( array( - 'post_type' => 'post', - 'post_status' => 'publish', - 'post_name' => 'gutenberg-block-test', - 'post_title' => 'My cool block', - 'post_content' => self::$demo_post_content, - ) ); - - self::$editor_id = $factory->user->create( array( - 'role' => 'editor', - ) ); + self::$test_block_post_id = wp_insert_post( + array( + 'post_type' => 'post', + 'post_status' => 'publish', + 'post_name' => 'gutenberg-block-test', + 'post_title' => 'My cool block', + 'post_content' => self::$demo_post_content, + ) + ); + + self::$editor_id = $factory->user->create( + array( + 'role' => 'editor', + ) + ); } /** diff --git a/phpunit/class-rest-blocks-controller-test.php b/phpunit/class-rest-blocks-controller-test.php index 9f278859977eb..c5f31de010ceb 100644 --- a/phpunit/class-rest-blocks-controller-test.php +++ b/phpunit/class-rest-blocks-controller-test.php @@ -84,7 +84,8 @@ public function test_get_items() { 'title' => 'My cool block', 'content' => '

Hello!

', ), - ), $response->get_data() + ), + $response->get_data() ); } @@ -103,7 +104,8 @@ public function test_get_item() { 'id' => self::$post_id, 'title' => 'My cool block', 'content' => '

Hello!

', - ), $response->get_data() + ), + $response->get_data() ); } @@ -129,7 +131,8 @@ public function test_create_item() { 'id' => self::$post_id, 'title' => 'New cool block', 'content' => '

Wow!

', - ), $response->get_data() + ), + $response->get_data() ); } @@ -155,7 +158,8 @@ public function test_update_item() { 'id' => self::$post_id, 'title' => 'Updated cool block', 'content' => '

Nice!

', - ), $response->get_data() + ), + $response->get_data() ); } @@ -178,7 +182,8 @@ public function test_delete_item() { 'title' => 'My cool block', 'content' => '

Hello!

', ), - ), $response->get_data() + ), + $response->get_data() ); } From 812af84a7b1bf4f2ccd40955bf2a2dd83290fb62 Mon Sep 17 00:00:00 2001 From: Adam Silverstein Date: Thu, 5 Nov 2020 14:32:21 -0700 Subject: [PATCH 43/44] Simplify data construction approach. --- lib/blocks.php | 28 +++++++--------------------- 1 file changed, 7 insertions(+), 21 deletions(-) diff --git a/lib/blocks.php b/lib/blocks.php index 0f137b19ab254..4a542cd7d30b7 100644 --- a/lib/blocks.php +++ b/lib/blocks.php @@ -251,31 +251,17 @@ function gutenberg_add_blocks_to_post_resource( $content ) { $blocks = $parser->parse( $content ); $data = array(); + $attributes = array( 'blockName', 'attrs', 'innerHTML', 'innerBlocks', 'innerContent' ); + // Loop thru the blocks, adding rendered content when available. foreach ( $blocks as $block ) { - $block_name = isset( $block['blockName'] ) ? $block['blockName'] : null; - $attributes = is_array( $block['attrs'] ) ? $block['attrs'] : null; - $raw_content = isset( $block['rawContent'] ) ? $block['rawContent'] : null; - - // Skip block if we didn’t get a valid block name. - if ( null === $block_name ) { - continue; - } - - // Set up rendered content, if available. - $block['renderedContent'] = null; - $block_type = $registry->get_registered( $block_name ); - if ( null !== $block_type ) { - $block['renderedContent'] = $block_type->render( $attributes, $raw_content ); + foreach( $attributes as $attribute ) { + if ( isset( $block[ $attribute ] ) ) { + $item[ $attribute ] = $block[ $attribute ]; + } } - // Add the item data. - $data[] = array( - 'type' => $block_name, - 'attributes' => $attributes, - 'content' => $raw_content, - 'rendered' => $block['renderedContent'], - ); + $data[] = $item; } return $data; From 8258cb6585f4f18c7fd16feb698bcfafdd115168 Mon Sep 17 00:00:00 2001 From: Adam Silverstein Date: Thu, 5 Nov 2020 15:17:24 -0700 Subject: [PATCH 44/44] Remove unrelated changes. --- phpunit/class-rest-blocks-api-test.php | 99 -------- phpunit/class-rest-blocks-controller-test.php | 211 ------------------ 2 files changed, 310 deletions(-) delete mode 100644 phpunit/class-rest-blocks-api-test.php delete mode 100644 phpunit/class-rest-blocks-controller-test.php diff --git a/phpunit/class-rest-blocks-api-test.php b/phpunit/class-rest-blocks-api-test.php deleted file mode 100644 index 64c18df1b8e16..0000000000000 --- a/phpunit/class-rest-blocks-api-test.php +++ /dev/null @@ -1,99 +0,0 @@ - 'post', - 'post_status' => 'publish', - 'post_name' => 'gutenberg-block-test', - 'post_title' => 'My cool block', - 'post_content' => self::$demo_post_content, - ) - ); - - self::$editor_id = $factory->user->create( - array( - 'role' => 'editor', - ) - ); - } - - /** - * Delete our fake data after our tests run. - */ - public static function wpTearDownAfterClass() { - wp_delete_post( self::$test_block_post_id ); - - self::delete_user( self::$editor_id ); - } - - /** - * Check that we can GET blocks from a post request. - */ - public function test_get_items() { - global $wp_rest_server; - wp_set_current_user( self::$editor_id ); - - $request = new WP_REST_Request( 'GET', '/wp/v2/posts/' . self::$test_block_post_id ); - $this->assertNotEquals( null, $request ); - - $response = $wp_rest_server->dispatch( $request ); - - $this->assertEquals( 200, $response->get_status() ); - $response->get_data(); - - $blocks = isset( $response->data['content']['blocks'] ) ? $response->data['content']['blocks'] : false; - - $first_block_url_attribute = wp_unslash( $blocks[0]['attributes']['url'] ); - $first_block_type = wp_unslash( $blocks[0]['type'] ); - - $this->assertEquals( count( $blocks ), 36, 'The demo post content api call should contain 36 blocks.' ); - $this->assertEquals( 'https://cldup.com/Fz-ASbo2s3.jpg', $first_block_url_attribute, 'Block attributes should be returned correctly.' ); - $this->assertEquals( 'core/cover-image', $first_block_type, 'Block type should be returned correctly.' ); - } - -} diff --git a/phpunit/class-rest-blocks-controller-test.php b/phpunit/class-rest-blocks-controller-test.php deleted file mode 100644 index c5f31de010ceb..0000000000000 --- a/phpunit/class-rest-blocks-controller-test.php +++ /dev/null @@ -1,211 +0,0 @@ - 'wp_block', - 'post_status' => 'publish', - 'post_title' => 'My cool block', - 'post_content' => '

Hello!

', - ) - ); - - self::$user_id = $factory->user->create( - array( - 'role' => 'editor', - ) - ); - } - - /** - * Delete our fake data after our tests run. - */ - public static function wpTearDownAfterClass() { - wp_delete_post( self::$post_id ); - - self::delete_user( self::$user_id ); - } - - /** - * Check that our routes get set up properly. - */ - public function test_register_routes() { - $routes = $this->server->get_routes(); - - $this->assertArrayHasKey( '/wp/v2/blocks', $routes ); - $this->assertCount( 2, $routes['/wp/v2/blocks'] ); - $this->assertArrayHasKey( '/wp/v2/blocks/(?P[\d]+)', $routes ); - $this->assertCount( 3, $routes['/wp/v2/blocks/(?P[\d]+)'] ); - } - - /** - * Check that we can GET a collection of blocks. - */ - public function test_get_items() { - wp_set_current_user( self::$user_id ); - - $request = new WP_REST_Request( 'GET', '/wp/v2/blocks' ); - $response = $this->server->dispatch( $request ); - - $this->assertEquals( 200, $response->get_status() ); - $this->assertEquals( - array( - array( - 'id' => self::$post_id, - 'title' => 'My cool block', - 'content' => '

Hello!

', - ), - ), - $response->get_data() - ); - } - - /** - * Check that we can GET a single block. - */ - public function test_get_item() { - wp_set_current_user( self::$user_id ); - - $request = new WP_REST_Request( 'GET', '/wp/v2/blocks/' . self::$post_id ); - $response = $this->server->dispatch( $request ); - - $this->assertEquals( 200, $response->get_status() ); - $this->assertEquals( - array( - 'id' => self::$post_id, - 'title' => 'My cool block', - 'content' => '

Hello!

', - ), - $response->get_data() - ); - } - - /** - * Check that we can POST to create a new block. - */ - public function test_create_item() { - wp_set_current_user( self::$user_id ); - - $request = new WP_REST_Request( 'POST', '/wp/v2/blocks/' . self::$post_id ); - $request->set_body_params( - array( - 'title' => 'New cool block', - 'content' => '

Wow!

', - ) - ); - - $response = $this->server->dispatch( $request ); - - $this->assertEquals( 200, $response->get_status() ); - $this->assertEquals( - array( - 'id' => self::$post_id, - 'title' => 'New cool block', - 'content' => '

Wow!

', - ), - $response->get_data() - ); - } - - /** - * Check that we can PUT to update a block. - */ - public function test_update_item() { - wp_set_current_user( self::$user_id ); - - $request = new WP_REST_Request( 'PUT', '/wp/v2/blocks/' . self::$post_id ); - $request->set_body_params( - array( - 'title' => 'Updated cool block', - 'content' => '

Nice!

', - ) - ); - - $response = $this->server->dispatch( $request ); - - $this->assertEquals( 200, $response->get_status() ); - $this->assertEquals( - array( - 'id' => self::$post_id, - 'title' => 'Updated cool block', - 'content' => '

Nice!

', - ), - $response->get_data() - ); - } - - /** - * Check that we can DELETE a block. - */ - public function test_delete_item() { - wp_set_current_user( self::$user_id ); - - $request = new WP_REST_Request( 'DELETE', '/wp/v2/blocks/' . self::$post_id ); - - $response = $this->server->dispatch( $request ); - - $this->assertEquals( 200, $response->get_status() ); - $this->assertEquals( - array( - 'deleted' => true, - 'previous' => array( - 'id' => 9, - 'title' => 'My cool block', - 'content' => '

Hello!

', - ), - ), - $response->get_data() - ); - } - - /** - * Check that we have defined a JSON schema. - */ - public function test_get_item_schema() { - $request = new WP_REST_Request( 'OPTIONS', '/wp/v2/blocks' ); - $response = $this->server->dispatch( $request ); - $data = $response->get_data(); - $properties = $data['schema']['properties']; - - $this->assertEquals( 3, count( $properties ) ); - $this->assertArrayHasKey( 'id', $properties ); - $this->assertArrayHasKey( 'title', $properties ); - $this->assertArrayHasKey( 'content', $properties ); - } - - public function test_context_param() { - $this->markTestSkipped( 'Controller doesn\'t implement get_context_param().' ); - } - public function test_prepare_item() { - $this->markTestSkipped( 'Controller doesn\'t implement prepare_item().' ); - } -}