0

I'm trying to manipulate the editor content(blocks) before it's shown in the editor. So ideally I would perform a search and replace and the editor will have a modified version of blocks, but will not be saved until the user clicks "Save".

Is there a filter for post content?

I think this should be done in REST, but I have no luck finding it.

Any help is highly appreciated.

0

I found that there is no way to change the data which is coming to editor when it is loaded. But it's possible to replace the data after that.

JS: script.js

wp.domReady(function () {
    const newData = window.myNewBlocksData;

    if (newData) {
        wp.data.dispatch('core/block-editor').resetBlocks(wp.blocks.parse(newData));
        console.log('replaced');
    }
}) 

PHP:

<?php

class MyBlocksManipulation
{
    public $prefix = 'my';

    public function __construct()
    {
        add_action('admin_enqueue_scripts', [$this, 'modifyData'], 999);
        add_action('save_post', [$this, 'markPostManipulationDone'], 999, 3);
    }

    public function newDataType()
    {
        $screen = get_current_screen();

        if (!(
            $screen !== null &&
            !empty($screen->is_block_editor) &&
            !empty($screen->base) &&
            $screen->base === 'post'
        )) {
            return;
        }

        $currentPost = get_post();
        $alreadyManipulated = get_post_meta($currentPost->ID, "{$this->prefix}_data_is_modified", true);

        if (!empty($alreadyManipulated)) {
            return;
        }

        $newData = wp_slash($this->modifyData());

        wp_add_inline_script('wp-editor', "var myNewBlocksData=`{$newData}`");

        wp_enqueue_script(
            'my-data-manipulation',
            'path/to/my/script.js',
            ['wp-editor'],
            false,
            true
        );
    }

    public function modifyData()
    {
        $currentPost = get_post();
        $content = $currentPost->post_content;

        return preg_replace_callback("<!-- wp:(.*) ({(.*)}) \/-->", function ($matches) {
            if (!empty($matches[2])) {
                $array = self::decode_block_attributes($matches[2]);


                // ...
                // Do something with this $array ...
                // ...


                $block = new WP_Block_Parser_Block($matches[1], $array, [], '', []);

                $serialized = serialize_block((array)$block);

                $serialized = trim($serialized, '<>');

                return $serialized;
            }

            return "<$matches[0]>";
        }, $content);
    }

    public static function is_json($item)
    {
        if (is_string($item)) {
            $json = json_decode($item, true);

            return is_array($json) && json_last_error() == JSON_ERROR_NONE;
        }

        return false;
    }

    public static function decode_block_attributes($item)
    {
        if (self::is_json($item) || is_array($item)) {
            $json = is_array($item) ? $item : json_decode($item, true);

            return $json;
        }

        return $item;
    }

    public function markPostManipulationDone($postId, $post, $update)
    {
        if (
            !$update ||
            $post->post_type === 'revision' ||
            !current_user_can('edit_post', $postId)
        ) {
            return $postId;
        }

        return update_post_meta($postId, "{$this->prefix}_data_is_modified", current_time('U'));
    }
}

new MyBlocksManipulation(); // Somwhere on top, before the theme or plugin content is rendered.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.