Extending WordPress Blocks

Sep 11, 2024

THIS IS A DRAFT I WILL COMPLETE THE ARTICLE AS SOON AS I CAN!

Introduction

WordPress blocks are elements used to build and design content in the WordPress Block Editor (Gutenberg). Each block represents a piece of content, such as an image, heading, button, etc. These blocks make it easy to rearrange the structure of a webpage. They can also be extended or customized to fit specific needs. Now that we know what WordPress blocks are and what they’re used for, let’s explore a common problem we might encounter and its solution!

Before we start i highly recommend to read this articles:

  1. Tutorial: Build your first block
  2. @WordPress/scripts
  3. WordPress Filter Hooks
  4. WordPress Action Hooks

Multilingual Website using FSE and Blocks

WordPress doesn’t support multilingual websites by default, so we need a plugin to enable this functionality. One such plugin is Polylang, a popular and powerful solution. In the past, with classic templates, we could use shortcodes and widgets to integrate Polylang into the frontend. However, these widgets no longer work as they used to. The main issue here is that we now need separate headers, footers, and template files for each language. While this is our example, you can imagine other limitations that need to be addressed.

Whats the solution?

There can be multiple solutions, but the first one that comes to mind is extending and modifying WordPress blocks. In the next sections, we’ll explore how to modify blocks within the theme folder. I assume you have basic knowledge of WordPress development and theme structure.

Steps we will face

  1. Get the development environment ready
  2. Adding block attributes
  3. Adding the Editor user interface
  4. Modifying a block's frontend markup

Step by step guide to extending a WordPress block

1. Get the development environment ready

A simple WordPress theme folder structure looks like this:

├── assets
├── functions.php
├── includes
├── parts
├── patterns
├── screenshot.png
├── style.css
├── templates
└── theme.json

First, we need to add a new JavaScript package, which is a collection of reusable scripts tailored for WordPress development.

npm init //can be used to set up a new or existing npm package.
npm install @WordPress/scripts --save-dev

What is @worpdress/scripts? Its a collection of reusable scripts tailored for WordPress development. For convenience, every tool provided in this package comes with an integrated recommended configuration. If you interested you can read "Get started with wp-scripts".

After executing these commands, your theme folder structure will look like this:

├── assets
├── build
├── functions.php
├── includes
├── node_modules
├── package.json
├── parts
├── patterns
├── screenshot.png
├── src
├── style.css
├── templates
└── theme.json

//package.json
{
  ...
  "scripts": {
    "start": "wp-scripts start",
    "build": "wp-scripts build"
  },
  ...
}

Let's create a new folder called src/ and, inside it, another folder named language-condition/. In that folder, we will need two files: block.json and index.js.

Inside includes folder add new file called language-condition.php.

By now, our folder structure looks like this:

├── ...
├── parts
├── includes
    └── language-condition.php
├── src
    └── language-condition
      ├── block.json
      └── index.js
├── patterns
├── screenshot.png
├── ...

NOTE: I didn't pay attention to name conventions.

//block.json
{
  "editorScript": "file:index.js"
}

By default, wp-scripts will look for any folder containing block.json and read the necessary content from it before building the files.

So what we have in block.json says index.js within folder must be build.

2. Adding block attributes

//language-condition/index.js

function addDisplayByLanguageConditionAttribute(settings, name) {
  // When reach to core/group block do the following code
	if (name === "core/group") {
    // Add new attribute call displayLanguage to core/group block
		settings.attributes = {
			...settings.attributes,
			displayLanguage: {
				enum: ["unset", "fa", "en", "ru"],
				default: "unset",
			},
		};
	}

  // You can console.log settings and name variable
  // to see what are stored in them. its a good curiosity!
  // You can see console.log inside your WordPress
  // template editor. (Appereance > Editor > Any Template)
	return settings;
}

addFilter(
	"blocks.registerBlockType",
	"theme-namespace/display-by-language-condition-attribute",
	addDisplayByLanguageConditionAttribute,
);

TO BE CONTINUED...