Last active
May 19, 2023 15:24
-
-
Save kingkool68/cd0738987eada4db28e79a35476760c3 to your computer and use it in GitHub Desktop.
How I use Advanced Custom Fields' Blocks to make custom components for WordPress sites. Logic is all in PHP, HTML templating is done in Twig via https://github.com/kingkool68/sprig This is in response to a tweet https://twitter.com/Gravnetic/status/1517511382102540288
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
/** | |
* A block with an image and text on the side | |
*/ | |
class CoderPad_Text_Image_Block { | |
/** | |
* Get an instance of this class | |
*/ | |
public static function get_instance() { | |
static $instance = null; | |
if ( null === $instance ) { | |
$instance = new static(); | |
$instance->setup_actions(); | |
} | |
return $instance; | |
} | |
/** | |
* Hook into WordPress via actions | |
*/ | |
public function setup_actions() { | |
add_action( 'acf/init', array( $this, 'action_acf_init' ) ); | |
} | |
/** | |
* Register Advanced Custom Fields | |
*/ | |
public function action_acf_init() { | |
// Custom fields for the block | |
$args = array( | |
'name' => 'coderpad-text-image', | |
'title' => 'CoderPad Text/Image', | |
'description' => 'A custom Text/Image block.', | |
'render_callback' => array( $this, 'render_from_block' ), | |
'category' => 'coderpad', | |
'icon' => 'align-left', | |
'keywords' => array( 'text/image', 'text image' ), | |
); | |
acf_register_block_type( $args ); | |
$args = array( | |
'key' => 'text_image_block_fields', | |
'title' => 'Call to Action Block Fields', | |
'fields' => array( | |
array( | |
'key' => 'field_text_image_block_image_id', | |
'name' => 'text_image_block_image_id', | |
'label' => 'Image', | |
'type' => 'image', | |
'return_format' => 'id', | |
), | |
array( | |
'key' => 'field_text_image_block_image_size', | |
'name' => 'text_image_block_image_size', | |
'label' => 'Image Size', | |
'type' => 'select', | |
'choices' => CoderPad_Media::get_image_size_names(), | |
'allow_null' => true, | |
), | |
array( | |
'key' => 'field_text_image_block_image_alignment', | |
'name' => 'text_image_block_image_alignment', | |
'label' => 'Image Alignment', | |
'type' => 'select', | |
'choices' => array( | |
'left' => 'Left', | |
'right' => 'Right', | |
), | |
), | |
array( | |
'key' => 'field_text_image_block_image_proportion', | |
'name' => 'text_image_block_image_proportion', | |
'label' => 'Image Proportion', | |
'type' => 'select', | |
'choices' => array( | |
'one-third' => '1/3', | |
'half' => '1/2', | |
'two-thirds' => '2/3', | |
), | |
'allow_null' => true, | |
), | |
array( | |
'key' => 'field_text_image_block_headline', | |
'name' => 'text_image_block_headline', | |
'label' => 'Headline', | |
'type' => 'text', | |
), | |
array( | |
'key' => 'field_text_image_block_headline_url', | |
'name' => 'text_image_block_headline_url', | |
'label' => 'Headline URL', | |
'instructions' => 'Link the headline and image to a URL', | |
'type' => 'text', | |
), | |
array( | |
'key' => 'field_text_image_block_description', | |
'name' => 'text_image_block_description', | |
'label' => 'Description', | |
'type' => 'wysiwyg', | |
'toolbar' => 'basic', | |
'media_upload' => false, | |
), | |
array( | |
'key' => 'field_text_image_block_cta_label', | |
'name' => 'text_image_block_cta_label', | |
'label' => 'Call to Action Label', | |
'type' => 'text', | |
), | |
array( | |
'key' => 'field_text_image_block_cta_url', | |
'name' => 'text_image_block_cta_url', | |
'label' => 'Call to Action URL', | |
'type' => 'url', | |
), | |
array( | |
'key' => 'field_text_image_block_cta_style', | |
'name' => 'text_image_block_cta_style', | |
'label' => 'Call to Action Style', | |
'type' => 'select', | |
'choices' => array( | |
'primary' => 'Primary', | |
'outline' => 'Outline', | |
), | |
), | |
), | |
'location' => array( | |
array( | |
array( | |
'param' => 'block', | |
'operator' => '==', | |
'value' => 'acf/coderpad-text-image', | |
), | |
), | |
), | |
'description' => 'Text/Image fields', | |
); | |
acf_add_local_field_group( $args ); | |
} | |
/** | |
* Render a Text Image component | |
* | |
* @param array $args Arguments to modify what is rendered | |
*/ | |
public static function render( $args = array() ) { | |
$defaults = array( | |
'image' => '', | |
'image_alignment' => 'left', | |
'image_proportion' => '', | |
'headline' => '', | |
'headline_url' => '', | |
'cta_label' => '', | |
'cta_url' => '', | |
'cta_style' => 'primary', | |
); | |
$context = wp_parse_args( $args, $defaults ); | |
if ( $context['image_alignment'] !== 'right' ) { | |
$context['image_alignment'] = $defaults['image_alignment']; | |
} | |
if ( ! empty( $context['headline'] ) ) { | |
$context['headline'] = apply_filters( 'the_title', $context['headline'] ); | |
} | |
if ( ! empty( $context['description'] ) ) { | |
$context['description'] = apply_filters( 'the_content', $context['description'] ); | |
} | |
return Sprig::render( 'text-image-block.twig', $context ); | |
} | |
/** | |
* Call to Action block callback function | |
* | |
* @param array $block The block settings and attributes. | |
* @param string $content The block inner HTML (empty). | |
* @param bool $is_preview True during AJAX preview. | |
* @param (int|string) $post_id The post ID this block is saved to. | |
*/ | |
public function render_from_block( $block = array(), $content = '', $is_preview = false, $post_id = 0 ) { | |
$image_id = get_field( 'text_image_block_image_id' ); | |
$image_args = array(); | |
$image_size = get_field( 'text_image_block_image_size' ); | |
if ( ! empty( $image_size ) ) { | |
$image_args['size'] = $image_size; | |
} | |
$headline_url = get_field( 'text_image_block_headline_url' ); | |
if ( $is_preview ) { | |
$headline_url = ''; | |
} | |
if ( ! empty( $headline_url ) ) { | |
$image_args['link_url'] = $headline_url; | |
} | |
$args = array( | |
'image' => CoderPad_Media::render_image_from_post( $image_id, $image_args ), | |
'image_alignment' => get_field( 'text_image_block_image_alignment' ), | |
'image_proportion' => get_field( 'text_image_block_image_proportion' ), | |
'image_size' => get_field( 'text_image_block_image_size' ), | |
'headline' => get_field( 'text_image_block_headline' ), | |
'headline_url' => $headline_url, | |
'description' => get_field( 'text_image_block_description' ), | |
'cta_label' => get_field( 'text_image_block_cta_label' ), | |
'cta_url' => get_field( 'text_image_block_cta_url' ), | |
'cta_style' => get_field( 'text_image_block_cta_style' ), | |
); | |
if ( empty( $args['headline'] ) && $is_preview ) { | |
echo '(Fill in Text/Image Block Details)'; | |
return; | |
} | |
echo static::render( $args ); | |
} | |
} | |
CoderPad_Text_Image_Block::get_instance(); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<div class=" | |
text-image-block | |
text-image-block--align-{{ image_alignment|sanitize_html_class }} | |
{% if not image %} | |
text-image-block--no-image | |
{% endif %} | |
"> | |
<div class=" | |
media | |
{% if image_proportion %} | |
proportion--{{ image_proportion|sanitize_html_class }} | |
{% endif %} | |
"> | |
{{ image }} | |
</div> | |
<div class="content"> | |
{% if headline %} | |
<h3 class="headline"> | |
{% if headline_url %} | |
<a href="{{ headline_url|esc_url }}">{{ headline }}</a> | |
{% else %} | |
{{ headline }} | |
{% endif %} | |
</h3> | |
{% endif %} | |
{{ description }} | |
{% if cta_label and cta_url %} | |
<a href="{{ cta_url|esc_url }}" class="cta cta-style--{{ cta_style|sanitize_html_class }}">{{ cta_label }}</a> | |
{% endif %} | |
</div> | |
</div> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment