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.
Best Answer
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.