Gravid Banner

Building a WordPress Plugin for the Block Editor

Recently I needed to create a new wordpress plugin to display the results of an API. I figured that it should be a relatively easy task. My initial issue was that a lot of the immediate results that I found for how to do it related to the old WordPress editor and not the new block editor.

After a bit of digging however, I found thus Youtube video which put me on the right track. The video wasn’t quite what I needed, but I was able to adapt the mechanisms it suggested to get the result I needed.

The key to the issue was that I needed to create the code to display the widget on the server, not on the client. Once I knew that this code sits in render.php the rest of the picture was fairly straight forward.

Creating a generic plugin

In order to create a modern wordpress plugin you need a Node installation on your development machine. Depending on your environment there are a number of different ways to do this

  • Via Node Package Manager (npm) on Mac or Linuc
  • Via Homebrew on Mac
  • Via Node Version Manager (nvm) on windows

I already had NPM on my computer, but I did need to upgrade the version before I could proceed.

Once Node is installed and up to date, we can use it to create a ‘hello world’ block plugin. There are two types of blocks. Static blocks – whose content is fixed at during the page editing phase – and dynamic blocks who’s content can be set as the page is being rendered. To display the result of an API we need a dynamic block. The following command creates one for us.

npx @wordpress/create-block --variant dynamic my-plugin
PHP

Hello World (Ad)

The structure of the plugin

The comamnd above creates a functional, if not terribly useful WordPress plugin, with the following structure.

my-plugin
  - build (dir)
  - my-plugin.php *
  - node-modules (dir)
  - package-lock.json
  - package.json
  - readme.txt *
  - src
    - my-plugin
      - block.json *
      - edit.js *
      - editor.scss
      - index.js
      - render.php *
      - style.css
      - view.js ?
Bash

The build directory is where the compiled files will go, and you should never need to touch it. The node-modules directory contains a whole load of libraries for node for the build process. Again there is no need to touch it. From the rest the key files you will need to edit are marked with an asterisk (*).

my-plugin.php contains the plugin registration details in the comment at the top. This will need to be changed to enter your own details. You can also modify the php to add actions and register additional blocks. For my code I did not need to change anything.

The readme.txt file contains the information that https://wordpress.org/plugins/ will use to describe your plugin. There is a detailed description of what goes into the readme in the wordpress documentation.

We also need to modify the block.json to personalise the block information. The main code of the plugin is contained in the edit.js, render.php and view.js files. I’ll describe these lower down. Finally there are two sccs files, one which styles the plugin in the block editor and one which styles it for the website. You may want to edit these to change the appearance of your plugin

Building the plugin

My wordpress installation was on my host, so to test the plugin I ran the following two commands. The first compiles the source, and the second creates a zipped plugin which I uploaded and unzipped on the server

npm run build
npm run plugin-zip
PHP

Once the plugin has been installed, you can activate it in from the Plugins option in the WordPress dashboard.

Modifying the plugin

In order to get the plugin to do something useful, there are several files that we need to edit. The main one is src/render.php

This is the file which creates the content that WordPress will present to the user on the public page. The create process gives a very bland hello script, which we can completely replace.

<?php
/**
 * @see https://github.com/WordPress/gutenberg/blob/trunk/docs/reference-guides/block-api/block-metadata.md#render
 */
?>
<p <?php echo get_block_wrapper_attributes(); ?>>
	<?php esc_html_e( 'My Plugin – hello from a dynamic block!', 'my-plugin' ); ?>
</p>
PHP

For my plugin I needed to pull some data from a public API and render this on the page. In order to meet WordPress submission guidelines having retrieved the content from the API we need to escape the output to ensure that there is no malicious content.

<?php
$response = wp_remote_get("https://my-api-url/");
$json = wp_remote_retrieve_body( $response );
if ($json) {
  $myApi = json_decode($json);
}
?>
<?php if ($myApi): ?>
  <div class="my-api-div">
  <h2><?php echo esc_html($myApi->title); ?></h2>
  <p><?php echo esc_html($myApi->content); ?></p>
  <p>Data from <a href="<?php echo esc_url($myApi->url); ?>">my api website</a></p>
  </div>
<? endif ?>
PHP

If we want to submit our plugin to the WordPress Plugin directory we can’t include that final URL without an opt in from the blog owner. In order to do this we need to add an option to the block editor to allow the blog owner to turn the URL on or off. In order to do this we need to add an attribute to the plugin in block.json

	"description": "Description of my ",
	"attributes" :{
		"allowExternalUrls": {
			"type": "boolean",
			"default":false
		},
PHP

To change the value of this attribute in the block editor, we need to modify the edit.js script Note that I have removed most of the comment fluff in this example to make the code a little more obvious. This code creates a toggle in the settings panel of the block editor. It also sets the text which the admin users sees when they include the plugin in a page. It does not affect the text that the end user sees (that is fully sourced from render.php).

// Translation strings
import { __ } from '@wordpress/i18n';

// Panel componenets
import { InspectorControls, useBlockProps } from '@wordpress/block-editor';
import { PanelBody, ToggleControl } from '@wordpress/components';

// Styles
import './editor.scss';
export default function Edit( { attributes, setAttributes } ) {
  const { allowExternalUrls } = attributes;

  return (
    <>
      <InspectorControls>
        <PanelBody title={ __( 'Settings', 'my-plugin-block' ) }>
          <ToggleControl
            checked={ allowExternalUrls }
            label={ __(
              'Show link back to API Website',
              'my-plugin-block'
            ) }
            onChange={ () =>
              setAttributes( {
                allowExternalUrls: ! allowExternalUrls,
              } )
            }
          />
        </PanelBody>
      </InspectorControls>
      <p { ...useBlockProps() }>Text from the API will go here</p>
    </>
  );
}
JavaScript

With this in place, we need to check the attribute in render.php to show or hide the url

<?php if(isset( $attributes['allowExternalUrls'] ) && 
                $attributes['allowExternalUrls'] == true): ?>
  <p>Data from <a href="<?php echo esc_url($myApi->url); ?>">my api website</a></p>
<?php endif ?>
PHP

Whilst this was all of the code required to get my plugin working, there are several other files which need to be adjusted to complete the plugin.

With these changes in place, we can rebuild and test the plugin.

Removing unused code

For my plugin I did not require any front-end javascript. This means that the view.js file is unnecessary. Helpfully it tells you what to do in the comments.

 /*
 * If you're not making any changes to this file because your project doesn't need any
 * JavaScript running in the front-end, then you should delete this file and remove
 * the `viewScript` property from `block.json`.
JavaScript

Rebuild and test

With all of these changes done, it is time to rebuild and test the plugin. In order to debug the plugin I turned on debug in wp-config.php

define( 'WP_DEBUG', true );

define( 'WP_DEBUG_DISPLAY', true );
define( 'WP_DEBUG_LOG', true );
define( 'SCRIPT_DEBUG', true );
PHP

There is also a useful plugin called Check Plugin which you can run to review your plugin and fix any issues it identifies before you submit it to WordPress.

WordPress Plugin Development (Ad)


Comments

Leave a Reply

Your email address will not be published. Required fields are marked *