- Introduction
- Video Guides
- Generate a Block with Middleware
- Creating Custom Block Field/Model Middleware
- Registering Middleware
Block middelware is loosely modeled after Laravel's Request Middleware.
This feature gives us the power to do two things:
- Modify a block's
Block_Config
just before it's registered with ACF. - Modify a block's
Base_Model
before data is passed to a controller.
This utilizes a Pipeline design pattern, where the block can be passed through any number of middleware implementations in the order they are registered. Each stage, or "pipe", can decide if it's going to modify the block in some way and either make a modification and pass it to the next stage, or simply skip doing anything and passing it to the next stage. Your middleware should always pass the modified data to the next stage.
- Block Middleware Overview - A technical overview of the entire Block Middleware system.
- How to add the Color Theme Middleware to an existing block
- How to add the Color Theme Middleware to a repeater - IMPORTANT: This is currently outdated, see the Color Theme README.md for up-to-date examples.
- Post Loop Field Overview
- How to configure the Post Loop Field Middleware - IMPORTANT: This is currently outdated as the middleware key you provide in
get_middleware_params()
should now return an array of$config
instances. See [generating a new block with Post Loop Field Middleware](#example---generate-a-new-block-named-my_custom_block-that-has-post-loop-middleware-support) for the most up-to-date example. - How to use the Post Loop Field in non-block controllers
- Global or shared field systems. Create a set of ACF fields, inject them into a block, and then you can change that field in a single spot and have it update across all blocks where it's enabled.
- Modify any fields/field data on the fly, for example of a field had to be renamed, but you want to use the old data until the post is saved by a user.
New options have been added to the wp s1 generate block
command, run the following help command to see the options:
TIP: Remove the
so
prefix if you're not using Tribe's local docker environment.
so wp help s1 generate block
so wp -- s1 generate block My_Custom_Block --with-post-loop-middleware
The above command will create all the files required to create a block with Post Loop Middleware, the only thing it currently doesn't do is build the cards/output the posts in the view. Once generated, you can begin to customize the block as you see fit.
If you have made other custom middleware and need to generate a block that has the basic building blocks to configure that middleware, you can pass the --with-middleware
option.
Example - Generate a new block named My_Other_Custom_Block
that contains the skeleton for a middleware implementation:
so wp -- s1 generate block My_Other_Custom_Block --with-middleware
Use the CLI generator to create example Block Middleware you can then customize, see available options by running the help command:
TIP: Remove the
so
prefix if you're not using Tribe's local docker environment.
so wp s1 help generate block:middleware
so wp s1 generate block:middleware Inject_Css
The above command will perform the following actions:
- Generate a
Inject_Css_Field_Middleware
class that injects a text field called Custom CSS into blocks that are configured to process middleware in the Block_Middleware_Definer. - Generate a
Inject_Css_Model_Middleware
class that will take the entered CSS class, and merge it into the block's existing CSS classes. - Automatically registers the Field/Model Middleware in the Block_Middleware_Definer.
- Generate integration tests for the Field/Model Middleware that should later be customized by the developer as they make modifications to the example implementation.
TIP: Not all middleware requires both a Field and Model implementation. Simply delete the classes you don't need and remove them from the Block_Middleware_Definer and delete respective automated test classes.
You can currently create two types of middleware out of the box:
- Middleware that extends Abstract_Field_Middleware: This will allow you to modify the fields of a block before it's registered with ACF.
- Middleware that extends Abstract_Model_Middleware: This will allow you to append data to a block model.
All registrations happen in the Block_Middleware_Definer.
Add your field middleware to the collection in the order you want it to run:
/**
* Add custom Block Middleware field definitions to dynamically
* attach fields to existing blocks.
*
* @var \Tribe\Project\Block_Middleware\Contracts\Field_Middleware[]
*/
self::FIELD_MIDDLEWARE_COLLECTION => DI\add( [
DI\get( Color_Theme_Field_Middleware::class ),
] ),
Add your model middleware to the collection in the order you want it to run:
/**
* Add custom Block Model middleware to dynamically append new data
* to the existing block's model data.
*
* @var \Tribe\Project\Block_Middleware\Contracts\Model_Middleware[]
*/
self::MODEL_MIDDLEWARE_COLLECTION => DI\add( [
DI\get( Color_Theme_Field_Model_Middleware::class ),
] ),
Block models under the MODEL_MIDDLEWARE
constant will be passed through all model middleware, e.g.
use Tribe\Project\Blocks\Types\Accordion\Accordion_Model;
// etc...
/**
* Define the block models that accept middleware.
*
* A block can also define specific middleware
* as an array.
*
* @phpstan-ignore-next-line
*
* @link https://github.com/phpstan/phpstan/issues/7273 (phpstan bug)
*
* @var array<class-string, bool|\Tribe\Project\Block_Middleware\Contracts\Middleware[]>
*/
public const MODEL_MIDDLEWARE = [
Accordion_Model::class => true,
Card_Grid_Model::class => true,
Content_Loop_Model::class => true,
Hero_Model::class => true,
];
Alternatively, you can specify an array of model middleware classes if the block should only use those. For example, if you have many different model middleware classes, the Accordion_Model
will only pass through the Color_Theme_Field_Model_Middleware
and ignore the rest.
use Tribe\Project\Blocks\Types\Accordion\Accordion_Model;
// etc
public const MODEL_MIDDLEWARE = [
Accordion_Model::class => [
Color_Theme_Field_Model_Middleware::class,
],
Card_Grid_Model::class => true,
Content_Loop_Model::class => true,
Hero_Model::class => true,
];
For block field middleware, it's nearly the same process, but you must utilize the DI\add()
array function and pass the instance of the block's Block_Config
class.
use Tribe\Project\Blocks\Types\Accordion\Accordion;
//etc
/**
* Define the blocks that accept middleware.
*
* A block can also define specific middleware
* as an array.
*
* @var array<class-string, bool|\Tribe\Project\Block_Middleware\Contracts\Middleware[]>
*/
self::BLOCK_MIDDLEWARE => DI\add( [
Accordion::class => true,
Card_Grid::class => true,
Content_Loop::class => true,
Hero::class => true,
] ),
Or, selectively run field middleware on certain blocks. The Hero
block will only pass through the Color_Theme_Field_Middleware
and ignore any others:
/**
* Define the blocks that accept middleware.
*
* A block can also define specific middleware
* as an array.
*
* @var array<class-string, bool|\Tribe\Project\Block_Middleware\Contracts\Middleware[]>
*/
self::BLOCK_MIDDLEWARE => DI\add( [
Accordion::class => true,
Card_Grid::class => true,
Content_Loop::class => true,
Hero::class => [
Color_Theme_Field_Middleware::class,
],
] ),