Make WordPress Core

Changeset 56621


Ignore:
Timestamp:
09/19/2023 04:15:52 PM (10 months 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.