Make WordPress Core

Changeset 56621


Ignore:
Timestamp:
09/19/2023 04:15:52 PM (3 years ago)
Author:
spacedmonkey
Message:

Themes: Improve performance of get_block_theme_folders function

This commit enhances the performance of the get_block_theme_folders function by introducing a new method called get_block_template_folders within the WP_Theme class. Previously, this function suffered from poor performance due to repeated file lookups using file_exists. The new method implements basic caching, storing the result in the theme's cache, similar to how block themes are cached in the block_theme property (see [55236]).

Additionally, this change improves error handling by checking if a theme exists before attempting to look up the file. It also enhances test coverage.

Props spacedmonkey, thekt12, swissspidy, flixos90, costdev, mukesh27.
Fixes #58319.

Location:
trunk
Files:
7 added
4 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/wp-includes/block-template-utils.php

    r56620 r56621  
    3838 */
    3939function get_block_theme_folders( $theme_stylesheet = null ) {
    40         $theme_name = null === $theme_stylesheet ? get_stylesheet() : $theme_stylesheet;
    41         $root_dir   = get_theme_root( $theme_name );
    42         $theme_dir  = "$root_dir/$theme_name";
    43 
    44         if ( file_exists( $theme_dir . '/block-templates' ) || file_exists( $theme_dir . '/block-template-parts' ) ) {
     40        $theme = wp_get_theme( (string) $theme_stylesheet );
     41        if ( ! $theme->exists() ) {
     42                // Return the default folders if the theme doesn't exist.
    4543                return array(
    46                         'wp_template'      => 'block-templates',
    47                         'wp_template_part' => 'block-template-parts',
     44                        'wp_template'      => 'templates',
     45                        'wp_template_part' => 'parts',
    4846                );
    4947        }
    50 
    51         return array(
    52                 'wp_template'      => 'templates',
    53                 'wp_template_part' => 'parts',
    54         );
     48        return $theme->get_block_template_folders();
    5549}
    5650
  • trunk/src/wp-includes/class-wp-theme.php

    r56523 r56621  
    196196
    197197        /**
     198         * Block template folders.
     199         *
     200         * @since 6.4.0
     201         * @var string[]
     202         */
     203        private $block_template_folders;
     204
     205        /**
     206         * Default values for template folders.
     207         *
     208         * @since 6.4.0
     209         * @var string[]
     210         */
     211        private $default_template_folders = array(
     212                'wp_template'      => 'templates',
     213                'wp_template_part' => 'parts',
     214        );
     215
     216        /**
    198217         * Flag for whether the themes cache bucket should be persistently cached.
    199218         *
    … …  
    263282
    264283                if ( is_array( $cache ) ) {
    265                         foreach ( array( 'block_theme', 'errors', 'headers', 'template' ) as $key ) {
     284                        foreach ( array( 'block_template_folders', 'block_theme', 'errors', 'headers', 'template' ) as $key ) {
    266285                                if ( isset( $cache[ $key ] ) ) {
    267286                                        $this->$key = $cache[ $key ];
    … …  
    288307                                $this->errors = new WP_Error( 'theme_no_stylesheet', __( 'Stylesheet is missing.' ) );
    289308                        }
    290                         $this->template    = $this->stylesheet;
    291                         $this->block_theme = false;
     309                        $this->template               = $this->stylesheet;
     310                        $this->block_theme            = false;
     311                        $this->block_template_folders = $this->default_template_folders;
    292312                        $this->cache_add(
    293313                                'theme',
    294314                                array(
    295                                         'block_theme' => $this->block_theme,
    296                                         'headers'     => $this->headers,
    297                                         'errors'      => $this->errors,
    298                                         'stylesheet'  => $this->stylesheet,
    299                                         'template'    => $this->template,
     315                                        'block_template_folders' => $this->block_template_folders,
     316                                        'block_theme'            => $this->block_theme,
     317                                        'headers'                => $this->headers,
     318                                        'errors'                 => $this->errors,
     319                                        'stylesheet'             => $this->stylesheet,
     320                                        'template'               => $this->template,
    300321                                )
    301322                        );
    … …  
    305326                        return;
    306327                } elseif ( ! is_readable( $this->theme_root . '/' . $theme_file ) ) {
    307                         $this->headers['Name'] = $this->stylesheet;
    308                         $this->errors          = new WP_Error( 'theme_stylesheet_not_readable', __( 'Stylesheet is not readable.' ) );
    309                         $this->template        = $this->stylesheet;
    310                         $this->block_theme     = false;
     328                        $this->headers['Name']        = $this->stylesheet;
     329                        $this->errors                 = new WP_Error( 'theme_stylesheet_not_readable', __( 'Stylesheet is not readable.' ) );
     330                        $this->template               = $this->stylesheet;
     331                        $this->block_theme            = false;
     332                        $this->block_template_folders = $this->default_template_folders;
    311333                        $this->cache_add(
    312334                                'theme',
    313335                                array(
    314                                         'block_theme' => $this->block_theme,
    315                                         'headers'     => $this->headers,
    316                                         'errors'      => $this->errors,
    317                                         'stylesheet'  => $this->stylesheet,
    318                                         'template'    => $this->template,
     336                                        'block_template_folders' => $this->block_template_folders,
     337                                        'block_theme'            => $this->block_theme,
     338                                        'headers'                => $this->headers,
     339                                        'errors'                 => $this->errors,
     340                                        'stylesheet'             => $this->stylesheet,
     341                                        'template'               => $this->template,
    319342                                )
    320343                        );
    … …  
    346369                                'theme',
    347370                                array(
    348                                         'block_theme' => $this->is_block_theme(),
    349                                         'headers'     => $this->headers,
    350                                         'errors'      => $this->errors,
    351                                         'stylesheet'  => $this->stylesheet,
     371                                        'block_template_folders' => $this->get_block_template_folders(),
     372                                        'block_theme'            => $this->is_block_theme(),
     373                                        'headers'                => $this->headers,
     374                                        'errors'                 => $this->errors,
     375                                        'stylesheet'             => $this->stylesheet,
    352376                                )
    353377                        );
    … …  
    379403                                        'theme',
    380404                                        array(
    381                                                 'block_theme' => $this->block_theme,
    382                                                 'headers'     => $this->headers,
    383                                                 'errors'      => $this->errors,
    384                                                 'stylesheet'  => $this->stylesheet,
    385                                                 'template'    => $this->template,
     405                                                'block_template_folders' => $this->get_block_template_folders(),
     406                                                'block_theme'            => $this->block_theme,
     407                                                'headers'                => $this->headers,
     408                                                'errors'                 => $this->errors,
     409                                                'stylesheet'             => $this->stylesheet,
     410                                                'template'               => $this->template,
    386411                                        )
    387412                                );
    … …  
    420445                                        'theme',
    421446                                        array(
    422                                                 'block_theme' => $this->is_block_theme(),
    423                                                 'headers'     => $this->headers,
    424                                                 'errors'      => $this->errors,
    425                                                 'stylesheet'  => $this->stylesheet,
    426                                                 'template'    => $this->template,
     447                                                'block_template_folders' => $this->get_block_template_folders(),
     448                                                'block_theme'            => $this->is_block_theme(),
     449                                                'headers'                => $this->headers,
     450                                                'errors'                 => $this->errors,
     451                                                'stylesheet'             => $this->stylesheet,
     452                                                'template'               => $this->template,
    427453                                        )
    428454                                );
    … …  
    448474                                        'theme',
    449475                                        array(
    450                                                 'block_theme' => $_child->is_block_theme(),
    451                                                 'headers'     => $_child->headers,
    452                                                 'errors'      => $_child->errors,
    453                                                 'stylesheet'  => $_child->stylesheet,
    454                                                 'template'    => $_child->template,
     476                                                'block_template_folders' => $_child->get_block_template_folders(),
     477                                                'block_theme'            => $_child->is_block_theme(),
     478                                                'headers'                => $_child->headers,
     479                                                'errors'                 => $_child->errors,
     480                                                'stylesheet'             => $_child->stylesheet,
     481                                                'template'               => $_child->template,
    455482                                        )
    456483                                );
    … …  
    468495                                                'theme',
    469496                                                array(
    470                                                         'block_theme' => $this->is_block_theme(),
    471                                                         'headers'     => $this->headers,
    472                                                         'errors'      => $this->errors,
    473                                                         'stylesheet'  => $this->stylesheet,
    474                                                         'template'    => $this->template,
     497                                                        'block_template_folders' => $this->get_block_template_folders(),
     498                                                        'block_theme'            => $this->is_block_theme(),
     499                                                        'headers'                => $this->headers,
     500                                                        'errors'                 => $this->errors,
     501                                                        'stylesheet'             => $this->stylesheet,
     502                                                        'template'               => $this->template,
    475503                                                )
    476504                                        );
    … …  
    489517                if ( ! is_array( $cache ) ) {
    490518                        $cache = array(
    491                                 'block_theme' => $this->is_block_theme(),
    492                                 'headers'     => $this->headers,
    493                                 'errors'      => $this->errors,
    494                                 'stylesheet'  => $this->stylesheet,
    495                                 'template'    => $this->template,
     519                                'block_theme'            => $this->is_block_theme(),
     520                                'block_template_folders' => $this->get_block_template_folders(),
     521                                'headers'                => $this->headers,
     522                                'errors'                 => $this->errors,
     523                                'stylesheet'             => $this->stylesheet,
     524                                'template'               => $this->template,
    496525                        );
    497526                        // If the parent theme is in another root, we'll want to cache this. Avoids an entire branch of filesystem calls above.
    … …  
    780809                        wp_cache_delete( $key . '-' . $this->cache_hash, 'themes' );
    781810                }
    782                 $this->template          = null;
    783                 $this->textdomain_loaded = null;
    784                 $this->theme_root_uri    = null;
    785                 $this->parent            = null;
    786                 $this->errors            = null;
    787                 $this->headers_sanitized = null;
    788                 $this->name_translated   = null;
    789                 $this->block_theme       = null;
    790                 $this->headers           = array();
     811                $this->template               = null;
     812                $this->textdomain_loaded      = null;
     813                $this->theme_root_uri         = null;
     814                $this->parent                 = null;
     815                $this->errors                 = null;
     816                $this->headers_sanitized      = null;
     817                $this->name_translated        = null;
     818                $this->block_theme            = null;
     819                $this->block_template_folders = null;
     820                $this->headers                = array();
    791821                $this->__construct( $this->stylesheet, $this->theme_root );
    792822        }
    … …  
    17161746
    17171747        /**
     1748         * Returns the folder names of the block template directories.
     1749         *
     1750         * @since 6.4.0
     1751         *
     1752         * @return string[] {
     1753         *     Folder names used by block themes.
     1754         *
     1755         *     @type string $wp_template      Theme-relative directory name for block templates.
     1756         *     @type string $wp_template_part Theme-relative directory name for block template parts.
     1757         * }
     1758         */
     1759        public function get_block_template_folders() {
     1760                // Return set/cached value if available.
     1761                if ( isset( $this->block_template_folders ) ) {
     1762                        return $this->block_template_folders;
     1763                }
     1764
     1765                $this->block_template_folders = $this->default_template_folders;
     1766
     1767                $stylesheet_directory = $this->get_stylesheet_directory();
     1768                // If the theme uses deprecated block template folders.
     1769                if ( file_exists( $stylesheet_directory . '/block-templates' ) || file_exists( $stylesheet_directory . '/block-template-parts' ) ) {
     1770                        $this->block_template_folders = array(
     1771                                'wp_template'      => 'block-templates',
     1772                                'wp_template_part' => 'block-template-parts',
     1773                        );
     1774                }
     1775                return $this->block_template_folders;
     1776        }
     1777
     1778        /**
    17181779         * Enables a theme for all sites on the current network.
    17191780         *
  • trunk/tests/phpunit/tests/block-template.php

    r56559 r56621  
    277277
    278278        /**
     279         * @ticket 58319
     280         *
     281         * @covers ::get_block_theme_folders
     282         *
     283         * @dataProvider data_get_block_theme_folders
     284         *
     285         * @param string   $theme    The theme's stylesheet.
     286         * @param string[] $expected The expected associative array of block theme folders.
     287         */
     288        public function test_get_block_theme_folders( $theme, $expected ) {
     289                $wp_theme = wp_get_theme( $theme );
     290                $wp_theme->cache_delete(); // Clear cache.
     291
     292                $this->assertSame( $expected, get_block_theme_folders( $theme ), 'Incorrect block theme folders were retrieved.' );
     293                $reflection = new ReflectionMethod( $wp_theme, 'cache_get' );
     294                $reflection->setAccessible( true );
     295                $theme_cache  = $reflection->invoke( $wp_theme, 'theme' );
     296                $cached_value = $theme_cache['block_template_folders'];
     297                $reflection->setAccessible( false );
     298
     299                $this->assertSame( $expected, $cached_value, 'The cached value is incorrect.' );
     300        }
     301
     302        /**
     303         * Data provider.
     304         *
     305         * @return array[]
     306         */
     307        public function data_get_block_theme_folders() {
     308                return array(
     309                        'block-theme'                       => array(
     310                                'block-theme',
     311                                array(
     312                                        'wp_template'      => 'templates',
     313                                        'wp_template_part' => 'parts',
     314                                ),
     315                        ),
     316                        'block-theme-deprecated-path'       => array(
     317                                'block-theme-deprecated-path',
     318                                array(
     319                                        'wp_template'      => 'block-templates',
     320                                        'wp_template_part' => 'block-template-parts',
     321                                ),
     322                        ),
     323                        'block-theme-child'                 => array(
     324                                'block-theme-child',
     325                                array(
     326                                        'wp_template'      => 'templates',
     327                                        'wp_template_part' => 'parts',
     328                                ),
     329                        ),
     330                        'block-theme-child-deprecated-path' => array(
     331                                'block-theme-child-deprecated-path',
     332                                array(
     333                                        'wp_template'      => 'block-templates',
     334                                        'wp_template_part' => 'block-template-parts',
     335                                ),
     336                        ),
     337                        'this-is-an-invalid-theme'          => array(
     338                                'this-is-an-invalid-theme',
     339                                array(
     340                                        'wp_template'      => 'templates',
     341                                        'wp_template_part' => 'parts',
     342                                ),
     343                        ),
     344                        'null'                              => array(
     345                                null,
     346                                array(
     347                                        'wp_template'      => 'templates',
     348                                        'wp_template_part' => 'parts',
     349                                ),
     350                        ),
     351                );
     352        }
     353
     354        /**
    279355         * Registers a test block to log `in_the_loop()` results.
    280356         *
  • trunk/tests/phpunit/tests/theme/themeDir.php

    r56548 r56621  
    177177                        'Block Theme',
    178178                        'Block Theme Child Theme',
     179                        'Block Theme Child Deprecated Path',
    179180                        'Block Theme Child with no theme.json',
    180181                        'Block Theme Child Theme With Fluid Layout',
Note: See TracChangeset for help on using the changeset viewer.