Themes: Open and close the block theme document in get_header() and get_footer() - #12746
Themes: Open and close the block theme document in get_header() and get_footer()#12746AceMedia wants to merge 1 commit into
Conversation
…et_footer(). Block themes ship no header.php or footer.php, so both functions fall through to the templates in wp-includes/theme-compat/, deprecated since 3.0.0. On a block theme that prints the old default theme's page frame, the site title and description, a "proudly powered by WordPress" footer and a design credit comment into the page, on top of the deprecation notice. Both functions now print the document opening and closing that the template canvas already uses, whenever the active theme is a block theme providing no template of its own. Classic themes are untouched and still fall back. The canvas markup moves into _wp_block_theme_document_start() and _wp_block_theme_document_end() so the document has a single definition; template-canvas.php calls them and its output is byte for byte unchanged. See #55023.
|
The following accounts have interacted with this PR and/or linked issues. I will continue to update these lists as activity occurs. You can also manually ask me to refresh this list by adding the Core Committers: Use this line as a base for the props when committing in SVN: To understand the WordPress project's expectations around crediting contributors, please review the Contributor Attribution page in the Core Handbook. |
There was a problem hiding this comment.
Pull request overview
This PR fixes block-theme rendering when code calls get_header() / get_footer() but the active block theme does not provide header.php / footer.php, preventing WordPress from falling back to deprecated wp-includes/theme-compat/ markup and instead emitting the same document wrapper used by the block template canvas.
Changes:
- Add shared private helpers to output the block theme document opening/closing markup and reuse them from the template canvas.
- Add a private
_wp_theme_has_template()helper so callers can detect whether the active (child/parent) theme actually ships a given template, ignoringtheme-compat/fallbacks. - Update
get_header()/get_footer()to use the block theme document wrapper when appropriate, and add PHPUnit coverage for both block and classic themes.
Reviewed changes
Copilot reviewed 5 out of 5 changed files in this pull request and generated 1 comment.
Show a summary per file
| File | Description |
|---|---|
| tests/phpunit/tests/general/template.php | Adds tests asserting block themes avoid theme-compat fallbacks and classic themes still trigger them (including deprecation). |
| src/wp-includes/template.php | Introduces _wp_theme_has_template() to detect theme-provided templates without considering theme-compat/. |
| src/wp-includes/template-canvas.php | Refactors canvas document wrapper markup to call shared helpers. |
| src/wp-includes/general-template.php | Updates get_header() / get_footer() to open/close the block theme document when the theme provides no header/footer template. |
| src/wp-includes/block-template.php | Adds _wp_block_theme_document_start() / _wp_block_theme_document_end() to centralize block theme document wrapper output. |
Comments suppressed due to low confidence (2)
src/wp-includes/block-template.php:263
- In _wp_block_theme_document_start(), there’s no unconditional newline after
wp_body_open(). With no hooked callbacks, any following markup will start on the same line, whereas the previous template-canvas structure always had a newline after thewp_body_open()call. Adding an explicit line break keeps the document opening formatting consistent.
echo '<body ';
body_class();
echo ">\n";
wp_body_open();
}
src/wp-includes/block-template.php:277
- In _wp_block_theme_document_end(),
</body>is printed immediately afterwp_footer()returns. Previously,wp_footer()was on its own line (with a guaranteed trailing newline from the file), so</body>was always on the next line even whenwp_footer()printed nothing. Consider echoing a newline afterwp_footer()to preserve the prior output formatting.
echo "\n";
wp_footer();
echo "</body>\n";
echo "</html>\n";
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Test using WordPress PlaygroundThe changes in this pull request can previewed and tested using a WordPress Playground instance. WordPress Playground is an experimental project that creates a full WordPress instance entirely within the browser. Some things to be aware of
For more details about these limitations and more, check out the Limitations page in the WordPress Playground documentation. |
Trac ticket: https://core.trac.wordpress.org/ticket/55023
The problem, seen in production
I found this in the served markup of my own news site, which runs a block theme:
<!-- Gorgeous design by Michael Heilemann - http://binarybonsai.com/ -->Tracing it back, a plugin of mine serves several routes from PHP and calls
get_header()andget_footer()around its own markup, which plugins are allowed to do. A block theme ships noheader.phporfooter.php, solocate_template()falls through towp-includes/theme-compat/, and those routes were being served like this:Eight public URLs were affected. My own header and footer were nowhere in the markup; in their place were the old default theme's page frame, a duplicate site title and tagline, a "proudly powered by WordPress" promo, and a design credit for a theme the site has never used. The deprecation notice discussed on this ticket is that same fallback announcing itself. The markup is what visitors and crawlers actually received.
wp-signup.phpandwp-activate.phpreach the same fallback inside core, which is where the ticket started.The change
get_header()andget_footer()now print the document opening and closing that the template canvas already uses, whenever the active theme is a block theme providing no template of its own. A block theme therefore opens the same document whether the page is rendered by a block template or by a caller of these functions.Classic themes are untouched: with no
header.phpthey still reachwp-includes/theme-compat/and still raise the deprecation notice, which for them remains correct advice.This follows the approach the ticket converged on in comment 23, that the markup needed is the one in
template-canvas.php, rather thanblock_header_area()/block_footer_area(), which cannot open and close a document and were argued against there for exactly that reason._wp_block_theme_document_start()and_wp_block_theme_document_end()inblock-template.phphold the document markup so it has a single definition.template-canvas.phpcalls them, and its output is byte for byte unchanged._wp_theme_has_template()intemplate.phpanswers whether the theme itself provides a template, whichlocate_template()cannot be asked, since it is the function doing the falling back.Tests
Four tests added to
tests/phpunit/tests/general/template.php:get_header()opens a document and prints none of the theme-compat frame;get_footer()closes the document and prints no "proudly powered by";header.phpstill gets the fallback and still raises the notice.Run against trunk:
phpcsis clean on every changed file.Notes
block-template.php, I'm happy to move them.