Skip to content

Instantly share code, notes, and snippets.

@fabrizim
Last active January 17, 2024 02:30
Show Gist options
  • Save fabrizim/9c0f36365f20705f7f73 to your computer and use it in GitHub Desktop.
Save fabrizim/9c0f36365f20705f7f73 to your computer and use it in GitHub Desktop.
Plugin to allow for Advanced Custom Fields to be used in widgets within the Customizer
<?php
/*
Plugin Name: ACF Customizer Patch
Plugin URI: https://gist.github.com/fabrizim/9c0f36365f20705f7f73
Description: A class to allow acf widget fields to be stored with normal widget settings and allow for use in customizer.
Author: Mark Fabrizio
Version: 1.0
Author URI: http://owlwatch.com/
*/
class acf_customizer_patch
{
protected $_capture_options = false;
protected $_captured_options = array();
protected $_instance;
public function __construct()
{
add_filter('widget_display_callback', array($this, 'before_widget_display'), 20, 3);
add_filter('in_widget_form', array($this, 'before_edit_form'), 9, 3);
add_filter('widget_update_callback', array($this, 'before_save_acf_fields'), 9, 3);
add_filter('pre_update_option', array($this, 'pre_update_option'), 8, 3);
add_filter('widget_update_callback', array($this, 'after_save_acf_fields'), 11, 3);
// need to include the acf input scripts
// This could be included in the 'acf_input_listener' class
add_action('customize_controls_print_footer_scripts', array( $this, 'admin_footer'), 20 );
}
public function admin_footer() {
do_action('acf/input/admin_footer');
}
/**
* There may be a better way to find out if we are in the customizer,
* but this works for now. If someone has a better way, let me know.
*/
protected function in_customizer()
{
return @$_REQUEST['wp_customize'] == 'on' || basename($_SERVER['SCRIPT_NAME']) == 'customize.php';
}
/**
* @wp.filter widget_display_callback
* @wp.priority 20
*/
public function before_widget_display( $instance, $widget, $args )
{
$this->prepare_widget_options( $widget, $instance );
return $instance;
}
/**
* @wp.filter in_widget_form
* @wp.priority 9
*/
public function before_edit_form( $widget, $return, $instance )
{
$this->prepare_widget_options( $widget, $instance );
return $widget;
}
public function prepare_widget_options( $widget, $instance )
{
$this->_instance = $instance;
$field_groups = acf_get_field_groups(array(
'widget' => $widget->id_base
));
if( count( $field_groups ) ) foreach( $field_groups as $group ){
$fields = acf_get_fields( $group );
if( count($fields) ) foreach( $fields as $field ){
$name = $field['name'];
add_filter("pre_option_widget_{$widget->id}_{$name}", array($this, 'pre_get_option') );
}
}
return $widget;
}
public function pre_get_option( $value )
{
$filter = current_filter();
$name = str_replace('pre_option_widget_', '', $filter);
preg_match('/(.+\-\d+?)_(.+)/', $name, $matches );
list( $full, $widget_id, $var ) = $matches;
if( $this->_instance && isset( $this->_instance[$var] ) ) return $this->_instance[$var];
return $value;
}
/**
* @wp.filter widget_update_callback
* @wp.priority 9
*/
public function before_save_acf_fields( $instance, $new_instance, $old_instance )
{
global $wp_customize;
$this->_capture_options = true;
if( $this->in_customizer() )
remove_filter( 'pre_update_option', array( $wp_customize->widgets, 'capture_filter_pre_update_option' ), 10);
return $instance;
}
/**
* @wp.filter pre_update_option
* @wp.priority 8
*/
public function pre_update_option( $value, $option, $old_value )
{
global $wp_customize;
if( !$this->_capture_options ) return $value;
if( preg_match('/^([^_].+\-\d+?)_(.+)/', $option, $matches ) ){
$this->_captured_options[$matches[2]] = $value;
}
// if this is not an acf field, this should be the actual
// widget option (which needs to be captured by the customizer)
if( !preg_match('/^(.+\-\d+?)_(.+)/', $option ) && $this->in_customizer() ){
$wp_customize->widgets->capture_filter_pre_update_option( $value, $option, $old_value );
}
return $this->in_customizer() ? $old_value : $value;
}
/**
* @wp.filter widget_update_callback
* @wp.priority 11
*/
public function after_save_acf_fields( $instance, $new_instance, $old_instance )
{
$instance = array_merge( $instance, $this->_captured_options );
$this->_capture_options = false;
return $instance;
}
}
$acf_customizer_patch = new acf_customizer_patch();
@certainlyakey
Copy link

Thanks for this! Could you explain a bit on how this can be used?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment