PluginProbe
Advanced Custom Fields (ACF®) / 6.0.0
Advanced Custom Fields (ACF®) v6.0.0
6.8.9 6.8.8 6.8.7 6.8.6 6.8.5 6.8.4 6.8.3 6.8.2 6.8.1 5.8.5 5.8.6 5.8.7 5.8.8 5.8.9 5.9.0 5.9.1 5.9.2 5.9.3 5.9.4 5.9.5 5.9.6 5.9.7 5.9.8 5.9.9 6.0.0 All 230 releases
advanced-custom-fields / includes / forms / form-customizer.php
form-customizer.php
471 lines 9.6 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 if ( ! defined( 'ABSPATH' ) ) {
4 exit; // Exit if accessed directly
5 }
6
7 if ( ! class_exists( 'acf_form_customizer' ) ) :
8
9 class acf_form_customizer {
10
11
12 /*
13 * __construct
14 *
15 * This function will setup the class functionality
16 *
17 * @type function
18 * @date 5/03/2014
19 * @since 5.0.0
20 *
21 * @param n/a
22 * @return n/a
23 */
24
25 function __construct() {
26
27 // vars
28 $this->preview_values = array();
29 $this->preview_fields = array();
30 $this->preview_errors = array();
31
32 // actions
33 add_action( 'customize_controls_init', array( $this, 'customize_controls_init' ) );
34 add_action( 'customize_preview_init', array( $this, 'customize_preview_init' ), 1, 1 );
35 add_action( 'customize_save', array( $this, 'customize_save' ), 1, 1 );
36
37 // save
38 add_filter( 'widget_update_callback', array( $this, 'save_widget' ), 10, 4 );
39
40 }
41
42
43 /*
44 * admin_enqueue_scripts
45 *
46 * This action is run after post query but before any admin script / head actions.
47 * It is a good place to register all actions.
48 *
49 * @type action (admin_enqueue_scripts)
50 * @date 26/01/13
51 * @since 3.6.0
52 *
53 * @param N/A
54 * @return N/A
55 */
56
57 function customize_controls_init() {
58
59 // load acf scripts
60 acf_enqueue_scripts(
61 array(
62 'context' => 'customize_controls',
63 )
64 );
65
66 // actions
67 add_action( 'acf/input/admin_footer', array( $this, 'admin_footer' ), 1 );
68
69 }
70
71
72 /*
73 * save_widget
74 *
75 * This function will hook into the widget update filter and save ACF data
76 *
77 * @type function
78 * @date 27/05/2015
79 * @since 5.2.3
80 *
81 * @param $instance (array) widget settings
82 * @param $new_instance (array) widget settings
83 * @param $old_instance (array) widget settings
84 * @param $widget (object) widget info
85 * @return $instance
86 */
87
88 function save_widget( $instance, $new_instance, $old_instance, $widget ) {
89
90 // bail early if not valid (customize + acf values + nonce)
91 if ( ! isset( $_POST['wp_customize'] ) || ! isset( $new_instance['acf'] ) || ! acf_verify_nonce( 'widget' ) ) {
92 return $instance;
93 }
94
95 // vars
96 $data = array(
97 'post_id' => "widget_{$widget->id}",
98 'values' => array(),
99 'fields' => array(),
100 );
101
102 // append values
103 $data['values'] = $new_instance['acf'];
104
105 // append fields (name => key relationship) - used later in 'acf/get_field_reference' for customizer previews
106 foreach ( $data['values'] as $k => $v ) {
107
108 // get field
109 $field = acf_get_field( $k );
110
111 // continue if no field
112 if ( ! $field ) {
113 continue;
114 }
115
116 // update
117 $data['fields'][ $field['name'] ] = $field['key'];
118
119 }
120
121 // append data to instance
122 $instance['acf'] = $data;
123
124 // return
125 return $instance;
126
127 }
128
129
130 /*
131 * settings
132 *
133 * This function will return an array of cutomizer settings that include ACF data
134 * similar to `$customizer->settings();`
135 *
136 * @type function
137 * @date 22/03/2016
138 * @since 5.3.2
139 *
140 * @param $customizer (object)
141 * @return $value (mixed)
142 */
143
144 function settings( $customizer ) {
145
146 // vars
147 $data = array();
148 $settings = $customizer->settings();
149
150 // bail early if no settings
151 if ( empty( $settings ) ) {
152 return false;
153 }
154
155 // loop over settings
156 foreach ( $settings as $setting ) {
157
158 // vars
159 $id = $setting->id;
160
161 // verify settings type
162 if ( substr( $id, 0, 6 ) == 'widget' || substr( $id, 0, 7 ) == 'nav_menu' ) {
163 // allow
164 } else {
165 continue;
166 }
167
168 // get value
169 $value = $setting->post_value();
170
171 // bail early if no acf
172 if ( ! is_array( $value ) || ! isset( $value['acf'] ) ) {
173 continue;
174 }
175
176 // set data
177 $setting->acf = $value['acf'];
178
179 // append
180 $data[] = $setting;
181
182 }
183
184 // bail early if no settings
185 if ( empty( $data ) ) {
186 return false;
187 }
188
189 // return
190 return $data;
191
192 }
193
194
195 /*
196 * customize_preview_init
197 *
198 * This function is called when customizer preview is initialized
199 *
200 * @type function
201 * @date 22/03/2016
202 * @since 5.3.2
203 *
204 * @param $customizer (object)
205 * @return n/a
206 */
207
208 function customize_preview_init( $customizer ) {
209
210 // get customizer settings (widgets)
211 $settings = $this->settings( $customizer );
212
213 // bail early if no settings
214 if ( empty( $settings ) ) {
215 return;
216 }
217
218 // append values
219 foreach ( $settings as $setting ) {
220
221 // get acf data
222 $data = $setting->acf;
223
224 // append acf_value to preview_values
225 $this->preview_values[ $data['post_id'] ] = $data['values'];
226 $this->preview_fields[ $data['post_id'] ] = $data['fields'];
227
228 }
229
230 // bail early if no preview_values
231 if ( empty( $this->preview_values ) ) {
232 return;
233 }
234
235 // add filters
236 add_filter( 'acf/pre_load_value', array( $this, 'pre_load_value' ), 10, 3 );
237 add_filter( 'acf/pre_load_reference', array( $this, 'pre_load_reference' ), 10, 3 );
238
239 }
240
241 /**
242 * pre_load_value
243 *
244 * Used to inject preview value
245 *
246 * @date 2/2/18
247 * @since 5.6.5
248 *
249 * @param type $var Description. Default.
250 * @return type Description.
251 */
252
253 function pre_load_value( $value, $post_id, $field ) {
254
255 // check
256 if ( isset( $this->preview_values[ $post_id ][ $field['key'] ] ) ) {
257 return $this->preview_values[ $post_id ][ $field['key'] ];
258 }
259
260 // return
261 return $value;
262 }
263
264 /**
265 * pre_load_reference
266 *
267 * Used to inject preview value
268 *
269 * @date 2/2/18
270 * @since 5.6.5
271 *
272 * @param type $var Description. Default.
273 * @return type Description.
274 */
275
276 function pre_load_reference( $field_key, $field_name, $post_id ) {
277
278 // check
279 if ( isset( $this->preview_fields[ $post_id ][ $field_name ] ) ) {
280 return $this->preview_fields[ $post_id ][ $field_name ];
281 }
282
283 // return
284 return $field_key;
285 }
286
287
288 /*
289 * customize_save
290 *
291 * This function is called when customizer saves a widget.
292 * Normally, the widget_update_callback filter would be used, but the customizer disables this and runs a custom action
293 * class-customizer-settings.php will save the widget data via the function set_root_value which uses update_option
294 *
295 * @type function
296 * @date 22/03/2016
297 * @since 5.3.2
298 *
299 * @param $customizer (object)
300 * @return n/a
301 */
302
303 function customize_save( $customizer ) {
304
305 // get customizer settings (widgets)
306 $settings = $this->settings( $customizer );
307
308 // bail early if no settings
309 if ( empty( $settings ) ) {
310 return;
311 }
312
313 // append values
314 foreach ( $settings as $setting ) {
315
316 // get acf data
317 $data = $setting->acf;
318
319 // save acf data
320 acf_save_post( $data['post_id'], $data['values'] );
321
322 // remove [acf] data from saved widget array
323 $id_data = $setting->id_data();
324 add_filter( 'pre_update_option_' . $id_data['base'], array( $this, 'pre_update_option' ), 10, 3 );
325
326 }
327
328 }
329
330
331 /*
332 * pre_update_option
333 *
334 * this function will remove the [acf] data from widget insance
335 *
336 * @type function
337 * @date 22/03/2016
338 * @since 5.3.2
339 *
340 * @param $post_id (int)
341 * @return $post_id (int)
342 */
343
344 function pre_update_option( $value, $option, $old_value ) {
345
346 // bail early if no value
347 if ( empty( $value ) ) {
348 return $value;
349 }
350
351 // loop over widgets
352 // WP saves all widgets (of the same type) as an array of widgets
353 foreach ( $value as $i => $widget ) {
354
355 // bail early if no acf
356 if ( ! isset( $widget['acf'] ) ) {
357 continue;
358 }
359
360 // remove widget
361 unset( $value[ $i ]['acf'] );
362
363 }
364
365 // return
366 return $value;
367
368 }
369
370
371 /*
372 * admin_footer
373 *
374 * This function will add some custom HTML to the footer of the edit page
375 *
376 * @type function
377 * @date 11/06/2014
378 * @since 5.0.0
379 *
380 * @param n/a
381 * @return n/a
382 */
383
384 function admin_footer() {
385
386 ?>
387 <script type="text/javascript">
388 (function($) {
389
390 // customizer saves widget on any input change, so unload is not needed
391 acf.unload.active = 0;
392
393
394 // hack customizer function to remove bug caused by WYSIWYG field using aunique ID
395 // customizer compares returned AJAX HTML with the HTML of the widget form.
396 // the _getInputsSignature() function is used to generate a string based of input name + id.
397 // because ACF generates a unique ID on the WYSIWYG field, this string will not match causing the preview function to bail.
398 // 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.
399 // source: wp-admin/js/customize-widgets.js
400
401 // vars
402 var WidgetControl = wp.customize.Widgets.WidgetControl.prototype;
403
404
405 // backup functions
406 WidgetControl.__getInputsSignature = WidgetControl._getInputsSignature;
407 WidgetControl.__setInputState = WidgetControl._setInputState;
408
409
410 // modify __getInputsSignature
411 WidgetControl._getInputsSignature = function( inputs ) {
412
413 // vars
414 var signature = this.__getInputsSignature( inputs );
415 safe = [];
416
417
418 // split
419 signature = signature.split(';');
420
421
422 // loop
423 for( var i in signature ) {
424
425 // vars
426 var bit = signature[i];
427
428
429 // bail early if acf is found
430 if( bit.indexOf('acf') !== -1 ) continue;
431
432
433 // append
434 safe.push( bit );
435
436 }
437
438
439 // update
440 signature = safe.join(';');
441
442
443 // return
444 return signature;
445
446 };
447
448
449 // modify _setInputState
450 // this function deosn't seem to run on widget title/content, only custom fields
451 // either way, this function is not needed and will break ACF fields
452 WidgetControl._setInputState = function( input, state ) {
453
454 return true;
455
456 };
457
458 })(jQuery);
459 </script>
460 <?php
461
462 }
463
464 }
465
466 new acf_form_customizer();
467
468 endif;
469
470 ?>
471