-
Notifications
You must be signed in to change notification settings - Fork 4.5k
Description
Previously: #21467
Related: Automattic/jetpack#15515
As part of the implementation of block context in #21467, the function signature of render_callback
was revised in such a way that was intended to be fully backward-compatible. It did so by creating a custom block class which implemented the PHP ArrayAccess
interface, where attempting to access array members of the first argument would be proxied automatically to block attribute members, to simulate the same effect of the previous signature wherein an array of block attributes was passed. The intention was to seamlessly allow the argument to be used either as an instance of the block class, or as an array of a block's attributes.
Problem:
While implementing ArrayAccess
is expected to satisfy a majority of common usage, it has become obvious that it does not faithfully uphold full backward compatibility. Some of these are rare and extreme edge cases, while others may be more common to anticipate.
Examples:
- In Podcast Player: handle dual-behaviour of render_callback fn Automattic/jetpack#15515, changes were necessary where a block was using
extract
andjson_encode
on the argument value. The latter can be accommodated by further implementing the PHPJsonSerializable
interface, but the former cannot be supported. - Array methods would not accept the class directly. A common problem may be a case where a block implementation checks to see if an attribute member is set in the array.
empty( $block_attributes['foo'] )
andisset( $block_attributes['foo'] )
would work, but notablyarray_key_exists( 'foo', $block_attributes )
would not work after the changes in Block API: Add Block Context support #21467.
Possible Solutions:
Some options to consider include:
- Accept these as consequences of the changes in Block API: Add Block Context support #21467, ideally with clear documentation and devnotes including as seamless an upgrade path as possible for these sorts of usages.
- Optionally, extend additional default interfaces, becoming more like
ArrayObject
in implementingIteratorAggregate
,ArrayAccess
,Serializable
,JsonSerializable
,Countable
- See: Block API: WP_Block implements JsonSerializable, Serializable, IteratorAggregate, Countable #21798 (example implementation)
- Optionally, extend additional default interfaces, becoming more like
- Change the implementation of Block API: Add Block Context support #21467, most likely in a way which requires the developer to opt in to receiving the block instance.
- Implement a separate render method which accepts the block instance.
- Example:
render_callback_with_block( $block )
(qualified variant of existing name) - Example:
render( $block )
(new name)
- Example:
- Implement a property of settings which acts as a flag to control the behavior
- Example:
'render_callback_receives_block' => true
- Example:
- If possible, reflect on the
render_callback
callable to consider if it specifies a type hint in its parameter signature.- Example:
render_callback( WP_Block $block )
vs.render_callback( $block_attributes )
- Related:
- Example:
- Implement a separate render method which accepts the block instance.
- Return to earlier implementations considered
- Make
$block
instance available as a global contextualized to therender_callback
, but don't otherwise change the function signature.- Example: Early iterations of Block API: Add Block Context support #21467
- Make
$block
available as a third argument ofrender_callback
- Make
Personal preference: I'm most keen to see if there are options around method reflection, in order to avoid the addition of a new settings property while giving the developers the choice to explicitly opt in to the behavior of receiving the block instance. It is not clear to me yet if this is a viable option.
Action Plan:
If a decision amongst the above (or additional) options cannot be reached and implemented before this Friday, April 24, then #21467 should be reverted to allow more time to consider the decision, or at least parts which affect the public API of render_callback
.