Skip to content

Commit 9a734f3

Browse files
committed
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. git-svn-id: https://develop.svn.wordpress.org/trunk@56621 602fd350-edb4-49c9-b593-d223f7449a82
1 parent 48b9b6c commit 9a734f3

8 files changed

Lines changed: 284 additions & 67 deletions

File tree

src/wp-includes/block-template-utils.php

Lines changed: 6 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -37,21 +37,15 @@
3737
* }
3838
*/
3939
function 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

5751
/**

src/wp-includes/class-wp-theme.php

Lines changed: 116 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -194,6 +194,25 @@ final class WP_Theme implements ArrayAccess {
194194
*/
195195
private $cache_hash;
196196

197+
/**
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+
197216
/**
198217
* Flag for whether the themes cache bucket should be persistently cached.
199218
*
@@ -262,7 +281,7 @@ public function __construct( $theme_dir, $theme_root, $_child = null ) {
262281
$cache = $this->cache_get( 'theme' );
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 ];
268287
}
@@ -287,35 +306,39 @@ public function __construct( $theme_dir, $theme_root, $_child = null ) {
287306
} else {
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
);
302323
if ( ! file_exists( $this->theme_root ) ) { // Don't cache this one.
303324
$this->errors->add( 'theme_root_missing', __( '<strong>Error:</strong> The themes directory is either empty or does not exist. Please check your installation.' ) );
304325
}
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
);
321344
return;
@@ -345,10 +368,11 @@ public function __construct( $theme_dir, $theme_root, $_child = null ) {
345368
$this->cache_add(
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
);
354378

@@ -378,11 +402,12 @@ public function __construct( $theme_dir, $theme_root, $_child = null ) {
378402
$this->cache_add(
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
);
388413
return;
@@ -419,11 +444,12 @@ public function __construct( $theme_dir, $theme_root, $_child = null ) {
419444
$this->cache_add(
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
);
429455
$this->parent = new WP_Theme( $this->template, $this->theme_root, $this );
@@ -447,11 +473,12 @@ public function __construct( $theme_dir, $theme_root, $_child = null ) {
447473
$_child->cache_add(
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
);
457484
// The two themes actually reference each other with the Template header.
@@ -467,11 +494,12 @@ public function __construct( $theme_dir, $theme_root, $_child = null ) {
467494
$this->cache_add(
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
);
477505
}
@@ -488,11 +516,12 @@ public function __construct( $theme_dir, $theme_root, $_child = null ) {
488516
// We're good. If we didn't retrieve from cache, set it.
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.
498527
if ( isset( $theme_root_template ) ) {
@@ -779,15 +808,16 @@ public function cache_delete() {
779808
foreach ( array( 'theme', 'screenshot', 'headers', 'post_templates' ) as $key ) {
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
}
793823

@@ -1714,6 +1744,37 @@ public static function get_allowed_on_site( $blog_id = null ) {
17141744
return (array) apply_filters( 'site_allowed_themes', $allowed_themes[ $blog_id ], $blog_id );
17151745
}
17161746

1747+
/**
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+
17171778
/**
17181779
* Enables a theme for all sites on the current network.
17191780
*
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
<!-- wp:paragraph -->
2+
<p>Small Header Template Part</p>
3+
<!-- /wp:paragraph -->
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
/*
2+
Theme Name: Block Theme Child Deprecated Path
3+
Theme URI: https://wordpress.org/
4+
Description: For testing purposes only.
5+
Template: block-theme
6+
Version: 1.0.0
7+
Text Domain: block-theme-child-deprecated-path
8+
*/
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
<!-- wp:paragraph -->
2+
<p>Index Template</p>
3+
<!-- /wp:paragraph -->
Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
{
2+
"version": 1,
3+
"settings": {
4+
"color": {
5+
"palette": [
6+
{
7+
"slug": "light",
8+
"name": "Light",
9+
"color": "#f5f7f9"
10+
},
11+
{
12+
"slug": "dark",
13+
"name": "Dark",
14+
"color": "#000"
15+
}
16+
],
17+
"gradients": [
18+
{
19+
"name": "Custom gradient",
20+
"gradient": "linear-gradient(135deg,rgba(0,0,0) 0%,rgb(0,0,0) 100%)",
21+
"slug": "custom-gradient"
22+
}
23+
],
24+
"custom": false,
25+
"customGradient": false
26+
},
27+
"typography": {
28+
"fontSizes": [
29+
{
30+
"name": "Custom",
31+
"slug": "custom",
32+
"size": "100px"
33+
}
34+
],
35+
"customFontSize": false,
36+
"customLineHeight": true
37+
},
38+
"spacing": {
39+
"units": [
40+
"rem"
41+
],
42+
"customPadding": true
43+
},
44+
"blocks": {
45+
"core/paragraph": {
46+
"color": {
47+
"palette": [
48+
{
49+
"slug": "light",
50+
"name": "Light",
51+
"color": "#f5f7f9"
52+
}
53+
]
54+
}
55+
}
56+
}
57+
},
58+
"customTemplates": [
59+
{
60+
"name": "page-home",
61+
"title": "Homepage template"
62+
}
63+
],
64+
"templateParts": [
65+
{
66+
"name": "small-header",
67+
"title": "Small Header",
68+
"area": "header"
69+
}
70+
]
71+
}

0 commit comments

Comments
 (0)