PluginProbe
Customify / 2.7.0
Customify v2.7.0
2.10.9 1.2.3 1.2.4 1.2.5 1.2.6 1.2.7 1.2.7.1 1.3.0 1.3.1 1.4.0 1.4.1 1.4.2 1.5.0 1.5.1 1.5.2 1.5.3 1.5.4 1.5.5 1.5.6 1.5.7 1.6.0 1.6.0.1 1.6.5 1.7.0 1.7.1 All 77 releases
customify / includes / class-customify-customizer.php

class-customify-customizer.php in Customify 2.7.0, at includes/class-customify-customizer.php

1,522 lines 49.2 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * This is the class that handles the overall logic for the Customizer.
4 *
5 * @see https://pixelgrade.com
6 * @author Pixelgrade
7 * @since 2.4.0
8 */
9
10 if ( ! defined( 'ABSPATH' ) ) {
11 exit; // Exit if accessed directly
12 }
13
14 if ( ! class_exists( 'PixCustomify_Customizer' ) ) :
15
16 class PixCustomify_Customizer {
17
18 /**
19 * Holds the only instance of this class.
20 * @var null|PixCustomify_Customizer
21 * @access protected
22 * @since 2.4.0
23 */
24 protected static $_instance = null;
25
26 protected $localized = array();
27
28 protected $media_queries = array();
29
30 // these properties will get 'px' as a default unit
31 public static $pixel_dependent_css_properties = array(
32 'width',
33 'max-width',
34 'min-width',
35
36 'height',
37 'max-height',
38 'min-height',
39
40 'padding',
41 'padding-left',
42 'padding-right',
43 'padding-top',
44 'padding-bottom',
45
46 'margin',
47 'margin-right',
48 'margin-left',
49 'margin-top',
50 'margin-bottom',
51
52 'right',
53 'left',
54 'top',
55 'bottom',
56
57 'font-size',
58 'letter-spacing',
59
60 'border-size',
61 'border-width',
62 'border-bottom-width',
63 'border-left-width',
64 'border-right-width',
65 'border-top-width'
66 );
67
68 /**
69 * Constructor.
70 *
71 * @since 2.4.0
72 */
73 protected function __construct() {
74 // We will initialize the Customizer logic after the plugin has finished with it's configuration (at priority 15).
75 add_action( 'init', array( $this, 'init' ), 15 );
76 }
77
78 /**
79 * Initialize this module.
80 *
81 * @since 2.4.0
82 */
83 public function init() {
84 // Others will be able to add data here via the 'customify_localized_js_settings' filter.
85 // This is a just-in-time filter, triggered as late as possible.
86 $this->localized = array(
87 'config' => array(
88 'options_name' => PixCustomifyPlugin()->get_options_key(),
89 'ajax_url' => admin_url( 'admin-ajax.php' ),
90 'webfontloader_url' => plugins_url( 'js/vendor/webfontloader-1-6-28.js', PixCustomifyPlugin()->get_file() ),
91 'px_dependent_css_props' => self::$pixel_dependent_css_properties,
92 ),
93 // For localizing strings.
94 'l10n' => array(
95 'panelResetButton' => esc_html__( 'Panel\'s defaults', 'customify' ),
96 'sectionResetButton' => esc_html__( 'Reset All Options for This Section', 'customify' ),
97 'resetGlobalConfirmMessage' => wp_kses_post( __( 'Do you really want to reset to defaults all the fields? Watch out, this will reset all your Customify options and will save them!', 'customify' ) ),
98 'resetPanelConfirmMessage' => wp_kses_post( __( 'Do you really want to reset the settings in this panel?', 'customify' ) ),
99 'resetSectionConfirmMessage' => wp_kses_post( __( 'Do you really want to reset the settings in this section?', 'customify' ) ),
100 )
101 );
102
103 // Hook up.
104 $this->add_hooks();
105 }
106
107 /**
108 * Initiate our hooks
109 *
110 * @since 2.4.0
111 */
112 public function add_hooks() {
113
114 // Styles for the Customizer
115 add_action( 'customize_controls_init', array( $this, 'register_admin_customizer_styles' ), 10 );
116 add_action( 'customize_controls_enqueue_scripts', array( $this, 'enqueue_admin_customizer_styles' ), 10 );
117 // Scripts enqueued in the Customizer
118 add_action( 'customize_controls_init', array( $this, 'register_admin_customizer_scripts' ), 15 );
119 add_action( 'customize_controls_enqueue_scripts', array( $this, 'enqueue_admin_customizer_scripts' ), 15 );
120
121 // Scripts enqueued only in the theme preview
122 add_action( 'customize_preview_init', array( $this, 'customizer_live_preview_register_scripts' ), 10 );
123 add_action( 'customize_preview_init', array( $this, 'customizer_live_preview_enqueue_scripts' ), 99999 );
124
125 // Add extra settings data to _wpCustomizeSettings.settings of the parent window.
126 add_action( 'customize_controls_print_footer_scripts', array( $this, 'customize_pane_settings_additional_data' ), 10000 );
127
128 // The frontend effects of the Customizer controls
129 $load_location = PixCustomifyPlugin()->settings->get_plugin_setting( 'style_resources_location', 'wp_head' );
130
131 add_action( $load_location, array( $this, 'output_dynamic_style' ), 99 );
132
133 add_action( 'customize_register', array( $this, 'remove_default_sections' ), 11 );
134 add_action( 'customize_register', array( $this, 'process_customizer_config' ), 12 );
135 // Maybe the theme has instructed us to do things like removing sections or controls.
136 add_action( 'customize_register', array( $this, 'maybe_process_config_extras' ), 13 );
137
138 /*
139 * Development related
140 */
141 if ( defined( 'CUSTOMIFY_DEV_FORCE_DEFAULTS' ) && true === CUSTOMIFY_DEV_FORCE_DEFAULTS ) {
142 // If the development constant CUSTOMIFY_DEV_FORCE_DEFAULTS has been defined we will not save anything in the database
143 // Always go with the default
144 add_filter( 'customize_changeset_save_data', array( $this, 'prevent_changeset_save_in_devmode' ), 50, 1 );
145 // Add a JS to display a notification
146 add_action( 'customize_controls_print_footer_scripts', array( $this, 'prevent_changeset_save_in_devmode_notification' ), 100 );
147 }
148 }
149
150 /**
151 * Register Customizer admin styles
152 */
153 function register_admin_customizer_styles() {
154 $rtl_suffix = is_rtl() ? '-rtl' : '';
155 wp_register_style( 'customify_style', plugins_url( 'css/customizer' . $rtl_suffix . '.css', PixCustomifyPlugin()->get_file() ), array( 'dashicons' ), PixCustomifyPlugin()->get_version() );
156 }
157
158 /**
159 * Enqueue Customizer admin styles
160 */
161 function enqueue_admin_customizer_styles() {
162 wp_enqueue_style( 'customify_style' );
163 }
164
165 /**
166 * Register Customizer admin scripts
167 */
168 function register_admin_customizer_scripts() {
169 $suffix = ( defined( 'SCRIPT_DEBUG' ) && SCRIPT_DEBUG ) ? '' : '.min';
170
171 wp_register_script( PixCustomifyPlugin()->get_slug() . '-select2',
172 plugins_url( 'js/vendor/select2' . $suffix . '.js', PixCustomifyPlugin()->get_file() ),
173 array( 'jquery' ), PixCustomifyPlugin()->get_version() );
174 wp_register_script( 'jquery-react',
175 plugins_url( 'js/vendor/jquery-react' . $suffix . '.js', PixCustomifyPlugin()->get_file() ),
176 array( 'jquery' ), PixCustomifyPlugin()->get_version() );
177 wp_register_script( PixCustomifyPlugin()->get_slug() . '-fontfields',
178 plugins_url( 'js/customizer/font-fields' . $suffix . '.js', PixCustomifyPlugin()->get_file() ),
179 array( 'jquery', 'underscore' ), PixCustomifyPlugin()->get_version() );
180
181 wp_register_script( PixCustomifyPlugin()->get_slug() . '-customizer-scripts',
182 plugins_url( 'js/customizer' . $suffix . '.js', PixCustomifyPlugin()->get_file() ),
183 array(
184 'jquery',
185 PixCustomifyPlugin()->get_slug() . '-select2',
186 'underscore',
187 'customize-controls',
188 PixCustomifyPlugin()->get_slug() . '-fontfields',
189 ),
190 PixCustomifyPlugin()->get_version() );
191 }
192
193 /**
194 * Enqueue Customizer admin scripts
195 */
196 function enqueue_admin_customizer_scripts() {
197 wp_enqueue_script( 'jquery-react' );
198 wp_enqueue_script( PixCustomifyPlugin()->get_slug() . '-customizer-scripts' );
199
200 wp_add_inline_script( PixCustomifyPlugin()->get_slug() . '-customizer-scripts',
201 self::getlocalizeToWindowScript( 'customify',
202 apply_filters( 'customify_localized_js_settings', $this->localized )
203 ), 'before' );
204 }
205
206 /** Register Customizer scripts loaded only on previewer page */
207 function customizer_live_preview_register_scripts() {
208 $suffix = ( defined( 'SCRIPT_DEBUG' ) && SCRIPT_DEBUG ) ? '' : '.min';
209
210 wp_register_script( PixCustomifyPlugin()->get_slug() . '-CSSOM',
211 plugins_url( 'js/vendor/CSSOM' . $suffix . '.js', PixCustomifyPlugin()->get_file() ),
212 array(),
213 PixCustomifyPlugin()->get_version(), true );
214
215 wp_register_script( PixCustomifyPlugin()->get_slug() . '-cssUpdate',
216 plugins_url( 'js/jquery.cssUpdate' . $suffix . '.js', PixCustomifyPlugin()->get_file() ),
217 array( 'jquery' ),
218 PixCustomifyPlugin()->get_version(), true );
219
220 wp_register_script( PixCustomifyPlugin()->get_slug() . '-previewer-scripts',
221 plugins_url( 'js/customizer_preview' . $suffix . '.js', PixCustomifyPlugin()->get_file() ),
222 array(
223 'jquery',
224 'customize-preview',
225 'underscore',
226 PixCustomifyPlugin()->get_slug() . '-CSSOM',
227 PixCustomifyPlugin()->get_slug() . '-cssUpdate'
228 ),
229 PixCustomifyPlugin()->get_version(), true );
230 }
231
232 /** Enqueue Customizer scripts loaded only on previewer page */
233 function customizer_live_preview_enqueue_scripts() {
234 wp_enqueue_script( PixCustomifyPlugin()->get_slug() . '-previewer-scripts' );
235 }
236
237 /**
238 * Prevent saving of plugin options in the Customizer
239 *
240 * @param array $data The data to save
241 *
242 * @return array
243 */
244 public function prevent_changeset_save_in_devmode( $data ) {
245 // Get the options key
246 $options_key = PixCustomifyPlugin()->get_options_key();
247 if ( ! empty( $options_key ) ) {
248 // Remove any Customify data thus preventing it from saving
249 foreach ( $data as $option_id => $value ) {
250 if ( false !== strpos( $option_id, $options_key ) && ! PixCustomifyPlugin()->skip_dev_mode_force_defaults( $option_id ) ) {
251 unset( $data[ $option_id ] );
252 }
253 }
254 }
255
256 return $data;
257 }
258
259 public function prevent_changeset_save_in_devmode_notification() { ?>
260 <script type="application/javascript">
261 (function ( $, exports, wp ) {
262 'use strict';
263 // when the customizer is ready add our notification
264 wp.customize.bind('ready', function () {
265 wp.customize.notifications.add( 'customify_force_defaults', new wp.customize.Notification(
266 'customify_force_defaults',
267 {
268 type: 'warning',
269 message: '<?php echo wp_kses_post( __( '<strong>Customify: Development Mode</strong><p>All options are switched to default. While they are changing in the live preview, they will not be kept when you hit publish.</p>', 'customify' ) ); ?>'
270 }
271 ) );
272 });
273 })(jQuery, window, wp);
274 </script>
275 <?php }
276
277 /**
278 * Output CSS style generated by customizer
279 */
280 function output_dynamic_style() { ?>
281 <style id="customify_output_style">
282 <?php echo $this->get_dynamic_style(); ?>
283 </style>
284 <?php
285
286 /**
287 * from now on we output only style tags only for the preview purpose
288 * so don't cry if you see 30+ style tags for each section
289 */
290 if ( ! isset( $GLOBALS['wp_customize'] ) ) {
291 return;
292 }
293
294 foreach ( PixCustomifyPlugin()->get_options_details( false, true ) as $option_id => $option_details ) {
295
296 if ( isset( $option_details['type'] ) && $option_details['type'] === 'custom_background' ) {
297 $custom_background_output = $this->process_custom_background_field_output( $option_details ); ?>
298
299 <style id="custom_background_output_for_<?php echo sanitize_html_class( $option_id ); ?>">
300 <?php
301 if ( ! empty( $custom_background_output )) {
302 echo $custom_background_output;
303 } ?>
304 </style>
305 <?php }
306
307 if ( ! isset( $option_details['live'] ) || $option_details['live'] !== true ) {
308 continue;
309 }
310
311 if ( ! empty( $option_details['css'] ) ) {
312 foreach ( $option_details['css'] as $key => $properties_set ) {
313 // We need to use a class because we may have multiple <style>s with the same "ID" for example
314 // when targeting the same property but with different selectors.
315 $unique_class = 'dynamic_setting_' . $option_id . '_property_' . str_replace( '-', '_', $properties_set['property'] ) . '_' . $key;
316
317 $inline_style = '<style class="' . sanitize_html_class( $unique_class ) . '" type="text/css">';
318
319 if ( isset( $properties_set['media'] ) && ! empty( $properties_set['media'] ) ) {
320 $inline_style .= '@media '. $properties_set['media'] . ' {';
321 }
322
323 if ( isset( $properties_set['selector'] ) && isset( $properties_set['property'] ) ) {
324 $css_output = $this->process_css_property($properties_set, $option_details['value']);
325 if ( ! empty( $css_output ) ) {
326 $inline_style .= $css_output;
327 }
328 }
329
330 if ( isset( $properties_set['media'] ) && ! empty( $properties_set['media'] ) ) {
331 $inline_style .= '}';
332 }
333 $inline_style .= '</style>';
334
335 echo $inline_style;
336 }
337 }
338 }
339 }
340
341 function get_dynamic_style() {
342 $custom_css = '';
343
344 foreach ( PixCustomifyPlugin()->get_options_details( true ) as $option_id => $option_details ) {
345
346 if ( isset( $option_details['css'] ) && ! empty( $option_details['css'] ) ) {
347 // now process each
348 $custom_css .= $this->convert_setting_to_css( $option_id, $option_details );
349 }
350
351 if ( isset( $option_details['type'] ) && $option_details['type'] === 'custom_background' ) {
352 $custom_css .= $this->process_custom_background_field_output( $option_details ) . "\n";
353 }
354 }
355
356 if ( ! empty( $this->media_queries ) ) {
357
358 foreach ( $this->media_queries as $media_query => $properties ) {
359
360 if ( empty( $properties ) ) {
361 continue;
362 }
363
364 $media_query_custom_css = '';
365
366 foreach ( $properties as $key => $property ) {
367 $property_settings = $property['property'];
368 $property_value = $property['value'];
369 $css_output = $this->process_css_property( $property_settings, $property_value );
370 if ( ! empty( $css_output ) ) {
371 $media_query_custom_css .= "\t" . $css_output . "\n";
372 }
373 }
374
375 if ( ! empty( $media_query_custom_css ) ) {
376 $media_query_custom_css = "\n" . '@media ' . $media_query . " { " . "\n" . "\n" . $media_query_custom_css . "}" . "\n";
377 }
378
379 if ( ! empty( $media_query_custom_css ) ) {
380 $custom_css .= $media_query_custom_css;
381 }
382
383 }
384 }
385
386 return apply_filters( 'customify_dynamic_style', $custom_css );
387 }
388
389 /**
390 * Turn css options into a valid CSS output
391 *
392 * @param $option_id
393 * @param array $option_details
394 *
395 * @return string
396 */
397 protected function convert_setting_to_css( $option_id, $option_details ) {
398 $output = '';
399
400 if ( empty( $option_details['css'] ) ) {
401 return $output;
402 }
403
404 foreach ( $option_details['css'] as $css_property ) {
405
406 if ( isset( $css_property['media'] ) && ! empty( $css_property['media'] ) ) {
407 $this->media_queries[ $css_property['media'] ][ $option_id ] = array(
408 'property' => $css_property,
409 'value' => $option_details['value']
410 );
411 continue;
412 }
413
414 if ( isset( $css_property['selector'] ) && isset( $css_property['property'] ) ) {
415 $output .= $this->process_css_property( $css_property, $option_details['value'] );
416 }
417 }
418
419 return $output;
420 }
421
422 protected function process_css_property( $css_property, $value ) {
423 $unit = isset( $css_property['unit'] ) ? $css_property['unit'] : '';
424 // If the unit is empty (string, not boolean false) but the property should have a unit force 'px' as it
425 if ( '' === $unit && in_array( $css_property['property'], self::$pixel_dependent_css_properties ) ) {
426 $unit = 'px';
427 }
428
429 $css_property['selector'] = apply_filters( 'customify_css_selector', $this->cleanup_whitespace_css( $css_property['selector'] ), $css_property );
430 if ( empty( $css_property['selector'] ) ) {
431 return '';
432 }
433
434 $property_output = $css_property['selector'] . ' { ' . $css_property['property'] . ': ' . $value . $unit . "; }" . "\n";
435
436 // Handle the value filter callback.
437 if ( isset( $css_property['filter_value_cb'] ) ) {
438 $value = $this->maybe_apply_filter( $css_property['filter_value_cb'], $value );
439 }
440
441 // Handle output callback.
442 if ( isset( $css_property['callback_filter'] ) && is_callable( $css_property['callback_filter'] ) ) {
443 $property_output = call_user_func( $css_property['callback_filter'], $value, $css_property['selector'], $css_property['property'], $unit );
444 }
445
446 return $property_output;
447 }
448
449 /**
450 * Apply a filter (config) to a value.
451 *
452 * We currently handle filters like these:
453 * // Elaborate filter config
454 * array(
455 * 'callback' => 'is_post_type_archive',
456 * // The arguments we should pass to the check function.
457 * // Think post types, taxonomies, or nothing if that is the case.
458 * // It can be an array of values or a single value.
459 * 'args' => array(
460 * 'jetpack-portfolio',
461 * ),
462 * ),
463 * // Simple filter - just the function name
464 * 'is_404',
465 *
466 * @param array|string $filter
467 * @param mixed $value The value to apply the filter to.
468 *
469 * @return mixed The filtered value.
470 */
471 public function maybe_apply_filter( $filter, $value ) {
472 // Let's get some obvious things off the table.
473 // On invalid data, we just return what we've received.
474 if ( empty( $filter ) ) {
475 return $value;
476 }
477
478 // First, we handle the shorthand version: just a function name
479 if ( is_string( $filter ) && is_callable( $filter ) ) {
480 $value = call_user_func( $filter );
481 } elseif ( is_array( $filter ) && ! empty( $filter['callback'] ) && is_callable( $filter['callback'] ) ) {
482 if ( empty( $filter['args'] ) ) {
483 $filter['args'] = array();
484 }
485 // The value is always the first argument.
486 $filter['args'] = array( $value ) + $filter['args'];
487
488 $value = call_user_func_array( $filter['callback'], $filter['args'] );
489 }
490
491 return $value;
492 }
493
494 protected function process_custom_background_field_output( $option_details ) {
495 $selector = $output = '';
496
497 if ( ! isset( $option_details['value'] ) ) {
498 return false;
499 }
500 $value = $option_details['value'];
501
502 if ( ! isset( $option_details['output'] ) ) {
503 return $selector;
504 } elseif ( is_string( $option_details['output'] ) ) {
505 $selector = $option_details['output'];
506 } elseif ( is_array( $option_details['output'] ) ) {
507 $selector = implode( ' ', $option_details['output'] );
508 }
509
510 // Loose the ton of tabs.
511 $selector = trim( preg_replace( '/\t+/', '', $selector ) );
512
513 $output .= $selector . " {";
514 if ( isset( $value['background-image'] ) && ! empty( $value['background-image'] ) ) {
515 $output .= "background-image: url( " . $value['background-image'] . ");";
516 } else {
517 $output .= "background-image: none;";
518 }
519
520 if ( isset( $value['background-repeat'] ) && ! empty( $value['background-repeat'] ) ) {
521 $output .= "background-repeat:" . $value['background-repeat'] . ";";
522 }
523
524 if ( isset( $value['background-position'] ) && ! empty( $value['background-position'] ) ) {
525 $output .= "background-position:" . $value['background-position'] . ";";
526 }
527
528 if ( isset( $value['background-size'] ) && ! empty( $value['background-size'] ) ) {
529 $output .= "background-size:" . $value['background-size'] . ";";
530 }
531
532 if ( isset( $value['background-attachment'] ) && ! empty( $value['background-attachment'] ) ) {
533 $output .= "background-attachment:" . $value['background-attachment'] . ";";
534 }
535 $output .= "}\n";
536
537 return $output;
538 }
539
540 protected function load_customizer_controls() {
541
542 // First require the base customizer extend class.
543 require_once( PixCustomifyPlugin()->get_base_path() . 'features/customizer/class-Pix_Customize_Control.php' );
544
545 // Now load all the controls' files.
546 $path = apply_filters( 'customify_customizer_controls_path', PixCustomifyPlugin()->get_base_path() . 'features/customizer/controls/' );
547 pixcustomify::require_all( $path );
548
549 do_action( 'customify_loaded_customizer_controls' );
550 }
551
552 /**
553 * Register all the panels, sections and controls we receive through the plugin's config.
554 *
555 * @param WP_Customize_Manager $wp_customize
556 */
557 function process_customizer_config( $wp_customize ) {
558
559 do_action( 'customify_before_process_customizer_config', $wp_customize );
560
561 // Require all the control classes available.
562 $this->load_customizer_controls();
563
564 // Load the customizer config.
565 $customizer_config = apply_filters( 'customify_customizer_config_pre_processing', PixCustomifyPlugin()->get_customizer_config(), $wp_customize );
566
567 // Bail if we don't have a config, or we are missing the 'opt-name' entry.
568 if ( empty( $customizer_config ) || empty( $customizer_config['opt-name'] ) ) {
569 do_action( 'customify_skip_process_customizer_config', $customizer_config, $wp_customize );
570 return;
571 }
572
573 $options_name = $customizer_config['opt-name'];
574 $wp_customize->options_key = $options_name;
575
576 // Handle panels.
577 if ( isset( $customizer_config['panels'] ) && ! empty( $customizer_config['panels'] ) ) {
578
579 foreach ( $customizer_config['panels'] as $panel_id => $panel_config ) {
580
581 if ( ! empty( $panel_id ) && isset( $panel_config['sections'] ) && ! empty( $panel_config['sections'] ) ) {
582
583 // If we have been explicitly given a panel ID we will use that
584 if ( ! empty( $panel_config['panel_id'] ) ) {
585 $panel_id = $panel_config['panel_id'];
586 } else {
587 $panel_id = $options_name . '[' . $panel_id . ']';
588 }
589
590 $panel_args = array(
591 'priority' => 10,
592 'capability' => 'edit_theme_options',
593 'title' => esc_html__( 'Panel title is required', 'customify' ),
594 'description' => esc_html__( 'Description of what this panel does.', 'customify' ),
595 'auto_expand_sole_section' => false,
596 );
597
598 if ( isset( $panel_config['priority'] ) && ! empty( $panel_config['priority'] ) ) {
599 $panel_args['priority'] = $panel_config['priority'];
600 }
601
602 if ( isset( $panel_config['title'] ) && ! empty( $panel_config['title'] ) ) {
603 $panel_args['title'] = $panel_config['title'];
604 }
605
606 if ( isset( $panel_config['description'] ) && ! empty( $panel_config['description'] ) ) {
607 $panel_args['description'] = $panel_config['description'];
608 }
609
610 if ( isset( $panel_config['auto_expand_sole_section'] ) ) {
611 $panel_args['auto_expand_sole_section'] = $panel_config['auto_expand_sole_section'];
612 }
613
614
615 $panel = $wp_customize->add_panel( $panel_id, $panel_args );
616 // Fire a general added panel hook
617 do_action( 'customify_process_customizer_config_added_panel', $panel, $panel_args, $wp_customize );
618
619 foreach ( $panel_config['sections'] as $section_id => $section_config ) {
620 if ( ! empty( $section_id ) && isset( $section_config['options'] ) && ! empty( $section_config['options'] ) ) {
621 $this->register_section( $panel_id, $section_id, $options_name, $section_config, $wp_customize );
622 }
623 }
624
625 // Fire a general finished panel hook
626 do_action( 'customify_process_customizer_config_finished_panel', $panel, $panel_args, $wp_customize );
627 }
628 }
629 }
630
631 // Handle sections.
632 if ( isset( $customizer_config['sections'] ) && ! empty( $customizer_config['sections'] ) ) {
633
634 foreach ( $customizer_config['sections'] as $section_id => $section_config ) {
635 if ( ! empty( $section_id ) && isset( $section_config['options'] ) && ! empty( $section_config['options'] ) ) {
636 $this->register_section( $panel_id = false, $section_id, $options_name, $section_config, $wp_customize );
637 }
638 }
639 }
640
641 // Handle development helper buttons.
642 if ( PixCustomifyPlugin()->settings->get_plugin_setting('enable_reset_buttons') ) {
643 // create a toolbar section which will be present all the time
644 $reset_section_settings = array(
645 'title' => esc_html__( 'Customify Toolbox', 'customify' ),
646 'capability' => 'manage_options',
647 'priority' => 999999999,
648 'options' => array(
649 'reset_all_button' => array(
650 'type' => 'button',
651 'label' => esc_html__( 'Reset Customify', 'customify' ),
652 'action' => 'reset_customify',
653 'value' => 'Reset',
654 ),
655 )
656 );
657
658 $wp_customize->add_section(
659 'customify_toolbar',
660 $reset_section_settings
661 );
662
663 $wp_customize->add_setting(
664 'reset_customify',
665 array()
666 );
667 $wp_customize->add_control( new Pix_Customize_Button_Control(
668 $wp_customize,
669 'reset_customify',
670 array(
671 'label' => esc_html__( 'Reset All Customify Options to Default', 'customify' ),
672 'section' => 'customify_toolbar',
673 'settings' => 'reset_customify',
674 'action' => 'reset_customify',
675 )
676 ) );
677 }
678
679 do_action( 'customify_after_process_customizer_config', $wp_customize );
680 }
681
682 /**
683 * @param string $panel_id
684 * @param string $section_key
685 * @param string $options_name
686 * @param array $section_config
687 * @param WP_Customize_Manager $wp_customize
688 */
689 protected function register_section( $panel_id, $section_key, $options_name, $section_config, $wp_customize ) {
690
691 // If we have been explicitly given a section ID we will use that
692 if ( ! empty( $section_config['section_id'] ) ) {
693 $section_id = $section_config['section_id'];
694 } else {
695 $section_id = $options_name . '[' . $section_key . ']';
696 }
697
698 // Add the new section to the Customizer, but only if it is not already added.
699 if ( ! $wp_customize->get_section( $section_id ) ) {
700 // Merge the section settings with the defaults
701 $section_args = wp_parse_args( $section_config, array(
702 'priority' => 10,
703 'panel' => $panel_id,
704 'capability' => 'edit_theme_options',
705 'theme_supports' => '',
706 'title' => esc_html__( 'Title Section is required', 'customify' ),
707 'description' => '',
708 'type' => 'default',
709 'description_hidden' => false,
710 ) );
711
712 // Only add the section if it is not of type `hidden`
713 if ( 'hidden' !== $section_args['type'] ) {
714 $section = $wp_customize->add_section( $section_id, $section_args );
715 // Fire a general added section hook
716 do_action( 'customify_process_customizer_config_added_section', $section, $section_args, $wp_customize );
717 }
718 }
719
720 // Now go through each section option and add the fields
721 foreach ( $section_config['options'] as $option_id => $option_config ) {
722
723 if ( empty( $option_id ) || ! isset( $option_config['type'] ) ) {
724 continue;
725 }
726
727 // If we have been explicitly given a setting ID we will use that
728 if ( ! empty( $option_config['setting_id'] ) ) {
729 $setting_id = $option_config['setting_id'];
730 } else {
731 $setting_id = $options_name . '[' . $option_id . ']';
732 }
733
734 // Add the option config to the localized array so we can pass the info to JS.
735 // @todo Maybe we should ensure that the connected_fields configs passed here follow the same format and logic as the ones in ::customize_pane_settings_additional_data() thus maybe having the data in the same place.
736
737 // Filter some settings that have purely visual purpose.
738 if ( ! empty( $option_config['type'] ) && ! in_array( $option_config['type'], array( 'html', 'button' ) ) ) {
739 $this->localized['config']['settings'][ $setting_id ] = $option_config;
740 }
741
742 // Generate a safe option ID (not the final setting ID) to us in HTML attributes like ID or class
743 $this->localized['config']['settings'][ $setting_id ]['html_safe_option_id'] = sanitize_html_class( $option_id );
744
745 $this->register_field( $section_id, $setting_id, $option_config, $wp_customize );
746 }
747
748 // Fire a general finished section hook
749 do_action( 'customify_process_customizer_config_finished_section', $section_id, $wp_customize );
750 }
751
752 /**
753 * Register a Customizer field (setting and control).
754 *
755 * @see WP_Customize_Setting
756 * @see WP_Customize_Control
757 *
758 * @param string $section_id
759 * @param string $setting_id
760 * @param array $field_config
761 * @param WP_Customize_Manager $wp_customize
762 */
763 protected function register_field( $section_id, $setting_id, $field_config, $wp_customize ) {
764
765 $add_control = true;
766 // defaults
767 $setting_args = array(
768 'type' => 'theme_mod',
769 'default' => '',
770 'capability' => 'edit_theme_options',
771 'transport' => 'refresh',
772 );
773 $control_args = array(
774 'priority' => 10,
775 'label' => '',
776 'section' => $section_id,
777 'settings' => $setting_id,
778 );
779
780 // sanitize settings
781 if ( ! empty( $field_config['live'] ) || $field_config['type'] === 'font' ) {
782 $setting_args['transport'] = 'postMessage';
783 }
784
785 if ( isset( $field_config['default'] ) ) {
786 $setting_args['default'] = $field_config['default'];
787 if ( is_array( $setting_args['default'] ) ) {
788 $setting_args['default'] = (object) $setting_args['default'];
789 }
790 }
791
792 if ( ! empty( $field_config['capability'] ) ) {
793 $setting_args['capability'] = $field_config['capability'];
794 }
795
796 // If the setting defines it's own type we will respect that, otherwise we will follow the global plugin setting.
797 if ( ! empty( $field_config['setting_type'] ) && 'option' === $field_config['setting_type'] ) {
798 $setting_args['type'] = 'option';
799 } elseif ( PixCustomifyPlugin()->settings->get_plugin_setting('values_store_mod') === 'option' ) {
800 $setting_args['type'] = 'option';
801 }
802
803 if ( ! empty( $field_config['sanitize_callback'] ) && is_callable( $field_config['sanitize_callback'] ) ) {
804 $setting_args['sanitize_callback'] = $field_config['sanitize_callback'];
805 } elseif ( 'checkbox' === $field_config['type'] ) {
806 $setting_args['sanitize_callback'] = array( $this, 'setting_sanitize_checkbox' );
807 }
808
809 // Add the setting
810 $wp_customize->add_setting( $setting_id, $setting_args );
811
812 // Stop the control registration, if we are presented with the right type.
813 if ( 'hidden_control' === $field_config['type'] ) {
814 return;
815 }
816
817 $control_args['type'] = $field_config['type'];
818
819 // now sanitize the control
820 if ( ! empty( $field_config['label'] ) ) {
821 $control_args['label'] = $field_config['label'];
822 }
823
824 if ( ! empty( $field_config['priority'] ) ) {
825 $control_args['priority'] = $field_config['priority'];
826 }
827
828 if ( ! empty( $field_config['desc'] ) ) {
829 $control_args['description'] = $field_config['desc'];
830 }
831
832 if ( ! empty( $field_config['active_callback'] ) ) {
833 $control_args['active_callback'] = $field_config['active_callback'];
834 }
835
836 // select the control type
837 // but first init a default
838 $control_class_name = 'Pix_Customize_Text_Control';
839
840 // If is a standard wp field type call it here and skip the rest.
841 if ( in_array( $field_config['type'], array(
842 'checkbox',
843 'dropdown-pages',
844 'url',
845 'date',
846 'time',
847 'datetime',
848 'week',
849 'search'
850 ) ) ) {
851 $wp_customize->add_control( $setting_id . '_control', $control_args );
852
853 return;
854 } elseif ( in_array( $field_config['type'], array(
855 'radio',
856 'select'
857 ) ) && ! empty( $field_config['choices'] )
858 ) {
859 $control_args['choices'] = $field_config['choices'];
860 $wp_customize->add_control( $setting_id . '_control', $control_args );
861
862 return;
863 } elseif ( in_array( $field_config['type'], array( 'range' ) ) && ! empty( $field_config['input_attrs'] ) ) {
864
865 $control_args['input_attrs'] = $field_config['input_attrs'];
866
867 $wp_customize->add_control( $setting_id . '_control', $control_args );
868 }
869
870 // If we arrive here this means we have a custom field control (with a corresponding class in features/customizer/controls).
871 switch ( $field_config['type'] ) {
872
873 case 'text':
874 if ( isset( $field_config['live'] ) ) {
875 $control_args['live'] = $field_config['live'];
876 }
877
878 $control_class_name = 'Pix_Customize_Text_Control';
879 break;
880
881 case 'textarea':
882 if ( isset( $field_config['live'] ) ) {
883 $control_args['live'] = $field_config['live'];
884 }
885
886 $control_class_name = 'Pix_Customize_Textarea_Control';
887 break;
888
889 case 'color':
890 $control_class_name = 'WP_Customize_Color_Control';
891 break;
892
893 case 'color_drop':
894 $control_class_name = 'Pix_Customize_Color_Drop_Control';
895 break;
896
897 case 'ace_editor':
898 if ( isset( $field_config['live'] ) ) {
899 $control_args['live'] = $field_config['live'];
900 }
901
902 if ( isset( $field_config['editor_type'] ) ) {
903 $control_args['editor_type'] = $field_config['editor_type'];
904 }
905
906 $control_class_name = 'Pix_Customize_Ace_Editor_Control';
907 break;
908
909 case 'upload':
910 $control_class_name = 'WP_Customize_Upload_Control';
911 break;
912
913 case 'image':
914 $control_class_name = 'WP_Customize_Image_Control';
915 break;
916
917 case 'media':
918 $control_class_name = 'WP_Customize_Media_Control';
919 break;
920
921 case 'custom_background':
922 if ( isset( $field_config['field'] ) ) {
923 $control_args['field'] = $field_config['field'];
924 }
925
926 $control_class_name = 'Pix_Customize_Background_Control';
927 break;
928
929 case 'cropped_image':
930 case 'cropped_media': // 'cropped_media' no longer works
931 if ( isset( $field_config['width'] ) ) {
932 $control_args['width'] = $field_config['width'];
933 }
934
935 if ( isset( $field_config['height'] ) ) {
936 $control_args['height'] = $field_config['height'];
937 }
938
939 if ( isset( $field_config['flex_width'] ) ) {
940 $control_args['flex_width'] = $field_config['flex_width'];
941 }
942
943 if ( isset( $field_config['flex_height'] ) ) {
944 $control_args['flex_height'] = $field_config['flex_height'];
945 }
946
947 if ( isset( $field_config['button_labels'] ) ) {
948 $control_args['button_labels'] = $field_config['button_labels'];
949 }
950
951 $control_class_name = 'WP_Customize_Cropped_Image_Control';
952 break;
953
954 case 'font' :
955
956 // Only add the control if typography is turned on in the plugin settings.
957 if ( ! PixCustomifyPlugin()->settings->get_plugin_setting( 'typography', '1' ) ) {
958 $add_control = false;
959 break;
960 }
961
962 $control_class_name = 'Pix_Customize_Font_Control';
963
964 if ( isset( $field_config['recommended'] ) ) {
965 $control_args['recommended'] = $field_config['recommended'];
966 }
967
968 if ( isset( $field_config['live'] ) ) {
969 $control_args['live'] = $field_config['live'];
970 }
971
972 // This is used only as an extreme failsafe.
973 // Normally, when there is no value, the WP Settings system will fallback on the default given for the setting.
974 // See above when registering the setting corresponding to this control.
975 if ( isset( $field_config['default'] ) ) {
976 $control_args['default'] = $field_config['default'];
977 }
978
979 // We should always receive a subfields configuration.
980 if ( isset( $field_config['fields'] ) ) {
981 $control_args['fields'] = $field_config['fields'];
982 } else {
983 $control_args['fields'] = array();
984 }
985
986 break;
987
988 case 'select2' :
989 if ( ! isset( $field_config['choices'] ) || empty( $field_config['choices'] ) ) {
990 return;
991 }
992
993 $control_args['choices'] = $field_config['choices'];
994
995 $control_class_name = 'Pix_Customize_Select2_Control';
996 break;
997
998 case 'sm_radio' :
999 if ( ! isset( $field_config['choices'] ) || empty( $field_config['choices'] ) ) {
1000 return;
1001 }
1002
1003 $control_args['choices'] = $field_config['choices'];
1004
1005 $control_class_name = 'Pix_Customize_SM_radio_Control';
1006 break;
1007
1008 case 'sm_palette_filter' :
1009 if ( ! isset( $field_config['choices'] ) || empty( $field_config['choices'] ) ) {
1010 return;
1011 }
1012
1013 $control_args['choices'] = $field_config['choices'];
1014
1015 $control_class_name = 'Pix_Customize_SM_palette_filter_Control';
1016 break;
1017
1018 case 'sm_switch' :
1019 if ( ! isset( $field_config['choices'] ) || empty( $field_config['choices'] ) ) {
1020 return;
1021 }
1022
1023 $control_args['choices'] = $field_config['choices'];
1024
1025 $control_class_name = 'Pix_Customize_SM_switch_Control';
1026 break;
1027
1028 case 'preset' :
1029 if ( ! isset( $field_config['choices'] ) || empty( $field_config['choices'] ) ) {
1030 return;
1031 }
1032
1033 $control_args['choices'] = $field_config['choices'];
1034
1035 if ( isset( $field_config['choices_type'] ) || ! empty( $field_config['choices_type'] ) ) {
1036 $control_args['choices_type'] = $field_config['choices_type'];
1037 }
1038
1039 if ( isset( $field_config['desc'] ) || ! empty( $field_config['desc'] ) ) {
1040 $control_args['description'] = $field_config['desc'];
1041 }
1042
1043
1044 $control_class_name = 'Pix_Customize_Preset_Control';
1045 break;
1046
1047 case 'radio_image' :
1048 if ( ! isset( $field_config['choices'] ) || empty( $field_config['choices'] ) ) {
1049 return;
1050 }
1051
1052 $control_args['choices'] = $field_config['choices'];
1053
1054 if ( isset( $field_config['choices_type'] ) || ! empty( $field_config['choices_type'] ) ) {
1055 $control_args['choices_type'] = $field_config['choices_type'];
1056 }
1057
1058 if ( isset( $field_config['desc'] ) || ! empty( $field_config['desc'] ) ) {
1059 $control_args['description'] = $field_config['desc'];
1060 }
1061
1062
1063 $control_class_name = 'Pix_Customize_Radio_Image_Control';
1064 break;
1065
1066 case 'radio_html' :
1067 if ( ! isset( $field_config['choices'] ) || empty( $field_config['choices'] ) ) {
1068 return;
1069 }
1070
1071 $control_args['choices'] = $field_config['choices'];
1072
1073 if ( isset( $field_config['desc'] ) || ! empty( $field_config['desc'] ) ) {
1074 $control_args['description'] = $field_config['desc'];
1075 }
1076
1077 $control_class_name = 'Pix_Customize_Radio_HTML_Control';
1078 break;
1079
1080 case 'button' :
1081 if ( ! isset( $field_config['action'] ) || empty( $field_config['action'] ) ) {
1082 return;
1083 }
1084
1085 $control_args['action'] = $field_config['action'];
1086
1087 $control_class_name = 'Pix_Customize_Button_Control';
1088
1089 break;
1090
1091 case 'html' :
1092 if ( isset( $field_config['html'] ) || ! empty( $field_config['html'] ) ) {
1093 $control_args['html'] = $field_config['html'];
1094 }
1095
1096 $control_class_name = 'Pix_Customize_HTML_Control';
1097 break;
1098
1099 default:
1100 // if we don't have a real control just quit, it doesn't even matter
1101 return;
1102 break;
1103 }
1104
1105 $this_control = new $control_class_name(
1106 $wp_customize,
1107 $setting_id . '_control',
1108 $control_args
1109 );
1110
1111 if ( $add_control ) {
1112 $wp_customize->add_control( $this_control );
1113 }
1114 }
1115
1116 /**
1117 * Remove the sections selected by user
1118 *
1119 * @param WP_Customize_Manager $wp_customize
1120 */
1121 function remove_default_sections( $wp_customize ) {
1122 global $wp_registered_sidebars;
1123
1124 $to_remove = PixCustomifyPlugin()->settings->get_plugin_setting( 'disable_default_sections' );
1125
1126 if ( ! empty( $to_remove ) ) {
1127 foreach ( $to_remove as $section => $nothing ) {
1128
1129 if ( $section === 'widgets' ) {
1130 foreach ( $wp_registered_sidebars as $widget => $settings ) {
1131 $wp_customize->remove_section( 'sidebar-widgets-' . $widget );
1132 }
1133 continue;
1134 }
1135
1136 $wp_customize->remove_section( $section );
1137 }
1138 }
1139 }
1140
1141 /**
1142 * Print JavaScript for adding additional data to _wpCustomizeSettings.settings object of the main window (not the preview window).
1143 */
1144 public function customize_pane_settings_additional_data() {
1145 /**
1146 * @global WP_Customize_Manager $wp_customize
1147 */
1148 global $wp_customize;
1149
1150 $options_name = PixCustomifyPlugin()->get_options_key();
1151 // Without an options name we can't do much.
1152 if ( empty( $options_name ) ) {
1153 return;
1154 }
1155
1156 $customizer_settings = $wp_customize->settings();
1157 ?>
1158 <script type="text/javascript">
1159 if ( 'undefined' === typeof _wpCustomizeSettings.settings ) {
1160 _wpCustomizeSettings.settings = {};
1161 }
1162
1163 <?php
1164 echo "(function ( sAdditional ){\n";
1165
1166 $options = PixCustomifyPlugin()->get_options_details();
1167 foreach ( $options as $option_id => $option_config ) {
1168 // If we have been explicitly given a setting ID we will use that
1169 if ( ! empty( $option_config['setting_id'] ) ) {
1170 $setting_id = $option_config['setting_id'];
1171 } else {
1172 $setting_id = $options_name . '[' . $option_id . ']';
1173 }
1174 // @todo Right now we only handle the connected_fields key - make this more dynamic by adding the keys that are not returned by WP_Customize_Setting->json()
1175 if ( ! empty( $customizer_settings[ $setting_id ] ) && ! empty( $option_config['connected_fields'] ) ) {
1176 // Pass through all the connected fields and make sure the id is in the final format
1177 $connected_fields = array();
1178 foreach ( $option_config['connected_fields'] as $key => $connected_field_config ) {
1179 $connected_field_data = array();
1180
1181 if ( is_string( $connected_field_config ) ) {
1182 $connected_field_id = $connected_field_config;
1183 } elseif ( is_array( $connected_field_config ) ) {
1184 // We have a full blown connected field config
1185 if ( is_string( $key ) ) {
1186 $connected_field_id = $key;
1187 } else {
1188 continue;
1189 }
1190
1191 // We will pass to JS all the configured connected field details.
1192 $connected_field_data = $connected_field_config;
1193 }
1194
1195 // Continue if we don't have a connected field ID to work with.
1196 if ( empty( $connected_field_id ) ) {
1197 continue;
1198 }
1199
1200 // If the connected setting is not one of our's, we will use it's ID as it is.
1201 if ( ! array_key_exists( $connected_field_id, $options ) ) {
1202 $connected_field_data['setting_id'] = $connected_field_id;
1203 }
1204 // If the connected setting specifies a setting ID, we will not prefix it and use it as it is.
1205 elseif ( ! empty( $options[ $connected_field_id ] ) && ! empty( $options[ $connected_field_id ]['setting_id'] ) ) {
1206 $connected_field_data['setting_id'] = $options[ $connected_field_id ]['setting_id'];
1207 } else {
1208 $connected_field_data['setting_id'] = $options_name . '[' . $connected_field_id . ']';
1209 }
1210
1211 $connected_fields[] = $connected_field_data;
1212 }
1213
1214 printf(
1215 "sAdditional[%s].%s = %s;\n",
1216 wp_json_encode( $setting_id ),
1217 'connected_fields',
1218 wp_json_encode( $connected_fields, JSON_FORCE_OBJECT )
1219 );
1220 }
1221 }
1222 echo "})( _wpCustomizeSettings.settings );\n";
1223 ?>
1224 </script>
1225 <?php
1226 }
1227
1228 /**
1229 * Maybe process certain "commands" from the config.
1230 *
1231 * Mainly things like removing sections, controls, etc.
1232 *
1233 * @since 1.9.0
1234 *
1235 * @param WP_Customize_Manager $wp_customize
1236 */
1237 public function maybe_process_config_extras( $wp_customize ) {
1238 $customizer_config = PixCustomifyPlugin()->get_customizer_config();
1239
1240 // Bail if we have no external theme config data.
1241 if ( empty( $customizer_config ) || ! is_array( $customizer_config ) ) {
1242 return;
1243 }
1244
1245 // Maybe remove panels
1246 if ( ! empty( $customizer_config['remove_panels'] ) ) {
1247 // Standardize it.
1248 if ( is_string( $customizer_config['remove_panels'] ) ) {
1249 $customizer_config['remove_panels'] = array( $customizer_config['remove_panels'] );
1250 }
1251
1252 foreach ( $customizer_config['remove_panels'] as $panel_id ) {
1253 $wp_customize->remove_panel( $panel_id );
1254 }
1255 }
1256
1257 // Maybe change panel props.
1258 if ( ! empty( $customizer_config['change_panel_props'] ) ) {
1259 foreach ( $customizer_config['change_panel_props'] as $panel_id => $panel_props ) {
1260 if ( ! is_array( $panel_props ) ) {
1261 continue;
1262 }
1263
1264 $panel = $wp_customize->get_panel( $panel_id );
1265 if ( empty( $panel ) || ! $panel instanceof WP_Customize_Panel ) {
1266 continue;
1267 }
1268
1269 $public_props = get_class_vars( get_class( $panel ) );
1270 foreach ( $panel_props as $prop_name => $prop_value ) {
1271
1272 if ( ! in_array( $prop_name, array_keys( $public_props ) ) ) {
1273 continue;
1274 }
1275
1276 $panel->$prop_name = $prop_value;
1277 }
1278 }
1279 }
1280
1281 // Maybe remove sections
1282 if ( ! empty( $customizer_config['remove_sections'] ) ) {
1283 // Standardize it.
1284 if ( is_string( $customizer_config['remove_sections'] ) ) {
1285 $customizer_config['remove_sections'] = array( $customizer_config['remove_sections'] );
1286 }
1287
1288 foreach ( $customizer_config['remove_sections'] as $section_id ) {
1289
1290 if ( 'widgets' === $section_id ) {
1291 global $wp_registered_sidebars;
1292
1293 foreach ( $wp_registered_sidebars as $widget => $settings ) {
1294 $wp_customize->remove_section( 'sidebar-widgets-' . $widget );
1295 }
1296 continue;
1297 }
1298
1299 $wp_customize->remove_section( $section_id );
1300 }
1301 }
1302
1303 // Maybe change section props.
1304 if ( ! empty( $customizer_config['change_section_props'] ) ) {
1305 foreach ( $customizer_config['change_section_props'] as $section_id => $section_props ) {
1306 if ( ! is_array( $section_props ) ) {
1307 continue;
1308 }
1309
1310 $section = $wp_customize->get_section( $section_id );
1311 if ( empty( $section ) || ! $section instanceof WP_Customize_Section ) {
1312 continue;
1313 }
1314
1315 $public_props = get_class_vars( get_class( $section ) );
1316 foreach ( $section_props as $prop_name => $prop_value ) {
1317
1318 if ( ! in_array( $prop_name, array_keys( $public_props ) ) ) {
1319 continue;
1320 }
1321
1322 $section->$prop_name = $prop_value;
1323 }
1324 }
1325 }
1326
1327 // Maybe remove settings
1328 if ( ! empty( $customizer_config['remove_settings'] ) ) {
1329 // Standardize it.
1330 if ( is_string( $customizer_config['remove_settings'] ) ) {
1331 $customizer_config['remove_settings'] = array( $customizer_config['remove_settings'] );
1332 }
1333
1334 foreach ( $customizer_config['remove_settings'] as $setting_id ) {
1335 $wp_customize->remove_setting( $setting_id );
1336 }
1337 }
1338
1339 // Maybe change setting props.
1340 if ( ! empty( $customizer_config['change_setting_props'] ) ) {
1341 foreach ( $customizer_config['change_setting_props'] as $setting_id => $setting_props ) {
1342 if ( ! is_array( $setting_props ) ) {
1343 continue;
1344 }
1345
1346 $setting = $wp_customize->get_setting( $setting_id );
1347 if ( empty( $setting ) || ! $setting instanceof WP_Customize_Setting ) {
1348 continue;
1349 }
1350
1351 $public_props = get_class_vars( get_class( $setting ) );
1352 foreach ( $setting_props as $prop_name => $prop_value ) {
1353
1354 if ( ! in_array( $prop_name, array_keys( $public_props ) ) ) {
1355 continue;
1356 }
1357
1358 $setting->$prop_name = $prop_value;
1359 }
1360 }
1361 }
1362
1363 // Maybe remove controls
1364 if ( ! empty( $customizer_config['remove_controls'] ) ) {
1365 // Standardize it.
1366 if ( is_string( $customizer_config['remove_controls'] ) ) {
1367 $customizer_config['remove_controls'] = array( $customizer_config['remove_controls'] );
1368 }
1369
1370 foreach ( $customizer_config['remove_controls'] as $control_id ) {
1371 $wp_customize->remove_control( $control_id );
1372 }
1373 }
1374
1375 // Maybe change control props.
1376 if ( ! empty( $customizer_config['change_control_props'] ) ) {
1377 foreach ( $customizer_config['change_control_props'] as $control_id => $control_props ) {
1378 if ( ! is_array( $control_props ) ) {
1379 continue;
1380 }
1381
1382 $control = $wp_customize->get_control( $control_id );
1383 if ( empty( $control ) || ! $control instanceof WP_Customize_Control ) {
1384 continue;
1385 }
1386
1387 $public_props = get_class_vars( get_class( $control ) );
1388 foreach ( $control_props as $prop_name => $prop_value ) {
1389
1390 if ( ! in_array( $prop_name, array_keys( $public_props ) ) ) {
1391 continue;
1392 }
1393
1394 $control->$prop_name = $prop_value;
1395 }
1396 }
1397 }
1398 }
1399
1400 /* HELPERS */
1401
1402 /**
1403 * Cleanup stuff like tab characters.
1404 *
1405 * @param string $string
1406 *
1407 * @return string
1408 */
1409 function cleanup_whitespace_css( $string ) {
1410 $string = normalize_whitespace( $string );
1411
1412 return $string;
1413 }
1414
1415 public function get_fields_by_key( $fields_config, $key, $value, &$results, $input_key = 0 ) {
1416 if ( ! is_array( $fields_config ) ) {
1417 return;
1418 }
1419
1420 if ( isset( $fields_config[ $key ] ) && $fields_config[ $key ] == $value ) {
1421 $results[ $input_key ] = $fields_config;
1422
1423 $default = null;
1424 if ( isset( $fields_config['default'] ) ) {
1425 $default = $fields_config['default'];
1426 }
1427
1428 $results[ $input_key ]['value'] = PixCustomifyPlugin()->get_option( $input_key, $default );
1429 }
1430
1431 foreach ( $fields_config as $i => $subarray ) {
1432 $this->get_fields_by_key( $subarray, $key, $value, $results, $i );
1433 }
1434 }
1435
1436 /**
1437 * Return a script for flexibly localizing data to a window property.
1438 *
1439 * Unlike wp_localize_script() that simply creates a variable and assigns it the value,
1440 * thus overwriting anything that may have been in that variable, we will output a script that
1441 * will test if the variable exists and only overwrite the first level nodes, not everything.
1442 *
1443 * @since 2.7.0
1444 *
1445 * @param string $object_name Name of the variable that will contain the data.
1446 * @param array $l10n Array of data to localize.
1447 *
1448 * @return bool True on success, false on failure.
1449 */
1450 public static function getlocalizeToWindowScript( $object_name, $l10n ) {
1451 $script = "window.$object_name = window.$object_name || parent.$object_name || {};\n";
1452
1453 foreach ( (array) $l10n as $key => $value ) {
1454 if ( is_scalar( $value ) ) {
1455 $value = html_entity_decode( (string) $value, ENT_QUOTES, 'UTF-8' );
1456 }
1457
1458 $script .= "$object_name.$key = " . wp_json_encode( $value ) . ";\n";
1459 }
1460
1461 return $script;
1462 }
1463
1464 /* SANITIZATION HELPERS */
1465
1466 /**
1467 * Sanitize the checkbox.
1468 *
1469 * @param boolean $input .
1470 *
1471 * @return boolean true if is 1 or '1', false if anything else
1472 */
1473 function setting_sanitize_checkbox( $input ) {
1474 if ( 1 == $input ) {
1475 return true;
1476 } else {
1477 return false;
1478 }
1479 }
1480
1481 /**
1482 * Main PixCustomify_Customizer Instance
1483 *
1484 * Ensures only one instance of PixCustomify_Customizer is loaded or can be loaded.
1485 *
1486 * @since 2.4.0
1487 * @static
1488 *
1489 * @return PixCustomify_Customizer Main PixCustomify_Customizer instance
1490 */
1491 public static function instance() {
1492
1493 if ( is_null( self::$_instance ) ) {
1494 self::$_instance = new self();
1495 }
1496
1497 return self::$_instance;
1498 } // End instance ()
1499
1500 /**
1501 * Cloning is forbidden.
1502 *
1503 * @since 2.4.0
1504 */
1505 public function __clone() {
1506
1507 _doing_it_wrong( __FUNCTION__,esc_html__( 'You should not do that!', 'customify' ), null );
1508 }
1509
1510 /**
1511 * Unserializing instances of this class is forbidden.
1512 *
1513 * @since 2.4.0
1514 */
1515 public function __wakeup() {
1516
1517 _doing_it_wrong( __FUNCTION__, esc_html__( 'You should not do that!', 'customify' ), null );
1518 }
1519 }
1520
1521 endif;
1522