diff --git a/lib/compat/wordpress-5.9/block-template-utils.php b/lib/compat/wordpress-5.9/block-template-utils.php index cf54b4b69cd05..ab3ed98688ed3 100644 --- a/lib/compat/wordpress-5.9/block-template-utils.php +++ b/lib/compat/wordpress-5.9/block-template-utils.php @@ -550,6 +550,8 @@ function _build_block_template_result_from_post( $post ) { return new WP_Error( 'template_missing_theme', __( 'No theme is defined for this template.', 'gutenberg' ) ); } + $origin = get_post_meta( $post->ID, 'origin', true ); + $theme = $terms[0]->name; $has_theme_file = wp_get_theme()->get_stylesheet() === $theme && null !== _get_block_template_file( $post->post_type, $post->post_name ); @@ -561,12 +563,14 @@ function _build_block_template_result_from_post( $post ) { $template->content = $post->post_content; $template->slug = $post->post_name; $template->source = 'custom'; + $template->origin = ! empty( $origin ) ? $origin : null; $template->type = $post->post_type; $template->description = $post->post_excerpt; $template->title = $post->post_title; $template->status = $post->post_status; $template->has_theme_file = $has_theme_file; $template->is_custom = true; + $template->author = $post->post_author; if ( 'wp_template' === $post->post_type && isset( $default_template_types[ $template->slug ] ) ) { $template->is_custom = false; diff --git a/lib/compat/wordpress-5.9/class-gutenberg-rest-templates-controller.php b/lib/compat/wordpress-5.9/class-gutenberg-rest-templates-controller.php index 02b5deec05bb8..be6116c6c2a55 100644 --- a/lib/compat/wordpress-5.9/class-gutenberg-rest-templates-controller.php +++ b/lib/compat/wordpress-5.9/class-gutenberg-rest-templates-controller.php @@ -245,6 +245,10 @@ public function update_item( $request ) { $changes = $this->prepare_item_for_database( $request ); + if ( is_wp_error( $changes ) ) { + return $changes; + } + if ( 'custom' === $template->source ) { $result = wp_update_post( wp_slash( (array) $changes ), true ); } else { @@ -283,7 +287,12 @@ public function create_item_permissions_check( $request ) { * @return WP_REST_Response|WP_Error Response object on success, or WP_Error object on failure. */ public function create_item( $request ) { - $changes = $this->prepare_item_for_database( $request ); + $changes = $this->prepare_item_for_database( $request ); + + if ( is_wp_error( $changes ) ) { + return $changes; + } + $changes->post_name = $request['slug']; $result = wp_insert_post( wp_slash( (array) $changes ), true ); if ( is_wp_error( $result ) ) { @@ -385,6 +394,9 @@ protected function prepare_item_for_database( $request ) { $changes->tax_input = array( 'wp_theme' => $template->theme, ); + $changes->meta_input = array( + 'origin' => $template->source, + ); } else { $changes->post_name = $template->slug; $changes->ID = $template->wp_id; @@ -416,6 +428,24 @@ protected function prepare_item_for_database( $request ) { } } + if ( ! empty( $request['author'] ) ) { + $post_author = (int) $request['author']; + + if ( get_current_user_id() !== $post_author ) { + $user_obj = get_userdata( $post_author ); + + if ( ! $user_obj ) { + return new WP_Error( + 'rest_invalid_author', + __( 'Invalid author ID.', 'gutenberg' ), + array( 'status' => 400 ) + ); + } + } + + $changes->post_author = $post_author; + } + return $changes; } @@ -434,6 +464,7 @@ public function prepare_item_for_response( $template, $request ) { // phpcs:igno 'content' => array( 'raw' => $template->content ), 'slug' => $template->slug, 'source' => $template->source, + 'origin' => $template->origin, 'type' => $template->type, 'description' => $template->description, 'title' => array( @@ -443,6 +474,7 @@ public function prepare_item_for_response( $template, $request ) { // phpcs:igno 'status' => $template->status, 'wp_id' => $template->wp_id, 'has_theme_file' => $template->has_theme_file, + 'author' => (int) $template->author, ); if ( 'wp_template' === $template->type ) { @@ -578,6 +610,12 @@ public function get_item_schema() { 'context' => array( 'embed', 'view', 'edit' ), 'readonly' => true, ), + 'origin' => array( + 'description' => __( 'Source of customized template', 'gutenberg' ), + 'type' => 'string', + 'context' => array( 'embed', 'view', 'edit' ), + 'readonly' => true, + ), 'content' => array( 'description' => __( 'Content of template.', 'gutenberg' ), 'type' => array( 'object', 'string' ), @@ -614,6 +652,11 @@ public function get_item_schema() { 'context' => array( 'embed', 'view', 'edit' ), 'readonly' => true, ), + 'author' => array( + 'description' => __( 'The ID for the author of the template.', 'gutenberg' ), + 'type' => 'integer', + 'context' => array( 'view', 'edit', 'embed' ), + ), ), ); diff --git a/lib/full-site-editing/class-wp-block-template.php b/lib/full-site-editing/class-wp-block-template.php index 176e1105554df..0068ebb6eec90 100644 --- a/lib/full-site-editing/class-wp-block-template.php +++ b/lib/full-site-editing/class-wp-block-template.php @@ -67,6 +67,15 @@ class WP_Block_Template { */ public $source = 'theme'; + /** + * Origin of the content when the content has been customized. + * When customized, origin takes on the value of source and source becomes + * 'custom'. + * + * @var string + */ + public $origin; + /** * Post Id. * @@ -94,4 +103,13 @@ class WP_Block_Template { * @var bool */ public $is_custom = true; + + /** + * Author. + * + * A value of 0 means no author. + * + * @var int + */ + public $author = 0; } diff --git a/lib/full-site-editing/template-parts.php b/lib/full-site-editing/template-parts.php index fec3b775116bf..143a0452fb354 100644 --- a/lib/full-site-editing/template-parts.php +++ b/lib/full-site-editing/template-parts.php @@ -53,6 +53,7 @@ function gutenberg_register_template_part_post_type() { 'excerpt', 'editor', 'revisions', + 'author', ), ); diff --git a/lib/full-site-editing/templates.php b/lib/full-site-editing/templates.php index 6c4bad7a7ce1d..601ce5e88bf1f 100644 --- a/lib/full-site-editing/templates.php +++ b/lib/full-site-editing/templates.php @@ -54,6 +54,7 @@ function gutenberg_register_template_post_type() { 'excerpt', 'editor', 'revisions', + 'author', ), ); diff --git a/phpunit/class-gutenberg-rest-template-controller-test.php b/phpunit/class-gutenberg-rest-template-controller-test.php index ab8a6a2530e94..e048b3d2343d6 100644 --- a/phpunit/class-gutenberg-rest-template-controller-test.php +++ b/phpunit/class-gutenberg-rest-template-controller-test.php @@ -77,6 +77,8 @@ function find_and_normalize_template_by_id( $templates, $id ) { 'wp_id' => null, 'has_theme_file' => true, 'is_custom' => false, + 'origin' => null, + 'author' => 0, ), find_and_normalize_template_by_id( $data, 'tt1-blocks//index' ) ); @@ -102,6 +104,8 @@ function find_and_normalize_template_by_id( $templates, $id ) { 'wp_id' => null, 'area' => WP_TEMPLATE_PART_AREA_HEADER, 'has_theme_file' => true, + 'origin' => null, + 'author' => 0, ), find_and_normalize_template_by_id( $data, 'tt1-blocks//header' ) ); @@ -131,6 +135,8 @@ public function test_get_item() { 'wp_id' => null, 'has_theme_file' => true, 'is_custom' => false, + 'origin' => null, + 'author' => 0, ), $data ); @@ -157,6 +163,8 @@ public function test_get_item() { 'wp_id' => null, 'area' => WP_TEMPLATE_PART_AREA_HEADER, 'has_theme_file' => true, + 'origin' => null, + 'author' => 0, ), $data ); @@ -192,6 +200,8 @@ public function test_get_item_works_with_a_single_slash( $endpoint_url ) { 'wp_id' => null, 'has_theme_file' => true, 'is_custom' => false, + 'origin' => null, + 'author' => 0, ), $data ); @@ -267,6 +277,8 @@ public function test_create_item() { ), 'has_theme_file' => false, 'is_custom' => true, + 'origin' => null, + 'author' => 0, ), $data ); @@ -305,6 +317,8 @@ public function test_create_item() { ), 'area' => 'header', 'has_theme_file' => false, + 'origin' => null, + 'author' => 0, ), $data );