|
<?php |
|
/** |
|
* Utility to allow even easier registration of ACF Gutenberg Blocks. |
|
* Adds additional field group options and dynamicly registers the blocks. |
|
* All you have to do is create field group and block template. |
|
* |
|
* Requires ACF V5.8 or greater. |
|
*/ |
|
|
|
|
|
/** |
|
* Add custom gutenberg block category for ACF blocks |
|
* |
|
* @param array $categories existing block categories. |
|
* @param WP_Post $post current post object. |
|
* @return array |
|
*/ |
|
function solum_add_acf_block_category( $categories, $post ) { |
|
return array_merge( |
|
$categories, |
|
array( |
|
array( |
|
'slug' => 'acf-blocks', |
|
'title' => __( 'Advanced Blocks' ), |
|
'icon' => 'welcome-widgets-menus', |
|
), |
|
) |
|
); |
|
} |
|
add_filter( 'block_categories', 'solum_add_acf_block_category', 10, 2 ); |
|
|
|
/** |
|
* Parsing of field groups that have the block logic enabled. |
|
* |
|
* @return void |
|
*/ |
|
function solum_register_dynamic_acf_blocks() { |
|
if ( function_exists( 'acf_register_block' ) ) { |
|
$field_groups = acf_get_field_groups(); |
|
|
|
foreach ( $field_groups as $field_group ) { |
|
if ( ! empty( $field_group['as_block'] ) && 1 === $field_group['as_block'] ) { |
|
// Support for namespacing blocks with "Block: " and avoid naming the block with it. |
|
$title = str_replace( 'Block: ', '', $field_group['title'] ); |
|
$slug = sanitize_title( $title ); |
|
|
|
acf_register_block( |
|
array( |
|
'name' => $slug, |
|
'title' => $title, |
|
'description' => $field_group['description'] ?? '', |
|
'render_callback' => 'solum_render_dynamic_acf_block_partial', |
|
'category' => ! empty( $field_group['block_category'] ) ? $field_group['block_category'] : 'acf-blocks', |
|
'icon' => ! empty( $field_group['block_icon'] ) ? $field_group['block_icon'] : 'welcome-widgets-menus', |
|
'align' => ! empty( $field_group['block_align'] ) ? $field_group['block_align'] : '', |
|
'keywords' => explode( ' ', $field_group['block_keywords'] ), |
|
'post_types' => $field_group['block_post_types'] ? $field_group['block_post_types'] : [], |
|
'mode' => ! empty( $field_group['block_mode'] ) ? $field_group['block_mode'] : 'preview', |
|
'supports' => [ |
|
'align' => ! empty( $field_group['block_alignments'] ) ? $field_group['block_alignments'] : false, |
|
'anchor' => $field_group['block_anchor'] ?? true, |
|
'customClassNames' => $field_group['block_customClassNames'] ?? true, |
|
'multiple' => $field_group['block_multiple'] ?? true, |
|
'reusable' => $field_group['block_reusable'] ?? true, |
|
], |
|
) |
|
); |
|
} |
|
} |
|
} |
|
} |
|
add_action( 'acf/init', 'solum_register_dynamic_acf_blocks' ); |
|
|
|
/** |
|
* Global render helper to parse to the proper template partial for each block type |
|
* |
|
* @param array $block the block being parsed. |
|
* @return void |
|
*/ |
|
function solum_render_dynamic_acf_block_partial( $block ) { |
|
// Convert name ("acf/block_name") into path friendly slug. |
|
$slug = str_replace( 'acf/', '', $block['name'] ); |
|
$title = $block['title']; |
|
|
|
// Allow partial's location to be filtered. |
|
$template_root = apply_filters( 'solum_dynamic_acf_block_partials_location', 'templates/acf-blocks' ); |
|
$block_template = "{$template_root}/{$slug}.php"; |
|
// Attempt to include a template part from within the defined templates folder. |
|
if ( file_exists( locate_template( $block_template ) ) ) { |
|
include locate_template( $block_template ); |
|
} elseif ( defined( 'WP_ENV' ) && 'development' === WP_ENV ) { |
|
// Template not found, add recomendation. |
|
error_log( "[WARNING] Create {$block_template} to complete registration for the \"{$title}\" acf block." ); |
|
} |
|
} |
|
|
|
/** |
|
* Add field groupoptions to convert field group to a gutenberg block. |
|
* |
|
* @param array $field_group Field group data. |
|
* @return void |
|
*/ |
|
function solum_add_acf_fieldgroup_fields_for_blocks( $field_group ) { |
|
acf_render_field_wrap( |
|
array( |
|
'label' => __( 'Gutenberg Block' ), |
|
'instructions' => 'Turn this field group into a gutenberg block. (Will overwrite any location rules!)', |
|
'type' => 'true_false', |
|
'name' => 'as_block', |
|
'key' => 'as_block', // for conditional logic. |
|
'prefix' => 'acf_field_group', |
|
'value' => $field_group['as_block'] ?? 0, |
|
'ui' => 1, |
|
) |
|
); |
|
|
|
$when_as_block_is_enabled = [ |
|
'field' => 'as_block', |
|
'operator' => '==', |
|
'value' => 1, |
|
]; |
|
|
|
acf_render_field_wrap( |
|
array( |
|
'label' => __( 'Icon' ), |
|
'instructions' => 'Can be any of <a href="https://developer.wordpress.org/resource/dashicons/" target="_blank">WordPress’ Dashicons</a>, or a custom svg element.', |
|
'type' => 'text', |
|
'placeholder' => 'welcome-widgets-menus', |
|
'name' => 'block_icon', |
|
'prefix' => 'acf_field_group', |
|
'value' => $field_group['block_icon'] ?? 'welcome-widgets-menus', |
|
'conditional_logic' => $when_as_block_is_enabled, |
|
) |
|
); |
|
|
|
$category_chocies = array( |
|
'common' => 'Common', |
|
'formatting' => 'Formatting', |
|
'layout' => 'Layout', |
|
'widgets' => 'Widgets', |
|
'embed' => 'Embed', |
|
'acf-blocks' => 'Advanced Blocks', |
|
); |
|
|
|
acf_render_field_wrap( |
|
array( |
|
'label' => __( 'Category' ), |
|
'instructions' => 'Blocks are grouped into categories to help users browse and discover them.', |
|
'type' => 'select', |
|
'name' => 'block_category', |
|
'prefix' => 'acf_field_group', |
|
'value' => $field_group['block_category'] ?? 'acf-blocks', |
|
'default' => 'acf-blocks', |
|
'choices' => $category_chocies, |
|
'conditional_logic' => $when_as_block_is_enabled, |
|
) |
|
); |
|
|
|
acf_render_field_wrap( |
|
array( |
|
'label' => __( 'Keywords' ), |
|
'instructions' => 'A block may have aliases that help users discover it while searching.', |
|
'type' => 'text', |
|
'name' => 'block_keywords', |
|
'prefix' => 'acf_field_group', |
|
'value' => $field_group['block_keywords'] ?? '', |
|
'conditional_logic' => $when_as_block_is_enabled, |
|
) |
|
); |
|
|
|
$_post_types = get_post_types( null, 'objects' ); |
|
$exclude_acf = [ 'acf-field', 'acf-field-group' ]; |
|
$post_type_chocies = array_reduce( |
|
$_post_types, |
|
function( $carry, $item ) use ( $exclude_acf ) { |
|
if ( in_array( $item->name, $exclude_acf, true ) || $item->_builtin && ! $item->public ) { |
|
return $carry; |
|
} |
|
$carry[ $item->name ] = $item->label; |
|
return $carry; |
|
}, |
|
[] |
|
); |
|
|
|
acf_render_field_wrap( |
|
array( |
|
'label' => __( 'Supported Post Types' ), |
|
'instructions' => 'Post types that can use this block. (Leave blank to for all post types)', |
|
'type' => 'select', |
|
'multiple' => 1, |
|
'ui' => 1, |
|
'name' => 'block_post_types', |
|
'prefix' => 'acf_field_group', |
|
'value' => $field_group['block_category'] ?? 'acf-blocks', |
|
'choices' => $post_type_chocies, |
|
'conditional_logic' => $when_as_block_is_enabled, |
|
) |
|
); |
|
|
|
$alignment_choices = [ |
|
'left' => 'Left', |
|
'center' => 'Center', |
|
'right' => 'Right', |
|
]; |
|
|
|
if ( get_theme_support( 'align-wide' ) ) { |
|
$alignment_choices['wide'] = 'Wide'; |
|
$alignment_choices['full'] = 'Full'; |
|
} |
|
|
|
acf_render_field_wrap( |
|
array( |
|
'label' => __( 'Alignment Options' ), |
|
'instructions' => 'Alignment options to allow.', |
|
'type' => 'checkbox', |
|
'name' => 'block_alignments', |
|
'prefix' => 'acf_field_group', |
|
'value' => $field_group['block_alignments'] ?? [ 'left', 'center', 'right' ], |
|
'choices' => $alignment_choices, |
|
'conditional_logic' => $when_as_block_is_enabled, |
|
) |
|
); |
|
|
|
$default_alignment_choices = [ |
|
null => '-- Choose Alignment Options First --', |
|
]; |
|
if ( ! empty( $field_group['block_alignments'] ) ) { |
|
$default_alignment_choices = wp_array_slice_assoc( $alignment_choices, $field_group['block_alignments'] ); |
|
} |
|
acf_render_field_wrap( |
|
array( |
|
'label' => __( 'Default Alignment' ), |
|
'instructions' => 'Select a default from the chosen Alignmet Options values. (save to update available options)', |
|
'type' => 'select', |
|
'name' => 'block_align', |
|
'prefix' => 'acf_field_group', |
|
'value' => $field_group['block_align'] ?? [ 'left' ], |
|
'choices' => $default_alignment_choices, |
|
'conditional_logic' => $when_as_block_is_enabled, |
|
) |
|
); |
|
|
|
acf_render_field_wrap( |
|
array( |
|
'label' => __( 'Default Mode' ), |
|
'instructions' => 'What to display when adding this block.', |
|
'type' => 'radio', |
|
'name' => 'block_mode', |
|
'value' => $field_group['block_mode'] ?? 'preview', |
|
'prefix' => 'acf_field_group', |
|
'choices' => [ |
|
'preview' => 'Preview', |
|
'edit' => 'Editor', |
|
], |
|
'conditional_logic' => $when_as_block_is_enabled, |
|
) |
|
); |
|
|
|
$misc_supports_options = [ |
|
[ |
|
'name' => 'block_anchor', |
|
'label' => 'Anchor', |
|
'instructions' => 'Support for an anchor link to the specific block.', |
|
'default' => 1, |
|
], |
|
[ |
|
'name' => 'block_customClassNames', |
|
'label' => 'Custom Class Names', |
|
'instructions' => 'Support for the custom class names input.', |
|
'default' => 1, |
|
], |
|
[ |
|
'name' => 'block_multiple', |
|
'label' => 'Multiple in a post', |
|
'instructions' => 'Allow multiple instances of this block in a post', |
|
'default' => 1, |
|
], |
|
[ |
|
'name' => 'block_reusable', |
|
'label' => 'Reusable block', |
|
'instructions' => 'Allow this block to be converted to a reusable block.', |
|
'default' => 1, |
|
], |
|
]; |
|
|
|
foreach ( $misc_supports_options as $supports ) { |
|
acf_render_field_wrap( |
|
array( |
|
'label' => $supports['label'], |
|
'instructions' => $supports['instructions'], |
|
'type' => 'true_false', |
|
'name' => $supports['name'], |
|
'prefix' => 'acf_field_group', |
|
'value' => $field_group[ $supports['name'] ] ?? $supports['default'], |
|
'default' => $supports['default'], |
|
'conditional_logic' => $when_as_block_is_enabled, |
|
'ui' => 1, |
|
) |
|
); |
|
} |
|
} |
|
add_action( 'acf/render_field_group_settings', 'solum_add_acf_fieldgroup_fields_for_blocks', 10, 1 ); |
|
|
|
/** |
|
* Force field to be saved as a block location |
|
* |
|
* @param array $field_group field group. |
|
* @return array $field_group |
|
*/ |
|
function solum_acf_fieldgroup_save_as_block( $field_group ) { |
|
if ( ! empty( $field_group['as_block'] ) && 1 === $field_group['as_block'] ) { |
|
$title = str_replace( 'Block: ', '', $field_group['title'] ); |
|
$slug = sanitize_title( $title ); |
|
|
|
$field_group['location'] = [ |
|
[ |
|
[ |
|
'param' => 'block', |
|
'operator' => '==', |
|
'value' => 'acf/' . $slug, |
|
], |
|
], |
|
]; |
|
} |
|
|
|
return $field_group; |
|
} |
|
add_filter( 'acf/validate_field_group', 'solum_acf_fieldgroup_save_as_block', 10, 1 ); |
|
|
|
|
|
/** |
|
* DEBUG: Add block template column to ACF field Groups |
|
* |
|
* @param array $defaults existing columns. |
|
* @return array |
|
*/ |
|
function solum_debug_acf_add_admin_column_block_template( $defaults ) { |
|
$defaults['block_template'] = 'Block Template Path'; |
|
|
|
return $defaults; |
|
} |
|
|
|
/** |
|
* DEBUG: Output location of block template |
|
* |
|
* @param string $column current column. |
|
* @param integer $post_id current post id. |
|
* @return void |
|
*/ |
|
function solum_debug_acf_output_block_template_column( $column, $post_id ) { |
|
if ( 'block_template' === $column ) { |
|
global $post; |
|
$field_group = (array) maybe_unserialize( $post->post_content ); |
|
|
|
if ( ! empty( $field_group['as_block'] ) && $field_group['as_block'] ) { |
|
$title = str_replace( 'Block: ', '', $post->post_title ); |
|
$slug = sanitize_title( $title ); |
|
|
|
$template_root = apply_filters( 'solum_dynamic_acf_block_partials_location', 'templates/acf-blocks' ); |
|
$template = "{$template_root}/{$slug}.php"; |
|
|
|
echo '<code>' . $template . '</code>'; |
|
if (!file_exists( locate_template($template) )) { |
|
echo '<br/><strong style="color: red;">TEMPLATE MISSING</strong>'; |
|
} |
|
} |
|
} |
|
} |
|
|
|
/** |
|
* Add admin columns to field groups that dislays the template locations to be loaded. |
|
*/ |
|
if ( defined( 'WP_ENV' ) && 'development' === WP_ENV ) { |
|
add_action( 'manage_edit-acf-field-group_columns', 'solum_debug_acf_add_admin_column_block_template', 35, 1 ); |
|
add_action( 'manage_acf-field-group_posts_custom_column', 'solum_debug_acf_output_block_template_column', 10, 2 ); |
|
} |