| Server IP : 65.108.144.40 / Your IP : 216.73.217.165 Web Server : Apache/2.4.52 (Ubuntu) System : Linux ubuntu-8gb-hel1-1 5.15.0-173-generic #183-Ubuntu SMP Fri Mar 6 13:29:34 UTC 2026 x86_64 User : dev ( 1000) PHP Version : 8.2.30 Disable Function : NONE MySQL : OFF | cURL : ON | WGET : ON | Perl : ON | Python : ON | Sudo : ON | Pkexec : ON Directory : /var/www/html/coopermain/wp-content/mu-plugins/blockstrap/ |
Upload File : |
<?php
namespace LambAgency\CLI;
/**
* Helpers for creating Gutenberg blocks
*/
class Block {
private $dir;
private static $output_path = 'modules';
private static $replace_with_class_name = '_Module';
private static $boilerplate_dir = __DIR__ . '/boilerplate/block';
private static $block_repo = '/opt-in-modules/src/docs/modules';
private static $fileIgnore = ['.', '..'];
function __construct()
{
$this->dir = \get_stylesheet_directory() . "/{$this::$output_path}/";
$this->optInSrc = dirname(ABSPATH, 1) . $this::$block_repo;
}
/**
* Generates one or several new Gutenberg blocks with basic boilerplate
*
* ## OPTIONS
*
* <names>...
* : The name (or names) of the blocks to bootstrap
*
* [--exclude=<exclusions>]
* : Which optional files to not bootstrap
* ---
* options:
* - all
* - js
* - css
* - sass
* - scss
* - class
* - js,css
* - js,class
* - css,class
* ---
*
* ## EXAMPLES
*
* wp block new "post listing"
* wp block new form wayfinder
* wp block new anchor --exclude=all
* wp block new accordion "call to action" --exclude=class
*
* @subcommand new
*/
public function _new( $names, $assoc_args = [])
{
$exclude = !empty($assoc_args['exclude']) ? explode(',', $assoc_args['exclude']) : [];
\WP_CLI::log("Bootstrapping " . count($names) . (count($names) === 1 ? " block" : " blocks"));
foreach($names as $name) {
$this->bootstrap_block($name, $exclude);
}
}
/**
* Imports blocks from the opt-in repo. Checks the block isn't already installed first
*
* ## OPTIONS
*
* <names>...
* : The name (or names) of the blocks to import (must match the folder name)
*
* ## EXAMPLES
*
* wp block import accordion icon-grid
*
* @subcommand import
*/
public function _import($names) {
$newNames = [];
foreach($names as $name) {
$logText = '';
$blockCheck = $this->check_block($name);
if(!$blockCheck) {
$logText = "Ready to import $name";
$newNames[] = $name;
} else {
$logText = "The folder for $name already exists locally";
}
\WP_CLI::log("\n$logText");
}
if(!empty($newNames)) {
$nameCount = count($newNames);
\WP_CLI::log("\n---Importing $nameCount blocks---");
$this->get_blocks($newNames);
} else {
\WP_CLI::log("No new blocks found.");
}
}
/**
* Creates a new Gutenberg / ACF block
*
* @param string $name
* @param string[] $exclude
*/
private function bootstrap_block($name, $exclude)
{
$name = implode(
' ',
array_map(
function($word){
return ucfirst($word);
},
explode(' ', $name)
)
);
\WP_CLI::log("\nCreating new block: $name");
$className = 'Module' . str_replace(' ', '', $name);
$slug = strtolower(str_replace(' ', '-', $name));
$dest = $this->dir . $slug;
if(!file_exists($dest)) {
\mkdir($dest, 0755, true);
}
\WP_CLI::log("\nAdding core files for $name");
$this::block_cp(
$this::$boilerplate_dir,
$dest,
$slug,
(in_array('all', $exclude) || in_array('class', $exclude)) ? "Module" : $className
);
$acf_data = $this::acf($slug, $name, $dest);
if(!in_array('all', $exclude)) {
\WP_CLI::log("\nAdding optional files for $name");
if (!in_array('class', $exclude)) {
$this::class_cp($this::$boilerplate_dir, $dest, $className);
}
if (!in_array('scss', $exclude) && !in_array('css', $exclude) && !in_array('sass', $exclude)) {
$this::scss_cp($this::$boilerplate_dir, $dest, $slug, $className);
}
if (!in_array('js', $exclude)) {
$this::js_cp($this::$boilerplate_dir, $dest, $slug, $className);
}
}
\WP_CLI::log("\n");
$this::acf_sync($acf_data);
}
/**
* Check the folder they're trying to import doesn't already exist
*
* @param string $name
* @return boolean
*/
private function check_block($name)
{
$slug = strtolower(str_replace(' ', '-', $name));
$dest = $this->dir . $slug;
return file_exists($dest);
}
/**
* Import block folders if they exist
*
* @param array $names
*/
private function get_blocks($names)
{
$fileChecker = array_diff(scandir($this->optInSrc), array('..', '.'));
foreach($names as $name) {
if(in_array($name, $fileChecker)) {
\WP_CLI::log("\nImporting $name...");
$source = $this->optInSrc . '/' . $name;
$destination = $this->dir . '/' . $name;
$this->copy_block_files($source, $destination);
\WP_CLI::log("...Import successful");
} else {
\WP_CLI::log("\n$name not found in opt-in modules. Ignoring.");
}
}
}
/**
* Copy directory contents over (recursive)
*
* @param string $source
* @param string $destination
*/
private function copy_block_files($source, $destination) {
$dir = @opendir($source);
if (!file_exists($destination)) {
@mkdir($destination);
}
/* Recursively copy */
while (false !== ($file = readdir($dir))) {
if (!in_array($file, $this::$fileIgnore)) {
if (is_dir("$source/$file") ) {
$this->copy_block_files("$source/$file", "$destination/$file");
} else {
copy("$source/$file", "$destination/$file");
}
}
}
closedir($dir);
}
/**
* Change instances of particular strings in copied files
*
* @param string $file
* @param string $className
* @param string $slug
*/
private static function update_strings($file, $className = "Module{uniqid()}", $slug = '')
{
$content = \file_get_contents($file);
$replaced = str_replace(self::$replace_with_class_name, $className, $content);
\file_put_contents($file, $replaced);
}
/**
* Creates ACF blocks JSON file in module directory
*
* @param string $slug
* @param string $name
* @param string $dest
*
* @return array
*/
private static function acf($slug, $name = '', $dest)
{
\WP_CLI::log('Creating ACF Blocks local JSON file');
$field_key = "group_" . uniqid();
$title_key = "field_" . uniqid();
$data = [
'key' => $field_key,
'title' => "Block $name",
'fields' => [
[
'key' => $title_key,
'label' => $name,
'name' => '',
'type' => 'message',
'instructions' => '',
'required' => 0,
'conditional_logic' => 0,
'wrapper' => [
'width' => '',
'class' => '',
'id' => ''
],
'message' => '',
'new_lines' => 'wpautop',
'esc_html' => 0
]
],
'location' => [
[
[
'param' => 'block',
'operator' => '==',
'value' => "acf/{$slug}"
]
]
],
'active' => 1,
'modified' => time()
];
if (function_exists('acf_json_encode')) {
\file_put_contents("$dest/$field_key.json", \acf_json_encode($data));
}
return $data;
}
/**
* Copies PHP boilerplate block to theme modules
*
* @param string $src
* @param string $dest
* @param string $slug
* @param string $className
*/
private static function block_cp($src, $dest, $slug, $className)
{
\WP_CLI::log('Creating PHP boilerplate block file');
\copy("$src/block.php", "$dest/$slug.php");
self::update_strings("$dest/$slug.php", $className);
}
/**
* Copies PHP boilerplate class to theme modules
*
* @param string $src
* @param string $dest
* @param string $className
*/
private static function class_cp($src, $dest, $className)
{
\WP_CLI::log('Creating PHP boilerplate class file');
\copy("$src/class.php", "$dest/$className.php");
self::update_strings("$dest/$className.php", $className);
}
/**
* Copies SCSS boilerplate to theme modules
*
* @param string $src
* @param string $dest
* @param string $slug
* @param string $className
*/
private static function scss_cp($src, $dest, $slug, $className)
{
\WP_CLI::log('Creating SCSS boilerplate file');
\copy("$src/block.scss", "$dest/$slug.scss");
self::update_strings("$dest/$slug.scss", $className);
}
/**
* Copies JS boilerplate to theme modules
*
* @param string $src
* @param string $dest
* @param string $slug
* @param string $className
*/
private static function js_cp($src, $dest, $slug, $className)
{
\WP_CLI::log('Creating JS boilerplate file');
\copy("$src/block.js", "$dest/$slug.js");
self::update_strings("$dest/$slug.js", $className);
}
/**
* Syncs the empty block with ACF inside WordPress
*
* @param array $data
*/
private static function acf_sync($data)
{
if (function_exists('acf_import_field_group')) {
acf_import_field_group($data);
\WP_CLI::log('Syncing ACF Fields');
}
}
}
if (class_exists('WP_CLI')) {
$block_commands = new Block();
\WP_CLI::add_command('block', $block_commands);
}