Changeset 56765
- Timestamp:
- 10/03/2023 03:16:55 PM (18 months ago)
- Location:
- trunk
- Files:
-
- 5 added
- 5 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/wp-admin/includes/theme.php
r56639 r56765 82 82 do_action( 'delete_theme', $stylesheet ); 83 83 84 $theme = wp_get_theme( $stylesheet ); 85 84 86 $themes_dir = trailingslashit( $themes_dir ); 85 87 $theme_dir = trailingslashit( $themes_dir . $stylesheet ); … … 125 127 WP_Theme::network_disable_theme( $stylesheet ); 126 128 } 129 130 // Clear theme caches. 131 $theme->cache_delete(); 127 132 128 133 // Force refresh of theme update information. -
trunk/src/wp-includes/block-patterns.php
r56738 r56765 320 320 /** 321 321 * Register any patterns that the active theme may provide under its 322 * `./patterns/` directory. Each pattern is defined as a PHP file and defines 323 * its metadata using plugin-style headers. The minimum required definition is: 324 * 325 * /** 326 * * Title: My Pattern 327 * * Slug: my-theme/my-pattern 328 * * 329 * 330 * The output of the PHP source corresponds to the content of the pattern, e.g.: 331 * 332 * <main><p><?php echo "Hello"; ?></p></main> 333 * 334 * If applicable, this will collect from both parent and child theme. 335 * 336 * Other settable fields include: 337 * 338 * - Description 339 * - Viewport Width 340 * - Inserter (yes/no) 341 * - Categories (comma-separated values) 342 * - Keywords (comma-separated values) 343 * - Block Types (comma-separated values) 344 * - Post Types (comma-separated values) 345 * - Template Types (comma-separated values) 322 * `./patterns/` directory. 346 323 * 347 324 * @since 6.0.0 348 325 * @since 6.1.0 The `postTypes` property was added. 349 326 * @since 6.2.0 The `templateTypes` property was added. 327 * @since 6.4.0 Uses the `_wp_get_block_patterns` function. 350 328 * @access private 351 329 */ 352 330 function _register_theme_block_patterns() { 331 /* 332 * Register patterns for the active theme. If the theme is a child theme, 333 * let it override any patterns from the parent theme that shares the same slug. 334 */ 335 $themes = array(); 336 $theme = wp_get_theme(); 337 $themes[] = $theme; 338 if ( $theme->parent() ) { 339 $themes[] = $theme->parent(); 340 } 341 $registry = WP_Block_Patterns_Registry::get_instance(); 342 343 foreach ( $themes as $theme ) { 344 $pattern_data = _wp_get_block_patterns( $theme ); 345 $dirpath = $theme->get_stylesheet_directory() . '/patterns/'; 346 $text_domain = $theme->get( 'TextDomain' ); 347 348 foreach ( $pattern_data['patterns'] as $file => $pattern_data ) { 349 if ( $registry->is_registered( $pattern_data['slug'] ) ) { 350 continue; 351 } 352 353 // The actual pattern content is the output of the file. 354 ob_start(); 355 include $dirpath . $file; 356 $pattern_data['content'] = ob_get_clean(); 357 if ( ! $pattern_data['content'] ) { 358 continue; 359 } 360 361 // Translate the pattern metadata. 362 // phpcs:ignore WordPress.WP.I18n.NonSingularStringLiteralText,WordPress.WP.I18n.NonSingularStringLiteralDomain,WordPress.WP.I18n.LowLevelTranslationFunction 363 $pattern_data['title'] = translate_with_gettext_context( $pattern_data['title'], 'Pattern title', $text_domain ); 364 if ( ! empty( $pattern_data['description'] ) ) { 365 // phpcs:ignore WordPress.WP.I18n.NonSingularStringLiteralText,WordPress.WP.I18n.NonSingularStringLiteralDomain,WordPress.WP.I18n.LowLevelTranslationFunction 366 $pattern_data['description'] = translate_with_gettext_context( $pattern_data['description'], 'Pattern description', $text_domain ); 367 } 368 369 register_block_pattern( $pattern_data['slug'], $pattern_data ); 370 } 371 } 372 } 373 add_action( 'init', '_register_theme_block_patterns' ); 374 375 /** 376 * Gets block pattern data for a specified theme. 377 * Each pattern is defined as a PHP file and defines 378 * its metadata using plugin-style headers. The minimum required definition is: 379 * 380 * /** 381 * * Title: My Pattern 382 * * Slug: my-theme/my-pattern 383 * * 384 * 385 * The output of the PHP source corresponds to the content of the pattern, e.g.: 386 * 387 * <main><p><?php echo "Hello"; ?></p></main> 388 * 389 * If applicable, this will collect from both parent and child theme. 390 * 391 * Other settable fields include: 392 * 393 * - Description 394 * - Viewport Width 395 * - Inserter (yes/no) 396 * - Categories (comma-separated values) 397 * - Keywords (comma-separated values) 398 * - Block Types (comma-separated values) 399 * - Post Types (comma-separated values) 400 * - Template Types (comma-separated values) 401 * 402 * @since 6.4.0 403 * @access private 404 * 405 * @param WP_Theme $theme Theme object. 406 * @return array Block pattern data. 407 */ 408 409 function _wp_get_block_patterns( WP_Theme $theme ) { 410 if ( ! $theme->exists() ) { 411 return array( 412 'version' => false, 413 'patterns' => array(), 414 ); 415 } 416 417 $transient_name = 'wp_theme_patterns_' . $theme->get_stylesheet(); 418 $version = $theme->get( 'Version' ); 419 $can_use_cached = ! wp_is_development_mode( 'theme' ); 420 421 if ( $can_use_cached ) { 422 $pattern_data = get_transient( $transient_name ); 423 if ( is_array( $pattern_data ) && $pattern_data['version'] === $version ) { 424 return $pattern_data; 425 } 426 } 427 428 $pattern_data = array( 429 'version' => $version, 430 'patterns' => array(), 431 ); 432 $dirpath = $theme->get_stylesheet_directory() . '/patterns/'; 433 434 if ( ! file_exists( $dirpath ) ) { 435 if ( $can_use_cached ) { 436 set_transient( $transient_name, $pattern_data ); 437 } 438 return $pattern_data; 439 } 440 $files = glob( $dirpath . '*.php' ); 441 if ( ! $files ) { 442 if ( $can_use_cached ) { 443 set_transient( $transient_name, $pattern_data ); 444 } 445 return $pattern_data; 446 } 447 353 448 $default_headers = array( 354 449 'title' => 'Title', … … 364 459 ); 365 460 366 /* 367 * Register patterns for the active theme. If the theme is a child theme, 368 * let it override any patterns from the parent theme that shares the same slug. 369 */ 370 $themes = array(); 371 $stylesheet = get_stylesheet(); 372 $template = get_template(); 373 if ( $stylesheet !== $template ) { 374 $themes[] = wp_get_theme( $stylesheet ); 375 } 376 $themes[] = wp_get_theme( $template ); 377 378 foreach ( $themes as $theme ) { 379 $dirpath = $theme->get_stylesheet_directory() . '/patterns/'; 380 if ( ! is_dir( $dirpath ) || ! is_readable( $dirpath ) ) { 461 $properties_to_parse = array( 462 'categories', 463 'keywords', 464 'blockTypes', 465 'postTypes', 466 'templateTypes', 467 ); 468 469 foreach ( $files as $file ) { 470 $pattern = get_file_data( $file, $default_headers ); 471 472 if ( empty( $pattern['slug'] ) ) { 473 _doing_it_wrong( 474 __FUNCTION__, 475 sprintf( 476 /* translators: %s: file name. */ 477 __( 'Could not register file "%s" as a block pattern ("Slug" field missing)' ), 478 $file 479 ), 480 '6.0.0' 481 ); 381 482 continue; 382 483 } 383 if ( file_exists( $dirpath ) ) { 384 $files = glob( $dirpath . '*.php' ); 385 if ( $files ) { 386 foreach ( $files as $file ) { 387 $pattern_data = get_file_data( $file, $default_headers ); 388 389 if ( empty( $pattern_data['slug'] ) ) { 390 _doing_it_wrong( 391 '_register_theme_block_patterns', 392 sprintf( 393 /* translators: %s: file name. */ 394 __( 'Could not register file "%s" as a block pattern ("Slug" field missing)' ), 395 $file 396 ), 397 '6.0.0' 398 ); 399 continue; 400 } 401 402 if ( ! preg_match( '/^[A-z0-9\/_-]+$/', $pattern_data['slug'] ) ) { 403 _doing_it_wrong( 404 '_register_theme_block_patterns', 405 sprintf( 406 /* translators: %1s: file name; %2s: slug value found. */ 407 __( 'Could not register file "%1$s" as a block pattern (invalid slug "%2$s")' ), 408 $file, 409 $pattern_data['slug'] 410 ), 411 '6.0.0' 412 ); 413 } 414 415 if ( WP_Block_Patterns_Registry::get_instance()->is_registered( $pattern_data['slug'] ) ) { 416 continue; 417 } 418 419 // Title is a required property. 420 if ( ! $pattern_data['title'] ) { 421 _doing_it_wrong( 422 '_register_theme_block_patterns', 423 sprintf( 424 /* translators: %1s: file name; %2s: slug value found. */ 425 __( 'Could not register file "%s" as a block pattern ("Title" field missing)' ), 426 $file 427 ), 428 '6.0.0' 429 ); 430 continue; 431 } 432 433 // For properties of type array, parse data as comma-separated. 434 foreach ( array( 'categories', 'keywords', 'blockTypes', 'postTypes', 'templateTypes' ) as $property ) { 435 if ( ! empty( $pattern_data[ $property ] ) ) { 436 $pattern_data[ $property ] = array_filter( 437 preg_split( 438 '/[\s,]+/', 439 (string) $pattern_data[ $property ] 440 ) 441 ); 442 } else { 443 unset( $pattern_data[ $property ] ); 444 } 445 } 446 447 // Parse properties of type int. 448 foreach ( array( 'viewportWidth' ) as $property ) { 449 if ( ! empty( $pattern_data[ $property ] ) ) { 450 $pattern_data[ $property ] = (int) $pattern_data[ $property ]; 451 } else { 452 unset( $pattern_data[ $property ] ); 453 } 454 } 455 456 // Parse properties of type bool. 457 foreach ( array( 'inserter' ) as $property ) { 458 if ( ! empty( $pattern_data[ $property ] ) ) { 459 $pattern_data[ $property ] = in_array( 460 strtolower( $pattern_data[ $property ] ), 461 array( 'yes', 'true' ), 462 true 463 ); 464 } else { 465 unset( $pattern_data[ $property ] ); 466 } 467 } 468 469 // Translate the pattern metadata. 470 $text_domain = $theme->get( 'TextDomain' ); 471 // phpcs:ignore WordPress.WP.I18n.NonSingularStringLiteralText,WordPress.WP.I18n.NonSingularStringLiteralDomain,WordPress.WP.I18n.LowLevelTranslationFunction 472 $pattern_data['title'] = translate_with_gettext_context( $pattern_data['title'], 'Pattern title', $text_domain ); 473 if ( ! empty( $pattern_data['description'] ) ) { 474 // phpcs:ignore WordPress.WP.I18n.NonSingularStringLiteralText,WordPress.WP.I18n.NonSingularStringLiteralDomain,WordPress.WP.I18n.LowLevelTranslationFunction 475 $pattern_data['description'] = translate_with_gettext_context( $pattern_data['description'], 'Pattern description', $text_domain ); 476 } 477 478 // The actual pattern content is the output of the file. 479 ob_start(); 480 include $file; 481 $pattern_data['content'] = ob_get_clean(); 482 if ( ! $pattern_data['content'] ) { 483 continue; 484 } 485 486 register_block_pattern( $pattern_data['slug'], $pattern_data ); 487 } 484 485 if ( ! preg_match( '/^[A-z0-9\/_-]+$/', $pattern['slug'] ) ) { 486 _doing_it_wrong( 487 __FUNCTION__, 488 sprintf( 489 /* translators: %1s: file name; %2s: slug value found. */ 490 __( 'Could not register file "%1$s" as a block pattern (invalid slug "%2$s")' ), 491 $file, 492 $pattern['slug'] 493 ), 494 '6.0.0' 495 ); 496 } 497 498 // Title is a required property. 499 if ( ! $pattern['title'] ) { 500 _doing_it_wrong( 501 __FUNCTION__, 502 sprintf( 503 /* translators: %1s: file name. */ 504 __( 'Could not register file "%s" as a block pattern ("Title" field missing)' ), 505 $file 506 ), 507 '6.0.0' 508 ); 509 continue; 510 } 511 512 // For properties of type array, parse data as comma-separated. 513 foreach ( $properties_to_parse as $property ) { 514 if ( ! empty( $pattern[ $property ] ) ) { 515 $pattern[ $property ] = array_filter( wp_parse_list( (string) $pattern[ $property ] ) ); 516 } else { 517 unset( $pattern[ $property ] ); 488 518 } 489 519 } 490 } 491 } 492 add_action( 'init', '_register_theme_block_patterns' ); 520 521 // Parse properties of type int. 522 $property = 'viewportWidth'; 523 if ( ! empty( $pattern[ $property ] ) ) { 524 $pattern[ $property ] = (int) $pattern[ $property ]; 525 } else { 526 unset( $pattern[ $property ] ); 527 } 528 529 // Parse properties of type bool. 530 $property = 'inserter'; 531 if ( ! empty( $pattern[ $property ] ) ) { 532 $pattern[ $property ] = in_array( 533 strtolower( $pattern[ $property ] ), 534 array( 'yes', 'true' ), 535 true 536 ); 537 } else { 538 unset( $pattern[ $property ] ); 539 } 540 541 $key = str_replace( $dirpath, '', $file ); 542 543 $pattern_data['patterns'][ $key ] = $pattern; 544 } 545 546 if ( $can_use_cached ) { 547 set_transient( $transient_name, $pattern_data ); 548 } 549 550 return $pattern_data; 551 } -
trunk/src/wp-includes/class-wp-theme.php
r56727 r56765 822 822 $this->headers = array(); 823 823 $this->__construct( $this->stylesheet, $this->theme_root ); 824 $this->delete_pattern_cache(); 825 } 826 827 /** 828 * Clear block pattern cache. 829 * 830 * @since 6.4.0 831 */ 832 public function delete_pattern_cache() { 833 delete_transient( 'wp_theme_patterns_' . $this->stylesheet ); 824 834 } 825 835 -
trunk/src/wp-includes/theme.php
r56748 r56765 873 873 $wp_stylesheet_path = null; 874 874 $wp_template_path = null; 875 876 // Clear pattern caches. 877 $new_theme->delete_pattern_cache(); 878 $old_theme->delete_pattern_cache(); 875 879 876 880 /** -
trunk/tests/phpunit/tests/theme/themeDir.php
r56759 r56765 186 186 'Block Theme [1.0.0] in subdirectory', 187 187 'Block Theme Deprecated Path', 188 'Block Theme Patterns', 188 189 'Block Theme Post Content Default', 189 190 'Block Theme with defined Typography Fonts',
Note: See TracChangeset
for help on using the changeset viewer.