最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

Bulk converting shortcodes to blocks with embeds

programmeradmin1浏览0评论

Is there a way to do a mass conversion of shortcode embeds to Gutenberg block-style embeds, including converting a classic block to a Gutenberg block?

I'm in the process of moving a WordPress site over that hasn't has its theme updated in almost ten years. It has thousands of audio files embedded with a SoundCloud shortcode that looks something like this:

[soundcloud url="; params="auto_play=false&show_artwork=false&color=ff7700" width="100%" height="180" iframe="true" /]

However, in order for them to work automatically with an on-screen player which shows the audio files at the bottom of the page when scrolling, they need to be converted to block-style embeds:

<figure class="wp-block-embed is-type-rich is-provider-soundcloud wp-block-embed-soundcloud"><div class="wp-block-embed__wrapper">;/div></figure>

It's easy enough to do a regex search of the database and change these.

However, the old shortcodes are in classic blocks and if those classic blocks aren't converted to Gutenberg blocks before the regex search-and-replace, then WordPress doesn't treat the newly replaced text as proper block-style embeds. It just treats them as meaningless code that it does not interpret.

So the question is, is there a way to mass-convert classic blocks to to Gutenberg blocks? I have seen and tried all of the plugins in the WordPress store that purport to do this, and they no longer work, and solutions offered in their comments do not work, either. I have also looked at their code to determine if I could make them work, but that is beyond my skill level.

Is there a way to do a mass conversion of shortcode embeds to Gutenberg block-style embeds, including converting a classic block to a Gutenberg block?

I'm in the process of moving a WordPress site over that hasn't has its theme updated in almost ten years. It has thousands of audio files embedded with a SoundCloud shortcode that looks something like this:

[soundcloud url="http://api.soundcloud.com/tracks/11111111" params="auto_play=false&show_artwork=false&color=ff7700" width="100%" height="180" iframe="true" /]

However, in order for them to work automatically with an on-screen player which shows the audio files at the bottom of the page when scrolling, they need to be converted to block-style embeds:

<figure class="wp-block-embed is-type-rich is-provider-soundcloud wp-block-embed-soundcloud"><div class="wp-block-embed__wrapper">http://api.soundcloud.com/tracks/11111111</div></figure>

It's easy enough to do a regex search of the database and change these.

However, the old shortcodes are in classic blocks and if those classic blocks aren't converted to Gutenberg blocks before the regex search-and-replace, then WordPress doesn't treat the newly replaced text as proper block-style embeds. It just treats them as meaningless code that it does not interpret.

So the question is, is there a way to mass-convert classic blocks to to Gutenberg blocks? I have seen and tried all of the plugins in the WordPress store that purport to do this, and they no longer work, and solutions offered in their comments do not work, either. I have also looked at their code to determine if I could make them work, but that is beyond my skill level.

Share Improve this question asked Oct 8, 2021 at 4:00 Grant BarrettGrant Barrett 314 bronze badges 3
  • Instead of trying to engineer something complicated, it might make sense to simply go through all of these and click "convert to blocks". Have you considered that? – kero Commented Oct 8, 2021 at 14:37
  • With fresh brain and eyes, I made some progress today. Going into the database, I was able to see that the complete structure of the new SoundCloud embeds is <!-- wp:embed {"url":"http://api.soundcloud.com/tracks/$1","type":"rich","providerNameSlug":"soundcloud","responsive":true} --> <figure class="wp-block-embed is-type-rich is-provider-soundcloud wp-block-embed-soundcloud"><div class="wp-block-embed__wrapper"> http://api.soundcloud.com/tracks/$1 </div></figure> <!-- /wp:embed --> But I still have to change each post to blocks from classic as the embeds do not work with the player. – Grant Barrett Commented Oct 8, 2021 at 15:21
  • @kero There are 5,396 posts with audio embeds. It would take two weeks! – Grant Barrett Commented Oct 8, 2021 at 15:23
Add a comment  | 

1 Answer 1

Reset to default 2

Ultimately, I solved the problem by exporting the wp_posts table from the database and doing a regex search along the lines of

'([0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9] [0-9][0-9]:[0-9][0-9]:[0-9][0-9]', '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9] [0-9][0-9]:[0-9][0-9]:[0-9][0-9])', '(.*?)\[soundcloud url=\\"http://api\.soundcloud\.com/tracks/(.*?)\\" params=\\"auto_play=false&show_artwork=false&color=ff7700&show_playcount=false\\" width=\\"100%\\" height=\\"180\\" iframe=\\"true\\" /]

and replacing it with

'\1', '<!-- wp:paragraph -->\2<!-- /wp:paragraph --><!-- wp:embed \{"url":"http://api.soundcloud\.com/tracks/\3","type":"rich","providerNameSlug":"soundcloud","responsive":true\} --> <figure class="wp-block-embed is-type-rich is-provider-soundcloud wp-block-embed-soundcloud"><div class="wp-block-embed__wrapper"> http://api\.soundcloud\.com/tracks/\3 </div></figure> <!-- /wp:embed -->

Although this successfully converts each entire post (more than 5000) to two Gutenberg blocks, WordPress believes the paragraph block is damaged and needs to be recovered. To solve this, on a Github comment I found Javascript code for the edit admin page that will silently recover all supposedly damaged blocks when a post is opened for editing. I am including the code here (credit to AjXUthaya) in case the comment disappears.

admin.js:

import autoRecoverBlocks from './wordpress/autoRecoverBlocks';

// DECONSTRUCT: WP
const { wp = {} } = window || {};
const { domReady, data } = wp;

// AWAIT: jQuery to get ready
jQuery(document).ready(function ($) {
  // DEFINE: Validation variables
  const hasGutenbergClasses = $('body').hasClass('post-php') === true && $('.block-editor').length >= 1;
  const gutenbergHasObject = domReady !== undefined && data !== undefined;
  const gutenbergIsPresent = hasGutenbergClasses === true && gutenbergHasObject === true;

  // IF: Gutenberg editor is present
  if (gutenbergIsPresent === true) {
    autoRecoverBlocks(false);
  }
});

autoRecoverBlocks.js:

// FUNCTION: Recover block
const recoverBlock = (block = null, autoSave = false) => {
  // DECONSTRUCT: WP object
  const { wp = {} } = window || {};
  const { data = {}, blocks = {} } = wp;
  const { dispatch, select } = data;
  const { createBlock } = blocks;
  const { replaceBlock } = dispatch('core/block-editor');
  const wpRecoverBlock = ({ name = '', attributes = {}, innerBlocks = [] }) => createBlock(name, attributes, innerBlocks);

  // DEFINE: Validation variables
  const blockIsValid = block !== null
    && typeof block === 'object'
    && block.clientId !== null
    && typeof block.clientId === 'string';

  // IF: Block is not valid
  if (blockIsValid !== true) {
    return false;
  }

  // GET: Block based on ID, to make sure it exists
  const currentBlock = select('core/block-editor').getBlock(block.clientId);

  // IF: Block was found
  if (!currentBlock !== true) {
    // DECONSTRUCT: Block
    const {
      clientId: blockId = '',
      isValid: blockIsValid = true,
      innerBlocks: blockInnerBlocks = [],
    } = currentBlock;

    // DEFINE: Validation variables
    const blockInnerBlocksHasLength = blockInnerBlocks !== null
      && Array.isArray(blockInnerBlocks)
      && blockInnerBlocks.length >= 1;

    // IF: Block is not valid
    if (blockIsValid !== true) {
      // DEFINE: New recovered block
      const recoveredBlock = wpRecoverBlock(currentBlock);

      // REPLACE: Broke block
      replaceBlock(blockId, recoveredBlock);

      // IF: Auto save post
      if (autoSave === true) {
        wp.data.dispatch("core/editor").savePost();
      }
    }

    // IF: Inner blocks has length
    if (blockInnerBlocksHasLength) {
      blockInnerBlocks.forEach((innerBlock = {}) => {
        recoverBlock(innerBlock, autoSave);
      })
    }
  }

  // RETURN
  return false;
};

// FUNCTION: Attempt to recover broken blocks
const autoRecoverBlocks = (autoSave = false) => {
  // DECONSTRUCT: WP object
  const { wp = {} } = window || {};
  const { domReady, data = {} } = wp;
  const { select } = data;

  // AWAIT: For dom to get ready
  domReady(function () {
    setTimeout(
      function () {
        // DEFINE: Basic variables
        const blocksArray = select('core/block-editor').getBlocks();
        const blocksArrayHasLength = Array.isArray(blocksArray)
          && blocksArray.length >= 1;

        // IF: Blocks array has length
        if (blocksArrayHasLength === true) {
          blocksArray.forEach((element = {}) => {
            recoverBlock(element, autoSave);
          });
        }
      },
      1
    )
  });
}

// EXPORT
export default autoRecoverBlocks;

To use the Javascript, save the two sections as two files. Put them in a /js/ directory in your activated template's directory on your server. Then add an enqueuing function in your template's functions.php file. My code is straightforward:

function add_script_to_menu_page()
{
    // $pagenow, is a global variable referring to the filename of the current page, 
    // such as ‘admin.php’, ‘post-new.php’
    global $pagenow;
 
    if ($pagenow != 'post.php') {
        return;
    }
     
    // loading js
    wp_register_script( 'autoRecoverBlocks', get_template_directory_uri().'/js/autoRecoverBlocks.js', array('jquery-core'), false, true );
    wp_enqueue_script( 'autoRecoverBlocks' );
}
 
add_action( 'admin_enqueue_scripts', 'add_script_to_menu_page' );

Additionally, for pages that do not have broken blocks but for which I do want to have the classic blocks converted to Gutenberg blocks, I have installed the Convert to Blocks plugin, which silently does the conversion when a post is saved.

发布评论

评论列表(0)

  1. 暂无评论