PluginProbe ʕ •ᴥ•ʔ
Secure Custom Fields / 6.5.0
Secure Custom Fields v6.5.0
6.9.1 6.9.0 6.8.9 6.8.7 6.8.8 6.8.6 6.8.4 6.8.5 trunk 6.4.0-beta1 6.4.0-beta2 6.4.1 6.4.1-beta3 6.4.1-beta4 6.4.1-beta5 6.4.1-beta6 6.4.1-beta7 6.4.2 6.5.0 6.5.1 6.5.2 6.5.3 6.5.4 6.5.5 6.5.6 6.5.7 6.6.0 6.7.0 6.7.1 6.8.0 6.8.1 6.8.2 6.8.3
secure-custom-fields / includes / forms / form-customizer.php
secure-custom-fields / includes / forms Last commit date
WC_Order.php 1 year ago form-attachment.php 1 year ago form-comment.php 1 year ago form-customizer.php 1 year ago form-front.php 1 year ago form-gutenberg.php 1 year ago form-nav-menu.php 1 year ago form-post.php 1 year ago form-taxonomy.php 1 year ago form-user.php 1 year ago form-widget.php 1 year ago index.php 1 year ago
form-customizer.php
463 lines
1 <?php
2
3 if ( ! defined( 'ABSPATH' ) ) {
4 exit; // Exit if accessed directly
5 }
6
7 if ( ! class_exists( 'acf_form_customizer' ) || ! class_exists( 'ACF_Form_Customizer' ) ) :
8 /**
9 * ACF Form Customizer Class
10 *
11 * This class handles the integration of Advanced Custom Fields with the WordPress Customizer.
12 * It manages preview values, fields, and errors for the customizer interface, and handles
13 * saving ACF data when customizer changes are applied.
14 *
15 * @package wordpress/secure-custom-fields
16 * @since ACF 3.6.0
17 */
18 class ACF_Form_Customizer {
19
20
21 /**
22 * Values to be used in the preview.
23 *
24 * @var array
25 */
26 public $preview_values;
27
28 /**
29 * Fields to be used in the preview.
30 *
31 * @var array
32 */
33 public $preview_fields;
34
35
36 /**
37 * Errors to be used in the preview.
38 *
39 * @var array
40 */
41 public $preview_errors;
42
43 /**
44 * This function will setup the class functionality
45 *
46 * @type function
47 * @date 5/03/2014
48 * @since ACF 5.0.0
49 *
50 * @param n/a
51 * @return n/a
52 */
53 public function __construct() {
54
55 // vars
56 $this->preview_values = array();
57 $this->preview_fields = array();
58 $this->preview_errors = array();
59
60 // actions
61 add_action( 'customize_controls_init', array( $this, 'customize_controls_init' ) );
62 add_action( 'customize_preview_init', array( $this, 'customize_preview_init' ), 1, 1 );
63 add_action( 'customize_save', array( $this, 'customize_save' ), 1, 1 );
64
65 // save
66 add_filter( 'widget_update_callback', array( $this, 'save_widget' ), 10, 4 );
67 }
68
69
70 /**
71 * This action is run after post query but before any admin script / head actions.
72 * It is a good place to register all actions.
73 *
74 * @type action (admin_enqueue_scripts)
75 * @date 26/01/13
76 * @since ACF 3.6.0
77 * @return void
78 */
79 public function customize_controls_init() {
80
81 // load acf scripts
82 acf_enqueue_scripts(
83 array(
84 'context' => 'customize_controls',
85 )
86 );
87
88 // actions
89 add_action( 'acf/input/admin_footer', array( $this, 'admin_footer' ), 1 );
90 }
91
92
93 /**
94 * This function will hook into the widget update filter and save ACF data
95 *
96 * @type function
97 * @date 27/05/2015
98 * @since ACF 5.2.3
99 *
100 * @param array $instance (array) widget settings.
101 * @param array $new_instance (array) widget settings.
102 * @param array $old_instance (array) widget settings.
103 * @param object $widget (object) widget info.
104 * @return array $instance Widget settings.
105 */
106 public function save_widget( $instance, $new_instance, $old_instance, $widget ) {
107 // bail early if not valid (customize + acf values + nonce)
108
109 // phpcs:ignore WordPress.Security.NonceVerification.Missing -- nonce is verified in acf_verify_nonce.
110 if ( ! isset( $_POST['wp_customize'] ) || ! isset( $new_instance['acf'] ) || ! acf_verify_nonce( 'widget' ) ) {
111 return $instance;
112 }
113
114 // vars
115 $data = array(
116 'post_id' => "widget_{$widget->id}",
117 'values' => array(),
118 'fields' => array(),
119 );
120
121 // append values
122 $data['values'] = $new_instance['acf'];
123
124 // append fields (name => key relationship) - used later in 'acf/get_field_reference' for customizer previews
125 foreach ( $data['values'] as $k => $v ) {
126
127 // get field
128 $field = acf_get_field( $k );
129
130 // continue if no field
131 if ( ! $field ) {
132 continue;
133 }
134
135 // update
136 $data['fields'][ $field['name'] ] = $field['key'];
137 }
138
139 // append data to instance
140 $instance['acf'] = $data;
141
142 // return
143 return $instance;
144 }
145
146
147 /**
148 * This function will return an array of customizer settings that include ACF data
149 * similar to `$customizer->settings();`
150 *
151 * @type function
152 * @date 22/03/2016
153 * @since ACF 5.3.2
154 *
155 * @param WP_Customize_Manager $customizer Customizer object.
156 * @return Mixed boolean | array. The sCustomizer Settings Object.
157 */
158 public function settings( $customizer ) {
159
160 // vars
161 $data = array();
162 $settings = $customizer->settings();
163
164 // bail early if no settings
165 if ( empty( $settings ) ) {
166 return false;
167 }
168
169 // loop over settings
170 foreach ( $settings as $setting ) {
171
172 // vars
173 $id = $setting->id;
174 // Only process widget and nav_menu settings
175 if ( 'widget' !== substr( $id, 0, 6 ) && 'nav_menu' !== substr( $id, 0, 7 ) ) {
176 continue;
177 }
178
179 // At this point, we're dealing with either a widget or nav_menu setting
180
181 // get value
182 $value = $setting->post_value();
183
184 // bail early if no acf
185 if ( ! is_array( $value ) || ! isset( $value['acf'] ) ) {
186 continue;
187 }
188
189 // set data
190 $setting->acf = $value['acf'];
191
192 // append
193 $data[] = $setting;
194 }
195
196 // bail early if no settings
197 if ( empty( $data ) ) {
198 return false;
199 }
200
201 // return
202 return $data;
203 }
204
205
206 /**
207 * This function is called when customizer preview is initialized
208 *
209 * @type function
210 * @date 22/03/2016
211 * @since ACF 5.3.2
212 *
213 * @param WP_Customize_Manager $customizer Customizer object.
214 * @return void
215 */
216 public function customize_preview_init( $customizer ) {
217
218 // get customizer settings (widgets)
219 $settings = $this->settings( $customizer );
220
221 // bail early if no settings
222 if ( empty( $settings ) ) {
223 return;
224 }
225
226 // append values
227 foreach ( $settings as $setting ) {
228
229 // get acf data
230 $data = $setting->acf;
231
232 // append acf_value to preview_values
233 $this->preview_values[ $data['post_id'] ] = $data['values'];
234 $this->preview_fields[ $data['post_id'] ] = $data['fields'];
235 }
236
237 // bail early if no preview_values
238 if ( empty( $this->preview_values ) ) {
239 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 * Pre load value function.
249 *
250 * Used to inject preview value.
251 *
252 * @date 2/2/18
253 * @since ACF 5.6.5
254 *
255 * @param mixed $value The value to check.
256 * @param int $post_id The post ID.
257 * @param array $field The field array.
258 * @return mixed The preview value if exists, otherwise the original value.
259 */
260 public 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 function.
273 *
274 * Used to inject reference value.
275 *
276 * @date 2/2/18
277 * @since ACF 5.6.5
278 *
279 * @param string $field_key The field key.
280 * @param string $field_name The field name.
281 * @param int $post_id The post ID.
282 * @return string The field key if preview field exists, otherwise the original field key.
283 */
284 public function pre_load_reference( $field_key, $field_name, $post_id ) {
285
286 // check
287 if ( isset( $this->preview_fields[ $post_id ][ $field_name ] ) ) {
288 return $this->preview_fields[ $post_id ][ $field_name ];
289 }
290
291 // return
292 return $field_key;
293 }
294
295
296 /**
297 * This function is called when customizer saves a widget.
298 * Normally, the widget_update_callback filter would be used, but the customizer disables this and runs a custom action
299 * class-customizer-settings.php will save the widget data via the function set_root_value which uses update_option
300 *
301 * @type function
302 * @date 22/03/2016
303 * @since ACF 5.3.2
304 *
305 * @param WP_Customize_Manager $customizer The WordPress customizer manager object.
306 * @return void
307 */
308 public function customize_save( $customizer ) {
309
310 // get customizer settings (widgets)
311 $settings = $this->settings( $customizer );
312
313 // bail early if no settings
314 if ( empty( $settings ) ) {
315 return;
316 }
317
318 // append values
319 foreach ( $settings as $setting ) {
320
321 // get acf data
322 $data = $setting->acf;
323
324 // save acf data
325 acf_save_post( $data['post_id'], $data['values'] );
326
327 // remove [acf] data from saved widget array
328 $id_data = $setting->id_data();
329 add_filter( 'pre_update_option_' . $id_data['base'], array( $this, 'pre_update_option' ), 10, 1 );
330 }
331 }
332
333
334 /**
335 * This function will remove the [acf] data from widget instance
336 *
337 * @type function
338 * @date 22/03/2016
339 * @since ACF 5.3.2
340 *
341 * @param mixed $value The new option value.
342 * @return mixed The filtered option value.
343 */
344 public function pre_update_option( $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 // return
365 return $value;
366 }
367
368
369 /**
370 * This function will add some custom HTML to the footer of the edit page
371 *
372 * @type function
373 * @date 11/06/2014
374 * @since ACF 5.0.0
375 *
376 * @param n/a
377 * @return n/a
378 */
379 public function admin_footer() {
380
381 ?>
382 <script type="text/javascript">
383 (function($) {
384
385 // customizer saves widget on any input change, so unload is not needed
386 acf.unload.active = 0;
387
388
389 // hack customizer function to remove bug caused by WYSIWYG field using a unique ID
390 // customizer compares returned AJAX HTML with the HTML of the widget form.
391 // the _getInputsSignature() function is used to generate a string based of input name + id.
392 // because ACF generates a unique ID on the WYSIWYG field, this string will not match causing the preview function to bail.
393 // an attempt was made to remove the WYSIWYG unique ID, but this caused multiple issues in the wp-admin and ultimately doesn't make sense with the tinymce rule that all editors must have a unique ID.
394 // source: wp-admin/js/customize-widgets.js
395
396 // vars
397 var WidgetControl = wp.customize.Widgets.WidgetControl.prototype;
398
399
400 // backup functions
401 WidgetControl.__getInputsSignature = WidgetControl._getInputsSignature;
402 WidgetControl.__setInputState = WidgetControl._setInputState;
403
404
405 // modify __getInputsSignature
406 WidgetControl._getInputsSignature = function( inputs ) {
407
408 // vars
409 var signature = this.__getInputsSignature( inputs );
410 safe = [];
411
412
413 // split
414 signature = signature.split(';');
415
416
417 // loop
418 for( var i in signature ) {
419
420 // vars
421 var bit = signature[i];
422
423
424 // bail early if acf is found
425 if( bit.indexOf('acf') !== -1 ) continue;
426
427
428 // append
429 safe.push( bit );
430
431 }
432
433
434 // update
435 signature = safe.join(';');
436
437
438 // return
439 return signature;
440
441 };
442
443
444 // modify _setInputState
445 // this function doesn't seem to run on widget title/content, only custom fields
446 // either way, this function is not needed and will break ACF fields
447 WidgetControl._setInputState = function( input, state ) {
448
449 return true;
450
451 };
452
453 })(jQuery);
454 </script>
455 <?php
456 }
457 }
458
459 new ACF_Form_Customizer();
460 endif;
461
462 ?>
463