Skip to content

Instantly share code, notes, and snippets.

@javiermarinros
Created December 18, 2018 18:08
Show Gist options
  • Save javiermarinros/d415f17b4650995458e54cd416b420aa to your computer and use it in GitHub Desktop.
Save javiermarinros/d415f17b4650995458e54cd416b420aa to your computer and use it in GitHub Desktop.
Easy shortcode and Gutenberg block creation. Shared render function and no JS coding required
<?php
function create_block($namespace, $name, $params, $render_callback)
{
static $config = null;
if (!isset($config) && is_admin()) {
$config = [];
add_action(
'init',
function () use ($namespace, &$config) {
wp_add_inline_script('wp-editor', 'loadGutenbergShortcodeBlocks();');
add_action(
'admin_footer',
function () use ($namespace, &$config) {
?>
<script>
function loadGutenbergShortcodeBlocks() {
var wp = window.wp;
var registerBlockType = wp.blocks.registerBlockType;
var el = wp.element.createElement;
var __ = wp.i18n.__;
function clone(obj) {
if (null == obj || "object" != typeof obj) return obj;
var copy = obj.constructor();
for (var attr in obj) {
if (obj.hasOwnProperty(attr)) copy[attr] = obj[attr];
}
return copy;
}
var config = <?= json_encode($config) ?>;
for (var blockName in config) {
if (!config.hasOwnProperty(blockName)) {
continue;
}
var blockConfig = config[blockName];
var generateController = function (blockConfig) {
return function (props) {
var content = [el('h5', {}, blockConfig.title)];
for (var attributeName in blockConfig.attributes) {
if (!blockConfig.attributes.hasOwnProperty(attributeName)) {
continue;
}
var attrConfig = blockConfig.attributes[attributeName];
if (attrConfig.options) {
var editor = el(wp.components.SelectControl, {
value: props.attributes[attributeName],
options: attrConfig.options,
onChange: function (content) {
props.setAttributes({[attributeName]: content});
},
});
} else {
var editor = el(wp.editor.PlainText, {
value: props.attributes[attributeName],
placeholder: attrConfig.label,
required: true,
onChange: function (content) {
props.setAttributes({[attributeName]: content});
},
});
}
content.push(el('label', {}, attrConfig.label, editor));
}
return el('div', {style: {backgroundColor: '#f8f9f9', padding: '14px'}}, content);
}
};
registerBlockType(<?= json_encode($namespace) ?> +'/' + blockName, {
title: blockConfig.title,
category: <?= json_encode($namespace) ?>,
icon: blockConfig.icon,
attributes: clone(blockConfig.attributes),
edit: generateController(blockConfig),
save: function () {
return null;
}
});
}
};
</script>
<?php
},
9999
);
// Register block category
add_filter(
'block_categories',
function ($categories, $post) use ($namespace) {
if ($post->post_type !== 'post') {
return $categories;
}
return array_merge(
$categories,
[
[
'slug' => $namespace,
'title' => $namespace
],
]
);
},
10,
2
);
}
);
}
$config[$name] = $params;
$render = function ($block_params) use ($render_callback, $params) {
// Set default parameters
foreach ($params['attributes'] as $k => $param_info) {
if (!array_key_exists($k, $block_params)) {
$block_params[$k] = $param_info['default'];
}
}
return call_user_func($render_callback, $block_params);
};
// Register shortcode
add_shortcode($name, $render);
// Register Gutenberg block
if (function_exists('register_block_type')) {
add_action(
'init',
function () use ($namespace, $name, $render) {
register_block_type(
"{$namespace}/{$name}",
[
'attributes' => [
'match' => ['type' => 'string'],
'side' => ['type' => 'string']
],
'render_callback' => $render
]
);
}
);
}
}
// Usage
create_block(
'mycompany',
'hello-word',
[
'title' => __('Hello world'),
'icon' => 'groups',
'attributes' => [
'name' => [
'label' => __('Name'),
'type' => 'string',
'default' => 'World'
]
]
],
function ($params) {
return "Hello " . $params['name'];
}
);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment