Skip to content

Instantly share code, notes, and snippets.

@pento
Last active September 5, 2024 01:58
Show Gist options
  • Save pento/cf38fd73ce0f13fcf0f0ae7d6c4b685d to your computer and use it in GitHub Desktop.
Save pento/cf38fd73ce0f13fcf0f0ae7d6c4b685d to your computer and use it in GitHub Desktop.
Converting a shortcode to a block: this method is fast to do, but a mediocre UX. You should only use this as a stopgap until you can implement a full block UI.
// License: GPLv2+
var el = wp.element.createElement,
registerBlockType = wp.blocks.registerBlockType,
ServerSideRender = wp.components.ServerSideRender,
TextControl = wp.components.TextControl,
InspectorControls = wp.editor.InspectorControls;
/*
* Here's where we register the block in JavaScript.
*
* It's not yet possible to register a block entirely without JavaScript, but
* that is something I'd love to see happen. This is a barebones example
* of registering the block, and giving the basic ability to edit the block
* attributes. (In this case, there's only one attribute, 'foo'.)
*/
registerBlockType( 'pento/php-block', {
title: 'PHP Block',
icon: 'megaphone',
category: 'widgets',
/*
* In most other blocks, you'd see an 'attributes' property being defined here.
* We've defined attributes in the PHP, that information is automatically sent
* to the block editor, so we don't need to redefine it here.
*/
edit: function( props ) {
return [
/*
* The ServerSideRender element uses the REST API to automatically call
* php_block_render() in your PHP code whenever it needs to get an updated
* view of the block.
*/
el( ServerSideRender, {
block: 'pento/php-block',
attributes: props.attributes,
} ),
/*
* InspectorControls lets you add controls to the Block sidebar. In this case,
* we're adding a TextControl, which lets us edit the 'foo' attribute (which
* we defined in the PHP). The onChange property is a little bit of magic to tell
* the block editor to update the value of our 'foo' property, and to re-render
* the block.
*/
el( InspectorControls, {},
el( TextControl, {
label: 'Foo',
value: props.attributes.foo,
onChange: ( value ) => { props.setAttributes( { foo: value } ); },
} )
),
];
},
// We're going to be rendering in PHP, so save() can just return null.
save: function() {
return null;
},
} );
<?php
/*
Plugin Name: PHP Block
Description: A sample PHP rendered block, showing how to convert a shortcode to a block.
Author: Gary Pendergast
Version: 0.1
Author URI: https://pento.net/
License: GPLv2+
*/
/*
* Here's a little sample plugin that shows how to easily convert an existing shortcode
* to be a server-side rendered block. This lets you get your existing plugin functionality
* running in the block editor as quickly as possible, you can always go back later and
* improve the UX.
*
* In this case, we have an imaginary shortcode, [php_block], which accepts one argument, 'foo'.
* This shortcode would be used like so:
*
* [php_block foo=abcde]
*
* Because the block editor uses the same function signature when doing server-side rendering, we
* can reuse our entire shortcode logic when creating the block.
*/
/**
* Register our block and shortcode.
*/
function php_block_init() {
// Register our block editor script.
wp_register_script(
'php-block',
plugins_url( 'php-block.js', __FILE__ ),
array( 'wp-blocks', 'wp-element', 'wp-components', 'wp-editor' )
);
// Register our block, and explicitly define the attributes we accept.
register_block_type( 'pento/php-block', array(
'attributes' => array(
'foo' => array(
'type' => 'string',
),
),
'editor_script' => 'php-block', // The script name we gave in the wp_register_script() call.
'render_callback' => 'php_block_render',
) );
// Define our shortcode, too, using the same render function as the block.
add_shortcode( 'php_block', 'php_block_render' );
}
add_action( 'init', 'php_block_init' );
/**
* Our combined block and shortcode renderer.
*
* For more complex shortcodes, this would naturally be a much bigger function, but
* I've kept it brief for the sake of focussing on how to use it for block rendering.
*
* @param array $attributes The attributes that were set on the block or shortcode.
*/
function php_block_render( $attributes ) {
return '<p>' . print_r( $attributes, true ) . '</p>';
}
@fpalacioschaves
Copy link

