123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470 |
- <?php
- if ( ! defined( 'ABSPATH' ) ) {
- exit; // Exit if accessed directly
- }
- if ( ! class_exists( 'acf_form_customizer' ) ) :
- class acf_form_customizer {
- /*
- * __construct
- *
- * This function will setup the class functionality
- *
- * @type function
- * @date 5/03/2014
- * @since 5.0.0
- *
- * @param n/a
- * @return n/a
- */
- function __construct() {
- // vars
- $this->preview_values = array();
- $this->preview_fields = array();
- $this->preview_errors = array();
- // actions
- 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 );
- // save
- add_filter( 'widget_update_callback', array( $this, 'save_widget' ), 10, 4 );
- }
- /*
- * admin_enqueue_scripts
- *
- * This action is run after post query but before any admin script / head actions.
- * It is a good place to register all actions.
- *
- * @type action (admin_enqueue_scripts)
- * @date 26/01/13
- * @since 3.6.0
- *
- * @param N/A
- * @return N/A
- */
- function customize_controls_init() {
- // load acf scripts
- acf_enqueue_scripts(
- array(
- 'context' => 'customize_controls',
- )
- );
- // actions
- add_action( 'acf/input/admin_footer', array( $this, 'admin_footer' ), 1 );
- }
- /*
- * save_widget
- *
- * This function will hook into the widget update filter and save ACF data
- *
- * @type function
- * @date 27/05/2015
- * @since 5.2.3
- *
- * @param $instance (array) widget settings
- * @param $new_instance (array) widget settings
- * @param $old_instance (array) widget settings
- * @param $widget (object) widget info
- * @return $instance
- */
- function save_widget( $instance, $new_instance, $old_instance, $widget ) {
- // bail early if not valid (customize + acf values + nonce)
- if ( ! isset( $_POST['wp_customize'] ) || ! isset( $new_instance['acf'] ) || ! acf_verify_nonce( 'widget' ) ) {
- return $instance;
- }
- // vars
- $data = array(
- 'post_id' => "widget_{$widget->id}",
- 'values' => array(),
- 'fields' => array(),
- );
- // append values
- $data['values'] = $new_instance['acf'];
- // append fields (name => key relationship) - used later in 'acf/get_field_reference' for customizer previews
- foreach ( $data['values'] as $k => $v ) {
- // get field
- $field = acf_get_field( $k );
- // continue if no field
- if ( ! $field ) {
- continue;
- }
- // update
- $data['fields'][ $field['name'] ] = $field['key'];
- }
- // append data to instance
- $instance['acf'] = $data;
- // return
- return $instance;
- }
- /*
- * settings
- *
- * This function will return an array of cutomizer settings that include ACF data
- * similar to `$customizer->settings();`
- *
- * @type function
- * @date 22/03/2016
- * @since 5.3.2
- *
- * @param $customizer (object)
- * @return $value (mixed)
- */
- function settings( $customizer ) {
- // vars
- $data = array();
- $settings = $customizer->settings();
- // bail early if no settings
- if ( empty( $settings ) ) {
- return false;
- }
- // loop over settings
- foreach ( $settings as $setting ) {
- // vars
- $id = $setting->id;
- // verify settings type
- if ( substr( $id, 0, 6 ) == 'widget' || substr( $id, 0, 7 ) == 'nav_menu' ) {
- // allow
- } else {
- continue;
- }
- // get value
- $value = $setting->post_value();
- // bail early if no acf
- if ( ! is_array( $value ) || ! isset( $value['acf'] ) ) {
- continue;
- }
- // set data
- $setting->acf = $value['acf'];
- // append
- $data[] = $setting;
- }
- // bail early if no settings
- if ( empty( $data ) ) {
- return false;
- }
- // return
- return $data;
- }
- /*
- * customize_preview_init
- *
- * This function is called when customizer preview is initialized
- *
- * @type function
- * @date 22/03/2016
- * @since 5.3.2
- *
- * @param $customizer (object)
- * @return n/a
- */
- function customize_preview_init( $customizer ) {
- // get customizer settings (widgets)
- $settings = $this->settings( $customizer );
- // bail early if no settings
- if ( empty( $settings ) ) {
- return;
- }
- // append values
- foreach ( $settings as $setting ) {
- // get acf data
- $data = $setting->acf;
- // append acf_value to preview_values
- $this->preview_values[ $data['post_id'] ] = $data['values'];
- $this->preview_fields[ $data['post_id'] ] = $data['fields'];
- }
- // bail early if no preview_values
- if ( empty( $this->preview_values ) ) {
- return;
- }
- // add filters
- 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 );
- }
- /**
- * pre_load_value
- *
- * Used to inject preview value
- *
- * @date 2/2/18
- * @since 5.6.5
- *
- * @param type $var Description. Default.
- * @return type Description.
- */
- function pre_load_value( $value, $post_id, $field ) {
- // check
- if ( isset( $this->preview_values[ $post_id ][ $field['key'] ] ) ) {
- return $this->preview_values[ $post_id ][ $field['key'] ];
- }
- // return
- return $value;
- }
- /**
- * pre_load_reference
- *
- * Used to inject preview value
- *
- * @date 2/2/18
- * @since 5.6.5
- *
- * @param type $var Description. Default.
- * @return type Description.
- */
- function pre_load_reference( $field_key, $field_name, $post_id ) {
- // check
- if ( isset( $this->preview_fields[ $post_id ][ $field_name ] ) ) {
- return $this->preview_fields[ $post_id ][ $field_name ];
- }
- // return
- return $field_key;
- }
- /*
- * customize_save
- *
- * This function is called when customizer saves a widget.
- * Normally, the widget_update_callback filter would be used, but the customizer disables this and runs a custom action
- * class-customizer-settings.php will save the widget data via the function set_root_value which uses update_option
- *
- * @type function
- * @date 22/03/2016
- * @since 5.3.2
- *
- * @param $customizer (object)
- * @return n/a
- */
- function customize_save( $customizer ) {
- // get customizer settings (widgets)
- $settings = $this->settings( $customizer );
- // bail early if no settings
- if ( empty( $settings ) ) {
- return;
- }
- // append values
- foreach ( $settings as $setting ) {
- // get acf data
- $data = $setting->acf;
- // save acf data
- acf_save_post( $data['post_id'], $data['values'] );
- // remove [acf] data from saved widget array
- $id_data = $setting->id_data();
- add_filter( 'pre_update_option_' . $id_data['base'], array( $this, 'pre_update_option' ), 10, 3 );
- }
- }
- /*
- * pre_update_option
- *
- * this function will remove the [acf] data from widget insance
- *
- * @type function
- * @date 22/03/2016
- * @since 5.3.2
- *
- * @param $post_id (int)
- * @return $post_id (int)
- */
- function pre_update_option( $value, $option, $old_value ) {
- // bail early if no value
- if ( empty( $value ) ) {
- return $value;
- }
- // loop over widgets
- // WP saves all widgets (of the same type) as an array of widgets
- foreach ( $value as $i => $widget ) {
- // bail early if no acf
- if ( ! isset( $widget['acf'] ) ) {
- continue;
- }
- // remove widget
- unset( $value[ $i ]['acf'] );
- }
- // return
- return $value;
- }
- /*
- * admin_footer
- *
- * This function will add some custom HTML to the footer of the edit page
- *
- * @type function
- * @date 11/06/2014
- * @since 5.0.0
- *
- * @param n/a
- * @return n/a
- */
- 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 early 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();
- endif;
- ?>
|