<?php if (!defined('ABSPATH')) { exit; } if (!class_exists('acf_form_customizer')) { class acf_form_customizer { function __construct() { $this->preview_values = array(); $this->preview_fields = array(); $this->preview_errors = array(); add_action('customize_controls_init', array($this, 'customize_controls_init')); add_action('customize_preview_init', array($this, 'customize_preview_init'), 1, 1); add_action('customize_save', array($this, 'customize_save'), 1, 1); add_filter('widget_update_callback', array($this, 'save_widget'), 10, 4); } function customize_controls_init() { acf_enqueue_scripts(array('context' => 'customize_controls')); add_action('acf/input/admin_footer', array($this, 'admin_footer'), 1); } function save_widget($instance, $new_instance, $old_instance, $widget) { if (!isset($_POST['wp_customize']) || !isset($new_instance['acf']) || !acf_verify_nonce('widget')) { return $instance; } $data = array('post_id' => "widget_{$widget->id}", 'values' => array(), 'fields' => array()); $data['values'] = $new_instance['acf']; foreach ($data['values'] as $k => $v) { $field = acf_get_field($k); if (!$field) { continue; } $data['fields'][$field['name']] = $field['key']; } $instance['acf'] = $data; return $instance; } function settings($customizer) { $data = array(); $settings = $customizer->settings(); if (empty($settings)) { return false; } foreach ($settings as $setting) { $id = $setting->id; if (substr($id, 0, 6) == 'widget' || substr($id, 0, 7) == 'nav_menu') { } else { continue; } $value = $setting->post_value(); if (!is_array($value) || !isset($value['acf'])) { continue; } $setting->acf = $value['acf']; $data[] = $setting; } if (empty($data)) { return false; } return $data; } function customize_preview_init($customizer) { $settings = $this->settings($customizer); if (empty($settings)) { return; } foreach ($settings as $setting) { $data = $setting->acf; $this->preview_values[$data['post_id']] = $data['values']; $this->preview_fields[$data['post_id']] = $data['fields']; } if (empty($this->preview_values)) { return; } add_filter('acf/pre_load_value', array($this, 'pre_load_value'), 10, 3); add_filter('acf/pre_load_reference', array($this, 'pre_load_reference'), 10, 3); } function pre_load_value($value, $post_id, $field) { if (isset($this->preview_values[$post_id][$field['key']])) { return $this->preview_values[$post_id][$field['key']]; } return $value; } function pre_load_reference($field_key, $field_name, $post_id) { if (isset($this->preview_fields[$post_id][$field_name])) { return $this->preview_fields[$post_id][$field_name]; } return $field_key; } function customize_save($customizer) { $settings = $this->settings($customizer); if (empty($settings)) { return; } foreach ($settings as $setting) { $data = $setting->acf; acf_save_post($data['post_id'], $data['values']); $id_data = $setting->id_data(); add_filter('pre_update_option_' . $id_data['base'], array($this, 'pre_update_option'), 10, 3); } } function pre_update_option($value, $option, $old_value) { if (empty($value)) { return $value; } foreach ($value as $i => $widget) { if (!isset($widget['acf'])) { continue; } unset($value[$i]['acf']); } return $value; } function admin_footer() { ?> <script type="text/javascript"> (function($) { // customizer saves widget on any input change, so unload is not needed acf.unload.active = 0; // hack customizer function to remove bug caused by WYSIWYG field using aunique ID // customizer compares returned AJAX HTML with the HTML of the widget form. // the _getInputsSignature() function is used to generate a string based of input name + id. // because ACF generates a unique ID on the WYSIWYG field, this string will not match causing the preview function to bail. // an attempt was made to remove the WYSIWYG unique ID, but this caused multiple issues in the wp-admin and altimately doesn't make sense with the tinymce rule that all editors must have a unique ID. // source: wp-admin/js/customize-widgets.js // vars var WidgetControl = wp.customize.Widgets.WidgetControl.prototype; // backup functions WidgetControl.__getInputsSignature = WidgetControl._getInputsSignature; WidgetControl.__setInputState = WidgetControl._setInputState; // modify __getInputsSignature WidgetControl._getInputsSignature = function( inputs ) { // vars var signature = this.__getInputsSignature( inputs ); safe = []; // split signature = signature.split(';'); // loop for( var i in signature ) { // vars var bit = signature[i]; // bail ealry if acf is found if( bit.indexOf('acf') !== -1 ) continue; // append safe.push( bit ); } // update signature = safe.join(';'); // return return signature; }; // modify _setInputState // this function deosn't seem to run on widget title/content, only custom fields // either way, this function is not needed and will break ACF fields WidgetControl._setInputState = function( input, state ) { return true; }; })(jQuery); </script> <?php } } new acf_form_customizer(); }