* @copyright Copyright (c) 2021, Phi Phan */ namespace BoldBlocks; // Exit if accessed directly. defined( 'ABSPATH' ) || exit; if ( ! class_exists( 'CustomBlocks' ) ) : /** * Create/edit custom content blocks. */ class CustomBlocks { /** * Store all custom blocks * * @var array */ protected $all_custom_blocks = []; /** * Store all names of custom blocks * * @var array */ protected $custom_block_names = []; /** * Store all names of repeater blocks * * @var array */ protected $repeater_block_names = []; /** * A dummy constructor */ public function __construct() {} /** * Run main hooks * * @return void */ public function run() { // Register custom post type. add_action( 'init', [ $this, 'register_custom_post_type' ], 5 ); // Custom admin columns. add_filter( 'manage_edit-boldblocks_block_columns', [ $this, 'add_boldblocks_block_custom_columns' ] ); add_action( 'manage_boldblocks_block_posts_custom_column', [ $this, 'manage_boldblocks_block_columns' ], 10, 2 ); // Load custom blocks. add_action( 'init', [ $this, 'load_custom_blocks' ], 5 ); // Register scritps. add_action( 'init', [ $this, 'register_scripts' ] ); // Allow creating patterns from custom blocks. add_filter( 'boldblocks_get_pattern_allowed_blocks', [ $this, 'allow_creating_patterns' ] ); } /** * Register custom post type * * @return void */ public function register_custom_post_type() { // Custom block args. $labels = array( 'name' => _x( 'Custom Blocks', 'post type general name', 'boldblocks' ), 'singular_name' => _x( 'Custom Block', 'post type singular name', 'boldblocks' ), 'menu_name' => _x( 'Custom Blocks', 'admin menu', 'boldblocks' ), 'name_admin_bar' => _x( 'Custom Blocks', 'add new on admin bar', 'boldblocks' ), 'add_new' => _x( 'Add New', 'item', 'boldblocks' ), 'add_new_item' => __( 'Add New Custom Block', 'boldblocks' ), 'new_item' => __( 'New Custom Block', 'boldblocks' ), 'edit_item' => __( 'Edit Custom Block', 'boldblocks' ), 'view_item' => __( 'View Custom Block', 'boldblocks' ), 'all_items' => __( 'All Custom Blocks', 'boldblocks' ), 'search_items' => __( 'Search Custom Blocks', 'boldblocks' ), 'parent_item_colon' => __( 'Parent Custom Block:', 'boldblocks' ), 'not_found' => __( 'No items found.', 'boldblocks' ), 'not_found_in_trash' => __( 'No items found in trash.', 'boldblocks' ), ); $args = array( 'labels' => $labels, 'description' => __( 'All custom blocks', 'boldblocks' ), 'public' => true, 'publicly_queryable' => false, 'exclude_from_search' => true, 'show_ui' => true, 'show_in_menu' => true, 'show_in_nav_menus' => false, 'show_in_admin_bar' => true, 'show_in_rest' => true, 'query_var' => false, 'rewrite' => false, 'capability_type' => 'post', 'has_archive' => false, 'hierarchical' => false, 'menu_position' => 5, 'supports' => array( 'title', 'editor', 'author', 'custom-fields', 'revisions' ), 'can_export' => true, 'template_lock' => 'insert', ); // Register post type. register_post_type( 'boldblocks_block', $args ); // Meta fields. register_meta( 'post', 'boldblocks_block_blocks', array( 'object_subtype' => 'boldblocks_block', 'show_in_rest' => true, 'type' => 'string', 'default' => '{}', 'single' => true, ) ); register_meta( 'post', 'boldblocks_block_class', array( 'object_subtype' => 'boldblocks_block', 'show_in_rest' => true, 'type' => 'string', 'default' => '', 'single' => true, ) ); register_meta( 'post', 'boldblocks_block_description', array( 'object_subtype' => 'boldblocks_block', 'show_in_rest' => true, 'type' => 'string', 'default' => '', 'single' => true, ) ); register_meta( 'post', 'boldblocks_block_icon', array( 'object_subtype' => 'boldblocks_block', 'show_in_rest' => true, 'type' => 'string', 'default' => '', 'single' => true, ) ); register_meta( 'post', 'boldblocks_template_lock', array( 'object_subtype' => 'boldblocks_block', 'show_in_rest' => true, 'type' => 'string', 'default' => 'all', 'single' => true, ) ); register_meta( 'post', 'boldblocks_enable_variation_picker', array( 'object_subtype' => 'boldblocks_block', 'show_in_rest' => true, 'type' => 'boolean', 'default' => false, 'single' => true, ) ); register_meta( 'post', 'boldblocks_enable_repeater', array( 'object_subtype' => 'boldblocks_block', 'show_in_rest' => true, 'type' => 'boolean', 'default' => false, 'single' => true, ) ); register_meta( 'post', 'boldblocks_parent_layout_type', array( 'object_subtype' => 'boldblocks_block', 'show_in_rest' => true, 'type' => 'string', 'default' => 'vstack', 'single' => true, ) ); register_meta( 'post', 'boldblocks_parent_block_icon', array( 'objeparentpe' => 'boldblocks_block', 'show_in_rest' => true, 'type' => 'string', 'default' => '', 'single' => true, ) ); register_meta( 'post', 'boldblocks_parent_enable_variation_picker', array( 'object_subtype' => 'boldblocks_block', 'show_in_rest' => true, 'type' => 'boolean', 'default' => false, 'single' => true, ) ); register_meta( 'post', 'boldblocks_disable_standalone', array( 'object_subtype' => 'boldblocks_block', 'show_in_rest' => true, 'type' => 'boolean', 'default' => false, 'single' => true, ) ); register_meta( 'post', 'boldblocks_is_fixed_nested_item_count', array( 'object_subtype' => 'boldblocks_block', 'show_in_rest' => true, 'type' => 'boolean', 'default' => false, 'single' => true, ) ); register_meta( 'post', 'boldblocks_nested_item_count', array( 'object_subtype' => 'boldblocks_block', 'show_in_rest' => true, 'type' => 'integer', 'default' => 1, 'single' => true, ) ); register_meta( 'post', 'boldblocks_parent_block_name', array( 'object_subtype' => 'boldblocks_block', 'show_in_rest' => true, 'type' => 'string', 'default' => '', 'single' => true, ) ); register_meta( 'post', 'boldblocks_parent_block_title', array( 'object_subtype' => 'boldblocks_block', 'show_in_rest' => true, 'type' => 'string', 'default' => '', 'single' => true, ) ); register_meta( 'post', 'boldblocks_parent_block_description', array( 'object_subtype' => 'boldblocks_block', 'show_in_rest' => true, 'type' => 'string', 'default' => '', 'single' => true, ) ); register_meta( 'post', 'boldblocks_parent_block_class', array( 'object_subtype' => 'boldblocks_block', 'show_in_rest' => true, 'type' => 'string', 'default' => '', 'single' => true, ) ); } /** * Load all custom blocks * * @return void */ public function load_custom_blocks() { // Load all custom blocks. $this->all_custom_blocks = $this->get_all_custom_blocks(); // Build an array of custom block name. $this->custom_block_names = array_map( function ( $block_args ) { return $block_args['name']; }, $this->all_custom_blocks ); // Build an array of repeater block name. $this->repeater_block_names = array_filter( array_map( function ( $block_arg ) { return isset( $block_arg['parent'] ) ? $block_arg['parent']['name'] : false; }, $this->all_custom_blocks ) ); // Register all blocks. foreach ( array_merge( $this->custom_block_names, $this->repeater_block_names ) as $name ) { register_block_type( $name, [ 'editor_script' => 'boldblocks-custom-blocks', 'style' => 'boldblocks-custom-blocks', 'editor_style' => 'boldblocks-custom-blocks', ] ); } } /** * Register scripts * * @return void */ public function register_scripts() { // Get the plugin instance. $boldblocks_cbb = boldblocks_cbb_get_instance(); // Custom blocks access file. $custom_blocks_asset = $boldblocks_cbb->include_file( 'build/custom-blocks.asset.php' ); // Scripts. wp_register_script( 'boldblocks-custom-blocks', $boldblocks_cbb->get_file_uri( 'build/custom-blocks.js' ), $custom_blocks_asset['dependencies'] ?? [], BOLDBLOCKS_CBB_VERSION, true ); // Define localize sripts. $blocks_scripts = [ 'blocks' => $this->all_custom_blocks, 'allowedBlocks' => $this->get_custom_blocks_allowed_blocks(), ]; // Load all custom blocks for registration. wp_localize_script( 'boldblocks-custom-blocks', 'BoldblocksBlocks', $blocks_scripts ); // Styles. wp_register_style( 'boldblocks-custom-blocks', $boldblocks_cbb->get_file_uri( 'build/custom-blocks.css' ), [], BOLDBLOCKS_CBB_VERSION ); wp_set_script_translations( 'boldblocks-custom-blocks', 'boldblocks' ); } /** * Get all custom blocks. * * @return array */ public function get_all_custom_blocks() { $block_posts = get_posts( [ 'post_type' => 'boldblocks_block', 'posts_per_page' => -1, 'post_status' => 'publish', ] ); return array_map( function( $item ) { // Template lock. $template_lock = get_post_meta( $item->ID, 'boldblocks_template_lock', true ); // Convert boolean string to boolean. $template_lock = 'false' === $template_lock ? false : $template_lock; $block_args = [ 'name' => sprintf( 'boldblocks/%s', sanitize_key( $item->post_name ) ), 'title' => wp_strip_all_tags( $item->post_title ), 'postContent' => $item->post_content, 'blocks' => get_post_meta( $item->ID, 'boldblocks_block_blocks', true ), 'description' => get_post_meta( $item->ID, 'boldblocks_block_description', true ), 'templateLock' => $template_lock, 'className' => get_post_meta( $item->ID, 'boldblocks_block_class', true ), 'blockIcon' => get_post_meta( $item->ID, 'boldblocks_block_icon', true ), 'enableVariationPicker' => ! ! get_post_meta( $item->ID, 'boldblocks_enable_variation_picker', true ), ]; // Get parent block parameters. $enable_repeater = get_post_meta( $item->ID, 'boldblocks_enable_repeater', true ); if ( $enable_repeater ) { $parent_name = get_post_meta( $item->ID, 'boldblocks_parent_block_name', true ); if ( ! $parent_name ) { $parent_name = $item->post_name; } $parent_layout_type = get_post_meta( $item->ID, 'boldblocks_parent_layout_type', true ); $parent_title = get_post_meta( $item->ID, 'boldblocks_parent_block_title', true ); if ( ! $parent_title ) { // translators: Repeater block title. $parent_title = sprintf( __( 'Repeater: %s', 'boldblocks' ), $item->post_title ); } $disable_standalone = get_post_meta( $item->ID, 'boldblocks_disable_standalone', true ); $parent_args = [ 'name' => sprintf( 'boldblocks/%s-repeater', sanitize_key( $parent_name ) ), 'title' => wp_strip_all_tags( $parent_title ), 'description' => get_post_meta( $item->ID, 'boldblocks_parent_block_description', true ), 'className' => get_post_meta( $item->ID, 'boldblocks_parent_block_class', true ) ?? '', 'blockIcon' => get_post_meta( $item->ID, 'boldblocks_parent_block_icon', true ), 'enableVariationPicker' => ! ! get_post_meta( $item->ID, 'boldblocks_parent_enable_variation_picker', true ), ]; $is_fixed_nested_item_count = get_post_meta( $item->ID, 'boldblocks_is_fixed_nested_item_count', true ); if ( $is_fixed_nested_item_count ) { $nested_item_count = get_post_meta( $item->ID, 'boldblocks_nested_item_count', true ); $nested_item_count = $nested_item_count ? absint( $nested_item_count ) : 1; $parent_args['nestedItemCount'] = $nested_item_count ? $nested_item_count : 1; } $parent_args['layoutType'] = $parent_layout_type; $block_args['standalone'] = ! $disable_standalone; $block_args['parent'] = $parent_args; } return $block_args; }, $block_posts ); } /** * Add custom blocks to the list of blocks that can create patterns from. * * @param array $allowed_blocks * @return array */ public function allow_creating_patterns( $allowed_blocks ) { return array_merge( $allowed_blocks, $this->custom_block_names, $this->repeater_block_names ); } /** * Get list of blocks that allow creating custom blocks from toolbar menu. */ public function get_custom_blocks_allowed_blocks() { return apply_filters( 'boldblocks/get_custom_block_allowed_blocks', [ 'core/group', 'core/cover', 'core/columns', ] ); } /** * Add custom columns to custom post type * * @param array $columns The array of columns. * @return array */ public function add_boldblocks_block_custom_columns( $columns ) { $custom_columns = array( 'block_name' => esc_html__( 'Block name', 'boldblocks' ), 'parent_block_name' => esc_html__( 'Parent block name', 'boldblocks' ), ); // Add after title column. $return = array_slice( $columns, 0, 2, true ) + $custom_columns + array_slice( $columns, 2, count( $columns ) - 2, true ); return $return; } /** * Manage custom columns. * * @param string $column the column name. * @param int $post_id the post id. */ public function manage_boldblocks_block_columns( $column, $post_id ) { switch ( $column ) { case 'block_name': echo 'boldblocks/' . get_post_field( 'post_name', $post_id ); break; case 'parent_block_name': $enable_repeater = get_post_meta( $post_id, 'boldblocks_enable_repeater', true ); if ( $enable_repeater ) { echo 'boldblocks/' . get_post_field( 'post_name', $post_id ) . '-repeater'; } else { echo 'NA'; } break; // Just break out of the switch statement for everything else. default: break; } } } endif;