Changeset 56500
- Timestamp:
- 08/31/2023 09:47:40 PM (11 months ago)
- Location:
- trunk
- Files:
-
- 42 added
- 1 deleted
- 8 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/phpcs.xml.dist
r56392 r56500 260 260 <element value="WP_Tests_Image_Resize_UnitTestCase"/> 261 261 <element value="WP_Theme_UnitTestCase"/> 262 262 263 263 264 <!-- Mock classes. --> -
trunk/src/wp-admin/includes/admin-filters.php
r56199 r56500 169 169 // Append '(Draft)' to draft page titles in the privacy page dropdown. 170 170 add_filter( 'list_pages', '_wp_privacy_settings_filter_draft_page_titles', 10, 2 ); 171 172 173 -
trunk/src/wp-includes/block-editor.php
r56047 r56500 362 362 ob_start(); 363 363 wp_print_styles(); 364 364 365 $styles = ob_get_clean(); 365 366 -
trunk/src/wp-includes/default-filters.php
r56140 r56500 359 359 add_action( 'after_switch_theme', '_wp_sidebars_changed' ); 360 360 add_action( 'wp_print_styles', 'print_emoji_styles' ); 361 add_action( 'plugins_loaded', '_wp_theme_json_webfonts_handler' );362 361 363 362 if ( isset( $_GET['replytocom'] ) ) { … … 720 719 add_action( 'init', 'wp_create_initial_post_meta' ); 721 720 721 722 723 722 724 unset( $filter, $action ); -
trunk/src/wp-includes/deprecated.php
r56249 r56500 5368 5368 return $colors; 5369 5369 } 5370 5371 5372 5373 5374 5375 5376 5377 5378 5379 5380 5381 5382 5383 5384 5385 5386 5387 5388 5389 5390 5391 5392 5393 5394 5395 5396 5397 5398 5399 5400 5401 5402 5403 5404 5405 5406 5407 5408 5409 5410 5411 5412 5413 5414 5415 5416 5417 5418 5419 5420 5421 5422 5423 5424 5425 5426 5427 5428 5429 5430 5431 5432 5433 5434 5435 5436 5437 5438 5439 5440 5441 5442 5443 5444 5445 5446 5447 5448 5449 5450 5451 5452 5453 5454 5455 5456 5457 5458 5459 5460 5461 5462 5463 5464 5465 5466 5467 5468 5469 5470 5471 5472 5473 5474 5475 5476 5477 5478 5479 5480 5481 5482 5483 5484 5485 5486 5487 5488 5489 5490 5491 5492 5493 5494 5495 5496 5497 5498 5499 5500 5501 5502 5503 5504 5505 5506 5507 5508 5509 5510 5511 5512 5513 5514 5515 5516 5517 5518 5519 5520 5521 5522 5523 5524 5525 5526 5527 5528 5529 5530 5531 5532 5533 5534 5535 5536 5537 5538 5539 5540 5541 5542 5543 5544 5545 5546 5547 5548 5549 5550 5551 5552 5553 5554 5555 5556 5557 5558 5559 5560 5561 5562 5563 5564 5565 5566 5567 5568 5569 5570 5571 5572 5573 5574 5575 5576 5577 5578 5579 5580 5581 5582 5583 5584 5585 5586 5587 5588 5589 5590 5591 5592 5593 5594 5595 5596 5597 5598 5599 5600 5601 5602 5603 5604 5605 5606 5607 5608 5609 5610 5611 5612 5613 5614 5615 5616 5617 5618 5619 5620 5621 5622 5623 5624 5625 5626 5627 5628 5629 5630 5631 5632 5633 5634 5635 5636 5637 5638 5639 5640 5641 5642 5643 5644 5645 5646 5647 5648 5649 5650 5651 5652 5653 5654 5655 5656 5657 5658 5659 5660 5661 5662 5663 5664 5665 5666 5667 5668 5669 5670 5671 5672 5673 5674 5675 5676 5677 5678 5679 5680 5681 5682 5683 5684 5685 5686 5687 5688 5689 5690 5691 5692 5693 5694 5695 5696 5697 5698 5699 5700 5701 5702 5703 5704 5705 5706 5707 5708 5709 5710 5711 5712 5713 5714 5715 5716 5717 5718 5719 5720 5721 5722 5723 5724 5725 5726 5727 5728 5729 5730 5731 5732 5733 5734 5735 5736 5737 5738 5739 5740 5741 5742 5743 5744 5745 5746 5747 5748 5749 5750 5751 5752 5753 5754 5755 5756 5757 5758 5759 5760 5761 5762 5763 5764 5765 5766 5767 5768 5769 5770 5771 5772 5773 5774 5775 5776 5777 5778 5779 5780 5781 5782 5783 5784 5785 5786 5787 5788 5789 5790 5791 5792 5793 5794 5795 5796 5797 5798 5799 5800 5801 5802 5803 5804 5805 5806 5807 5808 5809 5810 5811 5812 5813 5814 5815 5816 5817 5818 5819 5820 5821 5822 5823 5824 5825 5826 5827 5828 5829 5830 5831 5832 5833 5834 5835 5836 5837 5838 5839 5840 5841 5842 5843 5844 5845 5846 5847 5848 5849 5850 5851 5852 5853 5854 5855 5856 5857 5858 5859 5860 5861 5862 5863 5864 5865 5866 5867 5868 5869 5870 5871 5872 -
trunk/src/wp-includes/script-loader.php
r56496 r56500 3225 3225 3226 3226 /** 3227 * Runs the theme.json webfonts handler.3228 *3229 * Using `WP_Theme_JSON_Resolver`, it gets the fonts defined3230 * in the `theme.json` for the current selection and style3231 * variations, validates the font-face properties, generates3232 * the '@font-face' style declarations, and then enqueues the3233 * styles for both the editor and front-end.3234 *3235 * Design Notes:3236 * This is not a public API, but rather an internal handler.3237 * A future public Webfonts API will replace this stopgap code.3238 *3239 * This code design is intentional.3240 * a. It hides the inner-workings.3241 * b. It does not expose API ins or outs for consumption.3242 * c. It only works with a theme's `theme.json`.3243 *3244 * Why?3245 * a. To avoid backwards-compatibility issues when3246 * the Webfonts API is introduced in Core.3247 * b. To make `fontFace` declarations in `theme.json` work.3248 *3249 * @link https://github.com/WordPress/gutenberg/issues/404723250 *3251 * @since 6.0.03252 * @access private3253 */3254 function _wp_theme_json_webfonts_handler() {3255 // Block themes are unavailable during installation.3256 if ( wp_installing() ) {3257 return;3258 }3259 3260 if ( ! wp_theme_has_theme_json() ) {3261 return;3262 }3263 3264 // Webfonts to be processed.3265 $registered_webfonts = array();3266 3267 /**3268 * Gets the webfonts from theme.json.3269 *3270 * @since 6.0.03271 *3272 * @return array Array of defined webfonts.3273 */3274 $fn_get_webfonts_from_theme_json = static function() {3275 // Get settings from theme.json.3276 $settings = WP_Theme_JSON_Resolver::get_merged_data()->get_settings();3277 3278 // If in the editor, add webfonts defined in variations.3279 if ( is_admin() || ( defined( 'REST_REQUEST' ) && REST_REQUEST ) ) {3280 $variations = WP_Theme_JSON_Resolver::get_style_variations();3281 foreach ( $variations as $variation ) {3282 // Skip if fontFamilies are not defined in the variation.3283 if ( empty( $variation['settings']['typography']['fontFamilies'] ) ) {3284 continue;3285 }3286 3287 // Initialize the array structure.3288 if ( empty( $settings['typography'] ) ) {3289 $settings['typography'] = array();3290 }3291 if ( empty( $settings['typography']['fontFamilies'] ) ) {3292 $settings['typography']['fontFamilies'] = array();3293 }3294 if ( empty( $settings['typography']['fontFamilies']['theme'] ) ) {3295 $settings['typography']['fontFamilies']['theme'] = array();3296 }3297 3298 // Combine variations with settings. Remove duplicates.3299 $settings['typography']['fontFamilies']['theme'] = array_merge( $settings['typography']['fontFamilies']['theme'], $variation['settings']['typography']['fontFamilies']['theme'] );3300 $settings['typography']['fontFamilies'] = array_unique( $settings['typography']['fontFamilies'] );3301 }3302 }3303 3304 // Bail out early if there are no settings for webfonts.3305 if ( empty( $settings['typography']['fontFamilies'] ) ) {3306 return array();3307 }3308 3309 $webfonts = array();3310 3311 // Look for fontFamilies.3312 foreach ( $settings['typography']['fontFamilies'] as $font_families ) {3313 foreach ( $font_families as $font_family ) {3314 3315 // Skip if fontFace is not defined.3316 if ( empty( $font_family['fontFace'] ) ) {3317 continue;3318 }3319 3320 // Skip if fontFace is not an array of webfonts.3321 if ( ! is_array( $font_family['fontFace'] ) ) {3322 continue;3323 }3324 3325 $webfonts = array_merge( $webfonts, $font_family['fontFace'] );3326 }3327 }3328 3329 return $webfonts;3330 };3331 3332 /**3333 * Transforms each 'src' into an URI by replacing 'file:./'3334 * placeholder from theme.json.3335 *3336 * The absolute path to the webfont file(s) cannot be defined in3337 * theme.json. `file:./` is the placeholder which is replaced by3338 * the theme's URL path to the theme's root.3339 *3340 * @since 6.0.03341 *3342 * @param array $src Webfont file(s) `src`.3343 * @return array Webfont's `src` in URI.3344 */3345 $fn_transform_src_into_uri = static function( array $src ) {3346 foreach ( $src as $key => $url ) {3347 // Tweak the URL to be relative to the theme root.3348 if ( ! str_starts_with( $url, 'file:./' ) ) {3349 continue;3350 }3351 3352 $src[ $key ] = get_theme_file_uri( str_replace( 'file:./', '', $url ) );3353 }3354 3355 return $src;3356 };3357 3358 /**3359 * Converts the font-face properties (i.e. keys) into kebab-case.3360 *3361 * @since 6.0.03362 *3363 * @param array $font_face Font face to convert.3364 * @return array Font faces with each property in kebab-case format.3365 */3366 $fn_convert_keys_to_kebab_case = static function( array $font_face ) {3367 foreach ( $font_face as $property => $value ) {3368 $kebab_case = _wp_to_kebab_case( $property );3369 $font_face[ $kebab_case ] = $value;3370 if ( $kebab_case !== $property ) {3371 unset( $font_face[ $property ] );3372 }3373 }3374 3375 return $font_face;3376 };3377 3378 /**3379 * Validates a webfont.3380 *3381 * @since 6.0.03382 *3383 * @param array $webfont The webfont arguments.3384 * @return array|false The validated webfont arguments, or false if the webfont is invalid.3385 */3386 $fn_validate_webfont = static function( $webfont ) {3387 $webfont = wp_parse_args(3388 $webfont,3389 array(3390 'font-family' => '',3391 'font-style' => 'normal',3392 'font-weight' => '400',3393 'font-display' => 'fallback',3394 'src' => array(),3395 )3396 );3397 3398 // Check the font-family.3399 if ( empty( $webfont['font-family'] ) || ! is_string( $webfont['font-family'] ) ) {3400 trigger_error( __( 'Webfont font family must be a non-empty string.' ) );3401 3402 return false;3403 }3404 3405 // Check that the `src` property is defined and a valid type.3406 if ( empty( $webfont['src'] ) || ( ! is_string( $webfont['src'] ) && ! is_array( $webfont['src'] ) ) ) {3407 trigger_error( __( 'Webfont src must be a non-empty string or an array of strings.' ) );3408 3409 return false;3410 }3411 3412 // Validate the `src` property.3413 foreach ( (array) $webfont['src'] as $src ) {3414 if ( ! is_string( $src ) || '' === trim( $src ) ) {3415 trigger_error( __( 'Each webfont src must be a non-empty string.' ) );3416 3417 return false;3418 }3419 }3420 3421 // Check the font-weight.3422 if ( ! is_string( $webfont['font-weight'] ) && ! is_int( $webfont['font-weight'] ) ) {3423 trigger_error( __( 'Webfont font weight must be a properly formatted string or integer.' ) );3424 3425 return false;3426 }3427 3428 // Check the font-display.3429 if ( ! in_array( $webfont['font-display'], array( 'auto', 'block', 'fallback', 'optional', 'swap' ), true ) ) {3430 $webfont['font-display'] = 'fallback';3431 }3432 3433 $valid_props = array(3434 'ascend-override',3435 'descend-override',3436 'font-display',3437 'font-family',3438 'font-stretch',3439 'font-style',3440 'font-weight',3441 'font-variant',3442 'font-feature-settings',3443 'font-variation-settings',3444 'line-gap-override',3445 'size-adjust',3446 'src',3447 'unicode-range',3448 );3449 3450 foreach ( $webfont as $prop => $value ) {3451 if ( ! in_array( $prop, $valid_props, true ) ) {3452 unset( $webfont[ $prop ] );3453 }3454 }3455 3456 return $webfont;3457 };3458 3459 /**3460 * Registers webfonts declared in theme.json.3461 *3462 * @since 6.0.03463 *3464 * @uses $registered_webfonts To access and update the registered webfonts registry (passed by reference).3465 * @uses $fn_get_webfonts_from_theme_json To run the function that gets the webfonts from theme.json.3466 * @uses $fn_convert_keys_to_kebab_case To run the function that converts keys into kebab-case.3467 * @uses $fn_validate_webfont To run the function that validates each font-face (webfont) from theme.json.3468 */3469 $fn_register_webfonts = static function() use ( &$registered_webfonts, $fn_get_webfonts_from_theme_json, $fn_convert_keys_to_kebab_case, $fn_validate_webfont, $fn_transform_src_into_uri ) {3470 $registered_webfonts = array();3471 3472 foreach ( $fn_get_webfonts_from_theme_json() as $webfont ) {3473 if ( ! is_array( $webfont ) ) {3474 continue;3475 }3476 3477 $webfont = $fn_convert_keys_to_kebab_case( $webfont );3478 3479 $webfont = $fn_validate_webfont( $webfont );3480 3481 $webfont['src'] = $fn_transform_src_into_uri( (array) $webfont['src'] );3482 3483 // Skip if not valid.3484 if ( empty( $webfont ) ) {3485 continue;3486 }3487 3488 $registered_webfonts[] = $webfont;3489 }3490 };3491 3492 /**3493 * Orders 'src' items to optimize for browser support.3494 *3495 * @since 6.0.03496 *3497 * @param array $webfont Webfont to process.3498 * @return array Ordered `src` items.3499 */3500 $fn_order_src = static function( array $webfont ) {3501 $src = array();3502 $src_ordered = array();3503 3504 foreach ( $webfont['src'] as $url ) {3505 // Add data URIs first.3506 if ( str_starts_with( trim( $url ), 'data:' ) ) {3507 $src_ordered[] = array(3508 'url' => $url,3509 'format' => 'data',3510 );3511 continue;3512 }3513 $format = pathinfo( $url, PATHINFO_EXTENSION );3514 $src[ $format ] = $url;3515 }3516 3517 // Add woff2.3518 if ( ! empty( $src['woff2'] ) ) {3519 $src_ordered[] = array(3520 'url' => sanitize_url( $src['woff2'] ),3521 'format' => 'woff2',3522 );3523 }3524 3525 // Add woff.3526 if ( ! empty( $src['woff'] ) ) {3527 $src_ordered[] = array(3528 'url' => sanitize_url( $src['woff'] ),3529 'format' => 'woff',3530 );3531 }3532 3533 // Add ttf.3534 if ( ! empty( $src['ttf'] ) ) {3535 $src_ordered[] = array(3536 'url' => sanitize_url( $src['ttf'] ),3537 'format' => 'truetype',3538 );3539 }3540 3541 // Add eot.3542 if ( ! empty( $src['eot'] ) ) {3543 $src_ordered[] = array(3544 'url' => sanitize_url( $src['eot'] ),3545 'format' => 'embedded-opentype',3546 );3547 }3548 3549 // Add otf.3550 if ( ! empty( $src['otf'] ) ) {3551 $src_ordered[] = array(3552 'url' => sanitize_url( $src['otf'] ),3553 'format' => 'opentype',3554 );3555 }3556 $webfont['src'] = $src_ordered;3557 3558 return $webfont;3559 };3560 3561 /**3562 * Compiles the 'src' into valid CSS.3563 *3564 * @since 6.0.03565 * @since 6.2.0 Removed local() CSS.3566 *3567 * @param string $font_family Font family.3568 * @param array $value Value to process.3569 * @return string The CSS.3570 */3571 $fn_compile_src = static function( $font_family, array $value ) {3572 $src = '';3573 3574 foreach ( $value as $item ) {3575 $src .= ( 'data' === $item['format'] )3576 ? ", url({$item['url']})"3577 : ", url('{$item['url']}') format('{$item['format']}')";3578 }3579 3580 $src = ltrim( $src, ', ' );3581 3582 return $src;3583 };3584 3585 /**3586 * Compiles the font variation settings.3587 *3588 * @since 6.0.03589 *3590 * @param array $font_variation_settings Array of font variation settings.3591 * @return string The CSS.3592 */3593 $fn_compile_variations = static function( array $font_variation_settings ) {3594 $variations = '';3595 3596 foreach ( $font_variation_settings as $key => $value ) {3597 $variations .= "$key $value";3598 }3599 3600 return $variations;3601 };3602 3603 /**3604 * Builds the font-family's CSS.3605 *3606 * @since 6.0.03607 *3608 * @uses $fn_compile_src To run the function that compiles the src.3609 * @uses $fn_compile_variations To run the function that compiles the variations.3610 *3611 * @param array $webfont Webfont to process.3612 * @return string This font-family's CSS.3613 */3614 $fn_build_font_face_css = static function( array $webfont ) use ( $fn_compile_src, $fn_compile_variations ) {3615 $css = '';3616 3617 // Wrap font-family in quotes if it contains spaces.3618 if (3619 str_contains( $webfont['font-family'], ' ' ) &&3620 ! str_contains( $webfont['font-family'], '"' ) &&3621 ! str_contains( $webfont['font-family'], "'" )3622 ) {3623 $webfont['font-family'] = '"' . $webfont['font-family'] . '"';3624 }3625 3626 foreach ( $webfont as $key => $value ) {3627 /*3628 * Skip "provider", since it's for internal API use,3629 * and not a valid CSS property.3630 */3631 if ( 'provider' === $key ) {3632 continue;3633 }3634 3635 // Compile the "src" parameter.3636 if ( 'src' === $key ) {3637 $value = $fn_compile_src( $webfont['font-family'], $value );3638 }3639 3640 // If font-variation-settings is an array, convert it to a string.3641 if ( 'font-variation-settings' === $key && is_array( $value ) ) {3642 $value = $fn_compile_variations( $value );3643 }3644 3645 if ( ! empty( $value ) ) {3646 $css .= "$key:$value;";3647 }3648 }3649 3650 return $css;3651 };3652 3653 /**3654 * Gets the '@font-face' CSS styles for locally-hosted font files.3655 *3656 * @since 6.0.03657 *3658 * @uses $registered_webfonts To access and update the registered webfonts registry (passed by reference).3659 * @uses $fn_order_src To run the function that orders the src.3660 * @uses $fn_build_font_face_css To run the function that builds the font-face CSS.3661 *3662 * @return string The `@font-face` CSS.3663 */3664 $fn_get_css = static function() use ( &$registered_webfonts, $fn_order_src, $fn_build_font_face_css ) {3665 $css = '';3666 3667 foreach ( $registered_webfonts as $webfont ) {3668 // Order the webfont's `src` items to optimize for browser support.3669 $webfont = $fn_order_src( $webfont );3670 3671 // Build the @font-face CSS for this webfont.3672 $css .= '@font-face{' . $fn_build_font_face_css( $webfont ) . '}';3673 }3674 3675 return $css;3676 };3677 3678 /**3679 * Generates and enqueues webfonts styles.3680 *3681 * @since 6.0.03682 *3683 * @uses $fn_get_css To run the function that gets the CSS.3684 */3685 $fn_generate_and_enqueue_styles = static function() use ( $fn_get_css ) {3686 // Generate the styles.3687 $styles = $fn_get_css();3688 3689 // Bail out if there are no styles to enqueue.3690 if ( '' === $styles ) {3691 return;3692 }3693 3694 // Enqueue the stylesheet.3695 wp_register_style( 'wp-webfonts', '' );3696 wp_enqueue_style( 'wp-webfonts' );3697 3698 // Add the styles to the stylesheet.3699 wp_add_inline_style( 'wp-webfonts', $styles );3700 };3701 3702 /**3703 * Generates and enqueues editor styles.3704 *3705 * @since 6.0.03706 *3707 * @uses $fn_get_css To run the function that gets the CSS.3708 */3709 $fn_generate_and_enqueue_editor_styles = static function() use ( $fn_get_css ) {3710 // Generate the styles.3711 $styles = $fn_get_css();3712 3713 // Bail out if there are no styles to enqueue.3714 if ( '' === $styles ) {3715 return;3716 }3717 3718 wp_add_inline_style( 'wp-block-library', $styles );3719 };3720 3721 add_action( 'wp_loaded', $fn_register_webfonts );3722 add_action( 'wp_enqueue_scripts', $fn_generate_and_enqueue_styles );3723 add_action( 'admin_init', $fn_generate_and_enqueue_editor_styles );3724 }3725 3726 /**3727 3227 * Loads classic theme styles on classic themes in the frontend. 3728 3228 * -
trunk/src/wp-settings.php
r56434 r56500 361 361 require ABSPATH . WPINC . '/style-engine/class-wp-style-engine-css-rules-store.php'; 362 362 require ABSPATH . WPINC . '/style-engine/class-wp-style-engine-processor.php'; 363 364 365 363 366 364 367 $GLOBALS['wp_embed'] = new WP_Embed(); -
trunk/tests/phpunit/tests/theme/themeDir.php
r55294 r56500 186 186 'Block Theme [1.0.0] in subdirectory', 187 187 'Block Theme Deprecated Path', 188 ' Webfonts theme',188 '', 189 189 'Empty `fontFace` in theme.json - no webfonts defined', 190 190 'A theme with the Update URI header',
Note: See TracChangeset
for help on using the changeset viewer.