Make WordPress Core


Ignore:
Timestamp:
09/20/2023 05:25:26 PM (8 months ago)
Author:
flixos90
Message:

Themes: Deprecate usage of TEMPLATEPATH and STYLESHEETPATH constants.

While generally the functions get_template_directory() and get_stylesheet_directory() were long recommended to use to get the parent or child theme directory, the TEMPLATEPATH and STYLESHEETPATH constants were still used in a few places in core, most importantly in template related logic.

The remaining usage was problematic as it prevented testability of certain key components of WordPress core.

This changeset replaces all remaining usage with the corresponding functions and effectively marks these constants as deprecated. It also adds test coverage accordingly and even unlocks some existing, previously commented out test coverage to work as expected.

Performance of the new approach has been benchmarked and shows no notable differences. Yet, given that the current theme directories are not expected to change within a regular WordPress page load, the get_template_directory() and get_stylesheet_directory() functions were amended with in-memory caching of the result, unless one of the defining values is being filtered.

Props thekt12, spacedmonkey, mukesh27, aaroncampbell, scribu, lloydbudd, cais, chipbennett, toscho, omarabid, CrazyJaco, DrewAPicture, obenland, wonderboymusic, nacin, helen, dd32, chriscct7, SergeyBiryukov, swissspidy, joemcgill, flixos90.
Fixes #18298.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/tests/phpunit/tests/theme.php

    r54663 r56635  
    3737        parent::set_up();
    3838
     39        // Sets up the `wp-content/themes/` directory to ensure consistency when running tests.
    3940        $this->orig_theme_dir = $wp_theme_directories;
    40         $wp_theme_directories = array( WP_CONTENT_DIR . '/themes' );
     41        $wp_theme_directories = array( WP_CONTENT_DIR . '/themes', realpath( DIR_TESTDATA . '/themedir1' ) );
    4142
    4243        add_filter( 'extra_theme_headers', array( $this, 'theme_data_extra_headers' ) );
     
    283284        for ( $i = 0; $i < 3; $i++ ) {
    284285            foreach ( $themes as $name => $theme ) {
     286                // Skip invalid theme directory names (such as `block_theme-[0.4.0]`).
     287                if ( ! preg_match( '/^[a-z0-9-]+$/', $theme['Stylesheet'] ) ) {
     288                    continue;
     289                }
     290
    285291                // Switch to this theme.
    286292                if ( 2 === $i ) {
     
    290296                }
    291297
    292                 $this->assertSame( $name, get_current_theme() );
     298                $this->assertSame( $theme['Name'], get_current_theme() );
    293299
    294300                // Make sure the various get_* functions return the correct values.
     
    296302                $this->assertSame( $theme['Stylesheet'], get_stylesheet() );
    297303
    298                 $root_fs = get_theme_root();
     304                $root_fs = $theme->get_theme_root();
    299305                $this->assertTrue( is_dir( $root_fs ) );
    300306
    301                 $root_uri = get_theme_root_uri();
     307                $root_uri = $theme->get_theme_root_uri();
    302308                $this->assertNotEmpty( $root_uri );
    303309
     
    310316                $this->assertSame( $root_uri . '/' . get_template(), get_template_directory_uri() );
    311317
    312                 // get_query_template()
     318                // Skip block themes for get_query_template() tests since this test is focused on classic templates.
     319                if ( wp_is_block_theme() && current_theme_supports( 'block-templates' ) ) {
     320                    continue;
     321                }
    313322
    314323                // Template file that doesn't exist.
     
    316325
    317326                // Template files that do exist.
    318                 /*
    319327                foreach ( $theme['Template Files'] as $path ) {
    320                     $file = basename($path, '.php');
    321                     FIXME: untestable because get_query_template() uses TEMPLATEPATH.
    322                     $this->assertSame('', get_query_template($file));
     328                    $file = basename( $path, '.php' );
     329
     330                    // The functions.php file is not a template.
     331                    if ( 'functions' === $file ) {
     332                        continue;
     333                    }
     334
     335                    // Underscores are not supported by `locate_template()`.
     336                    if ( 'taxonomy-post_format' === $file ) {
     337                        $file = 'taxonomy';
     338                    }
     339
     340                    $child_theme_file  = get_stylesheet_directory() . '/' . $file . '.php';
     341                    $parent_theme_file = get_template_directory() . '/' . $file . '.php';
     342                    if ( file_exists( $child_theme_file ) ) {
     343                        $this->assertSame( $child_theme_file, get_query_template( $file ) );
     344                    } elseif ( file_exists( $parent_theme_file ) ) {
     345                        $this->assertSame( $parent_theme_file, get_query_template( $file ) );
     346                    } else {
     347                        $this->assertSame( '', get_query_template( $file ) );
     348                    }
    323349                }
    324                 */
    325350
    326351                // These are kind of tautologies but at least exercise the code.
     
    856881
    857882    /**
     883     * Tests that a theme in the custom test data theme directory is recognized.
     884     *
     885     * @ticket 18298
     886     */
     887    public function test_theme_in_custom_theme_dir_is_valid() {
     888        switch_theme( 'block-theme' );
     889        $this->assertTrue( wp_get_theme()->exists() );
     890    }
     891
     892    /**
     893     * Tests that `is_child_theme()` returns true for child theme.
     894     *
     895     * @ticket 18298
     896     *
     897     * @covers ::is_child_theme
     898     */
     899    public function test_is_child_theme_true() {
     900        switch_theme( 'block-theme-child' );
     901        $this->assertTrue( is_child_theme() );
     902    }
     903
     904    /**
     905     * Tests that `is_child_theme()` returns false for parent theme.
     906     *
     907     * @ticket 18298
     908     *
     909     * @covers ::is_child_theme
     910     */
     911    public function test_is_child_theme_false() {
     912        switch_theme( 'block-theme' );
     913        $this->assertFalse( is_child_theme() );
     914    }
     915
     916    /**
     917     * Tests that the child theme directory is correctly detected.
     918     *
     919     * @ticket 18298
     920     *
     921     * @covers ::get_stylesheet_directory
     922     */
     923    public function test_get_stylesheet_directory() {
     924        switch_theme( 'block-theme-child' );
     925        $this->assertSame( realpath( DIR_TESTDATA ) . '/themedir1/block-theme-child', get_stylesheet_directory() );
     926    }
     927
     928    /**
     929     * Tests that the parent theme directory is correctly detected.
     930     *
     931     * @ticket 18298
     932     *
     933     * @covers ::get_template_directory
     934     */
     935    public function test_get_template_directory() {
     936        switch_theme( 'block-theme-child' );
     937        $this->assertSame( realpath( DIR_TESTDATA ) . '/themedir1/block-theme', get_template_directory() );
     938    }
     939
     940    /**
     941     * Tests that get_stylesheet_directory() behaves correctly with filters.
     942     *
     943     * @ticket 18298
     944     * @dataProvider data_get_stylesheet_directory_with_filter
     945     *
     946     * @covers ::get_stylesheet_directory
     947     *
     948     * @param string   $theme     Theme slug / directory name.
     949     * @param string   $hook_name Filter hook name.
     950     * @param callable $callback  Filter callback.
     951     * @param string   $expected  Expected stylesheet directory with the filter active.
     952     */
     953    public function test_get_stylesheet_directory_with_filter( $theme, $hook_name, $callback, $expected ) {
     954        switch_theme( $theme );
     955
     956        // Add filter, then call get_stylesheet_directory() to compute value.
     957        add_filter( $hook_name, $callback );
     958        $this->assertSame( $expected, get_stylesheet_directory(), 'Stylesheet directory returned incorrect result not considering filters' );
     959
     960        // Remove filter again, then ensure result is recalculated and not the same as before.
     961        remove_filter( $hook_name, $callback );
     962        $this->assertNotSame( $expected, get_stylesheet_directory(), 'Stylesheet directory returned previous value even though filters were removed' );
     963    }
     964
     965    /**
     966     * Data provider for `test_get_stylesheet_directory_with_filter()`.
     967     *
     968     * @return array[]
     969     */
     970    public function data_get_stylesheet_directory_with_filter() {
     971        return array(
     972            'with stylesheet_directory filter' => array(
     973                'block-theme',
     974                'stylesheet_directory',
     975                static function ( $dir ) {
     976                    return str_replace( realpath( DIR_TESTDATA ) . '/themedir1', '/fantasy-dir', $dir );
     977                },
     978                '/fantasy-dir/block-theme',
     979            ),
     980            'with theme_root filter'           => array(
     981                'block-theme',
     982                'theme_root',
     983                static function () {
     984                    return '/fantasy-dir';
     985                },
     986                '/fantasy-dir/block-theme',
     987            ),
     988            'with stylesheet filter'           => array(
     989                'block-theme',
     990                'stylesheet',
     991                static function () {
     992                    return 'another-theme';
     993                },
     994                // Because the theme does not exist, `get_theme_root()` returns the default themes directory.
     995                WP_CONTENT_DIR . '/themes/another-theme',
     996            ),
     997        );
     998    }
     999
     1000    /**
     1001     * Tests that get_template_directory() behaves correctly with filters.
     1002     *
     1003     * @ticket 18298
     1004     * @dataProvider data_get_template_directory_with_filter
     1005     *
     1006     * @covers ::get_template_directory
     1007     *
     1008     * @param string   $theme     Theme slug / directory name.
     1009     * @param string   $hook_name Filter hook name.
     1010     * @param callable $callback  Filter callback.
     1011     * @param string   $expected  Expected template directory with the filter active.
     1012     */
     1013    public function test_get_template_directory_with_filter( $theme, $hook_name, $callback, $expected ) {
     1014        switch_theme( $theme );
     1015
     1016        // Add filter, then call get_template_directory() to compute value.
     1017        add_filter( $hook_name, $callback );
     1018        $this->assertSame( $expected, get_template_directory(), 'Template directory returned incorrect result not considering filters' );
     1019
     1020        // Remove filter again, then ensure result is recalculated and not the same as before.
     1021        remove_filter( $hook_name, $callback );
     1022        $this->assertNotSame( $expected, get_template_directory(), 'Template directory returned previous value even though filters were removed' );
     1023    }
     1024
     1025    /**
     1026     * Data provider for `test_get_template_directory_with_filter()`.
     1027     *
     1028     * @return array[]
     1029     */
     1030    public function data_get_template_directory_with_filter() {
     1031        return array(
     1032            'with template_directory filter' => array(
     1033                'block-theme',
     1034                'template_directory',
     1035                static function ( $dir ) {
     1036                    return str_replace( realpath( DIR_TESTDATA ) . '/themedir1', '/fantasy-dir', $dir );
     1037                },
     1038                '/fantasy-dir/block-theme',
     1039            ),
     1040            'with theme_root filter'         => array(
     1041                'block-theme',
     1042                'theme_root',
     1043                static function () {
     1044                    return '/fantasy-dir';
     1045                },
     1046                '/fantasy-dir/block-theme',
     1047            ),
     1048            'with template filter'           => array(
     1049                'block-theme',
     1050                'template',
     1051                static function () {
     1052                    return 'another-theme';
     1053                },
     1054                // Because the theme does not exist, `get_theme_root()` returns the default themes directory.
     1055                WP_CONTENT_DIR . '/themes/another-theme',
     1056            ),
     1057        );
     1058    }
     1059
     1060    /**
    8581061     * Helper function to ensure that a block theme is available and active.
    8591062     */
Note: See TracChangeset for help on using the changeset viewer.