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