Home > Software design >  How can I build a wordpress gutenberg multiple blocks plugin that support dynamic content
How can I build a wordpress gutenberg multiple blocks plugin that support dynamic content

Time:11-20

I am creating a custom Wordpress theme with a set of custom Gutenberg Blocks. Previously I had all the blocks work as separate plugins and I started combining them into a single plugin as I thought it would be easier to maintain and update. My old folder structure looked like this:

wp-content
 |
  -- plugins
 |  |
 |   -- dir 1
 |  |   -- build
 |  |   -- node_modules
 |  |   -- src
 |  |  |   -- index.js (includes edit and save functions)
 |  |
 |   -- dir 2
 |  |   -- build
 |  |   -- node_modules
 |  |   -- src
 |  |  |   -- index.js (includes edit and save functions)

My new folder stucture looks like this (learned from this project: https://github.com/rmorse/multiple-blocks-plugin)

wp-content
 |
  -- plugins
 |  |
 |   -- multiple-blocks-plugin
 |  |  |
 |  |   -- blocks
 |  |  |  |
 |  |  |   -- dir 1
 |  |  |  |   -- build
 |  |  |  |   -- src
 |  |  |  |  |   -- edit.js
 |  |  |  |  |   -- index.js
 |  |  |  |  |   -- save.js
 |  |  |  |   -- block.json
 |  |  |  |
 |  |  |   -- dir 2
 |  |  |  |   -- build
 |  |  |  |   -- src
 |  |  |  |  |   -- edit.js
 |  |  |  |  |   -- index.js
 |  |  |  |  |   -- save.js
 |  |  |  |   -- block.json
 |  |  |  |
 |  |  |   -- dir 3
 |  |  |  |   -- build
 |  |  |  |   -- src
 |  |  |  |  |   -- edit.js
 |  |  |  |  |   -- index.js
 |  |  |  |   -- block.json
 |  |  |  |   -- index.php (the callback function is stored here)
 |  |  | 
 |  |   -- build
 |  |   -- node_modules
 |  |   -- multiple-blocks-plugin.php

Inside the multiple-blocks-plugin.php file, I maintain a list of all my plugins which I register using register_block_type() functions. These functions tell Wordpress to look for block.json files, where all my settings and attributes are now stored. One of my blocks is using dynamic content (a news block that should always show the latest three posts). My main problem is that I cannot get my new setup to read the callback_function when the function is stored inside the new folder structure. I aim to rebuild all my blocks to be dynamic, but I want to maintain a single plugin multiple-block setup.

This is the function that registers all of the different blocks and the faulty one for /blocks/news/

function create_block_multiple_blocks_block_init()
{
  register_block_type(plugin_dir_path(__FILE__) . 'blocks/column-block/');
  register_block_type(plugin_dir_path(__FILE__) . 'blocks/column-block-prices/');
  register_block_type(plugin_dir_path(__FILE__) . 'blocks/column-block-services/');
  register_block_type(plugin_dir_path(__FILE__) . 'blocks/column-block-specialists/');
  register_block_type(plugin_dir_path(__FILE__) . 'blocks/counter/');
  register_block_type(plugin_dir_path(__FILE__) . 'blocks/counter-list/');
  register_block_type(plugin_dir_path(__FILE__) . 'blocks/cta-banner/');
  register_block_type(plugin_dir_path(__FILE__) . 'blocks/gallery/');
  register_block_type(plugin_dir_path(__FILE__) . 'blocks/gallery-image/');
  register_block_type(plugin_dir_path(__FILE__) . 'blocks/image-text-block/');
  register_block_type(plugin_dir_path(__FILE__) . 'blocks/hero/');
  register_block_type_from_metadata(plugin_dir_path(__FILE__) . 'blocks/news/', array(
    "callback_function" => "news_register_block"
  ));
  register_block_type(plugin_dir_path(__FILE__) . 'blocks/opening-hours/');
  register_block_type(plugin_dir_path(__FILE__) . 'blocks/opening-hours-list/');
  register_block_type(plugin_dir_path(__FILE__) . 'blocks/process/');
  register_block_type(plugin_dir_path(__FILE__) . 'blocks/process-list/');
  register_block_type(plugin_dir_path(__FILE__) . 'blocks/why-choose-us/');
  register_block_type(plugin_dir_path(__FILE__) . 'blocks/why-choose-us-list/');
}
add_action('init', 'create_block_multiple_blocks_block_init');

Question

How do I set up a project that uses dynamic blocks, where all blocks are stored inside a single plugin? I am quite new to Wordpress development - I am used to working in Sitecore - and I would love to learn how to best set up such a project. Thank you.

CodePudding user response:

Using the feedback provided by Sebastian W, the correct code is supposed to look like this:

foreach (new DirectoryIterator(__DIR__ . '/blocks') as $item) {
  if ($item->isDir() && !$item->isDot()) if (file_exists($item->getPathname() . '/block.json')) {
    if (file_exists($item->getPathname() . '/' . $item->getBasename() . '.php')) {
      include($item->getPathname() . '/' . $item->getBasename() . '.php');
      register_block_type($item->getPathname(), array(
        'render_callback' => $item->getBasename() . '_render_callback'
      ));
    } else {
      register_block_type($item->getPathname());
    }
  }
}

CodePudding user response:

I'd use the DirectoryIterator to be as lazy as possible and scan that 'blocks' directory. Maybe I'd make it look if a block.json is present and then let it register this directory.

foreach ( $blocks = new DirectoryIterator( __DIR__ . '/blocks' ) as $item ) {
    if ( $item -> isDir() && !$item -> isDot() ) if ( file_exists( $item -> getPathname() . '/block.json' ) ) register_block_type( $item -> getPathname() ); 
}

Next step could be that you include a php file that is named exactly like the folder. In that folder you store a name-of-the-folder_render_callback function. If said file is present, include it and use the name-of-the-folder_render_callback in the register_block_type args.

foreach ( $blocks = new DirectoryIterator( __DIR__ . '/blocks' ) as $item ) {
    if ( $item -> isDir() && !$item -> isDot() ) if ( file_exists( $item -> getPathname() . '/block.json' ) ) {
        if ( file_exists( $item -> getPathname() . '/' . $item -> getBasename() . '.php' ) ) {
            include( $item -> getPathname() . '/' . $item -> getBasename() . '.php' );
            register_block_type( $item -> getPathname() , array( 'render_callback' => $item -> getBasename() . '_render_callback' ) );
        } else {
            register_block_type( $item -> getPathname() );
        }
    }
}

Untested, though.

  • Related