-
Notifications
You must be signed in to change notification settings - Fork 2.7k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Use a cache for block templates and block template parts content #5463
base: trunk
Are you sure you want to change the base?
Changes from all commits
d805e9c
b2408fc
d718931
ad18c94
fd3671f
af0de47
0adf093
fa387c8
a262dab
ed704e6
4414d8b
d0f971f
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -507,6 +507,73 @@ function _remove_theme_attribute_from_template_part_block( &$block ) { | |
} | ||
} | ||
|
||
/** | ||
* Gets the contents for the given template file path. | ||
* | ||
* @since 6.4.0 | ||
* @access private | ||
* | ||
* @param string $template_file_path Absolute path to a theme template file. | ||
* @return string The template file contents. | ||
*/ | ||
function _get_block_template_file_content( $template_file_path ) { | ||
$theme = wp_get_theme(); | ||
|
||
$template_file_path = wp_normalize_path( $template_file_path ); | ||
$theme_dir = wp_normalize_path( $theme->get_stylesheet_directory() ) . '/'; | ||
|
||
if ( str_starts_with( $template_file_path, $theme_dir ) ) { | ||
$relative_path = substr( $template_file_path, strlen( $theme_dir ) ); | ||
} elseif ( $theme->parent() ) { | ||
$theme = $theme->parent(); | ||
$theme_dir = wp_normalize_path( $theme->get_stylesheet_directory() ) . '/'; | ||
if ( str_starts_with( $template_file_path, $theme_dir ) ) { | ||
$relative_path = substr( $template_file_path, strlen( $theme_dir ) ); | ||
} | ||
} | ||
|
||
// Bypass cache if the file is not within the theme directory. | ||
if ( ! isset( $relative_path ) ) { | ||
return file_get_contents( $template_file_path ); | ||
} | ||
|
||
/* | ||
* Bypass cache while developing a theme. | ||
* If there is an existing cache, it should be deleted. | ||
* This ensures that no stale cache values can be served when temporarily | ||
* enabling "theme" development mode and then disabling it again. | ||
*/ | ||
if ( wp_is_development_mode( 'theme' ) ) { | ||
$template_data = get_transient( 'wp_theme_template_contents_' . $theme->get_stylesheet() ); | ||
if ( false !== $template_data ) { | ||
delete_transient( 'wp_theme_template_contents_' . $theme->get_stylesheet() ); | ||
} | ||
|
||
return file_get_contents( $template_file_path ); | ||
} | ||
|
||
// Check theme template cache first (if cached version matches the current theme version). | ||
$template_data = get_transient( 'wp_theme_template_contents_' . $theme->get_stylesheet() ); | ||
if ( is_array( $template_data ) && $template_data['version'] === $theme->get( 'Version' ) ) { | ||
if ( isset( $template_data['template_content'][ $relative_path ] ) ) { | ||
return $template_data['template_content'][ $relative_path ]; | ||
} | ||
felixarntz marked this conversation as resolved.
Show resolved
Hide resolved
|
||
} else { | ||
$template_data = array( | ||
'version' => $theme->get( 'Version' ), | ||
'template_content' => array(), | ||
); | ||
} | ||
|
||
// Retrieve fresh file contents if not found in cache. | ||
$template_data['template_content'][ $relative_path ] = file_get_contents( $template_file_path ); | ||
|
||
// Update the cache. | ||
set_transient( 'wp_theme_template_contents_' . $theme->get_stylesheet(), $template_data, WEEK_IN_SECONDS ); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This means this will not be autoloaded, is this by design. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @spacedmonkey I explained this here: #5463 (comment) One of your concerns was that these transients may become large and therefore shouldn't be autoloaded. I made this change in response to your feedback. |
||
|
||
return $template_data['template_content'][ $relative_path ]; | ||
} | ||
|
||
/** | ||
* Builds a unified template object based on a theme file. | ||
* | ||
|
@@ -520,7 +587,7 @@ function _remove_theme_attribute_from_template_part_block( &$block ) { | |
*/ | ||
function _build_block_template_result_from_file( $template_file, $template_type ) { | ||
$default_template_types = get_default_block_template_types(); | ||
$template_content = file_get_contents( $template_file['path'] ); | ||
$template_content = _get_block_template_file_content( $template_file['path'] ); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Instead of adding caching to to the file get, why don't we just save this data to the post table. This is how block themes work. You have files stored and once you edit them and save changes, it copies the changes to a post. Why not just copy the data to post on activation or first use. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'm not sure that that is possible. Only modified templates and template parts are saved in the posts table. If we do that for every template file in the theme, it will break existing functionality, as it will look like every template has been modified by the user. So that would not be feasible. |
||
$theme = get_stylesheet(); | ||
|
||
$template = new WP_Block_Template(); | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could use
str_replace()
here and below, similarly to how we're doing it inregister_core_block_style_handles()
:There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For this purpose,
str_replace()
is less precise thansubstr()
, since we want to replace the beginning of the string only, not the partial path wherever it is included in the string.This is obviously an edge case consideration, but has been pointed out to me in the past, and it makes sense. We shouldn't use
str_replace()
if we want to only replace a single specific instance of the substring.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hmmm...even so, if
$theme_dir
is not at the beginning of the string, then thesubstr()
function wouldn't remove what we intend to, which could be more confusing. You already have this inside an if statement that assures that$template_file_path
starts with$theme_dir
, so it really seems like both approaches are the same, with no possibility for edge cases to occur.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@joemcgill Let me clarify what I mean:
str_starts_with( '/dirname/dirname', '/dirname' )
results intrue
substr( '/dirname/dirname', strlen( '/dirname' ) )
results in the expected/dirname
str_replace( '/dirname', '', '/dirname/dirname' )
results in''
, which would be incorrectObviously this is not realistic to happen here since a file wouldn't be within a directory within the theme that has the same folder path as the overall theme directory. But if anything, it's safer to use
substr()
here overstr_replace()
to prevent it. IMOstr_replace()
is less precise since the intention here is to replace the instance of$theme
that the string starts with, not any instance of it within the string.Anyway, this is a nit-pick discussion 😂