Hi. I want to add your snippet in my own plugin to add a block that shows the shortcode for my plugin with all the parameters we need. But i have an error "rror loading block: No route was found matching the URL and request method". I change the php code in this way:

add_action( 'init', array($this,'php_block_init' ));

public function php_block_init() {
// Register our block editor script.
wp_register_script(
'easy-filtering-block',
plugins_url( '/assets/js/php-block.js', FILE ),
array( 'wp-blocks', 'wp-element', 'wp-components', 'wp-editor' )
);

	    // Register our block, and explicitly define the attributes we accept.
	    register_block_type( 'fpc/php-block', array(
		    'attributes'      => array(
			    'foo' => array(
				    'type' => 'string',
			    ),
		    ),
		    'editor_script'   => 'easy-filtering-block', // The script name we gave in the wp_register_script() call.
		    'render_callback' => array($this,'php_block_render'),
	    ) );

	    // Define our shortcode, too, using the same render function as the block.
	    add_shortcode( 'php_block', array($this,'php_block_render') );
    }

    public function php_block_render( $attributes ) {

	    return "<p>[easy-filtering filter_id='".$attributes["foo"]."']</p>";
    }

@mdempfle
Copy link

mdempfle commented Dec 6, 2018

Hi Gary,

I tried you example and it works fine. But now I'm stuck because on the right side in the editor there is a "advanced section". Can you provide a link/example how this can be changed, modified. There is an addition css section I don't need and which actually even throws an error once you enter something.

Do I need to change this in the InspectorControls?

Best, Michael

@JohnRamon
Copy link

Hi Gary,

I tried you example and it works fine. But now I'm stuck because on the right side in the editor there is a "advanced section". Can you provide a link/example how this can be changed, modified. There is an addition css section I don't need and which actually even throws an error once you enter something.

Do I need to change this in the InspectorControls?

Best, Michael

What Michael said, I have been trying all morning to get it to turn off or not throw an error.

@tomk17
Copy link

tomk17 commented Mar 14, 2019

Hi. I want to add your snippet in my own plugin to add a block that shows the shortcode for my plugin with all the parameters we need. But i have an error "rror loading block: No route was found matching the URL and request method". I change the php code in this way:

add_action( 'init', array($this,'php_block_init' ));

public function php_block_init() {
// Register our block editor script.
wp_register_script(
'easy-filtering-block',
plugins_url( '/assets/js/php-block.js', FILE ),
array( 'wp-blocks', 'wp-element', 'wp-components', 'wp-editor' )
);

	    // Register our block, and explicitly define the attributes we accept.
	    register_block_type( 'fpc/php-block', array(
		    'attributes'      => array(
			    'foo' => array(
				    'type' => 'string',
			    ),
		    ),
		    'editor_script'   => 'easy-filtering-block', // The script name we gave in the wp_register_script() call.
		    'render_callback' => array($this,'php_block_render'),
	    ) );

	    // Define our shortcode, too, using the same render function as the block.
	    add_shortcode( 'php_block', array($this,'php_block_render') );
    }

    public function php_block_render( $attributes ) {

	    return "<p>[easy-filtering filter_id='".$attributes["foo"]."']</p>";
    }

If you look at the resource called from block editor when fetching datas, you will see that bock editor uses wp rest api to fetch datas ... so what you need to do is to render your class on frontend part.
if your class is in admin part (is_admin(){...}) bock editor can't get datas from wp rest api.
Just render your class visible from frontend actions.
To be clear this is an exemple :
if (is_admin()) {
// Rest API can't access your datas...
}
// reste API can your class datas...

Best regard,
Tom

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment