Make WordPress Core


Ignore:
Timestamp:
11/16/2021 06:04:49 PM (3 years ago)
Author:
spacedmonkey
Message:

REST API: Make the templates controller follow core REST patterns.

The templates controller now respects the _fields parameter and filters the response accordingly. The schema has been updated to include all the fields returned. The content.block_version field has been added. The controller now returns WP_Error objects for improved error handling.

Add new unit tests.

Props TimothyBlynJacobs, hellofromtonya, zieladam.
Fixes #54422.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/wp-includes/rest-api/endpoints/class-wp-rest-templates-controller.php

    r52062 r52186  
    7171            '/' . $this->rest_base . '/(?P<id>[\/\w-]+)',
    7272            array(
     73                'args'   => array(
     74                    'id' => array(
     75                        'description' => __( 'The id of a template' ),
     76                        'type'        => 'string',
     77                    ),
     78                ),
    7379                array(
    7480                    'methods'             => WP_REST_Server::READABLE,
     
    7682                    'permission_callback' => array( $this, 'get_item_permissions_check' ),
    7783                    'args'                => array(
    78                         'id' => array(
    79                             'description' => __( 'The id of a template' ),
    80                             'type'        => 'string',
    81                         ),
     84                        'context' => $this->get_context_param( array( 'default' => 'view' ) ),
    8285                    ),
    8386                ),
     
    232235        if ( isset( $request['source'] ) && 'theme' === $request['source'] ) {
    233236            wp_delete_post( $template->wp_id, true );
    234             return $this->prepare_item_for_response( get_block_file_template( $request['id'], $this->post_type ), $request );
     237            $request->set_param( 'context', 'edit' );
     238
     239            $template = get_block_template( $request['id'], $this->post_type );
     240            $response = $this->prepare_item_for_response( $template, $request );
     241
     242            return rest_ensure_response( $response );
    235243        }
    236244
     
    242250            $result = wp_insert_post( wp_slash( (array) $changes ), true );
    243251        }
     252
    244253        if ( is_wp_error( $result ) ) {
     254            if ( 'db_update_error' === $result->get_error_code() ) {
     255                $result->add_data( array( 'status' => 500 ) );
     256            } else {
     257                $result->add_data( array( 'status' => 400 ) );
     258            }
    245259            return $result;
    246260        }
     
    252266        }
    253267
    254         return $this->prepare_item_for_response(
    255             get_block_template( $request['id'], $this->post_type ),
    256             $request
    257         );
     268        $request->set_param( 'context', 'edit' );
     269
     270        $response = $this->prepare_item_for_response( $template, $request );
     271
     272        return rest_ensure_response( $response );
    258273    }
    259274
     
    279294     */
    280295    public function create_item( $request ) {
    281         $changes            = $this->prepare_item_for_database( $request );
    282         $changes->post_name = $request['slug'];
    283         $result             = wp_insert_post( wp_slash( (array) $changes ), true );
    284         if ( is_wp_error( $result ) ) {
    285             return $result;
    286         }
    287         $posts = get_block_templates( array( 'wp_id' => $result ), $this->post_type );
     296        $prepared_post            = $this->prepare_item_for_database( $request );
     297        $prepared_post->post_name = $request['slug'];
     298        $post_id                  = wp_insert_post( wp_slash( (array) $prepared_post ), true );
     299        if ( is_wp_error( $post_id ) ) {
     300            if ( 'db_insert_error' === $post_id->get_error_code() ) {
     301                $post_id->add_data( array( 'status' => 500 ) );
     302            } else {
     303                $post_id->add_data( array( 'status' => 400 ) );
     304            }
     305
     306            return $post_id;
     307        }
     308        $posts = get_block_templates( array( 'wp_id' => $post_id ), $this->post_type );
    288309        if ( ! count( $posts ) ) {
    289             return new WP_Error( 'rest_template_insert_error', __( 'No templates exist with that id.' ) );
     310            return new WP_Error( 'rest_template_insert_error', __( 'No templates exist with that id.' ), array( 'status' => 400 ) );
    290311        }
    291312        $id            = $posts[0]->id;
     
    296317        }
    297318
    298         return $this->prepare_item_for_response(
    299             get_block_template( $id, $this->post_type ),
    300             $request
    301         );
     319        $response = $this->prepare_item_for_response( $template, $request );
     320        $response = rest_ensure_response( $response );
     321
     322        $response->set_status( 201 );
     323        $response->header( 'Location', rest_url( sprintf( '%s/%s/%s', $this->namespace, $this->rest_base, $template->id ) ) );
     324
     325        return $response;
    302326    }
    303327
     
    334358        $force = (bool) $request['force'];
    335359
     360        $request->set_param( 'context', 'edit' );
     361
    336362        // If we're forcing, then delete permanently.
    337363        if ( $force ) {
    338364            $previous = $this->prepare_item_for_response( $template, $request );
    339             wp_delete_post( $id, true );
     365            $result   = wp_delete_post( $id, true );
    340366            $response = new WP_REST_Response();
    341367            $response->set_data(
     
    345371                )
    346372            );
    347 
    348             return $response;
    349         }
    350 
    351         // Otherwise, only trash if we haven't already.
    352         if ( 'trash' === $template->status ) {
     373        } else {
     374            // Otherwise, only trash if we haven't already.
     375            if ( 'trash' === $template->status ) {
     376                return new WP_Error(
     377                    'rest_template_already_trashed',
     378                    __( 'The template has already been deleted.' ),
     379                    array( 'status' => 410 )
     380                );
     381            }
     382
     383            // (Note that internally this falls through to `wp_delete_post()`
     384            // if the Trash is disabled.)
     385            $result           = wp_trash_post( $id );
     386            $template->status = 'trash';
     387            $response         = $this->prepare_item_for_response( $template, $request );
     388        }
     389
     390        if ( ! $result ) {
    353391            return new WP_Error(
    354                 'rest_template_already_trashed',
    355                 __( 'The template has already been deleted.' ),
    356                 array( 'status' => 410 )
     392                'rest_cannot_delete',
     393                __( 'The template cannot be deleted.' ),
     394                array( 'status' => 500 )
    357395            );
    358396        }
    359397
    360         wp_trash_post( $id );
    361         $template->status = 'trash';
    362         return $this->prepare_item_for_response( $template, $request );
     398        return $response;
    363399    }
    364400
     
    393429        }
    394430        if ( isset( $request['content'] ) ) {
    395             $changes->post_content = $request['content'];
     431            if ( is_string( $request['content'] ) ) {
     432                $changes->post_content = $request['content'];
     433            } elseif ( isset( $request['content']['raw'] ) ) {
     434                $changes->post_content = $request['content']['raw'];
     435            }
    396436        } elseif ( null !== $template && 'custom' !== $template->source ) {
    397437            $changes->post_content = $template->content;
    398438        }
    399439        if ( isset( $request['title'] ) ) {
    400             $changes->post_title = $request['title'];
     440            if ( is_string( $request['title'] ) ) {
     441                $changes->post_title = $request['title'];
     442            } elseif ( ! empty( $request['title']['raw'] ) ) {
     443                $changes->post_title = $request['title']['raw'];
     444            }
    401445        } elseif ( null !== $template && 'custom' !== $template->source ) {
    402446            $changes->post_title = $template->title;
     
    434478        // Restores the more descriptive, specific name for use within this method.
    435479        $template = $item;
    436         $result   = array(
    437             'id'             => $template->id,
    438             'theme'          => $template->theme,
    439             'content'        => array( 'raw' => $template->content ),
    440             'slug'           => $template->slug,
    441             'source'         => $template->source,
    442             'type'           => $template->type,
    443             'description'    => $template->description,
    444             'title'          => array(
    445                 'raw'      => $template->title,
    446                 'rendered' => $template->title,
    447             ),
    448             'status'         => $template->status,
    449             'wp_id'          => $template->wp_id,
    450             'has_theme_file' => $template->has_theme_file,
    451         );
    452 
    453         if ( 'wp_template_part' === $template->type ) {
    454             $result['area'] = $template->area;
    455         }
    456 
    457         $result = $this->add_additional_fields_to_object( $result, $request );
    458 
    459         $response = rest_ensure_response( $result );
    460         $links    = $this->prepare_links( $template->id );
     480
     481        $fields = $this->get_fields_for_response( $request );
     482
     483        // Base fields for every template.
     484        $data = array();
     485
     486        if ( rest_is_field_included( 'id', $fields ) ) {
     487            $data['id'] = $template->id;
     488        }
     489
     490        if ( rest_is_field_included( 'theme', $fields ) ) {
     491            $data['theme'] = $template->theme;
     492        }
     493
     494        if ( rest_is_field_included( 'content', $fields ) ) {
     495            $data['content'] = array();
     496        }
     497        if ( rest_is_field_included( 'content.raw', $fields ) ) {
     498            $data['content']['raw'] = $template->content;
     499        }
     500
     501        if ( rest_is_field_included( 'content.block_version', $fields ) ) {
     502            $data['content']['block_version'] = block_version( $template->content );
     503        }
     504
     505        if ( rest_is_field_included( 'slug', $fields ) ) {
     506            $data['slug'] = $template->slug;
     507        }
     508
     509        if ( rest_is_field_included( 'source', $fields ) ) {
     510            $data['source'] = $template->source;
     511        }
     512
     513        if ( rest_is_field_included( 'type', $fields ) ) {
     514            $data['type'] = $template->type;
     515        }
     516
     517        if ( rest_is_field_included( 'description', $fields ) ) {
     518            $data['description'] = $template->description;
     519        }
     520
     521        if ( rest_is_field_included( 'title', $fields ) ) {
     522            $data['title'] = array();
     523        }
     524
     525        if ( rest_is_field_included( 'title.raw', $fields ) ) {
     526            $data['title']['raw'] = $template->title;
     527        }
     528
     529        if ( rest_is_field_included( 'title.rendered', $fields ) ) {
     530            if ( $template->wp_id ) {
     531                /** This filter is documented in wp-includes/post-template.php */
     532                $data['title']['rendered'] = apply_filters( 'the_title', $template->title, $template->wp_id );
     533            } else {
     534                $data['title']['rendered'] = $template->title;
     535            }
     536        }
     537
     538        if ( rest_is_field_included( 'status', $fields ) ) {
     539            $data['status'] = $template->status;
     540        }
     541
     542        if ( rest_is_field_included( 'wp_id', $fields ) ) {
     543            $data['wp_id'] = (int) $template->wp_id;
     544        }
     545
     546        if ( rest_is_field_included( 'has_theme_file', $fields ) ) {
     547            $data['has_theme_file'] = (bool) $template->has_theme_file;
     548        }
     549
     550        if ( rest_is_field_included( 'area', $fields ) && 'wp_template_part' === $template->type ) {
     551            $data['area'] = $template->area;
     552        }
     553
     554        $context = ! empty( $request['context'] ) ? $request['context'] : 'view';
     555        $data    = $this->add_additional_fields_to_object( $data, $request );
     556        $data    = $this->filter_response_by_context( $data, $context );
     557
     558        // Wrap the data in a response object.
     559        $response = rest_ensure_response( $data );
     560
     561        $links = $this->prepare_links( $template->id );
    461562        $response->add_links( $links );
    462563        if ( ! empty( $links['self']['href'] ) ) {
     
    531632    public function get_collection_params() {
    532633        return array(
    533             'context'   => $this->get_context_param(),
     634            'context'   => $this->get_context_param( array( 'default' => 'view' ) ),
    534635            'wp_id'     => array(
    535636                'description' => __( 'Limit to the specified post id.' ),
     
    584685                    'context'     => array( 'embed', 'view', 'edit' ),
    585686                ),
     687                'type'           => array(
     688                    'description' => __( 'Type of template.' ),
     689                    'type'        => 'string',
     690                    'context'     => array( 'embed', 'view', 'edit' ),
     691                ),
    586692                'source'         => array(
    587693                    'description' => __( 'Source of template' ),
     
    595701                    'default'     => '',
    596702                    'context'     => array( 'embed', 'view', 'edit' ),
     703                    'properties'  => array(
     704                        'raw'           => array(
     705                            'description' => __( 'Content for the template, as it exists in the database.' ),
     706                            'type'        => 'string',
     707                            'context'     => array( 'view', 'edit' ),
     708                        ),
     709                        'block_version' => array(
     710                            'description' => __( 'Version of the content block format used by the template.' ),
     711                            'type'        => 'integer',
     712                            'context'     => array( 'edit' ),
     713                            'readonly'    => true,
     714                        ),
     715                    ),
    597716                ),
    598717                'title'          => array(
     
    601720                    'default'     => '',
    602721                    'context'     => array( 'embed', 'view', 'edit' ),
     722                    'properties'  => array(
     723                        'raw'      => array(
     724                            'description' => __( 'Title for the template, as it exists in the database.' ),
     725                            'type'        => 'string',
     726                            'context'     => array( 'view', 'edit', 'embed' ),
     727                        ),
     728                        'rendered' => array(
     729                            'description' => __( 'HTML title for the template, transformed for display.' ),
     730                            'type'        => 'string',
     731                            'context'     => array( 'view', 'edit', 'embed' ),
     732                            'readonly'    => true,
     733                        ),
     734                    ),
    603735                ),
    604736                'description'    => array(
     
    611743                    'description' => __( 'Status of template.' ),
    612744                    'type'        => 'string',
     745                    'enum'        => array_keys( get_post_stati( array( 'internal' => false ) ) ),
    613746                    'default'     => 'publish',
    614747                    'context'     => array( 'embed', 'view', 'edit' ),
Note: See TracChangeset for help on using the changeset viewer.