wp/wp-includes/class-wp-block-patterns-registry.php
changeset 21 48c4eec2b7e6
parent 19 3d72ae0968f4
child 22 8c2e4d02f4ef
equal deleted inserted replaced
20:7b1b88e27a20 21:48c4eec2b7e6
    10 /**
    10 /**
    11  * Class used for interacting with block patterns.
    11  * Class used for interacting with block patterns.
    12  *
    12  *
    13  * @since 5.5.0
    13  * @since 5.5.0
    14  */
    14  */
       
    15 #[AllowDynamicProperties]
    15 final class WP_Block_Patterns_Registry {
    16 final class WP_Block_Patterns_Registry {
    16 	/**
    17 	/**
    17 	 * Registered block patterns array.
    18 	 * Registered block patterns array.
    18 	 *
    19 	 *
    19 	 * @since 5.5.0
    20 	 * @since 5.5.0
    40 	/**
    41 	/**
    41 	 * Registers a block pattern.
    42 	 * Registers a block pattern.
    42 	 *
    43 	 *
    43 	 * @since 5.5.0
    44 	 * @since 5.5.0
    44 	 * @since 5.8.0 Added support for the `blockTypes` property.
    45 	 * @since 5.8.0 Added support for the `blockTypes` property.
       
    46 	 * @since 6.1.0 Added support for the `postTypes` property.
       
    47 	 * @since 6.2.0 Added support for the `templateTypes` property.
       
    48 	 * @since 6.5.0 Added support for the `filePath` property.
    45 	 *
    49 	 *
    46 	 * @param string $pattern_name       Block pattern name including namespace.
    50 	 * @param string $pattern_name       Block pattern name including namespace.
    47 	 * @param array  $pattern_properties {
    51 	 * @param array  $pattern_properties {
    48 	 *     List of properties for the block pattern.
    52 	 *     List of properties for the block pattern.
    49 	 *
    53 	 *
    50 	 *     @type string $title         Required. A human-readable title for the pattern.
    54 	 *     @type string   $title         Required. A human-readable title for the pattern.
    51 	 *     @type string $content       Required. Block HTML markup for the pattern.
    55 	 *     @type string   $content       Optional. Block HTML markup for the pattern.
    52 	 *     @type string $description   Optional. Visually hidden text used to describe the pattern in the
    56 	 *                                   If not provided, the content will be retrieved from the `filePath` if set.
    53 	 *                                 inserter. A description is optional, but is strongly
    57 	 *                                   If both `content` and `filePath` are not set, the pattern will not be registered.
    54 	 *                                 encouraged when the title does not fully describe what the
    58 	 *     @type string   $description   Optional. Visually hidden text used to describe the pattern
    55 	 *                                 pattern does. The description will help users discover the
    59 	 *                                   in the inserter. A description is optional, but is strongly
    56 	 *                                 pattern while searching.
    60 	 *                                   encouraged when the title does not fully describe what the
    57 	 *     @type int    $viewportWidth Optional. The intended width of the pattern to allow for a scaled
    61 	 *                                   pattern does. The description will help users discover the
    58 	 *                                 preview within the pattern inserter.
    62 	 *                                   pattern while searching.
    59 	 *     @type array  $categories    Optional. A list of registered pattern categories used to group block
    63 	 *     @type int      $viewportWidth Optional. The intended width of the pattern to allow for a scaled
    60 	 *                                 patterns. Block patterns can be shown on multiple categories.
    64 	 *                                   preview within the pattern inserter.
    61 	 *                                 A category must be registered separately in order to be used
    65 	 *     @type bool     $inserter      Optional. Determines whether the pattern is visible in inserter.
    62 	 *                                 here.
    66 	 *                                   To hide a pattern so that it can only be inserted programmatically,
    63 	 *     @type array  $blockTypes    Optional. A list of block names including namespace that could use
    67 	 *                                   set this to false. Default true.
    64 	 *                                 the block pattern in certain contexts (placeholder, transforms).
    68 	 *     @type string[] $categories    Optional. A list of registered pattern categories used to group
    65 	 *                                 The block pattern is available in the block editor inserter
    69 	 *                                   block patterns. Block patterns can be shown on multiple categories.
    66 	 *                                 regardless of this list of block names.
    70 	 *                                   A category must be registered separately in order to be used here.
    67 	 *                                 Certain blocks support further specificity besides the block name
    71 	 *     @type string[] $keywords      Optional. A list of aliases or keywords that help users discover
    68 	 *                                 (e.g. for `core/template-part` you can specify areas
    72 	 *                                   the pattern while searching.
    69 	 *                                 like `core/template-part/header` or `core/template-part/footer`).
    73 	 *     @type string[] $blockTypes    Optional. A list of block names including namespace that could use
    70 	 *     @type array  $keywords      Optional. A list of aliases or keywords that help users discover the
    74 	 *                                   the block pattern in certain contexts (placeholder, transforms).
    71 	 *                                 pattern while searching.
    75 	 *                                   The block pattern is available in the block editor inserter
       
    76 	 *                                   regardless of this list of block names.
       
    77 	 *                                   Certain blocks support further specificity besides the block name
       
    78 	 *                                   (e.g. for `core/template-part` you can specify areas
       
    79 	 *                                   like `core/template-part/header` or `core/template-part/footer`).
       
    80 	 *     @type string[] $postTypes     Optional. An array of post types that the pattern is restricted
       
    81 	 *                                   to be used with. The pattern will only be available when editing one
       
    82 	 *                                   of the post types passed on the array. For all the other post types
       
    83 	 *                                   not part of the array the pattern is not available at all.
       
    84 	 *     @type string[] $templateTypes Optional. An array of template types where the pattern fits.
       
    85 	 *     @type string   $filePath      Optional. The full path to the file containing the block pattern content.
    72 	 * }
    86 	 * }
    73 	 * @return bool True if the pattern was registered with success and false otherwise.
    87 	 * @return bool True if the pattern was registered with success and false otherwise.
    74 	 */
    88 	 */
    75 	public function register( $pattern_name, $pattern_properties ) {
    89 	public function register( $pattern_name, $pattern_properties ) {
    76 		if ( ! isset( $pattern_name ) || ! is_string( $pattern_name ) ) {
    90 		if ( ! isset( $pattern_name ) || ! is_string( $pattern_name ) ) {
    89 				'5.5.0'
   103 				'5.5.0'
    90 			);
   104 			);
    91 			return false;
   105 			return false;
    92 		}
   106 		}
    93 
   107 
    94 		if ( ! isset( $pattern_properties['content'] ) || ! is_string( $pattern_properties['content'] ) ) {
   108 		if ( ! isset( $pattern_properties['filePath'] ) ) {
    95 			_doing_it_wrong(
   109 			if ( ! isset( $pattern_properties['content'] ) || ! is_string( $pattern_properties['content'] ) ) {
    96 				__METHOD__,
   110 				_doing_it_wrong(
    97 				__( 'Pattern content must be a string.' ),
   111 					__METHOD__,
    98 				'5.5.0'
   112 					__( 'Pattern content must be a string.' ),
    99 			);
   113 					'5.5.0'
   100 			return false;
   114 				);
       
   115 				return false;
       
   116 			}
   101 		}
   117 		}
   102 
   118 
   103 		$pattern = array_merge(
   119 		$pattern = array_merge(
   104 			$pattern_properties,
   120 			$pattern_properties,
   105 			array( 'name' => $pattern_name )
   121 			array( 'name' => $pattern_name )
   106 		);
   122 		);
       
   123 
   107 		$this->registered_patterns[ $pattern_name ] = $pattern;
   124 		$this->registered_patterns[ $pattern_name ] = $pattern;
   108 
   125 
   109 		// If the pattern is registered inside an action other than `init`, store it
   126 		// If the pattern is registered inside an action other than `init`, store it
   110 		// also to a dedicated array. Used to detect deprecated registrations inside
   127 		// also to a dedicated array. Used to detect deprecated registrations inside
   111 		// `admin_init` or `current_screen`.
   128 		// `admin_init` or `current_screen`.
   140 
   157 
   141 		return true;
   158 		return true;
   142 	}
   159 	}
   143 
   160 
   144 	/**
   161 	/**
       
   162 	 * Prepares the content of a block pattern. If hooked blocks are registered, they get injected into the pattern,
       
   163 	 * when they met the defined criteria.
       
   164 	 *
       
   165 	 * @since 6.4.0
       
   166 	 *
       
   167 	 * @param array $pattern       Registered pattern properties.
       
   168 	 * @param array $hooked_blocks The list of hooked blocks.
       
   169 	 * @return string The content of the block pattern.
       
   170 	 */
       
   171 	private function prepare_content( $pattern, $hooked_blocks ) {
       
   172 		$content = $pattern['content'];
       
   173 
       
   174 		$before_block_visitor = '_inject_theme_attribute_in_template_part_block';
       
   175 		$after_block_visitor  = null;
       
   176 		if ( ! empty( $hooked_blocks ) || has_filter( 'hooked_block_types' ) ) {
       
   177 			$before_block_visitor = make_before_block_visitor( $hooked_blocks, $pattern, 'insert_hooked_blocks_and_set_ignored_hooked_blocks_metadata' );
       
   178 			$after_block_visitor  = make_after_block_visitor( $hooked_blocks, $pattern, 'insert_hooked_blocks_and_set_ignored_hooked_blocks_metadata' );
       
   179 		}
       
   180 		$blocks  = parse_blocks( $content );
       
   181 		$content = traverse_and_serialize_blocks( $blocks, $before_block_visitor, $after_block_visitor );
       
   182 
       
   183 		return $content;
       
   184 	}
       
   185 
       
   186 	/**
       
   187 	 * Retrieves the content of a registered block pattern.
       
   188 	 *
       
   189 	 * @since 6.5.0
       
   190 	 *
       
   191 	 * @param string $pattern_name      Block pattern name including namespace.
       
   192 	 * @param bool   $outside_init_only Optional. Return only patterns registered outside the `init` action. Default false.
       
   193 	 * @return string The content of the block pattern.
       
   194 	 */
       
   195 	private function get_content( $pattern_name, $outside_init_only = false ) {
       
   196 		if ( $outside_init_only ) {
       
   197 			$patterns = &$this->registered_patterns_outside_init;
       
   198 		} else {
       
   199 			$patterns = &$this->registered_patterns;
       
   200 		}
       
   201 		if ( ! isset( $patterns[ $pattern_name ]['content'] ) && isset( $patterns[ $pattern_name ]['filePath'] ) ) {
       
   202 			ob_start();
       
   203 			include $patterns[ $pattern_name ]['filePath'];
       
   204 			$patterns[ $pattern_name ]['content'] = ob_get_clean();
       
   205 			unset( $patterns[ $pattern_name ]['filePath'] );
       
   206 		}
       
   207 		return $patterns[ $pattern_name ]['content'];
       
   208 	}
       
   209 
       
   210 	/**
   145 	 * Retrieves an array containing the properties of a registered block pattern.
   211 	 * Retrieves an array containing the properties of a registered block pattern.
   146 	 *
   212 	 *
   147 	 * @since 5.5.0
   213 	 * @since 5.5.0
   148 	 *
   214 	 *
   149 	 * @param string $pattern_name Block pattern name including namespace.
   215 	 * @param string $pattern_name Block pattern name including namespace.
   152 	public function get_registered( $pattern_name ) {
   218 	public function get_registered( $pattern_name ) {
   153 		if ( ! $this->is_registered( $pattern_name ) ) {
   219 		if ( ! $this->is_registered( $pattern_name ) ) {
   154 			return null;
   220 			return null;
   155 		}
   221 		}
   156 
   222 
   157 		return $this->registered_patterns[ $pattern_name ];
   223 		$pattern            = $this->registered_patterns[ $pattern_name ];
       
   224 		$pattern['content'] = $this->get_content( $pattern_name );
       
   225 		$pattern['content'] = $this->prepare_content( $pattern, get_hooked_blocks() );
       
   226 
       
   227 		return $pattern;
   158 	}
   228 	}
   159 
   229 
   160 	/**
   230 	/**
   161 	 * Retrieves all registered block patterns.
   231 	 * Retrieves all registered block patterns.
   162 	 *
   232 	 *
   165 	 * @param bool $outside_init_only Return only patterns registered outside the `init` action.
   235 	 * @param bool $outside_init_only Return only patterns registered outside the `init` action.
   166 	 * @return array[] Array of arrays containing the registered block patterns properties,
   236 	 * @return array[] Array of arrays containing the registered block patterns properties,
   167 	 *                 and per style.
   237 	 *                 and per style.
   168 	 */
   238 	 */
   169 	public function get_all_registered( $outside_init_only = false ) {
   239 	public function get_all_registered( $outside_init_only = false ) {
   170 		return array_values(
   240 		$patterns      = $outside_init_only
   171 			$outside_init_only
       
   172 				? $this->registered_patterns_outside_init
   241 				? $this->registered_patterns_outside_init
   173 				: $this->registered_patterns
   242 				: $this->registered_patterns;
   174 		);
   243 		$hooked_blocks = get_hooked_blocks();
       
   244 
       
   245 		foreach ( $patterns as $index => $pattern ) {
       
   246 			$pattern['content']            = $this->get_content( $pattern['name'], $outside_init_only );
       
   247 			$patterns[ $index ]['content'] = $this->prepare_content( $pattern, $hooked_blocks );
       
   248 		}
       
   249 
       
   250 		return array_values( $patterns );
   175 	}
   251 	}
   176 
   252 
   177 	/**
   253 	/**
   178 	 * Checks if a block pattern is registered.
   254 	 * Checks if a block pattern is registered.
   179 	 *
   255 	 *
   182 	 * @param string $pattern_name Block pattern name including namespace.
   258 	 * @param string $pattern_name Block pattern name including namespace.
   183 	 * @return bool True if the pattern is registered, false otherwise.
   259 	 * @return bool True if the pattern is registered, false otherwise.
   184 	 */
   260 	 */
   185 	public function is_registered( $pattern_name ) {
   261 	public function is_registered( $pattern_name ) {
   186 		return isset( $this->registered_patterns[ $pattern_name ] );
   262 		return isset( $this->registered_patterns[ $pattern_name ] );
       
   263 	}
       
   264 
       
   265 	public function __wakeup() {
       
   266 		if ( ! $this->registered_patterns ) {
       
   267 			return;
       
   268 		}
       
   269 		if ( ! is_array( $this->registered_patterns ) ) {
       
   270 			throw new UnexpectedValueException();
       
   271 		}
       
   272 		foreach ( $this->registered_patterns as $value ) {
       
   273 			if ( ! is_array( $value ) ) {
       
   274 				throw new UnexpectedValueException();
       
   275 			}
       
   276 		}
       
   277 		$this->registered_patterns_outside_init = array();
   187 	}
   278 	}
   188 
   279 
   189 	/**
   280 	/**
   190 	 * Utility method to retrieve the main instance of the class.
   281 	 * Utility method to retrieve the main instance of the class.
   191 	 *
   282 	 *