#57566 closed defect (bug) (fixed)
Issue registering blocks within a parent theme
Reported by: | jacknotman | Owned by: | audrasjb |
---|---|---|---|
Milestone: | 6.3 | Priority: | normal |
Severity: | major | Version: | 6.1.1 |
Component: | Editor | Keywords: | has-patch has-testing-info commit |
Focuses: | Cc: |
Description
Registering a block type using
register_block_type('./path/to/block/block.json')
does not work when called from a parent theme. Currently, any existing instances of the block added prior to enabling the child theme will show the
'Your site doesn’t include support for the "..." block.'
message. With
define( 'SCRIPT_DEBUG', true );
multiple errors are outputted to the dev console, indicating that the necessary CSS / JS files could not be loaded; this is due to the necessary files returning 404 errors as a result of WordPress appending the paths with the plugin directory URI.
This appears to be happening due to how WordPress handles registering blocks from themes. At
lines 137, and 234
of
wp-includes/blocks.php
when enqueuing necessary block assets from block.json the function
get_theme_file_path()
is used with an empty string ie:
get_theme_file_path('')
When passed an empty string this function returns the path to the currently active theme, which in this case is a child theme, therefor causing the subsequent
$is_theme_block
at
line 141
to equal
false
This causes the function to incorrectly use the
plugins_url(...)
path, rather than also checking the parent theme directory as would be expected.
Attachments (5)
Change History (26)
This ticket was mentioned in PR #3921 on WordPress/wordpress-develop by jack-h2ml.
2 years ago
#1
- Keywords has-patch added
@jacknotman commented on PR #3921:
2 years ago
#2
## Temporary Workaround
I have created a filter based workaround for the above issue, just incase anyone lands here!
Tested and working on my local dev server [MacOS 13.1, NGINX, PHP 8.0] and SiteGround Hosting [Linux, Apache, PHP 7.4.33] without issue thus far.
I do have some reservations with regards to other Plugins filtering theme_file_path
/ possibly with Windows based environments - use with caution and test on a dev server before adding to production._
### Commented
/** * * If registering a block which is solely defined in the current themes parent, * then add the `overrideThemeFilePath` filter to `theme_file_path`, this serves * as a temporary workaround for https://github.com/WordPress/wordpress-develop/pull/3921 * */ add_action('init', function() { // // The filter function for overriding `get_theme_file_path()` // function overrideThemeFilePath($_, $file) { $path = get_template_directory() . '/' . $file; return $path; } // // Add the filter where appropriate. // add_filter('block_type_metadata', function($metadata) { if(array_key_exists('file', $metadata)) { // Normalize the block path $blockPathNorm = wp_normalize_path($metadata['file']); // Cache the $templatePathNorm and $stylesheetPathNorm to avoid unnecessary additional calls. static $templatePathNorm = ''; static $stylesheetPathNorm = ''; if (!$templatePathNorm || !$stylesheetPathNorm) { $templatePathNorm = wp_normalize_path(get_template_directory()); $stylesheetPathNorm = wp_normalize_path(get_stylesheet_directory()); } // If looking at a block which is only defined in the parent theme then add the filter. $isTemplateBlock = str_starts_with($blockPathNorm, $templatePathNorm); $isStylesheetBlock = str_starts_with($blockPathNorm, $stylesheetPathNorm); if($isTemplateBlock && !$isStylesheetBlock) { add_filter('theme_file_path', 'overrideThemeFilePath', 10, 2); } } return $metadata; }, 10, 1); // // Ensure the filter is removed as soon as possible // add_filter('block_type_metadata_settings', function($settings, $metadata) { remove_filter('theme_file_path', 'overrideThemeFilePath', 10); return $settings; }, 10, 2); }, 10);
### Compacted
Note the three add_filter
calls are nested within the add_action
call, so do not split these lines or add code in between them.
/** * * If registering a block which is solely defined in the current themes parent, * then add the `overrideThemeFilePath` filter to `theme_file_path`, this serves * as a temporary workaround for https://github.com/WordPress/wordpress-develop/pull/3921 * */ add_action('init',function(){function overrideThemeFilePath($_,$file){$path=get_template_directory().'/'.$file;return $path;} add_filter('block_type_metadata',function($metadata){if(array_key_exists('file',$metadata)){$blockPathNorm=wp_normalize_path($metadata['file']);static $templatePathNorm='';static $stylesheetPathNorm='';if(!$templatePathNorm||!$stylesheetPathNorm){$templatePathNorm=wp_normalize_path(get_template_directory());$stylesheetPathNorm=wp_normalize_path(get_stylesheet_directory());}$isTemplateBlock=str_starts_with($blockPathNorm,$templatePathNorm);$isStylesheetBlock=str_starts_with($blockPathNorm,$stylesheetPathNorm);if($isTemplateBlock&&!$isStylesheetBlock){ add_filter('theme_file_path','overrideThemeFilePath',10,2);}} return $metadata;},10,1); add_filter('block_type_metadata_settings',function($settings,$metadata){remove_filter('theme_file_path','overrideThemeFilePath',10);return $settings;},10,2);},10);
@jacknotman commented on PR #3921:
23 months ago
#3
A note on the above workaround, ensure that the workaround is called before you register your blocks or it won't work, so for example call the above init filter with a priority of 1, and then register your blocks in a separate init filter with a priority >= 2.
#4
@
21 months ago
- Severity changed from normal to major
I ran into the same issue as you and glad I found this issue. I would like to raise this to a major issue, since without jumping through hoops described above, blocks registered by parent themes aren't working because of this.
This ticket was mentioned in PR #4788 on WordPress/wordpress-develop by @guillaumeturpin.
18 months ago
#5
#6
@
18 months ago
- Keywords needs-testing needs-testing-info added
- Milestone changed from Awaiting Review to 6.3
- Owner set to audrasjb
- Status changed from new to accepted
Moving for 6.3 consideration.
@audrasjb commented on PR #3921:
18 months ago
#7
Closing in favor of #4788
#8
@
18 months ago
Hello,
Here's how to reproduce the bug.
You need :
- a parent theme with blocks made with block.json
- then a child theme: with nothing in it (that's enough)
- activate the child theme and check whether the parent's blocks work
For the example, I've added 2 zips: parent.zip and child.zip 2 themes to reproduce the bug.
Simply download the 2 themes and activate the child theme.
Then test adding the "Todo List" block to see the errors in the console. (script errors, block not found).
And if you activate the parent theme, everything works correctly.
With @guillaumeturpin's PR, the problem is correctly corrected.
#9
@
18 months ago
Hi,
I was able to reproduce the bug thanks to the themes provided by @leprincenoir.
and I also tested with the PR patch from @guillaumeturpin and it corrects the problem.
#11
@
18 months ago
- Keywords has-testing-info added
I tested the patch against trunk
and it works fine on my side.
- First, I activated the parent test theme proposed by @leprincenoir in
parent.zip
:
🆗 the Todolist block is available
- Then, I activated the child test theme located in
child.zip
:
❌ the Todolist block is not available anymore
- Then, I applied the patch:
✅ the Todolist block is available again
Conclusion: the proposed patch works fine.
@
18 months ago
Second step: bug reproduced - the block is not available anymore when the child theme is activated
@audrasjb commented on PR #4788:
18 months ago
#17
Committed in https://core.trac.wordpress.org/changeset/56183
#18
@
18 months ago
Manually added missed props to @mukesh27 who reviewed and proposed changes to the PR.
#19
@
18 months ago
@audrasjb I wish we would have tackled these as part of #58525.
The current implementation takes 2 static variables that will take up memory. Moving betweens share logic and caches, should be the goal.
#20
@
18 months ago
@spacedmonkey we can still improve caching in #58525, this ticket was focused on fixing the major bug where blocks declared in parent theme were not available when the child theme is activated.
Improvements to caching can go in a follow-up ticket/commit in 6.4 (as beta cycle is only focused on bugs, not enhancements), but we had to fix the bug before the end of the beta cycle :)
Fixes for both the
register_block_script_handle()
andregister_block_style_handle()
functions withinwp-includes/blocks.js
, allowing for child themes to access and utilise blocks defined in parent themes.Previously these functions could not handle blocks registered in Parent themes, however the above changes fix this by determining whether the given asset path belongs to either of the template or stylesheet directories (Parent and Child themes respectively) as opposed to just checking using
get_theme_file_path('')
as is currently the case, thus mitigating this issue.An issue was raised under the WordPress / gutenberg Repo, however as
wp-includes/blocks.js
is included in the WordPress / wordpress-develop repo I have created the PR here instead. That original ticket can be found here.Trac ticket: Ticket