wp/wp-includes/rest-api/endpoints/class-wp-rest-block-patterns-controller.php
changeset 21 48c4eec2b7e6
parent 19 3d72ae0968f4
equal deleted inserted replaced
20:7b1b88e27a20 21:48c4eec2b7e6
    21 	 *
    21 	 *
    22 	 * @since 6.0.0
    22 	 * @since 6.0.0
    23 	 * @var bool
    23 	 * @var bool
    24 	 */
    24 	 */
    25 	private $remote_patterns_loaded;
    25 	private $remote_patterns_loaded;
       
    26 
       
    27 	/**
       
    28 	 * An array that maps old categories names to new ones.
       
    29 	 *
       
    30 	 * @since 6.2.0
       
    31 	 * @var array
       
    32 	 */
       
    33 	protected static $categories_migration = array(
       
    34 		'buttons' => 'call-to-action',
       
    35 		'columns' => 'text',
       
    36 		'query'   => 'posts',
       
    37 	);
    26 
    38 
    27 	/**
    39 	/**
    28 	 * Constructs the controller.
    40 	 * Constructs the controller.
    29 	 *
    41 	 *
    30 	 * @since 6.0.0
    42 	 * @since 6.0.0
    82 
    94 
    83 	/**
    95 	/**
    84 	 * Retrieves all block patterns.
    96 	 * Retrieves all block patterns.
    85 	 *
    97 	 *
    86 	 * @since 6.0.0
    98 	 * @since 6.0.0
       
    99 	 * @since 6.2.0 Added migration for old core pattern categories to the new ones.
    87 	 *
   100 	 *
    88 	 * @param WP_REST_Request $request Full details about the request.
   101 	 * @param WP_REST_Request $request Full details about the request.
    89 	 * @return WP_REST_Response|WP_Error Response object on success, or WP_Error object on failure.
   102 	 * @return WP_REST_Response|WP_Error Response object on success, or WP_Error object on failure.
    90 	 */
   103 	 */
    91 	public function get_items( $request ) {
   104 	public function get_items( $request ) {
    99 		}
   112 		}
   100 
   113 
   101 		$response = array();
   114 		$response = array();
   102 		$patterns = WP_Block_Patterns_Registry::get_instance()->get_all_registered();
   115 		$patterns = WP_Block_Patterns_Registry::get_instance()->get_all_registered();
   103 		foreach ( $patterns as $pattern ) {
   116 		foreach ( $patterns as $pattern ) {
   104 			$prepared_pattern = $this->prepare_item_for_response( $pattern, $request );
   117 			$migrated_pattern = $this->migrate_pattern_categories( $pattern );
       
   118 			$prepared_pattern = $this->prepare_item_for_response( $migrated_pattern, $request );
   105 			$response[]       = $this->prepare_response_for_collection( $prepared_pattern );
   119 			$response[]       = $this->prepare_response_for_collection( $prepared_pattern );
   106 		}
   120 		}
   107 		return rest_ensure_response( $response );
   121 		return rest_ensure_response( $response );
   108 	}
   122 	}
   109 
   123 
   110 	/**
   124 	/**
       
   125 	 * Migrates old core pattern categories to the new categories.
       
   126 	 *
       
   127 	 * Core pattern categories are revamped. Migration is needed to ensure
       
   128 	 * backwards compatibility.
       
   129 	 *
       
   130 	 * @since 6.2.0
       
   131 	 *
       
   132 	 * @param array $pattern Raw pattern as registered, before applying any changes.
       
   133 	 * @return array Migrated pattern.
       
   134 	 */
       
   135 	protected function migrate_pattern_categories( $pattern ) {
       
   136 		// No categories to migrate.
       
   137 		if (
       
   138 			! isset( $pattern['categories'] ) ||
       
   139 			! is_array( $pattern['categories'] )
       
   140 		) {
       
   141 			return $pattern;
       
   142 		}
       
   143 
       
   144 		foreach ( $pattern['categories'] as $index => $category ) {
       
   145 			// If the category exists as a key, then it needs migration.
       
   146 			if ( isset( static::$categories_migration[ $category ] ) ) {
       
   147 				$pattern['categories'][ $index ] = static::$categories_migration[ $category ];
       
   148 			}
       
   149 		}
       
   150 
       
   151 		return $pattern;
       
   152 	}
       
   153 
       
   154 	/**
   111 	 * Prepare a raw block pattern before it gets output in a REST API response.
   155 	 * Prepare a raw block pattern before it gets output in a REST API response.
   112 	 *
   156 	 *
   113 	 * @since 6.0.0
   157 	 * @since 6.0.0
       
   158 	 * @since 6.3.0 Added `source` property.
   114 	 *
   159 	 *
   115 	 * @param array           $item    Raw pattern as registered, before any changes.
   160 	 * @param array           $item    Raw pattern as registered, before any changes.
   116 	 * @param WP_REST_Request $request Request object.
   161 	 * @param WP_REST_Request $request Request object.
   117 	 * @return WP_REST_Response|WP_Error Response object on success, or WP_Error object on failure.
   162 	 * @return WP_REST_Response|WP_Error Response object on success, or WP_Error object on failure.
   118 	 */
   163 	 */
   119 	public function prepare_item_for_response( $item, $request ) {
   164 	public function prepare_item_for_response( $item, $request ) {
       
   165 		// Resolve pattern blocks so they don't need to be resolved client-side
       
   166 		// in the editor, improving performance.
       
   167 		$blocks          = parse_blocks( $item['content'] );
       
   168 		$blocks          = resolve_pattern_blocks( $blocks );
       
   169 		$item['content'] = serialize_blocks( $blocks );
       
   170 
   120 		$fields = $this->get_fields_for_response( $request );
   171 		$fields = $this->get_fields_for_response( $request );
   121 		$keys   = array(
   172 		$keys   = array(
   122 			'name'          => 'name',
   173 			'name'          => 'name',
   123 			'title'         => 'title',
   174 			'title'         => 'title',
       
   175 			'content'       => 'content',
   124 			'description'   => 'description',
   176 			'description'   => 'description',
   125 			'viewportWidth' => 'viewport_width',
   177 			'viewportWidth' => 'viewport_width',
   126 			'blockTypes'    => 'block_types',
   178 			'inserter'      => 'inserter',
   127 			'categories'    => 'categories',
   179 			'categories'    => 'categories',
   128 			'keywords'      => 'keywords',
   180 			'keywords'      => 'keywords',
   129 			'content'       => 'content',
   181 			'blockTypes'    => 'block_types',
   130 			'inserter'      => 'inserter',
   182 			'postTypes'     => 'post_types',
       
   183 			'templateTypes' => 'template_types',
       
   184 			'source'        => 'source',
   131 		);
   185 		);
   132 		$data   = array();
   186 		$data   = array();
   133 		foreach ( $keys as $item_key => $rest_key ) {
   187 		foreach ( $keys as $item_key => $rest_key ) {
   134 			if ( isset( $item[ $item_key ] ) && rest_is_field_included( $rest_key, $fields ) ) {
   188 			if ( isset( $item[ $item_key ] ) && rest_is_field_included( $rest_key, $fields ) ) {
   135 				$data[ $rest_key ] = $item[ $item_key ];
   189 				$data[ $rest_key ] = $item[ $item_key ];
   144 
   198 
   145 	/**
   199 	/**
   146 	 * Retrieves the block pattern schema, conforming to JSON Schema.
   200 	 * Retrieves the block pattern schema, conforming to JSON Schema.
   147 	 *
   201 	 *
   148 	 * @since 6.0.0
   202 	 * @since 6.0.0
       
   203 	 * @since 6.3.0 Added `source` property.
   149 	 *
   204 	 *
   150 	 * @return array Item schema data.
   205 	 * @return array Item schema data.
   151 	 */
   206 	 */
   152 	public function get_item_schema() {
   207 	public function get_item_schema() {
       
   208 		if ( $this->schema ) {
       
   209 			return $this->add_additional_fields_schema( $this->schema );
       
   210 		}
       
   211 
   153 		$schema = array(
   212 		$schema = array(
   154 			'$schema'    => 'http://json-schema.org/draft-04/schema#',
   213 			'$schema'    => 'http://json-schema.org/draft-04/schema#',
   155 			'title'      => 'block-pattern',
   214 			'title'      => 'block-pattern',
   156 			'type'       => 'object',
   215 			'type'       => 'object',
   157 			'properties' => array(
   216 			'properties' => array(
   165 					'description' => __( 'The pattern title, in human readable format.' ),
   224 					'description' => __( 'The pattern title, in human readable format.' ),
   166 					'type'        => 'string',
   225 					'type'        => 'string',
   167 					'readonly'    => true,
   226 					'readonly'    => true,
   168 					'context'     => array( 'view', 'edit', 'embed' ),
   227 					'context'     => array( 'view', 'edit', 'embed' ),
   169 				),
   228 				),
       
   229 				'content'        => array(
       
   230 					'description' => __( 'The pattern content.' ),
       
   231 					'type'        => 'string',
       
   232 					'readonly'    => true,
       
   233 					'context'     => array( 'view', 'edit', 'embed' ),
       
   234 				),
   170 				'description'    => array(
   235 				'description'    => array(
   171 					'description' => __( 'The pattern detailed description.' ),
   236 					'description' => __( 'The pattern detailed description.' ),
   172 					'type'        => 'string',
   237 					'type'        => 'string',
   173 					'readonly'    => true,
   238 					'readonly'    => true,
   174 					'context'     => array( 'view', 'edit', 'embed' ),
   239 					'context'     => array( 'view', 'edit', 'embed' ),
   177 					'description' => __( 'The pattern viewport width for inserter preview.' ),
   242 					'description' => __( 'The pattern viewport width for inserter preview.' ),
   178 					'type'        => 'number',
   243 					'type'        => 'number',
   179 					'readonly'    => true,
   244 					'readonly'    => true,
   180 					'context'     => array( 'view', 'edit', 'embed' ),
   245 					'context'     => array( 'view', 'edit', 'embed' ),
   181 				),
   246 				),
   182 				'block_types'    => array(
       
   183 					'description' => __( 'Block types that the pattern is intended to be used with.' ),
       
   184 					'type'        => 'array',
       
   185 					'readonly'    => true,
       
   186 					'context'     => array( 'view', 'edit', 'embed' ),
       
   187 				),
       
   188 				'categories'     => array(
       
   189 					'description' => __( 'The pattern category slugs.' ),
       
   190 					'type'        => 'array',
       
   191 					'readonly'    => true,
       
   192 					'context'     => array( 'view', 'edit', 'embed' ),
       
   193 				),
       
   194 				'keywords'       => array(
       
   195 					'description' => __( 'The pattern keywords.' ),
       
   196 					'type'        => 'array',
       
   197 					'readonly'    => true,
       
   198 					'context'     => array( 'view', 'edit', 'embed' ),
       
   199 				),
       
   200 				'content'        => array(
       
   201 					'description' => __( 'The pattern content.' ),
       
   202 					'type'        => 'string',
       
   203 					'readonly'    => true,
       
   204 					'context'     => array( 'view', 'edit', 'embed' ),
       
   205 				),
       
   206 				'inserter'       => array(
   247 				'inserter'       => array(
   207 					'description' => __( 'Determines whether the pattern is visible in inserter.' ),
   248 					'description' => __( 'Determines whether the pattern is visible in inserter.' ),
   208 					'type'        => 'boolean',
   249 					'type'        => 'boolean',
   209 					'readonly'    => true,
   250 					'readonly'    => true,
   210 					'context'     => array( 'view', 'edit', 'embed' ),
   251 					'context'     => array( 'view', 'edit', 'embed' ),
   211 				),
   252 				),
       
   253 				'categories'     => array(
       
   254 					'description' => __( 'The pattern category slugs.' ),
       
   255 					'type'        => 'array',
       
   256 					'readonly'    => true,
       
   257 					'context'     => array( 'view', 'edit', 'embed' ),
       
   258 				),
       
   259 				'keywords'       => array(
       
   260 					'description' => __( 'The pattern keywords.' ),
       
   261 					'type'        => 'array',
       
   262 					'readonly'    => true,
       
   263 					'context'     => array( 'view', 'edit', 'embed' ),
       
   264 				),
       
   265 				'block_types'    => array(
       
   266 					'description' => __( 'Block types that the pattern is intended to be used with.' ),
       
   267 					'type'        => 'array',
       
   268 					'readonly'    => true,
       
   269 					'context'     => array( 'view', 'edit', 'embed' ),
       
   270 				),
       
   271 				'post_types'     => array(
       
   272 					'description' => __( 'An array of post types that the pattern is restricted to be used with.' ),
       
   273 					'type'        => 'array',
       
   274 					'readonly'    => true,
       
   275 					'context'     => array( 'view', 'edit', 'embed' ),
       
   276 				),
       
   277 				'template_types' => array(
       
   278 					'description' => __( 'An array of template types where the pattern fits.' ),
       
   279 					'type'        => 'array',
       
   280 					'readonly'    => true,
       
   281 					'context'     => array( 'view', 'edit', 'embed' ),
       
   282 				),
       
   283 				'source'         => array(
       
   284 					'description' => __( 'Where the pattern comes from e.g. core' ),
       
   285 					'type'        => 'string',
       
   286 					'readonly'    => true,
       
   287 					'context'     => array( 'view', 'edit', 'embed' ),
       
   288 					'enum'        => array(
       
   289 						'core',
       
   290 						'plugin',
       
   291 						'theme',
       
   292 						'pattern-directory/core',
       
   293 						'pattern-directory/theme',
       
   294 						'pattern-directory/featured',
       
   295 					),
       
   296 				),
   212 			),
   297 			),
   213 		);
   298 		);
   214 
   299 
   215 		return $this->add_additional_fields_schema( $schema );
   300 		$this->schema = $schema;
       
   301 
       
   302 		return $this->add_additional_fields_schema( $this->schema );
   216 	}
   303 	}
   217 }
   304 }