在Gutenberg编辑器中加载前过滤POST_CONTENT

时间:2020-05-20 作者:Andrei Surdu

我试图在编辑器中显示之前操纵编辑器内容(块)。因此,理想情况下,我将执行搜索和替换,编辑器将具有修改后的块版本,但在用户单击“保存”之前不会保存。

是否有帖子内容的过滤器?

我想这应该在REST中完成,但我没有运气找到它。

非常感谢您的帮助。

1 个回复
最合适的回答,由SO网友:Andrei Surdu 整理而成

我发现,在加载编辑器时,无法更改即将到来的数据。但之后可以替换数据。

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.