Make WordPress Core

Opened 5 months ago

Last modified 4 months ago

#62407 new defect (bug)

PHP Notice: Undefined offset in WordPress core when using template registered in a plugin via register_block_template() in WordPress 6.7

Reported by: grigory-volochiy's profile Grigory Volochiy Owned by:
Milestone: Awaiting Review Priority: normal
Severity: normal Version: 6.7
Component: General Keywords: has-dev-note has-patch
Focuses: template Cc:

Description

Issue Description
With the release of WordPress 6.7, the register_block_template() function allows plugins to register block templates. While this functionality operates as intended, it triggers a PHP notice about an undefined offset within the WordPress core.

Affected file: wp-includes/block-editor.php
Line: 467
Code snippet: {{{#!php
<?php
$template_blocks = parse_blocks( $current_template[0]->content );
}}}

Cause of the Issue
The get_block_templates() function now returns an array with a mix of numerical keys and associative keys where the associative keys are the registered template IDs via plugin (e.g., 'my-pluginmy-template') instead of numerical keys.
The core code at block-editor.php line 467 expects $current_template to be a numerically indexed array.
When an associative key is encountered, it leads to a PHP notice: Notice: Undefined offset: 0 in /wp-includes/block-editor.php on line 467.

Impact
PHP Notice:
Notice: Undefined offset: 0 in /wp-includes/block-editor.php on line 467


Compatibility Issues:
Existing plugin code that relies on numerical keys within the templates array does not anticipate associative keys, potentially causing further functional discrepancies beyond the PHP notice.


Steps to Reproduce

Environment Setup:
WordPress Version: 6.7
PHP Version: [PHP 7.4.33 (or higher)]
Active Theme: [Twenty Twenty-Five (the notice appears with other themes too)]

Procedure:
Create a plugin that registers a block template using register_block_template().

<?php
function add_template() {

        $template_id = 'my-plugin//my-template';
        $existing_template = get_block_template( $template_id );

        if ( $existing_template || is_wp_error( $existing_template ) ) {
                return;
        }

        $template_content =
                '<!-- wp:template-part {"slug":"header"} /-->
                <!-- wp:post-content {"lock":{"remove":true}} /-->
                <!-- wp:template-part {"slug":"footer"} /-->';

        register_block_template( $template_id, [
                'title' => __( 'Template title', 'my-plugin' ),
                'description' => __( 'Template description', 'my-plugin' ),
                'content' => $template_content,
                'post_types'  => array( 'page' ),
        ] );
}



Ensure DEBUG is set to true in wp-config.php to see the notice printed in HTML.
Navigate to Pages -> Add New Page. Assign newly created template to the page. Publish the page. Reload the editor page.


Observation:
A PHP notice appears in the page HTML (it appears briefly in the editor and is better visible in browser developer tools when viewing the source HTML of the current page)

Notice: Undefined offset: 0 in /wp-includes/block-editor.php on line 467
And as additional result next PHP notice:
Trying to get property 'content' of non-object in /wp-includes/block-editor.php on line 467

Expected Behavior
The WordPress core should handle templates registered via register_block_template() without triggering any PHP notices or errors. Specifically, the get_block_templates() function should return a numerically indexed array compatible with existing code expectations.

Actual Behavior
A PHP notice about an undefined offset is displayed, indicating that get_block_templates() returns an associative array with template IDs as keys instead of a numerically indexed array. This discrepancy leads to compatibility issues with existing code that expects numerical keys.

Attachments (1)

Screenshot 2024-11-13 131326.png (50.2 KB) - added by Grigory Volochiy 5 months ago.
The PHP notices visible in the HTML source of the page editor.

Download all attachments as: .zip

Change History (3)

@Grigory Volochiy
5 months ago

The PHP notices visible in the HTML source of the page editor.

This ticket was mentioned in PR #8086 on WordPress/wordpress-develop by @lgersman.


4 months ago
#1

  • Keywords has-patch added; needs-patch removed

This ticket fixes using templates registered by register_block_template() in the Gutenberg editor.

Function get_block_templates() tries to accumulate registered block templates from the Block Template Registry

The problem is that the Block Template Registry call get_by_query( $query ) returns an associative array but the code expects a indexed array.

Trac ticket: https://core.trac.wordpress.org/ticket/62407

Could you have a look into it, @noisysocks ?

@lgersman commented on PR #8086:


4 months ago
#2

Hey @noisysocks,

I fixed the failing test test_get_block_templates_from_registry.

The documentation of the get_block_templates function does not clearly express whether an index-based or associative array will be returned.
I assume that get_block_templates should return either an index based OR an associative (key based) array.

Gutenberg assumes an index based array (see bug https://core.trac.wordpress.org/ticket/62407).
In any case, I found this more sensible than an array with mixed (!) indices as in the current implementation.

The bugfix and the corresponding test case have been adapted accordingly.

The one (gracefully) failing e2e check (https://github.com/WordPress/wordpress-develop/actions/runs/12610283240/job/35144694194) has nothing to do with the proposed check. I assume it's just an timeout.

Cheers,

Lars

Note: See TracTickets for help on using tickets.