Skip to content
Closed
Original file line number Diff line number Diff line change
Expand Up @@ -70,15 +70,18 @@ public function register_routes() {
$this->namespace,
'/' . $this->rest_base . '/(?P<id>[\/\w-]+)',
array(
'args' => array(
'id' => array(
'description' => __( 'The id of a template' ),
'type' => 'string',
),
),
array(
'methods' => WP_REST_Server::READABLE,
'callback' => array( $this, 'get_item' ),
'permission_callback' => array( $this, 'get_item_permissions_check' ),
'args' => array(
'id' => array(
'description' => __( 'The id of a template' ),
'type' => 'string',
),
'context' => $this->get_context_param( array( 'default' => 'view' ) ),
),
),
array(
Expand Down Expand Up @@ -231,7 +234,12 @@ public function update_item( $request ) {

if ( isset( $request['source'] ) && 'theme' === $request['source'] ) {
wp_delete_post( $template->wp_id, true );
return $this->prepare_item_for_response( get_block_file_template( $request['id'], $this->post_type ), $request );
$request->set_param( 'context', 'edit' );

$template = get_block_template( $request['id'], $this->post_type );
$response = $this->prepare_item_for_response( $template, $request );

return rest_ensure_response( $response );
}

$changes = $this->prepare_item_for_database( $request );
Expand All @@ -241,7 +249,13 @@ public function update_item( $request ) {
} else {
$result = wp_insert_post( wp_slash( (array) $changes ), true );
}

if ( is_wp_error( $result ) ) {
if ( 'db_update_error' === $result->get_error_code() ) {
Copy link
Contributor

@adamziel adamziel Nov 15, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Any chance this could come up because of an invalid input that e.g. violates some db constraint? An example would be trying to insert a duplicated value when a field is UNIQUE – it would appear to be a db error but the problem would actually be with the inputs. This specific one is unlikely here, but you get the idea.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Either way, if were get a database error, we should return that.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@adamziel I'm not aware of any such cases, but if they do exist, we should probably update wp_insert_post to handle those errors to return something more descriptive.

$result->add_data( array( 'status' => 500 ) );
} else {
$result->add_data( array( 'status' => 400 ) );
}
return $result;
}

Expand All @@ -251,10 +265,11 @@ public function update_item( $request ) {
return $fields_update;
}

return $this->prepare_item_for_response(
get_block_template( $request['id'], $this->post_type ),
$request
);
$request->set_param( 'context', 'edit' );

$response = $this->prepare_item_for_response( $template, $request );

return rest_ensure_response( $response );
}

/**
Expand All @@ -278,15 +293,21 @@ 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->post_name = $request['slug'];
$result = wp_insert_post( wp_slash( (array) $changes ), true );
if ( is_wp_error( $result ) ) {
return $result;
$prepared_post = $this->prepare_item_for_database( $request );
$prepared_post->post_name = $request['slug'];
$post_id = wp_insert_post( wp_slash( (array) $prepared_post ), true );
if ( is_wp_error( $post_id ) ) {
if ( 'db_insert_error' === $post_id->get_error_code() ) {
$post_id->add_data( array( 'status' => 500 ) );
} else {
$post_id->add_data( array( 'status' => 400 ) );
}

return $post_id;
}
$posts = get_block_templates( array( 'wp_id' => $result ), $this->post_type );
$posts = get_block_templates( array( 'wp_id' => $post_id ), $this->post_type );
if ( ! count( $posts ) ) {
return new WP_Error( 'rest_template_insert_error', __( 'No templates exist with that id.' ) );
return new WP_Error( 'rest_template_insert_error', __( 'No templates exist with that id.' ), array( 'status' => 400 ) );
}
$id = $posts[0]->id;
$template = get_block_template( $id, $this->post_type );
Expand All @@ -295,10 +316,13 @@ public function create_item( $request ) {
return $fields_update;
}

return $this->prepare_item_for_response(
get_block_template( $id, $this->post_type ),
$request
);
$response = $this->prepare_item_for_response( $template, $request );
$response = rest_ensure_response( $response );

$response->set_status( 201 );
$response->header( 'Location', rest_url( sprintf( '%s/%s/%s', $this->namespace, $this->rest_base, $template->id ) ) );

return $response;
}

/**
Expand Down Expand Up @@ -333,33 +357,45 @@ public function delete_item( $request ) {
$id = $template->wp_id;
$force = (bool) $request['force'];

$request->set_param( 'context', 'edit' );

// If we're forcing, then delete permanently.
if ( $force ) {
$previous = $this->prepare_item_for_response( $template, $request );
wp_delete_post( $id, true );
$result = wp_delete_post( $id, true );
$response = new WP_REST_Response();
$response->set_data(
array(
'deleted' => true,
'previous' => $previous->get_data(),
)
);
} else {
// Otherwise, only trash if we haven't already.
if ( 'trash' === $template->status ) {
return new WP_Error(
'rest_template_already_trashed',
__( 'The template has already been deleted.' ),
array( 'status' => 410 )
);
}

return $response;
// (Note that internally this falls through to `wp_delete_post()`
// if the Trash is disabled.)
$result = wp_trash_post( $id );
$template->status = 'trash';
$response = $this->prepare_item_for_response( $template, $request );
}

// Otherwise, only trash if we haven't already.
if ( 'trash' === $template->status ) {
if ( ! $result ) {
return new WP_Error(
'rest_template_already_trashed',
__( 'The template has already been deleted.' ),
array( 'status' => 410 )
'rest_cannot_delete',
__( 'The template cannot be deleted.' ),
array( 'status' => 500 )
);
}

wp_trash_post( $id );
$template->status = 'trash';
return $this->prepare_item_for_response( $template, $request );
return $response;
}

/**
Expand Down Expand Up @@ -392,12 +428,20 @@ protected function prepare_item_for_database( $request ) {
$changes->post_status = 'publish';
}
if ( isset( $request['content'] ) ) {
$changes->post_content = $request['content'];
if ( is_string( $request['content'] ) ) {
$changes->post_content = $request['content'];
} elseif ( isset( $request['content']['raw'] ) ) {
$changes->post_content = $request['content']['raw'];
}
} elseif ( null !== $template && 'custom' !== $template->source ) {
$changes->post_content = $template->content;
}
if ( isset( $request['title'] ) ) {
$changes->post_title = $request['title'];
if ( is_string( $request['title'] ) ) {
$changes->post_title = $request['title'];
} elseif ( ! empty( $request['title']['raw'] ) ) {
$changes->post_title = $request['title']['raw'];
}
} elseif ( null !== $template && 'custom' !== $template->source ) {
$changes->post_title = $template->title;
}
Expand Down Expand Up @@ -433,31 +477,88 @@ protected function prepare_item_for_database( $request ) {
public function prepare_item_for_response( $item, $request ) { // phpcs:ignore VariableAnalysis.CodeAnalysis.VariableAnalysis.UnusedVariable
// Restores the more descriptive, specific name for use within this method.
$template = $item;
$result = array(
'id' => $template->id,
'theme' => $template->theme,
'content' => array( 'raw' => $template->content ),
'slug' => $template->slug,
'source' => $template->source,
'type' => $template->type,
'description' => $template->description,
'title' => array(
'raw' => $template->title,
'rendered' => $template->title,
),
'status' => $template->status,
'wp_id' => $template->wp_id,
'has_theme_file' => $template->has_theme_file,
);

if ( 'wp_template_part' === $template->type ) {
$result['area'] = $template->area;
$fields = $this->get_fields_for_response( $request );

// Base fields for every template.
$data = array();

if ( rest_is_field_included( 'id', $fields ) ) {
$data['id'] = $template->id;
}

if ( rest_is_field_included( 'theme', $fields ) ) {
$data['theme'] = $template->theme;
}

if ( rest_is_field_included( 'content', $fields ) ) {
$data['content'] = array();
}
if ( rest_is_field_included( 'content.raw', $fields ) ) {
$data['content']['raw'] = $template->content;
}

if ( rest_is_field_included( 'content.block_version', $fields ) ) {
$data['content']['block_version'] = block_version( $template->content );
}

if ( rest_is_field_included( 'slug', $fields ) ) {
$data['slug'] = $template->slug;
}

if ( rest_is_field_included( 'source', $fields ) ) {
$data['source'] = $template->source;
}

$result = $this->add_additional_fields_to_object( $result, $request );
if ( rest_is_field_included( 'type', $fields ) ) {
$data['type'] = $template->type;
}

if ( rest_is_field_included( 'description', $fields ) ) {
$data['description'] = $template->description;
}

if ( rest_is_field_included( 'title', $fields ) ) {
$data['title'] = array();
}

if ( rest_is_field_included( 'title.raw', $fields ) ) {
$data['title']['raw'] = $template->title;
}

if ( rest_is_field_included( 'title.rendered', $fields ) ) {
if ( $template->wp_id ) {
/** This filter is documented in wp-includes/post-template.php */
$data['title']['rendered'] = apply_filters( 'the_title', $template->title, $template->wp_id );
} else {
$data['title']['rendered'] = $template->title;
}
}

if ( rest_is_field_included( 'status', $fields ) ) {
$data['status'] = $template->status;
}

if ( rest_is_field_included( 'wp_id', $fields ) ) {
$data['wp_id'] = (int) $template->wp_id;
}

$response = rest_ensure_response( $result );
$links = $this->prepare_links( $template->id );
if ( rest_is_field_included( 'has_theme_file', $fields ) ) {
$data['has_theme_file'] = (bool) $template->has_theme_file;
}

if ( rest_is_field_included( 'area', $fields ) && 'wp_template_part' === $template->type ) {
$data['area'] = $template->area;
}

$context = ! empty( $request['context'] ) ? $request['context'] : 'view';
$data = $this->add_additional_fields_to_object( $data, $request );
$data = $this->filter_response_by_context( $data, $context );

// Wrap the data in a response object.
$response = rest_ensure_response( $data );

$links = $this->prepare_links( $template->id );
$response->add_links( $links );
if ( ! empty( $links['self']['href'] ) ) {
$actions = $this->get_available_actions();
Expand Down Expand Up @@ -530,7 +631,7 @@ protected function get_available_actions() {
*/
public function get_collection_params() {
return array(
'context' => $this->get_context_param(),
'context' => $this->get_context_param( array( 'default' => 'view' ) ),
'wp_id' => array(
'description' => __( 'Limit to the specified post id.' ),
'type' => 'integer',
Expand Down Expand Up @@ -583,6 +684,11 @@ public function get_item_schema() {
'type' => 'string',
'context' => array( 'embed', 'view', 'edit' ),
),
'type' => array(
'description' => __( 'Type of template.' ),
'type' => 'string',
'context' => array( 'embed', 'view', 'edit' ),
),
'source' => array(
'description' => __( 'Source of template' ),
'type' => 'string',
Expand All @@ -594,12 +700,38 @@ public function get_item_schema() {
'type' => array( 'object', 'string' ),
'default' => '',
'context' => array( 'embed', 'view', 'edit' ),
'properties' => array(
'raw' => array(
'description' => __( 'Content for the template, as it exists in the database.' ),
'type' => 'string',
'context' => array( 'view', 'edit' ),
),
'block_version' => array(
'description' => __( 'Version of the content block format used by the template.' ),
'type' => 'integer',
'context' => array( 'edit' ),
'readonly' => true,
),
),
),
'title' => array(
'description' => __( 'Title of template.' ),
'type' => array( 'object', 'string' ),
'default' => '',
'context' => array( 'embed', 'view', 'edit' ),
'properties' => array(
'raw' => array(
'description' => __( 'Title for the template, as it exists in the database.' ),
'type' => 'string',
'context' => array( 'view', 'edit', 'embed' ),
),
'rendered' => array(
'description' => __( 'HTML title for the template, transformed for display.' ),
'type' => 'string',
'context' => array( 'view', 'edit', 'embed' ),
'readonly' => true,
),
),
),
'description' => array(
'description' => __( 'Description of template.' ),
Expand All @@ -610,6 +742,7 @@ public function get_item_schema() {
'status' => array(
'description' => __( 'Status of template.' ),
'type' => 'string',
'enum' => array_keys( get_post_stati( array( 'internal' => false ) ) ),
'default' => 'publish',
'context' => array( 'embed', 'view', 'edit' ),
),
Expand Down
Loading