[ Index ]

PHP Cross Reference of WordPress Trunk (Updated Daily)

Search

title

Body

[close]

/wp-includes/ -> block-patterns.php (source)

   1  <?php
   2  /**
   3   * Register the block patterns and block patterns categories
   4   *
   5   * @package WordPress
   6   * @since 5.5.0
   7   */
   8  
   9  add_theme_support( 'core-block-patterns' );
  10  
  11  /**
  12   * Registers a new block pattern.
  13   *
  14   * @since 5.5.0
  15   *
  16   * @param string $pattern_name       Block pattern name including namespace.
  17   * @param array  $pattern_properties List of properties for the block pattern.
  18   *                                   See WP_Block_Patterns_Registry::register() for accepted arguments.
  19   * @return bool True if the pattern was registered with success and false otherwise.
  20   */
  21  function register_block_pattern( $pattern_name, $pattern_properties ) {
  22      return WP_Block_Patterns_Registry::get_instance()->register( $pattern_name, $pattern_properties );
  23  }
  24  
  25  /**
  26   * Unregisters a block pattern.
  27   *
  28   * @since 5.5.0
  29   *
  30   * @param string $pattern_name Block pattern name including namespace.
  31   * @return bool True if the pattern was unregistered with success and false otherwise.
  32   */
  33  function unregister_block_pattern( $pattern_name ) {
  34      return WP_Block_Patterns_Registry::get_instance()->unregister( $pattern_name );
  35  }
  36  
  37  /**
  38   * Registers a new pattern category.
  39   *
  40   * @since 5.5.0
  41   *
  42   * @param string $category_name       Pattern category name including namespace.
  43   * @param array  $category_properties List of properties for the block pattern.
  44   *                                    See WP_Block_Pattern_Categories_Registry::register() for
  45   *                                    accepted arguments.
  46   * @return bool True if the pattern category was registered with success and false otherwise.
  47   */
  48  function register_block_pattern_category( $category_name, $category_properties ) {
  49      return WP_Block_Pattern_Categories_Registry::get_instance()->register( $category_name, $category_properties );
  50  }
  51  
  52  /**
  53   * Unregisters a pattern category.
  54   *
  55   * @since 5.5.0
  56   *
  57   * @param string $category_name Pattern category name including namespace.
  58   * @return bool True if the pattern category was unregistered with success and false otherwise.
  59   */
  60  function unregister_block_pattern_category( $category_name ) {
  61      return WP_Block_Pattern_Categories_Registry::get_instance()->unregister( $category_name );
  62  }
  63  
  64  /**
  65   * Registers the core block patterns and categories.
  66   *
  67   * @since 5.5.0
  68   * @since 6.3.0 Added source to core block patterns.
  69   * @access private
  70   */
  71  function _register_core_block_patterns_and_categories() {
  72      $should_register_core_patterns = get_theme_support( 'core-block-patterns' );
  73  
  74      if ( $should_register_core_patterns ) {
  75          $core_block_patterns = array(
  76              'query-standard-posts',
  77              'query-medium-posts',
  78              'query-small-posts',
  79              'query-grid-posts',
  80              'query-large-title-posts',
  81              'query-offset-posts',
  82              'navigation-overlay',
  83              'navigation-overlay-black-bg',
  84              'navigation-overlay-accent-bg',
  85              'navigation-overlay-centered',
  86              'navigation-overlay-centered-with-extras',
  87          );
  88  
  89          foreach ( $core_block_patterns as $core_block_pattern ) {
  90              $pattern           = require __DIR__ . '/block-patterns/' . $core_block_pattern . '.php';
  91              $pattern['source'] = 'core';
  92              register_block_pattern( 'core/' . $core_block_pattern, $pattern );
  93          }
  94      }
  95  
  96      register_block_pattern_category(
  97          'banner',
  98          array(
  99              'label'       => _x( 'Banners', 'Block pattern category' ),
 100              'description' => __( 'Bold sections designed to showcase key content.' ),
 101          )
 102      );
 103      register_block_pattern_category(
 104          'buttons',
 105          array(
 106              'label'       => _x( 'Buttons', 'Block pattern category' ),
 107              'description' => __( 'Patterns that contain buttons and call to actions.' ),
 108          )
 109      );
 110      register_block_pattern_category(
 111          'columns',
 112          array(
 113              'label'       => _x( 'Columns', 'Block pattern category' ),
 114              'description' => __( 'Multi-column patterns with more complex layouts.' ),
 115          )
 116      );
 117      register_block_pattern_category(
 118          'text',
 119          array(
 120              'label'       => _x( 'Text', 'Block pattern category' ),
 121              'description' => __( 'Patterns containing mostly text.' ),
 122          )
 123      );
 124      register_block_pattern_category(
 125          'query',
 126          array(
 127              'label'       => _x( 'Posts', 'Block pattern category' ),
 128              'description' => __( 'Display your latest posts in lists, grids or other layouts.' ),
 129          )
 130      );
 131      register_block_pattern_category(
 132          'featured',
 133          array(
 134              'label'       => _x( 'Featured', 'Block pattern category' ),
 135              'description' => __( 'A set of high quality curated patterns.' ),
 136          )
 137      );
 138      register_block_pattern_category(
 139          'call-to-action',
 140          array(
 141              'label'       => _x( 'Call to action', 'Block pattern category' ),
 142              'description' => __( 'Sections whose purpose is to trigger a specific action.' ),
 143          )
 144      );
 145      register_block_pattern_category(
 146          'team',
 147          array(
 148              'label'       => _x( 'Team', 'Block pattern category' ),
 149              'description' => __( 'A variety of designs to display your team members.' ),
 150          )
 151      );
 152      register_block_pattern_category(
 153          'testimonials',
 154          array(
 155              'label'       => _x( 'Testimonials', 'Block pattern category' ),
 156              'description' => __( 'Share reviews and feedback about your brand/business.' ),
 157          )
 158      );
 159      register_block_pattern_category(
 160          'services',
 161          array(
 162              'label'       => _x( 'Services', 'Block pattern category' ),
 163              'description' => __( 'Briefly describe what your business does and how you can help.' ),
 164          )
 165      );
 166      register_block_pattern_category(
 167          'contact',
 168          array(
 169              'label'       => _x( 'Contact', 'Block pattern category' ),
 170              'description' => __( 'Display your contact information.' ),
 171          )
 172      );
 173      register_block_pattern_category(
 174          'about',
 175          array(
 176              'label'       => _x( 'About', 'Block pattern category' ),
 177              'description' => __( 'Introduce yourself.' ),
 178          )
 179      );
 180      register_block_pattern_category(
 181          'portfolio',
 182          array(
 183              'label'       => _x( 'Portfolio', 'Block pattern category' ),
 184              'description' => __( 'Showcase your latest work.' ),
 185          )
 186      );
 187      register_block_pattern_category(
 188          'gallery',
 189          array(
 190              'label'       => _x( 'Gallery', 'Block pattern category' ),
 191              'description' => __( 'Different layouts for displaying images.' ),
 192          )
 193      );
 194      register_block_pattern_category(
 195          'media',
 196          array(
 197              'label'       => _x( 'Media', 'Block pattern category' ),
 198              'description' => __( 'Different layouts containing video or audio.' ),
 199          )
 200      );
 201      register_block_pattern_category(
 202          'videos',
 203          array(
 204              'label'       => _x( 'Videos', 'Block pattern category' ),
 205              'description' => __( 'Different layouts containing videos.' ),
 206          )
 207      );
 208      register_block_pattern_category(
 209          'audio',
 210          array(
 211              'label'       => _x( 'Audio', 'Block pattern category' ),
 212              'description' => __( 'Different layouts containing audio.' ),
 213          )
 214      );
 215      register_block_pattern_category(
 216          'posts',
 217          array(
 218              'label'       => _x( 'Posts', 'Block pattern category' ),
 219              'description' => __( 'Display your latest posts in lists, grids or other layouts.' ),
 220          )
 221      );
 222      register_block_pattern_category(
 223          'footer',
 224          array(
 225              'label'       => _x( 'Footers', 'Block pattern category' ),
 226              'description' => __( 'A variety of footer designs displaying information and site navigation.' ),
 227          )
 228      );
 229      register_block_pattern_category(
 230          'header',
 231          array(
 232              'label'       => _x( 'Headers', 'Block pattern category' ),
 233              'description' => __( 'A variety of header designs displaying your site title and navigation.' ),
 234          )
 235      );
 236      register_block_pattern_category(
 237          'navigation',
 238          array(
 239              'label'       => _x( 'Navigation', 'Block pattern category' ),
 240              'description' => __( 'A variety of designs displaying site navigation.' ),
 241          )
 242      );
 243  }
 244  
 245  /**
 246   * Normalize the pattern properties to camelCase.
 247   *
 248   * The API's format is snake_case, `register_block_pattern()` expects camelCase.
 249   *
 250   * @since 6.2.0
 251   * @access private
 252   *
 253   * @param array $pattern Pattern as returned from the Pattern Directory API.
 254   * @return array Normalized pattern.
 255   */
 256  function wp_normalize_remote_block_pattern( $pattern ) {
 257      if ( isset( $pattern['block_types'] ) ) {
 258          $pattern['blockTypes'] = $pattern['block_types'];
 259          unset( $pattern['block_types'] );
 260      }
 261  
 262      if ( isset( $pattern['viewport_width'] ) ) {
 263          $pattern['viewportWidth'] = $pattern['viewport_width'];
 264          unset( $pattern['viewport_width'] );
 265      }
 266  
 267      return (array) $pattern;
 268  }
 269  
 270  /**
 271   * Register Core's official patterns from wordpress.org/patterns.
 272   *
 273   * @since 5.8.0
 274   * @since 5.9.0 The $current_screen argument was removed.
 275   * @since 6.2.0 Normalize the pattern from the API (snake_case) to the
 276   *              format expected by `register_block_pattern` (camelCase).
 277   * @since 6.3.0 Add 'pattern-directory/core' to the pattern's 'source'.
 278   *
 279   * @param WP_Screen $deprecated Unused. Formerly the screen that the current request was triggered from.
 280   */
 281  function _load_remote_block_patterns( $deprecated = null ) {
 282      if ( ! empty( $deprecated ) ) {
 283          _deprecated_argument( __FUNCTION__, '5.9.0' );
 284          $current_screen = $deprecated;
 285          if ( ! $current_screen->is_block_editor ) {
 286              return;
 287          }
 288      }
 289  
 290      $supports_core_patterns = get_theme_support( 'core-block-patterns' );
 291  
 292      /**
 293       * Filter to disable remote block patterns.
 294       *
 295       * @since 5.8.0
 296       *
 297       * @param bool $should_load_remote
 298       */
 299      $should_load_remote = apply_filters( 'should_load_remote_block_patterns', true );
 300  
 301      if ( $supports_core_patterns && $should_load_remote ) {
 302          $request         = new WP_REST_Request( 'GET', '/wp/v2/pattern-directory/patterns' );
 303          $core_keyword_id = 11; // 11 is the ID for "core".
 304          $request->set_param( 'keyword', $core_keyword_id );
 305          $response = rest_do_request( $request );
 306          if ( $response->is_error() ) {
 307              return;
 308          }
 309          $patterns = $response->get_data();
 310  
 311          foreach ( $patterns as $pattern ) {
 312              $pattern['source']  = 'pattern-directory/core';
 313              $normalized_pattern = wp_normalize_remote_block_pattern( $pattern );
 314              $pattern_name       = 'core/' . sanitize_title( $normalized_pattern['title'] );
 315              register_block_pattern( $pattern_name, $normalized_pattern );
 316          }
 317      }
 318  }
 319  
 320  /**
 321   * Register `Featured` (category) patterns from wordpress.org/patterns.
 322   *
 323   * @since 5.9.0
 324   * @since 6.2.0 Normalized the pattern from the API (snake_case) to the
 325   *              format expected by `register_block_pattern()` (camelCase).
 326   * @since 6.3.0 Add 'pattern-directory/featured' to the pattern's 'source'.
 327   */
 328  function _load_remote_featured_patterns() {
 329      $supports_core_patterns = get_theme_support( 'core-block-patterns' );
 330  
 331      /** This filter is documented in wp-includes/block-patterns.php */
 332      $should_load_remote = apply_filters( 'should_load_remote_block_patterns', true );
 333  
 334      if ( ! $should_load_remote || ! $supports_core_patterns ) {
 335          return;
 336      }
 337  
 338      $request         = new WP_REST_Request( 'GET', '/wp/v2/pattern-directory/patterns' );
 339      $featured_cat_id = 26; // This is the `Featured` category id from pattern directory.
 340      $request->set_param( 'category', $featured_cat_id );
 341      $response = rest_do_request( $request );
 342      if ( $response->is_error() ) {
 343          return;
 344      }
 345      $patterns = $response->get_data();
 346      $registry = WP_Block_Patterns_Registry::get_instance();
 347      foreach ( $patterns as $pattern ) {
 348          $pattern['source']  = 'pattern-directory/featured';
 349          $normalized_pattern = wp_normalize_remote_block_pattern( $pattern );
 350          $pattern_name       = sanitize_title( $normalized_pattern['title'] );
 351          // Some patterns might be already registered as core patterns with the `core` prefix.
 352          $is_registered = $registry->is_registered( $pattern_name ) || $registry->is_registered( "core/$pattern_name" );
 353          if ( ! $is_registered ) {
 354              register_block_pattern( $pattern_name, $normalized_pattern );
 355          }
 356      }
 357  }
 358  
 359  /**
 360   * Registers patterns from Pattern Directory provided by a theme's
 361   * `theme.json` file.
 362   *
 363   * @since 6.0.0
 364   * @since 6.2.0 Normalized the pattern from the API (snake_case) to the
 365   *              format expected by `register_block_pattern()` (camelCase).
 366   * @since 6.3.0 Add 'pattern-directory/theme' to the pattern's 'source'.
 367   * @access private
 368   */
 369  function _register_remote_theme_patterns() {
 370      /** This filter is documented in wp-includes/block-patterns.php */
 371      if ( ! apply_filters( 'should_load_remote_block_patterns', true ) ) {
 372          return;
 373      }
 374  
 375      if ( ! wp_theme_has_theme_json() ) {
 376          return;
 377      }
 378  
 379      $pattern_settings = wp_get_theme_directory_pattern_slugs();
 380      if ( empty( $pattern_settings ) ) {
 381          return;
 382      }
 383  
 384      $request         = new WP_REST_Request( 'GET', '/wp/v2/pattern-directory/patterns' );
 385      $request['slug'] = $pattern_settings;
 386      $response        = rest_do_request( $request );
 387      if ( $response->is_error() ) {
 388          return;
 389      }
 390      $patterns          = $response->get_data();
 391      $patterns_registry = WP_Block_Patterns_Registry::get_instance();
 392      foreach ( $patterns as $pattern ) {
 393          $pattern['source']  = 'pattern-directory/theme';
 394          $normalized_pattern = wp_normalize_remote_block_pattern( $pattern );
 395          $pattern_name       = sanitize_title( $normalized_pattern['title'] );
 396          // Some patterns might be already registered as core patterns with the `core` prefix.
 397          $is_registered = $patterns_registry->is_registered( $pattern_name ) || $patterns_registry->is_registered( "core/$pattern_name" );
 398          if ( ! $is_registered ) {
 399              register_block_pattern( $pattern_name, $normalized_pattern );
 400          }
 401      }
 402  }
 403  
 404  /**
 405   * Register any patterns that the active theme may provide under its
 406   * `./patterns/` directory.
 407   *
 408   * @since 6.0.0
 409   * @since 6.1.0 The `postTypes` property was added.
 410   * @since 6.2.0 The `templateTypes` property was added.
 411   * @since 6.4.0 Uses the `WP_Theme::get_block_patterns` method.
 412   * @access private
 413   */
 414  function _register_theme_block_patterns() {
 415  
 416      /*
 417       * During the bootstrap process, a check for active and valid themes is run.
 418       * If no themes are returned, the theme's functions.php file will not be loaded,
 419       * which can lead to errors if patterns expect some variables or constants to
 420       * already be set at this point, so bail early if that is the case.
 421       */
 422      if ( empty( wp_get_active_and_valid_themes() ) ) {
 423          return;
 424      }
 425  
 426      /*
 427       * Register patterns for the active theme. If the theme is a child theme,
 428       * let it override any patterns from the parent theme that shares the same slug.
 429       */
 430      $themes   = array();
 431      $theme    = wp_get_theme();
 432      $themes[] = $theme;
 433      if ( $theme->parent() ) {
 434          $themes[] = $theme->parent();
 435      }
 436      $registry = WP_Block_Patterns_Registry::get_instance();
 437  
 438      foreach ( $themes as $theme ) {
 439          $patterns    = $theme->get_block_patterns();
 440          $dirpath     = $theme->get_stylesheet_directory() . '/patterns/';
 441          $text_domain = $theme->get( 'TextDomain' );
 442  
 443          foreach ( $patterns as $file => $pattern_data ) {
 444              if ( $registry->is_registered( $pattern_data['slug'] ) ) {
 445                  continue;
 446              }
 447  
 448              $file_path = $dirpath . $file;
 449  
 450              if ( ! file_exists( $file_path ) ) {
 451                  _doing_it_wrong(
 452                      __FUNCTION__,
 453                      sprintf(
 454                          /* translators: %s: file name. */
 455                          __( 'Could not register file "%s" as a block pattern as the file does not exist.' ),
 456                          $file
 457                      ),
 458                      '6.4.0'
 459                  );
 460                  $theme->delete_pattern_cache();
 461                  continue;
 462              }
 463  
 464              $pattern_data['filePath'] = $file_path;
 465  
 466              // Translate the pattern metadata.
 467              // phpcs:ignore WordPress.WP.I18n.NonSingularStringLiteralText,WordPress.WP.I18n.NonSingularStringLiteralDomain,WordPress.WP.I18n.LowLevelTranslationFunction
 468              $pattern_data['title'] = translate_with_gettext_context( $pattern_data['title'], 'Pattern title', $text_domain );
 469              if ( ! empty( $pattern_data['description'] ) ) {
 470                  // phpcs:ignore WordPress.WP.I18n.NonSingularStringLiteralText,WordPress.WP.I18n.NonSingularStringLiteralDomain,WordPress.WP.I18n.LowLevelTranslationFunction
 471                  $pattern_data['description'] = translate_with_gettext_context( $pattern_data['description'], 'Pattern description', $text_domain );
 472              }
 473  
 474              register_block_pattern( $pattern_data['slug'], $pattern_data );
 475          }
 476      }
 477  }
 478  add_action( 'init', '_register_theme_block_patterns' );


Generated : Wed Jun 24 08:20:11 2026 Cross-referenced by PHPXref