Make WordPress Core


Ignore:
Timestamp:
09/20/2023 05:25:26 PM (3 years 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.