WordPress.org

Make WordPress Core

Opened 7 months ago

Closed 5 months ago

Last modified 2 months ago

#45451 closed enhancement (fixed)

Filter to allow plugins override block attributes

Reported by: kkarpieszuk Owned by: pento
Milestone: 5.1 Priority: normal
Severity: normal Version: 5.0
Component: Editor Keywords: has-patch commit needs-dev-note
Focuses: Cc:

Description

## Description

Add a filter so plugins and themes can override block attributes.

Originally I submitted it as MR to Gutenberg here https://github.com/WordPress/gutenberg/pull/11730 but I have been asked to move it directly to WordPress repo.

## Why is this needed?

Dynamic blocks, rendered server side keep their values in block attributes. Some of those attributes might be texts printed in the front-end to be read by people. This kind of strings should be available for translation.

We are preparing in WPML code to make it translatable, but we need to hook somewhere in Gutenberg to filter values. This place seems to be most appropriate for this.

## How has this been tested?

This has been tested in WPML with following code example (to translate dynamic strings created with ACF Blocks beta).

add_filter( 'block_prepared_attributes', 'block_attributes_filter', 1, 10 );
function block_attributes_filter( $attributes, $block_type ) {
    if ( $block_type->name === 'my-plugin/my-block' &&  isset( $attributes['data'] ) ) {
            $original_post_id = apply_filters( 'wpml_object_id', get_the_ID(), get_post_type(), true, apply_filters( 'wpml_default_language', null) );
            foreach ( $attributes['data'] as $name => $value ) {
                $string_name = WPML_Gutenberg_Strings_In_Block::get_string_id($attributes['name'], $value);
                $translated = apply_filters( 'wpml_translate_string',
                    $value,
                    $string_name,
                    array('kind' => 'Gutenberg', 'name' => $original_post_id) );
                $attributes['data'][$name] = $translated;
            }
        }

        return $attributes;
}

## Types of changes

Add a new filter

## Checklist:

Attachments (2)

patch.diff (650 bytes) - added by kkarpieszuk 7 months ago.
proposed patch
45451.diff (1.1 KB) - added by pento 5 months ago.

Download all attachments as: .zip

Change History (20)

@kkarpieszuk
7 months ago

proposed patch

#1 @swissspidy
7 months ago

  • Keywords has-patch added
  • Milestone changed from Awaiting Review to 5.0.1

#2 @SergeyBiryukov
6 months ago

  • Component changed from General to Editor

#3 @pento
6 months ago

  • Milestone changed from 5.0.1 to 5.0.2

#4 @pento
6 months ago

  • Milestone changed from 5.0.2 to 5.0.3

#5 @kkarpieszuk
6 months ago

@swissspidy I see it is postponed again. While I understand why it was removed from the queue for 5.0.1, now I am starting to worry if it would be introduced ever :(

Bear in mind because of the lack of this filter WPML is still incompatible with WP 5.0. This is very bad for our business not to mention our users :(

#6 @swissspidy
6 months ago

@kkarpieszuk 5.0.2 is intended for bug fixes to 5.0 only, not necessarily new enhancements (which this filter basically is). I understand your frustration and I am sure we can get this filter added soon.

#7 @kkarpieszuk
6 months ago

I hope it will be soon :) Actions and filters is "WordPress blood" and it should be added a long time before 5.0. Waiting for it now, just... you know.

#8 @desrosj
5 months ago

  • Milestone changed from 5.0.3 to 5.1

New filters are not being added in 5.0.3. So going to punt this one more time.

@kkarpieszuk one nit, the $block_type description feels a little awkward. Not sure of a good alternative yet. The since needs to be changed to 5.1.0, but the person committing this can change that.

@pento
5 months ago

#9 @pento
5 months ago

Thank you for the patch, @kkarpieszuk!

I've been thinking about this some more, it seems like it would be more useful to filter a little higher, in render_block(). This will allow filtering static blocks, as well as block types that aren't registered.

#10 @desrosj
5 months ago

  • Keywords commit added

45451.diff looks good. There is an extra empty line at the end of the addition that needs to just be removed.

#11 @pento
5 months ago

  • Owner set to pento
  • Resolution set to fixed
  • Status changed from new to closed

In 44553:

Blocks: Add the pre_render_block and render_block_data filters.

At the start of render_block(), the pre_render_block filter allows the function to be short-circuited, and the render_block_data filter is applied to the $block parameter before it's processed.

Props kkarpieszuk, pento.
Fixes #45451.

#12 @pento
5 months ago

In 44555:

Blocks: Reverse the logic when checking the pre_render_block result.

We should be returning if the result isn't null, not when it is.

See #45451.

#13 @kkarpieszuk
5 months ago

@pento I agree with your idea for better placing the filter (earlier). If you need anything from me, please ask :)

#14 @dmsnell
5 months ago

I'm going to post this link to the PR in the plugin that I created some time ago to address this.

https://github.com/WordPress/gutenberg/pull/10108

I was using the pre_ filter to perform short-circuiting and adjust the block attributes but I can see where two would be helpful. In my reasoning there was a symmetry to the pre_ and post_ filters which expressed itself as "the filter which affects how a block is rendered" and "the filter which affects what was rendered in a block."

$block = apply_filters( 'render_block_data', $block );

In the above filter definition I wonder if anyone else considered adding the $source_block. I anticipate that block-transformation will be a common way that people write plugins: for example, pulling out a child block based on an attribute such as locale for translations or es5/es2015/es2017 for example code blocks; alternatively in applying different steps of transformation, such as when we want to filter all text content generally but have a markdown render - transform first from markdown to html then run the transformed block through the next filter in the chain.

In these cases I seemed to remember some valid use-cases for where we'd want to or need to know what the original pre-transformed block data was, most-frequently the block name, but maybe that can be equally handled via filter priority?

Anyway, those are some thoughts from me. Thanks @kkarpieszuk for working on this issue - it's close to my heart as I am pretty sure that with a solid filter API for blocks we can eliminate the concept of dynamic blocks and the render_callback, instead meeting that need through the consistent filtering API.

#15 @pento
5 months ago

Good thinking, thanks @dmsnell. I'll add that extra parameter in.

#16 @pento
5 months ago

In 44576:

Blocks: Add a $source_block parameter to the render_block_data filter.

This contains a copy of the block, unmodified by other filter functions, so that plugins have a clean reference to work from, if they need.

Props dmsnell.
Fixes #45451.

#17 @desrosj
4 months ago

  • Keywords needs-dev-note added

This ticket was mentioned in Slack in #core-media by desrosj. View the logs.


2 months ago

Note: See TracTickets for help on using tickets.