PluginProbe
Customify / 2.1.1
Customify v2.1.1
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
← All changes | class-pixcustomify.php +871 -340 1.5.62.1.1 View file →
@@ -43,15 +43,8 @@
43 43 * @var string
44 44 */
45 45 protected $plugin_screen_hook_suffix = null;
46 46
47 - /**
48 - * Path to the plugin.
49 - * @since 1.0.0
50 - * @var string
51 - */
52 - protected $plugin_basepath = null;
53 -
54 47 public $display_admin_menu = false;
55 48
56 49 private $config;
57 50
@@ -125,8 +118,16 @@
125 118 */
126 119 public $file;
127 120
128 121 /**
122 + * Style Manager class object.
123 + * @var Customify_Style_Manager
124 + * @access public
125 + * @since 1.0.0
126 + */
127 + public $style_manager = null;
128 +
129 + /**
129 130 * Minimal Required PHP Version
130 131 * @var string
131 132 * @access private
132 133 * @since 1.5.0
@@ -138,11 +139,8 @@
138 139 $this->file = $file;
139 140 //the current plugin version
140 141 $this->_version = $version;
141 142
142 - // Remember our base path
143 - $this->plugin_basepath = plugin_dir_path( $file );
144 -
145 143 if ( $this->php_version_check() ) {
146 144 // Only load and run the init function if we know PHP version can parse it.
147 145 $this->init();
148 146 }
@@ -156,8 +154,14 @@
156 154 $this->config = $this->get_config();
157 155 // Load the plugin's settings from the DB
158 156 $this->plugin_settings = get_option( $this->config['settings-key'] );
159 157
158 + /* Initialize the Style Manager logic. */
159 + require_once( $this->get_base_path() . 'includes/class-customify-style-manager.php' );
160 + if ( is_null( $this->style_manager ) ) {
161 + $this->style_manager = Customify_Style_Manager::instance( $this );
162 + }
163 +
160 164 // Register all the needed hooks
161 165 $this->register_hooks();
162 166 }
163 167
@@ -162,10 +166,8 @@
162 166 }
163 167
164 168 /**
165 169 * Register our actions and filters
166 - *
167 - * @return null
168 170 */
169 171 function register_hooks() {
170 172 /*
171 173 * Register hooks that are fired when the plugin is activated, deactivated, and uninstalled, respectively.
@@ -178,8 +180,13 @@
178 180 */
179 181 add_action( 'init', array( $this, 'load_plugin_textdomain' ) );
180 182
181 183 /*
184 + * Load the upgrade logic.
185 + */
186 + add_action( 'admin_init', array( $this, 'upgrade' ) );
187 +
188 + /*
182 189 * Prepare and load the configuration
183 190 */
184 191 $this->init_plugin_configs();
185 192
@@ -209,15 +216,18 @@
209 216 // Styles for the Customizer
210 217 add_action( 'customize_controls_init', array( $this, 'register_admin_customizer_styles' ), 10 );
211 218 add_action( 'customize_controls_enqueue_scripts', array( $this, 'enqueue_admin_customizer_styles' ), 10 );
212 219 // Scripts enqueued in the Customizer
213 - add_action( 'customize_controls_init', array( $this, 'register_admin_customizer_scripts' ), 10 );
214 - add_action( 'customize_controls_enqueue_scripts', array( $this, 'enqueue_admin_customizer_scripts' ), 10 );
220 + add_action( 'customize_controls_init', array( $this, 'register_admin_customizer_scripts' ), 15 );
221 + add_action( 'customize_controls_enqueue_scripts', array( $this, 'enqueue_admin_customizer_scripts' ), 15 );
215 222
216 223 // Scripts enqueued only in the theme preview
217 224 add_action( 'customize_preview_init', array( $this, 'customizer_live_preview_register_scripts' ), 10 );
218 225 add_action( 'customize_preview_init', array( $this, 'customizer_live_preview_enqueue_scripts' ), 99999 );
219 226
227 + // Add extra settings data to _wpCustomizeSettings.settings of the parent window.
228 + add_action( 'customize_controls_print_footer_scripts', array( $this, 'customize_pane_settings_additional_data' ), 10000 );
229 +
220 230 // The frontend effects of the Customizer controls
221 231 $load_location = $this->get_plugin_setting( 'style_resources_location', 'wp_head' );
222 232
223 233 add_action( $load_location, array( $this, 'output_dynamic_style' ), 99 );
@@ -224,31 +234,55 @@
224 234 add_action( 'wp_head', array( $this, 'output_typography_dynamic_style' ), 10 );
225 235
226 236 add_action( 'customize_register', array( $this, 'remove_default_sections' ), 11 );
227 237 add_action( 'customize_register', array( $this, 'register_customizer' ), 12 );
238 + // Maybe the theme has instructed us to do things like removing sections or controls.
239 + add_action( 'customize_register', array( $this, 'maybe_process_config_extras' ), 13 );
228 240
229 241 if ( $this->get_plugin_setting( 'enable_editor_style', true ) ) {
230 242 add_action( 'admin_head', array( $this, 'add_customizer_settings_into_wp_editor' ) );
231 243 }
232 244
245 + add_action( 'rest_api_init', array( $this, 'add_rest_routes_api' ) );
246 +
233 247 /*
234 - * Jetpack Related
248 + * Development related
235 249 */
236 - add_action( 'init', array( $this, 'set_jetpack_sharing_config') );
237 - add_filter( 'default_option_jetpack_active_modules', array( $this, 'default_jetpack_active_modules' ), 10, 1 );
238 - add_filter( 'jetpack_get_available_modules', array( $this, 'jetpack_hide_blocked_modules' ), 10, 1 );
239 - add_filter( 'default_option_sharing-options', array( $this, 'default_jetpack_sharing_options' ), 10, 1 );
250 + if ( defined( 'CUSTOMIFY_DEV_FORCE_DEFAULTS' ) && true === CUSTOMIFY_DEV_FORCE_DEFAULTS ) {
251 + // If the development constant CUSTOMIFY_DEV_FORCE_DEFAULTS has been defined we will not save anything in the database
252 + // Always go with the default
253 + add_filter( 'customize_changeset_save_data', array( $this, 'prevent_changeset_save_in_devmode' ), 50, 2 );
254 + // Add a JS to display a notification
255 + add_action( 'customize_controls_print_footer_scripts', array( $this, 'prevent_changeset_save_in_devmode_notification' ), 100 );
256 + }
257 + }
240 258
241 - add_action( 'rest_api_init', array( $this, 'add_rest_routes_api' ) );
259 + /**
260 + * Handle the logic to upgrade between versions. It will run only one per version change.
261 + */
262 + public function upgrade() {
263 + $customify_dbversion = get_option( 'customify_dbversion', '0.0.1' );
264 + if ( $this->get_version() === $customify_dbversion ) {
265 + return;
266 + }
267 +
268 + // For versions, previous of version 2.0.0 (the Color Palettes v2.0 release).
269 + if ( version_compare( $customify_dbversion, '2.0.0', '<' ) ) {
270 + // Delete the option holding the fact that the user offered feedback.
271 + delete_option( 'style_manager_user_feedback_provided' );
272 + }
273 +
274 + // Put the current version in the database.
275 + update_option( 'customify_dbversion', $this->get_version(), true );
242 276 }
243 277
244 278 /**
245 - * Initialize Configs, Options and Values methods
279 + * Initialize Configs, Options and Values methods.
246 280 */
247 281 function init_plugin_configs() {
248 282 $this->customizer_config = get_option( 'pixcustomify_config' );
249 283
250 - // no option so go for default
284 + // no option so go for default.
251 285 if ( empty( $this->customizer_config ) ) {
252 286 $this->customizer_config = $this->get_config_option( 'default_options' );
253 287 }
254 288
@@ -257,18 +291,21 @@
257 291 }
258 292 }
259 293
260 294 /**
261 - * Load the plugin configuration and options
295 + * Load the plugin configuration and options.
262 296 */
263 297 function load_plugin_configs() {
264 298
265 - // allow themes or other plugins to filter the config
299 + // Allow themes or other plugins to filter the config.
266 300 $this->customizer_config = apply_filters( 'customify_filter_fields', $this->customizer_config );
301 + // We apply a second filter for those that wish to work with the final config and not rely on a a huge priority number.
302 + $this->customizer_config = apply_filters( 'customify_final_config', $this->customizer_config );
303 +
267 304 $this->opt_name = $this->localized['options_name'] = $this->customizer_config['opt-name'];
268 305 $this->options_list = $this->get_options();
269 306
270 - // Load the current options values
307 + // Load the current options values.
271 308 $this->current_values = $this->get_current_values();
272 309
273 310 if ( $this->import_button_exists() ) {
274 311 $this->localized['import_rest_url'] = get_rest_url( '/customify/1.0/' );
@@ -277,73 +314,23 @@
277 314 $this->register_import_api();
278 315 }
279 316
280 317 $this->localized['theme_fonts'] = $this->theme_fonts = Customify_Font_Selector::instance()->get_theme_fonts();
281 - }
282 318
283 - function set_jetpack_sharing_config() {
284 - // Allow others to change the sharing config here
285 - $this->jetpack_sharing_default_options = apply_filters ( 'customify_filter_jetpack_sharing_default_options', array() );
319 + $this->localized['ajax_url'] = admin_url( 'admin-ajax.php' );
320 + $this->localized['style_manager_user_feedback_nonce'] = wp_create_nonce( 'customify_style_manager_user_feedback' );
321 + $this->localized['style_manager_user_feedback_provided'] = get_option( 'style_manager_user_feedback_provided', false );
286 322 }
287 323
288 - /**
289 - * Control the default modules that are activated in Jetpack.
290 - * Use the `customify_filter_jetpack_default_modules` to set your's.
291 - *
292 - * @param array $default The default value to return if the option does not exist
293 - * in the database.
294 - *
295 - * @return array
296 - */
297 - function default_jetpack_active_modules( $default ) {
298 - if ( ! is_array( $default ) ) {
299 - $default = array();
300 - }
301 - $jetpack_default_modules = array();
302 -
303 - $theme_default_modules = get_theme_mod( 'pixelgrade_jetpack_default_active_modules', array() );
304 -
305 - if ( ! is_array( $theme_default_modules ) ) {
306 - return array_merge( $default, $jetpack_default_modules );
307 - }
308 -
309 - foreach ( $theme_default_modules as $module ) {
310 - array_push( $jetpack_default_modules, $module );
311 - }
312 -
313 - return array_merge( $default, $jetpack_default_modules );
324 + public function get_version() {
325 + return $this->_version;
314 326 }
315 327
316 - /**
317 - * Control the default Jetpack Sharing options.
318 - * Use the `customify_filter_jetpack_sharing_default_options` to set your's.
319 - *
320 - * @param array $default The default value to return if the option does not exist
321 - * in the database.
322 - *
323 - * @return array
324 - */
325 - function default_jetpack_sharing_options( $default ) {
326 - if ( ! is_array( $default ) ) {
327 - $default = array();
328 - }
329 -
330 - return array_merge( $default, $this->jetpack_sharing_default_options );
328 + public function get_slug() {
329 + return $this->plugin_slug;
331 330 }
332 331
333 332 /**
334 - * Control the modules that are available in Jetpack (hide some of them).
335 - * Use the `customify_filter_jetpack_blocked_modules` filter to set your's.
336 - *
337 - * @param array $modules
338 - *
339 - * @return array
340 - */
341 - function jetpack_hide_blocked_modules( $modules ) {
342 - return array_diff_key( $modules, array_flip( $this->jetpack_blocked_modules ) );
343 - }
344 -
345 - /**
346 333 * Fired when the plugin is activated.
347 334 * @since 1.0.0
348 335 *
349 336 * @param boolean $network_wide True if WPMU superadmin uses "Network Activate" action, false if WPMU is disabled or plugin is activated on an individual blog.
@@ -394,13 +381,20 @@
394 381 function register_admin_customizer_scripts() {
395 382
396 383 wp_register_script( 'customify_select2', plugins_url( 'js/select2/js/select2.js', $this->file ), array( 'jquery' ), $this->_version );
397 384 wp_register_script( 'jquery-react', plugins_url( 'js/jquery-react.js', $this->file ), array( 'jquery' ), $this->_version );
385 +
386 + wp_register_script( 'customify-scale', plugins_url( 'js/customizer/scale-iframe.js', $this->file ), array( 'jquery' ), $this->_version );
387 + wp_register_script( 'customify-fontselectfields', plugins_url( 'js/customizer/font-select-fields.js', $this->file ), array( 'jquery' ), $this->_version );
388 +
398 389 wp_register_script( $this->plugin_slug . '-customizer-scripts', plugins_url( 'js/customizer.js', $this->file ), array(
399 390 'jquery',
400 391 'customify_select2',
401 392 'underscore',
402 - 'customize-controls'
393 + 'customize-controls',
394 + 'customify-fontselectfields',
395 +
396 + 'customify-scale',
403 397 ), $this->_version );
404 398 }
405 399
406 400 /**
@@ -409,9 +403,9 @@
409 403 function enqueue_admin_customizer_scripts() {
410 404 wp_enqueue_script( 'jquery-react' );
411 405 wp_enqueue_script( $this->plugin_slug . '-customizer-scripts' );
412 406
413 - wp_localize_script( $this->plugin_slug . '-customizer-scripts', 'customify_settings', $this->localized );
407 + wp_localize_script( $this->plugin_slug . '-customizer-scripts', 'customify_settings', apply_filters( 'customify_localized_js_settings', $this->localized ) );
414 408 }
415 409
416 410 /** Register Customizer scripts loaded only on previewer page */
417 411 function customizer_live_preview_register_scripts() {
@@ -482,9 +476,9 @@
482 476 ) );
483 477 }
484 478
485 479 function add_rest_routes_api(){
486 - register_rest_route( 'customfiy/v1', '/delete_theme_mod', array(
480 + register_rest_route( 'customify/v1', '/delete_theme_mod', array(
487 481 'methods' => 'POST',
488 482 'callback' => array( $this, 'delete_theme_mod' ),
489 483 'permission_callback' => array( $this, 'permission_nonce_callback' ),
490 484 ) );
@@ -490,11 +484,10 @@
490 484 ) );
491 485 }
492 486
493 487 function delete_theme_mod(){
494 - $user = wp_get_current_user();
495 - if ( ! $user->caps['administrator'] ) {
496 - wp_send_json_error('no admin');
488 + if ( ! current_user_can( 'manage_options' ) ) {
489 + wp_send_json_error('You don\'t have admin privileges.');
497 490 }
498 491
499 492 $config = apply_filters('customify_filter_fields', array() );
500 493
@@ -505,9 +498,9 @@
505 498 $key = $config['opt-name'];
506 499
507 500 remove_theme_mod( $key );
508 501
509 - wp_send_json_success('Bye bye ' . $key . '!');
502 + wp_send_json_success('Deleted ' . $key . ' theme mod!');
510 503 }
511 504
512 505 function permission_nonce_callback() {
513 506 return wp_verify_nonce( $this->get_nonce(), 'customify_settings_nonce' );
@@ -528,9 +521,9 @@
528 521 /**
529 522 * Public style generated by customizer
530 523 */
531 524 function output_dynamic_style() {
532 - $custom_css = "\n";
525 + $custom_css = '';
533 526
534 527 foreach ( $this->options_list as $option_id => $option ) {
535 528
536 529 if ( isset( $option['css'] ) && ! empty( $option['css'] ) ) {
@@ -537,11 +530,11 @@
537 530 // now process each
538 531 $custom_css .= $this->convert_setting_to_css( $option_id, $option['css'] );
539 532 }
540 533
541 - if ( $option['type'] === 'custom_background' ) {
534 + if ( isset( $option['type'] ) && $option['type'] === 'custom_background' ) {
542 535 $option['value'] = $this->get_option( $option_id );
543 - $custom_css .= $this->process_custom_background_field_output( $option_id, $option );
536 + $custom_css .= $this->process_custom_background_field_output( $option_id, $option ) . PHP_EOL;
544 537 }
545 538 }
546 539
547 540 if ( ! empty( $this->media_queries ) ) {
@@ -551,22 +544,20 @@
551 544 if ( empty( $properties ) ) {
552 545 continue;
553 546 }
554 547
555 - $custom_css .= '@media ' . $media_query . " { ";
548 + $custom_css .= PHP_EOL . '@media ' . $media_query . " { " . PHP_EOL . PHP_EOL;
556 549
557 550 foreach ( $properties as $key => $property ) {
558 551 $property_settings = $property['property'];
559 552 $property_value = $property['value'];
560 - $custom_css .= $this->proccess_css_property( $property_settings, $property_value );
553 + $custom_css .= "\t" . $this->proccess_css_property( $property_settings, $property_value ) . PHP_EOL;
561 554 }
562 555
563 - $custom_css .= " }\n";
556 + $custom_css .= "}" . PHP_EOL;
564 557
565 558 }
566 559 }
567 -
568 - $custom_css .= "\n";
569 560 ?>
570 561 <style id="customify_output_style">
571 562 <?php echo apply_filters( 'customify_dynamic_style', $custom_css ); ?>
572 563 </style><?php
@@ -580,13 +571,13 @@
580 571 }
581 572
582 573 foreach ( $this->options_list as $option_id => $options ) {
583 574
584 - if ( $options['type'] === 'custom_background' ) {
575 + if ( isset( $options['type'] ) && $options['type'] === 'custom_background' ) {
585 576 $options['value'] = $this->get_option( $option_id );
586 577 $custom_background_output = $this->process_custom_background_field_output( $option_id, $options ); ?>
587 578
588 - <style id="custom_background_output_for_<?php echo $option_id; ?>">
579 + <style id="custom_background_output_for_<?php echo sanitize_html_class( $option_id ); ?>">
589 580 <?php
590 581 if ( isset( $custom_background_output ) && ! empty( $custom_background_output )) {
591 582 echo $custom_background_output;
592 583 } ?>
@@ -597,57 +588,29 @@
597 588 continue;
598 589 }
599 590
600 591 $this_value = $this->get_option( $option_id );
601 - foreach ( $options['css'] as $key => $properties_set ) { ?>
602 - <style id="dynamic_setting_<?php echo $option_id . '_property_' . str_replace( '-', '_', $properties_set['property'] ); ?>"
603 - type="text/css"><?php
592 + if ( ! empty( $options['css'] ) ) {
593 + foreach ( $options['css'] as $key => $properties_set ) {
594 + // We need to use a class because we may have multiple <style>s with the same "ID" for example
595 + // when targeting the same property but with different selectors.
596 + ?>
597 + <style class="dynamic_setting_<?php echo sanitize_html_class( $option_id ) . '_property_' . str_replace( '-', '_', $properties_set['property'] ) . '_' . $key; ?>"
598 + type="text/css"><?php
604 599
605 600 if ( isset( $properties_set['media'] ) && ! empty( $properties_set['media'] ) ) {
606 - echo '@media '. $properties_set['media'] . " {\n";
601 + echo '@media '. $properties_set['media'] . " {" . PHP_EOL;
607 602 }
608 603
609 604 if ( isset( $properties_set['selector'] ) && isset( $properties_set['property'] ) ) {
610 - echo $this->proccess_css_property($properties_set, $this_value);
605 + echo $this->proccess_css_property($properties_set, $this_value) . PHP_EOL;
611 606 }
612 607
613 608 if ( isset( $properties_set['media'] ) && ! empty( $properties_set['media'] ) ) {
614 - echo "}\n";
609 + echo "}" . PHP_EOL;
615 610 } ?>
616 - </style>
617 - <?php }
618 - }
619 -
620 - if ( ! empty( $this->media_queries ) ) {
621 -
622 - foreach ( $this->media_queries as $media_query => $properties ) {
623 -
624 - if ( empty( $properties ) ) {
625 - continue;
626 - }
627 -
628 - $display = false;
629 - $media_q = '@media ' . $media_query . " {\n";
630 -
631 - foreach ( $properties as $key => $property ) {
632 -
633 - if ( ! isset( $options['live'] ) || $options['live'] !== true ) {
634 - continue;
635 - }
636 -
637 - $display = true; ?>
638 - <style id="dynamic_setting_<?php echo $key; ?>" type="text/css"><?php
639 - $property_settings = $property['property'];
640 - $property_value = $property['value'];
641 - $media_q .= "\t" . $this->proccess_css_property( $property_settings, $property_value );?>
642 611 </style>
643 612 <?php }
644 -
645 - $media_q .= "\n}\n";
646 -
647 - if ( $display ) {
648 - $custom_css .= $media_q;
649 - }
650 613 }
651 614 }
652 615 }
653 616
@@ -682,30 +645,39 @@
682 645 $load_all_weights = true;
683 646 }
684 647
685 648 // shim the time when this was an array
649 + // @todo Is this really needed? Or does it make sense?
686 650 if ( is_array( $font['value'] ) ) {
687 651 $font['value'] = stripslashes_deep( $font['value'] );
688 652 $font['value'] = json_encode( $font['value'] );
689 653 }
690 654
691 - $value = json_decode( wp_unslash( PixCustomifyPlugin::decodeURIComponent( $font['value'] ) ), true );
655 + $value = wp_unslash( PixCustomifyPlugin::decodeURIComponent( $font['value'] ) );
656 + if ( is_string( $value ) ) {
657 + $value = json_decode( $value, true );
658 + }
692 659
693 - // in case the value is still null, try default value(mostly for google fonts)
694 - if ( ! is_array( $value ) || $value === null ) {
660 + // In case the value is still null, try default value (mostly for google fonts)
661 + if ( $value === null || ! is_array( $value ) ) {
695 662 $value = $this->get_font_defaults_value( str_replace( '"', '', $font['value'] ) );
696 663 }
697 664
698 - //bail if by this time we don't have a value of some sort
665 + // Bail if by this time we don't have a value of some sort
699 666 if ( empty( $value ) ) {
700 667 continue;
701 668 }
702 669
703 - //Handle special logic for when the $value array is not an associative array
670 + // Handle special logic for when the $value array is not an associative array
704 671 if ( ! $this->is_assoc( $value ) ) {
705 - $value = $this->process_a_not_associative_font_default( $value );
672 + $value = $this->standardize_non_associative_font_default( $value );
706 673 }
707 674
675 + // Bail if empty or we don't have an array
676 + if ( empty( $value ) || ! is_array( $value ) ) {
677 + continue;
678 + }
679 +
708 680 if ( isset( $value['font_family'] ) && isset( $value['type'] ) && $value['type'] == 'google' ) {
709 681 $families .= "'" . $value['font_family'];
710 682
711 683 if ( $load_all_weights && is_array( $value['variants'] ) ) {
@@ -778,25 +750,35 @@
778 750 $load_all_weights = true;
779 751 }
780 752
781 753 if ( isset( $font['selector'] ) && isset( $font['value'] ) && ! empty( $font['value'] ) ) {
754 + // Make sure that the value is in the proper format
755 + $value = PixCustomifyPlugin::decodeURIComponent( $font['value'] );
756 + if ( is_string( $value ) ) {
757 + $value = json_decode( $value, true );
758 + }
782 759
783 - $value = json_decode( PixCustomifyPlugin::decodeURIComponent( $font['value'] ), true );
784 - // in case the value is still null, try default value(mostly for google fonts)
760 + // In case the value is null (most probably because the json_decode failed),
761 + // try the default value (mostly for google fonts)
785 762 if ( $value === null ) {
786 763 $value = $this->get_font_defaults_value( $font['value'] );
787 764 }
788 765
789 - // shim the old case when the default was only the font name
790 - if ( is_string( $value ) && ! empty( $value ) ) {
766 + // Shim the old case when the default was only the font name
767 + if ( ! empty( $value ) && is_string( $value ) ) {
791 768 $value = array( 'font_family' => $value );
792 769 }
793 770
794 - //Handle special logic for when the $value array is not an associative array
771 + // Handle special logic for when the $value array is not an associative array
795 772 if ( ! $this->is_assoc( $value ) ) {
796 - $value = $this->process_a_not_associative_font_default( $value );
773 + $value = $this->standardize_non_associative_font_default( $value );
797 774 }
798 775
776 + // Bail if empty or we don't have an array
777 + if ( empty( $value ) || ! is_array( $value ) ) {
778 + continue;
779 + }
780 +
799 781 $selected_variant = '';
800 782 if ( ! empty( $value['selected_variants'] ) ) {
801 783 if ( is_array( $value['selected_variants'] ) ) {
802 784 $selected_variant = $value['selected_variants'][0];
@@ -806,13 +788,13 @@
806 788 }
807 789
808 790 // First handle the case where we have the font-family in the selected variant (usually this means a custom font from our Fonto plugin)
809 791 if ( ! empty( $selected_variant ) && is_array( $selected_variant ) && ! empty( $selected_variant['font-family'] ) ) {
810 - //the variant's font-family
792 + // The variant's font-family
811 793 echo $font['selector'] . " {\nfont-family: " . $selected_variant['font-family'] . ";\n";
812 794
813 795 if ( ! $load_all_weights ) {
814 - // if this is a custom font (like from our plugin Fonto) with individual styles & weights - i.e. the font-family says it all
796 + // If this is a custom font (like from our plugin Fonto) with individual styles & weights - i.e. the font-family says it all
815 797 // we need to "force" the font-weight and font-style
816 798 if ( ! empty( $value['type'] ) && 'custom_individual' == $value['type'] ) {
817 799 $selected_variant['font-weight'] = '400 !important';
818 800 $selected_variant['font-style'] = 'normal !important';
@@ -817,14 +799,14 @@
817 799 $selected_variant['font-weight'] = '400 !important';
818 800 $selected_variant['font-style'] = 'normal !important';
819 801 }
820 802
821 - // output the font weight, if available
803 + // Output the font weight, if available
822 804 if ( ! empty( $selected_variant['font-weight'] ) ) {
823 805 echo "font-weight: " . $selected_variant['font-weight'] . ";\n";
824 806 }
825 807
826 - // output the font style, if available
808 + // Output the font style, if available
827 809 if ( ! empty( $selected_variant['font-style'] ) ) {
828 810 echo "font-style: " . $selected_variant['font-style'] . ";\n";
829 811 }
830 812 }
@@ -830,9 +812,9 @@
830 812 }
831 813
832 814 echo "}\n";
833 815 } elseif ( isset( $value['font_family'] ) ) {
834 - // the selected font family
816 + // The selected font family
835 817 echo $font['selector'] . " {\n font-family: " . $value['font_family'] . ";\n";
836 818
837 819 if ( ! empty( $selected_variant ) && ! $load_all_weights ) {
838 820 $weight_and_style = strtolower( $selected_variant );
@@ -868,14 +850,18 @@
868 850 /**
869 851 * Handle special logic for when the $value array is not an associative array
870 852 * Return a new associative array with proper keys
871 853 */
872 - public function process_a_not_associative_font_default( $value ) {
854 + public function standardize_non_associative_font_default( $value ) {
855 + // If the value provided is not array, simply return it
856 + if ( ! is_array( $value ) ) {
857 + return $value;
858 + }
873 859
874 860 $new_value = array();
875 861
876 - //Let's determine some type of font
877 - if ( ! isset( $value[2] ) || ( isset( $value[2] ) && 'google' == $value[2] ) ) {
862 + // Let's determine some type of font
863 + if ( ! isset( $value[2] ) || 'google' == $value[2] ) {
878 864 $new_value = $this->get_font_defaults_value( $value[0] );
879 865 } else {
880 866 $new_value['type'] = $value[2];
881 867 }
@@ -883,15 +869,15 @@
883 869 if ( null == $new_value ) {
884 870 $new_value = array();
885 871 }
886 872
887 - //The first entry is the font-family
873 + // The first entry is the font-family
888 874 if ( isset( $value[0] ) ) {
889 875 $new_value['font_family'] = $value[0];
890 876 }
891 877
892 - //In case we don't have an associative array
893 - //The second entry is the variants
878 + // In case we don't have an associative array
879 + // The second entry is the variants
894 880 if ( isset( $value[1] ) ) {
895 881 $new_value['selected_variants'] = $value[1];
896 882 }
897 883
@@ -954,10 +940,10 @@
954 940 );
955 941 continue;
956 942 }
957 943
958 - if ( ! isset( $css_property['selector'] ) || isset( $css_property['property'] ) ) {
959 - $output .= $this->proccess_css_property( $css_property, $this_value );
944 + if ( isset( $css_property['selector'] ) && isset( $css_property['property'] ) ) {
945 + $output .= $this->proccess_css_property( $css_property, $this_value ) . PHP_EOL;
960 946 }
961 947 }
962 948
963 949 return $output;
@@ -976,11 +962,17 @@
976 962 }
977 963 // lose the tons of tabs
978 964 $css_property['selector'] = trim( preg_replace( '/\t+/', '', $css_property['selector'] ) );
979 965
980 - $this_property_output = $css_property['selector'] . ' { ' . $css_property['property'] . ': ' . $this_value . $unit . "; }\n";
966 + $this_property_output = $css_property['selector'] . ' { ' . $css_property['property'] . ': ' . $this_value . $unit . "; }" . PHP_EOL;
981 967
982 - if ( isset( $css_property['callback_filter'] ) && function_exists( $css_property['callback_filter'] ) ) {
968 + // Handle the value filter callback.
969 + if ( isset( $css_property['filter_value_cb'] ) ) {
970 + $this_value = $this->maybe_apply_filter( $css_property['filter_value_cb'], $this_value );
971 + }
972 +
973 + // Handle output callback.
974 + if ( isset( $css_property['callback_filter'] ) && is_callable( $css_property['callback_filter'] ) ) {
983 975 $this_property_output = call_user_func( $css_property['callback_filter'], $this_value, $css_property['selector'], $css_property['property'], $unit );
984 976 }
985 977
986 978 return $this_property_output;
@@ -985,8 +977,53 @@
985 977
986 978 return $this_property_output;
987 979 }
988 980
981 + /**
982 + * Apply a filter (config) to a value.
983 + *
984 + * We currently handle filters like these:
985 + * // Elaborate filter config
986 + * array(
987 + * 'callback' => 'is_post_type_archive',
988 + * // The arguments we should pass to the check function.
989 + * // Think post types, taxonomies, or nothing if that is the case.
990 + * // It can be an array of values or a single value.
991 + * 'args' => array(
992 + * 'jetpack-portfolio',
993 + * ),
994 + * ),
995 + * // Simple filter - just the function name
996 + * 'is_404',
997 + *
998 + * @param array|string $filter
999 + * @param mixed $value The value to apply the filter to.
1000 + *
1001 + * @return mixed The filtered value.
1002 + */
1003 + public function maybe_apply_filter( $filter, $value ) {
1004 + // Let's get some obvious things off the table.
1005 + // On invalid data, we just return what we've received.
1006 + if ( empty( $filter ) ) {
1007 + return $value;
1008 + }
1009 +
1010 + // First, we handle the shorthand version: just a function name
1011 + if ( is_string( $filter ) && is_callable( $filter ) ) {
1012 + $value = call_user_func( $filter );
1013 + } elseif ( is_array( $filter ) && ! empty( $filter['callback'] ) && is_callable( $filter['callback'] ) ) {
1014 + if ( empty( $filter['args'] ) ) {
1015 + $filter['args'] = array();
1016 + }
1017 + // The value is always the first argument.
1018 + $filter['args'] = array( $value ) + $filter['args'];
1019 +
1020 + $value = call_user_func_array( $filter['callback'], $filter['args'] );
1021 + }
1022 +
1023 + return $value;
1024 + }
1025 +
989 1026 protected function process_custom_background_field_output( $option_id, $options ) {
990 1027 $selector = $output = '';
991 1028
992 1029 if ( ! isset( $options['value'] ) ) {
@@ -1044,9 +1081,9 @@
1044 1081 /* <![CDATA[ */
1045 1082 (function ($) {
1046 1083 $(window).load(function () {
1047 1084 /**
1048 - * @param iframe_id the id of the frame you whant to append the style
1085 + * @param iframe_id the id of the frame you want to append the style
1049 1086 * @param style_element the style element you want to append
1050 1087 */
1051 1088 var append_script_to_iframe = function (ifrm_id, scriptEl) {
1052 1089 var myIframe = document.getElementById(ifrm_id);
@@ -1059,8 +1096,11 @@
1059 1096 };
1060 1097
1061 1098 var append_style_to_iframe = function (ifrm_id, styleElment) {
1062 1099 var ifrm = window.frames[ifrm_id];
1100 + if ( typeof ifrm === "undefined" ) {
1101 + return;
1102 + }
1063 1103 ifrm = ( ifrm.contentDocument || ifrm.contentDocument || ifrm.document );
1064 1104 var head = ifrm.getElementsByTagName('head')[0];
1065 1105
1066 1106 if (typeof styleElment !== "undefined") {
@@ -1130,10 +1170,180 @@
1130 1170 pixcustomify::require_all( $path );
1131 1171 }
1132 1172
1133 1173 /**
1174 + * Maybe process certain "commands" from the config.
1175 + *
1176 + * Mainly things like removing sections, controls, etc.
1177 + *
1178 + * @since 1.9.0
1179 + *
1134 1180 * @param WP_Customize_Manager $wp_customize
1135 1181 */
1182 + public function maybe_process_config_extras( $wp_customize ) {
1183 + // Bail if we have no external theme config data.
1184 + if ( empty( $this->customizer_config ) || ! is_array( $this->customizer_config ) ) {
1185 + return;
1186 + }
1187 +
1188 + // Maybe remove panels
1189 + if ( ! empty( $this->customizer_config['remove_panels'] ) ) {
1190 + // Standardize it.
1191 + if ( is_string( $this->customizer_config['remove_panels'] ) ) {
1192 + $this->customizer_config['remove_panels'] = array( $this->customizer_config['remove_panels'] );
1193 + }
1194 +
1195 + foreach ( $this->customizer_config['remove_panels'] as $panel_id ) {
1196 + $wp_customize->remove_panel( $panel_id );
1197 + }
1198 + }
1199 +
1200 + // Maybe change panel props.
1201 + if ( ! empty( $this->customizer_config['change_panel_props'] ) ) {
1202 + foreach ( $this->customizer_config['change_panel_props'] as $panel_id => $panel_props ) {
1203 + if ( ! is_array( $panel_props ) ) {
1204 + continue;
1205 + }
1206 +
1207 + $panel = $wp_customize->get_panel( $panel_id );
1208 + if ( empty( $panel ) || ! $panel instanceof WP_Customize_Panel ) {
1209 + continue;
1210 + }
1211 +
1212 + $public_props = get_class_vars( get_class( $panel ) );
1213 + foreach ( $panel_props as $prop_name => $prop_value ) {
1214 +
1215 + if ( ! in_array( $prop_name, array_keys( $public_props ) ) ) {
1216 + continue;
1217 + }
1218 +
1219 + $panel->$prop_name = $prop_value;
1220 + }
1221 + }
1222 + }
1223 +
1224 + // Maybe remove sections
1225 + if ( ! empty( $this->customizer_config['remove_sections'] ) ) {
1226 + // Standardize it.
1227 + if ( is_string( $this->customizer_config['remove_sections'] ) ) {
1228 + $this->customizer_config['remove_sections'] = array( $this->customizer_config['remove_sections'] );
1229 + }
1230 +
1231 + foreach ( $this->customizer_config['remove_sections'] as $section_id ) {
1232 +
1233 + if ( 'widgets' === $section_id ) {
1234 + global $wp_registered_sidebars;
1235 +
1236 + foreach ( $wp_registered_sidebars as $widget => $settings ) {
1237 + $wp_customize->remove_section( 'sidebar-widgets-' . $widget );
1238 + }
1239 + continue;
1240 + }
1241 +
1242 + $wp_customize->remove_section( $section_id );
1243 + }
1244 + }
1245 +
1246 + // Maybe change section props.
1247 + if ( ! empty( $this->customizer_config['change_section_props'] ) ) {
1248 + foreach ( $this->customizer_config['change_section_props'] as $section_id => $section_props ) {
1249 + if ( ! is_array( $section_props ) ) {
1250 + continue;
1251 + }
1252 +
1253 + $section = $wp_customize->get_section( $section_id );
1254 + if ( empty( $section ) || ! $section instanceof WP_Customize_Section ) {
1255 + continue;
1256 + }
1257 +
1258 + $public_props = get_class_vars( get_class( $section ) );
1259 + foreach ( $section_props as $prop_name => $prop_value ) {
1260 +
1261 + if ( ! in_array( $prop_name, array_keys( $public_props ) ) ) {
1262 + continue;
1263 + }
1264 +
1265 + $section->$prop_name = $prop_value;
1266 + }
1267 + }
1268 + }
1269 +
1270 + // Maybe remove settings
1271 + if ( ! empty( $this->customizer_config['remove_settings'] ) ) {
1272 + // Standardize it.
1273 + if ( is_string( $this->customizer_config['remove_settings'] ) ) {
1274 + $this->customizer_config['remove_settings'] = array( $this->customizer_config['remove_settings'] );
1275 + }
1276 +
1277 + foreach ( $this->customizer_config['remove_settings'] as $setting_id ) {
1278 + $wp_customize->remove_setting( $setting_id );
1279 + }
1280 + }
1281 +
1282 + // Maybe change setting props.
1283 + if ( ! empty( $this->customizer_config['change_setting_props'] ) ) {
1284 + foreach ( $this->customizer_config['change_setting_props'] as $setting_id => $setting_props ) {
1285 + if ( ! is_array( $setting_props ) ) {
1286 + continue;
1287 + }
1288 +
1289 + $setting = $wp_customize->get_setting( $setting_id );
1290 + if ( empty( $setting ) || ! $setting instanceof WP_Customize_Setting ) {
1291 + continue;
1292 + }
1293 +
1294 + $public_props = get_class_vars( get_class( $setting ) );
1295 + foreach ( $setting_props as $prop_name => $prop_value ) {
1296 +
1297 + if ( ! in_array( $prop_name, array_keys( $public_props ) ) ) {
1298 + continue;
1299 + }
1300 +
1301 + $setting->$prop_name = $prop_value;
1302 + }
1303 + }
1304 + }
1305 +
1306 + // Maybe remove controls
1307 + if ( ! empty( $this->customizer_config['remove_controls'] ) ) {
1308 + // Standardize it.
1309 + if ( is_string( $this->customizer_config['remove_controls'] ) ) {
1310 + $this->customizer_config['remove_controls'] = array( $this->customizer_config['remove_controls'] );
1311 + }
1312 +
1313 + foreach ( $this->customizer_config['remove_controls'] as $control_id ) {
1314 + $wp_customize->remove_control( $control_id );
1315 + }
1316 + }
1317 +
1318 + // Maybe change control props.
1319 + if ( ! empty( $this->customizer_config['change_control_props'] ) ) {
1320 + foreach ( $this->customizer_config['change_control_props'] as $control_id => $control_props ) {
1321 + if ( ! is_array( $control_props ) ) {
1322 + continue;
1323 + }
1324 +
1325 + $control = $wp_customize->get_control( $control_id );
1326 + if ( empty( $control ) || ! $control instanceof WP_Customize_Control ) {
1327 + continue;
1328 + }
1329 +
1330 + $public_props = get_class_vars( get_class( $control ) );
1331 + foreach ( $control_props as $prop_name => $prop_value ) {
1332 +
1333 + if ( ! in_array( $prop_name, array_keys( $public_props ) ) ) {
1334 + continue;
1335 + }
1336 +
1337 + $control->$prop_name = $prop_value;
1338 + }
1339 + }
1340 + }
1341 + }
1342 +
1343 + /**
1344 + * @param WP_Customize_Manager $wp_customize
1345 + */
1136 1346 function register_customizer( $wp_customize ) {
1137 1347
1138 1348 $this->register_customizer_controls();
1139 1349
@@ -1141,9 +1351,9 @@
1141 1351
1142 1352 if ( ! empty ( $customizer_settings ) ) {
1143 1353
1144 1354 // first check the very needed options name
1145 - if ( ! isset ( $customizer_settings['opt-name'] ) || empty( $customizer_settings['opt-name'] ) ) {
1355 + if ( empty( $customizer_settings['opt-name'] ) ) {
1146 1356 return;
1147 1357 }
1148 1358 $options_name = $customizer_settings['opt-name'];
1149 1359 $wp_customize->options_key = $options_name;
@@ -1150,37 +1360,49 @@
1150 1360
1151 1361 // let's check if we have sections or panels
1152 1362 if ( isset( $customizer_settings['panels'] ) && ! empty( $customizer_settings['panels'] ) ) {
1153 1363
1154 - foreach ( $customizer_settings['panels'] as $panel_id => $panel_settings ) {
1364 + foreach ( $customizer_settings['panels'] as $panel_id => $panel_config ) {
1155 1365
1156 - if ( ! empty( $panel_id ) && isset( $panel_settings['sections'] ) && ! empty( $panel_settings['sections'] ) ) {
1366 + if ( ! empty( $panel_id ) && isset( $panel_config['sections'] ) && ! empty( $panel_config['sections'] ) ) {
1157 1367
1158 - $panel_id = $options_name . '[' . $panel_id . ']';
1368 + // If we have been explicitly given a panel ID we will use that
1369 + if ( ! empty( $panel_config['panel_id'] ) ) {
1370 + $panel_id = $panel_config['panel_id'];
1371 + } else {
1372 + $panel_id = $options_name . '[' . $panel_id . ']';
1373 + }
1374 +
1159 1375 $panel_args = array(
1160 - 'priority' => 10,
1161 - 'capability' => 'edit_theme_options',
1162 - 'title' => __( 'Panel title is required', 'pixcustomify' ),
1163 - 'description' => __( 'Description of what this panel does.', 'pixcustomify' ),
1376 + 'priority' => 10,
1377 + 'capability' => 'edit_theme_options',
1378 + 'title' => __( 'Panel title is required', 'customify' ),
1379 + 'description' => __( 'Description of what this panel does.', 'customify' ),
1380 + 'auto_expand_sole_section' => false,
1164 1381 );
1165 1382
1166 - if ( isset( $panel_settings['priority'] ) && ! empty( $panel_settings['priority'] ) ) {
1167 - $panel_args['priority'] = $panel_settings['priority'];
1383 + if ( isset( $panel_config['priority'] ) && ! empty( $panel_config['priority'] ) ) {
1384 + $panel_args['priority'] = $panel_config['priority'];
1168 1385 }
1169 1386
1170 - if ( isset( $panel_settings['title'] ) && ! empty( $panel_settings['title'] ) ) {
1171 - $panel_args['title'] = $panel_settings['title'];
1387 + if ( isset( $panel_config['title'] ) && ! empty( $panel_config['title'] ) ) {
1388 + $panel_args['title'] = $panel_config['title'];
1172 1389 }
1173 1390
1174 - if ( isset( $panel_settings['description'] ) && ! empty( $panel_settings['description'] ) ) {
1175 - $panel_args[10] = $panel_settings['description'];
1391 + if ( isset( $panel_config['description'] ) && ! empty( $panel_config['description'] ) ) {
1392 + $panel_args['description'] = $panel_config['description'];
1176 1393 }
1177 1394
1395 + if ( isset( $panel_config['auto_expand_sole_section'] ) ) {
1396 + $panel_args['auto_expand_sole_section'] = $panel_config['auto_expand_sole_section'];
1397 + }
1398 +
1399 +
1178 1400 $wp_customize->add_panel( $panel_id, $panel_args );
1179 1401
1180 - foreach ( $panel_settings['sections'] as $section_id => $section_settings ) {
1181 - if ( ! empty( $section_id ) && isset( $section_settings['options'] ) && ! empty( $section_settings['options'] ) ) {
1182 - $this->register_section( $panel_id, $section_id, $options_name, $section_settings, $wp_customize );
1402 + foreach ( $panel_config['sections'] as $section_id => $section_config ) {
1403 + if ( ! empty( $section_id ) && isset( $section_config['options'] ) && ! empty( $section_config['options'] ) ) {
1404 + $this->register_section( $panel_id, $section_id, $options_name, $section_config, $wp_customize );
1183 1405 }
1184 1406 }
1185 1407 }
1186 1408 }
@@ -1187,11 +1409,11 @@
1187 1409 }
1188 1410
1189 1411 if ( isset( $customizer_settings['sections'] ) && ! empty( $customizer_settings['sections'] ) ) {
1190 1412
1191 - foreach ( $customizer_settings['sections'] as $section_id => $section_settings ) {
1192 - if ( ! empty( $section_id ) && isset( $section_settings['options'] ) && ! empty( $section_settings['options'] ) ) {
1193 - $this->register_section( $panel_id = false, $section_id, $options_name, $section_settings, $wp_customize );
1413 + foreach ( $customizer_settings['sections'] as $section_id => $section_config ) {
1414 + if ( ! empty( $section_id ) && isset( $section_config['options'] ) && ! empty( $section_config['options'] ) ) {
1415 + $this->register_section( $panel_id = false, $section_id, $options_name, $section_config, $wp_customize );
1194 1416 }
1195 1417 }
1196 1418 }
1197 1419
@@ -1197,9 +1419,11 @@
1197 1419
1198 1420 if ( $this->plugin_settings['enable_reset_buttons'] ) {
1199 1421 // create a toolbar section which will be present all the time
1200 1422 $reset_section_settings = array(
1201 - 'title' => 'Customify toolbar',
1423 + 'title' => 'Customify Toolbox',
1424 + 'capability' => 'manage_options',
1425 + 'priority' => 999999999,
1202 1426 'options' => array(
1203 1427 'reset_all_button' => array(
1204 1428 'type' => 'button',
1205 1429 'label' => 'Reset Customify',
@@ -1210,12 +1434,9 @@
1210 1434 );
1211 1435
1212 1436 $wp_customize->add_section(
1213 1437 'customify_toolbar',
1214 - array(
1215 - 'title' => '',
1216 - 'priority' => 999999999
1217 - )
1438 + $reset_section_settings
1218 1439 );
1219 1440
1220 1441 $wp_customize->add_setting(
1221 1442 'reset_customify',
@@ -1224,9 +1445,9 @@
1224 1445 $wp_customize->add_control( new Pix_Customize_Button_Control(
1225 1446 $wp_customize,
1226 1447 'reset_customify',
1227 1448 array(
1228 - 'label' => __( 'Reset Customify to Defaults', 'customify' ),
1449 + 'label' => __( 'Reset All Customify Options to Default', 'customify' ),
1229 1450 'section' => 'customify_toolbar',
1230 1451 'settings' => 'reset_customify',
1231 1452 'action' => 'reset_customify',
1232 1453 )
@@ -1260,49 +1481,69 @@
1260 1481 /**
1261 1482 * @param string $panel_id
1262 1483 * @param string $section_key
1263 1484 * @param string $options_name
1264 - * @param array $section_settings
1485 + * @param array $section_config
1265 1486 * @param WP_Customize_Manager $wp_customize
1266 1487 */
1267 - protected function register_section( $panel_id, $section_key, $options_name, $section_settings, $wp_customize ) {
1488 + protected function register_section( $panel_id, $section_key, $options_name, $section_config, $wp_customize ) {
1268 1489
1269 1490 if ( isset( $this->plugin_settings['disable_customify_sections'] ) && isset( $this->plugin_settings['disable_customify_sections'][ $section_key ] ) ) {
1270 1491 return;
1271 1492 }
1272 1493
1273 - // Merge the section settings with the defaults
1274 - $section_args = wp_parse_args( $section_settings, array(
1275 - 'priority' => 10,
1276 - 'panel' => $panel_id,
1277 - 'capability' => 'edit_theme_options',
1278 - 'theme_supports' => '',
1279 - 'title' => __( 'Title Section is required', 'customify' ),
1280 - 'description' => '',
1281 - 'type' => 'default',
1282 - 'description_hidden' => false,
1283 - ) );
1284 - $section_id = $options_name . '[' . $section_key . ']';
1494 + // If we have been explicitly given a section ID we will use that
1495 + if ( ! empty( $section_config['section_id'] ) ) {
1496 + $section_id = $section_config['section_id'];
1497 + } else {
1498 + $section_id = $options_name . '[' . $section_key . ']';
1499 + }
1285 1500
1286 - // Add the new section to the Customizer
1287 - $wp_customize->add_section( $section_id, $section_args );
1501 + // Add the new section to the Customizer, but only if it is not already added.
1502 + if ( ! $wp_customize->get_section( $section_id ) ) {
1503 + // Merge the section settings with the defaults
1504 + $section_args = wp_parse_args( $section_config, array(
1505 + 'priority' => 10,
1506 + 'panel' => $panel_id,
1507 + 'capability' => 'edit_theme_options',
1508 + 'theme_supports' => '',
1509 + 'title' => esc_html__( 'Title Section is required', 'customify' ),
1510 + 'description' => '',
1511 + 'type' => 'default',
1512 + 'description_hidden' => false,
1513 + ) );
1288 1514
1515 + $wp_customize->add_section( $section_id, $section_args );
1516 + }
1517 +
1289 1518 // Now go through each section option and add the fields
1290 - foreach ( $section_settings['options'] as $option_id => $option_config ) {
1519 + foreach ( $section_config['options'] as $option_id => $option_config ) {
1291 1520
1292 1521 if ( empty( $option_id ) || ! isset( $option_config['type'] ) ) {
1293 1522 continue;
1294 1523 }
1295 1524
1296 - $option_id = $options_name . '[' . $option_id . ']';
1525 + // If we have been explicitly given a setting ID we will use that
1526 + if ( ! empty( $option_config['setting_id'] ) ) {
1527 + $setting_id = $option_config['setting_id'];
1528 + } else {
1529 + $setting_id = $options_name . '[' . $option_id . ']';
1530 + }
1297 1531
1298 - $this->register_field( $section_id, $option_id, $option_config, $wp_customize );
1532 + // Add the option config to the localized array so we can pass the info to JS.
1533 + // @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.
1534 + $this->localized['settings'][ $setting_id ] = $option_config;
1535 +
1536 + // Generate a safe option ID (not the final setting ID) to us in HTML attributes like ID or class
1537 + $this->localized['settings'][ $setting_id ]['html_safe_option_id'] = sanitize_html_class( $option_id );
1538 +
1539 + $this->register_field( $section_id, $setting_id, $option_config, $wp_customize );
1299 1540 }
1300 1541
1301 1542 }
1302 1543
1303 1544 /**
1304 - * Register a Customizer field
1545 + * Register a Customizer field (setting and control).
1305 1546 *
1306 1547 * @see WP_Customize_Setting
1307 1548 * @see WP_Customize_Control
1308 1549 *
@@ -1307,12 +1548,12 @@
1307 1548 * @see WP_Customize_Control
1308 1549 *
1309 1550 * @param string $section_id
1310 1551 * @param string $setting_id
1311 - * @param array $setting_config
1552 + * @param array $field_config
1312 1553 * @param WP_Customize_Manager $wp_customize
1313 1554 */
1314 - protected function register_field( $section_id, $setting_id, $setting_config, $wp_customize ) {
1555 + protected function register_field( $section_id, $setting_id, $field_config, $wp_customize ) {
1315 1556
1316 1557 $add_control = true;
1317 1558 // defaults
1318 1559 $setting_args = array(
@@ -1320,34 +1561,38 @@
1320 1561 'capability' => 'edit_theme_options',
1321 1562 'transport' => 'refresh',
1322 1563 );
1323 1564 $control_args = array(
1565 + 'priority' => 10,
1324 1566 'label' => '',
1325 1567 'section' => $section_id,
1326 1568 'settings' => $setting_id,
1327 1569 );
1328 1570
1329 - $this->localized['settings'][ $setting_id ] = $setting_config;
1330 -
1331 1571 // sanitize settings
1332 - if ( ( isset( $setting_config['live'] ) && $setting_config['live'] ) || $setting_config['type'] === 'font' ) {
1572 + if ( ! empty( $field_config['live'] ) || $field_config['type'] === 'font' ) {
1333 1573 $setting_args['transport'] = 'postMessage';
1334 1574 }
1335 1575
1336 - if ( isset( $setting_config['default'] ) ) {
1337 - $setting_args['default'] = $setting_config['default'];
1576 + if ( isset( $field_config['default'] ) ) {
1577 + $setting_args['default'] = $field_config['default'];
1338 1578 }
1339 1579
1340 - if ( isset( $setting_config['capability'] ) && ! empty( $setting_config['capability'] ) ) {
1341 - $setting_args['capability'] = $setting_config['capability'];
1580 + if ( ! empty( $field_config['capability'] ) ) {
1581 + $setting_args['capability'] = $field_config['capability'];
1342 1582 }
1343 1583
1344 - if ( $this->plugin_settings['values_store_mod'] == 'option' ) {
1584 + // If the setting defines it's own type we will respect that, otherwise we will follow the global plugin setting.
1585 + if ( ! empty( $field_config['setting_type'] ) ) {
1586 + if ( 'option' === $field_config['setting_type'] ) {
1587 + $setting_args['type'] = 'option';
1588 + }
1589 + } elseif ( $this->plugin_settings['values_store_mod'] === 'option' ) {
1345 1590 $setting_args['type'] = 'option';
1346 1591 }
1347 1592
1348 1593 // if we arrive here this means we have a custom field control
1349 - switch ( $setting_config['type'] ) {
1594 + switch ( $field_config['type'] ) {
1350 1595
1351 1596 case 'checkbox':
1352 1597
1353 1598 $setting_args['sanitize_callback'] = array( $this, 'setting_sanitize_checkbox' );
@@ -1356,41 +1601,41 @@
1356 1601 default:
1357 1602 break;
1358 1603 }
1359 1604
1360 - if ( isset( $setting_config['sanitize_callback'] ) && ! empty( $setting_config['sanitize_callback'] ) && function_exists( $setting_config['sanitize_callback'] ) ) {
1361 - $setting_args['sanitize_callback'] = $setting_config['sanitize_callback'];
1605 + if ( ! empty( $field_config['sanitize_callback'] ) && is_callable( $field_config['sanitize_callback'] ) ) {
1606 + $setting_args['sanitize_callback'] = $field_config['sanitize_callback'];
1362 1607 }
1363 1608
1364 - // and add it
1609 + // Add the setting
1365 1610 $wp_customize->add_setting( $setting_id, $setting_args );
1366 1611
1367 1612 // now sanitize the control
1368 - if ( isset( $setting_config['label'] ) && ! empty( $setting_config['label'] ) ) {
1369 - $control_args['label'] = $setting_config['label'];
1613 + if ( ! empty( $field_config['label'] ) ) {
1614 + $control_args['label'] = $field_config['label'];
1370 1615 }
1371 1616
1372 - if ( isset( $setting_config['priority'] ) && ! empty( $setting_config['priority'] ) ) {
1373 - $control_args['priority'] = $setting_config['priority'];
1617 + if ( ! empty( $field_config['priority'] ) ) {
1618 + $control_args['priority'] = $field_config['priority'];
1374 1619 }
1375 1620
1376 - if ( isset( $setting_config['desc'] ) && ! empty( $setting_config['desc'] ) ) {
1377 - $control_args['description'] = $setting_config['desc'];
1621 + if ( ! empty( $field_config['desc'] ) ) {
1622 + $control_args['description'] = $field_config['desc'];
1378 1623 }
1379 1624
1380 - if ( isset( $setting_config['active_callback'] ) && ! empty( $setting_config['active_callback'] ) ) {
1381 - $control_args['active_callback'] = $setting_config['active_callback'];
1625 + if ( ! empty( $field_config['active_callback'] ) ) {
1626 + $control_args['active_callback'] = $field_config['active_callback'];
1382 1627 }
1383 1628
1384 1629
1385 - $control_args['type'] = $setting_config['type'];
1630 + $control_args['type'] = $field_config['type'];
1386 1631
1387 1632 // select the control type
1388 1633 // but first init a default
1389 1634 $control_class_name = 'Pix_Customize_Text_Control';
1390 1635
1391 - // if is a standard wp field type call it here and skip the rest
1392 - if ( in_array( $setting_config['type'], array(
1636 + // If is a standard wp field type call it here and skip the rest.
1637 + if ( in_array( $field_config['type'], array(
1393 1638 'checkbox',
1394 1639 'dropdown-pages',
1395 1640 'url',
1396 1641 'date',
@@ -1401,30 +1646,30 @@
1401 1646 ) ) ) {
1402 1647 $wp_customize->add_control( $setting_id . '_control', $control_args );
1403 1648
1404 1649 return;
1405 - } elseif ( in_array( $setting_config['type'], array(
1650 + } elseif ( in_array( $field_config['type'], array(
1406 1651 'radio',
1407 1652 'select'
1408 - ) ) && isset( $setting_config['choices'] ) && ! empty( $setting_config['choices'] )
1653 + ) ) && ! empty( $field_config['choices'] )
1409 1654 ) {
1410 - $control_args['choices'] = $setting_config['choices'];
1655 + $control_args['choices'] = $field_config['choices'];
1411 1656 $wp_customize->add_control( $setting_id . '_control', $control_args );
1412 1657
1413 1658 return;
1414 - } elseif ( in_array( $setting_config['type'], array( 'range' ) ) && isset( $setting_config['input_attrs'] ) && ! empty( $setting_config['input_attrs'] ) ) {
1659 + } elseif ( in_array( $field_config['type'], array( 'range' ) ) && ! empty( $field_config['input_attrs'] ) ) {
1415 1660
1416 - $control_args['input_attrs'] = $setting_config['input_attrs'];
1661 + $control_args['input_attrs'] = $field_config['input_attrs'];
1417 1662
1418 1663 $wp_customize->add_control( $setting_id . '_control', $control_args );
1419 1664 }
1420 1665
1421 - // if we arrive here this means we have a custom field control
1422 - switch ( $setting_config['type'] ) {
1666 + // If we arrive here this means we have a custom field control.
1667 + switch ( $field_config['type'] ) {
1423 1668
1424 1669 case 'text':
1425 - if ( isset( $setting_config['live'] ) ) {
1426 - $control_args['live'] = $setting_config['live'];
1670 + if ( isset( $field_config['live'] ) ) {
1671 + $control_args['live'] = $field_config['live'];
1427 1672 }
1428 1673
1429 1674 $control_class_name = 'Pix_Customize_Text_Control';
1430 1675 break;
@@ -1429,10 +1674,10 @@
1429 1674 $control_class_name = 'Pix_Customize_Text_Control';
1430 1675 break;
1431 1676
1432 1677 case 'textarea':
1433 - if ( isset( $setting_config['live'] ) ) {
1434 - $control_args['live'] = $setting_config['live'];
1678 + if ( isset( $field_config['live'] ) ) {
1679 + $control_args['live'] = $field_config['live'];
1435 1680 }
1436 1681
1437 1682 $control_class_name = 'Pix_Customize_Textarea_Control';
1438 1683 break;
@@ -1445,14 +1690,14 @@
1445 1690 $control_class_name = 'Pix_Customize_Color_Drop_Control';
1446 1691 break;
1447 1692
1448 1693 case 'ace_editor':
1449 - if ( isset( $setting_config['live'] ) ) {
1450 - $control_args['live'] = $setting_config['live'];
1694 + if ( isset( $field_config['live'] ) ) {
1695 + $control_args['live'] = $field_config['live'];
1451 1696 }
1452 1697
1453 - if ( isset( $setting_config['editor_type'] ) ) {
1454 - $control_args['editor_type'] = $setting_config['editor_type'];
1698 + if ( isset( $field_config['editor_type'] ) ) {
1699 + $control_args['editor_type'] = $field_config['editor_type'];
1455 1700 }
1456 1701
1457 1702 $control_class_name = 'Pix_Customize_Ace_Editor_Control';
1458 1703 break;
@@ -1469,32 +1714,37 @@
1469 1714 $control_class_name = 'WP_Customize_Media_Control';
1470 1715 break;
1471 1716
1472 1717 case 'custom_background':
1473 - if ( isset( $setting_config['field'] ) ) {
1474 - $control_args['field'] = $setting_config['field'];
1718 + if ( isset( $field_config['field'] ) ) {
1719 + $control_args['field'] = $field_config['field'];
1475 1720 }
1476 1721
1477 1722 $control_class_name = 'Pix_Customize_Background_Control';
1478 1723 break;
1479 1724
1480 - case 'cropped_media':
1481 - if ( isset( $setting_config['width'] ) ) {
1482 - $control_args['width'] = $setting_config['width'];
1725 + case 'cropped_image':
1726 + case 'cropped_media': // 'cropped_media' no longer works
1727 + if ( isset( $field_config['width'] ) ) {
1728 + $control_args['width'] = $field_config['width'];
1483 1729 }
1484 1730
1485 - if ( isset( $setting_config['height'] ) ) {
1486 - $control_args['height'] = $setting_config['height'];
1731 + if ( isset( $field_config['height'] ) ) {
1732 + $control_args['height'] = $field_config['height'];
1487 1733 }
1488 1734
1489 - if ( isset( $setting_config['flex_width'] ) ) {
1490 - $control_args['flex_width'] = $setting_config['flex_width'];
1735 + if ( isset( $field_config['flex_width'] ) ) {
1736 + $control_args['flex_width'] = $field_config['flex_width'];
1491 1737 }
1492 1738
1493 - if ( isset( $setting_config['flex_height'] ) ) {
1494 - $control_args['flex_height'] = $setting_config['flex_height'];
1739 + if ( isset( $field_config['flex_height'] ) ) {
1740 + $control_args['flex_height'] = $field_config['flex_height'];
1495 1741 }
1496 1742
1743 + if ( isset( $field_config['button_labels'] ) ) {
1744 + $control_args['button_labels'] = $field_config['button_labels'];
1745 + }
1746 +
1497 1747 $control_class_name = 'WP_Customize_Cropped_Image_Control';
1498 1748 break;
1499 1749
1500 1750 // Custom types
@@ -1507,35 +1757,34 @@
1507 1757 }
1508 1758
1509 1759 $control_class_name = 'Pix_Customize_Typography_Control';
1510 1760
1511 - if ( isset( $setting_config['backup'] ) ) {
1512 - $control_args['backup'] = $setting_config['backup'];
1761 + if ( isset( $field_config['backup'] ) ) {
1762 + $control_args['backup'] = $field_config['backup'];
1513 1763 }
1514 1764
1515 - if ( isset( $setting_config['font_weight'] ) ) {
1516 - $control_args['font_weight'] = $setting_config['font_weight'];
1765 + if ( isset( $field_config['font_weight'] ) ) {
1766 + $control_args['font_weight'] = $field_config['font_weight'];
1517 1767 }
1518 1768
1519 - if ( isset( $setting_config['subsets'] ) ) {
1520 - $control_args['subsets'] = $setting_config['subsets'];
1769 + if ( isset( $field_config['subsets'] ) ) {
1770 + $control_args['subsets'] = $field_config['subsets'];
1521 1771 }
1522 1772
1523 - if ( isset( $setting_config['recommended'] ) ) {
1524 - $control_args['recommended'] = array_flip( $setting_config['recommended'] );
1773 + if ( isset( $field_config['recommended'] ) ) {
1774 + $control_args['recommended'] = array_flip( $field_config['recommended'] );
1525 1775 }
1526 1776
1527 - if ( isset( $setting_config['load_all_weights'] ) ) {
1528 - $control_args['load_all_weights'] = $setting_config['load_all_weights'];
1777 + if ( isset( $field_config['load_all_weights'] ) ) {
1778 + $control_args['load_all_weights'] = $field_config['load_all_weights'];
1529 1779 }
1530 1780
1531 - if ( isset( $setting_config['default'] ) ) {
1532 - $control_args['default'] = $setting_config['default'];
1781 + if ( isset( $field_config['default'] ) ) {
1782 + $control_args['default'] = $field_config['default'];
1533 1783 }
1534 1784
1535 1785 break;
1536 1786
1537 - // Custom types
1538 1787 case 'font' :
1539 1788 $use_typography = $this->get_plugin_setting( 'typography', '1' );
1540 1789
1541 1790 if ( $use_typography === false ) {
@@ -1544,34 +1793,34 @@
1544 1793 }
1545 1794
1546 1795 $control_class_name = 'Pix_Customize_Font_Control';
1547 1796
1548 - if ( isset( $setting_config['backup'] ) ) {
1549 - $control_args['backup'] = $setting_config['backup'];
1797 + if ( isset( $field_config['backup'] ) ) {
1798 + $control_args['backup'] = $field_config['backup'];
1550 1799 }
1551 1800
1552 - if ( isset( $setting_config['font_weight'] ) ) {
1553 - $control_args['font_weight'] = $setting_config['font_weight'];
1801 + if ( isset( $field_config['font_weight'] ) ) {
1802 + $control_args['font_weight'] = $field_config['font_weight'];
1554 1803 }
1555 1804
1556 - if ( isset( $setting_config['subsets'] ) ) {
1557 - $control_args['subsets'] = $setting_config['subsets'];
1805 + if ( isset( $field_config['subsets'] ) ) {
1806 + $control_args['subsets'] = $field_config['subsets'];
1558 1807 }
1559 1808
1560 - if ( isset( $setting_config['recommended'] ) ) {
1561 - $control_args['recommended'] = array_flip( $setting_config['recommended'] );
1809 + if ( isset( $field_config['recommended'] ) ) {
1810 + $control_args['recommended'] = array_flip( $field_config['recommended'] );
1562 1811 }
1563 1812
1564 - if ( isset( $setting_config['load_all_weights'] ) ) {
1565 - $control_args['load_all_weights'] = $setting_config['load_all_weights'];
1813 + if ( isset( $field_config['load_all_weights'] ) ) {
1814 + $control_args['load_all_weights'] = $field_config['load_all_weights'];
1566 1815 }
1567 1816
1568 - if ( isset( $setting_config['default'] ) ) {
1569 - $control_args['default'] = $setting_config['default'];
1817 + if ( isset( $field_config['default'] ) ) {
1818 + $control_args['default'] = $field_config['default'];
1570 1819 }
1571 1820
1572 - if ( isset( $setting_config['fields'] ) ) {
1573 - $control_args['fields'] = $setting_config['fields'];
1821 + if ( isset( $field_config['fields'] ) ) {
1822 + $control_args['fields'] = $field_config['fields'];
1574 1823 }
1575 1824 $control_args['live'] = true;
1576 1825
1577 1826 break;
@@ -1576,30 +1825,60 @@
1576 1825
1577 1826 break;
1578 1827
1579 1828 case 'select2' :
1580 - if ( ! isset( $setting_config['choices'] ) || empty( $setting_config['choices'] ) ) {
1829 + if ( ! isset( $field_config['choices'] ) || empty( $field_config['choices'] ) ) {
1581 1830 return;
1582 1831 }
1583 1832
1584 - $control_args['choices'] = $setting_config['choices'];
1833 + $control_args['choices'] = $field_config['choices'];
1585 1834
1586 1835 $control_class_name = 'Pix_Customize_Select2_Control';
1587 1836 break;
1837 +
1838 + case 'sm_radio' :
1839 + if ( ! isset( $field_config['choices'] ) || empty( $field_config['choices'] ) ) {
1840 + return;
1841 + }
1588 1842
1843 + $control_args['choices'] = $field_config['choices'];
1844 +
1845 + $control_class_name = 'Pix_Customize_SM_radio_Control';
1846 + break;
1847 +
1848 + case 'sm_palette_filter' :
1849 + if ( ! isset( $field_config['choices'] ) || empty( $field_config['choices'] ) ) {
1850 + return;
1851 + }
1852 +
1853 + $control_args['choices'] = $field_config['choices'];
1854 +
1855 + $control_class_name = 'Pix_Customize_SM_palette_filter_Control';
1856 + break;
1857 +
1858 + case 'sm_switch' :
1859 + if ( ! isset( $field_config['choices'] ) || empty( $field_config['choices'] ) ) {
1860 + return;
1861 + }
1862 +
1863 + $control_args['choices'] = $field_config['choices'];
1864 +
1865 + $control_class_name = 'Pix_Customize_SM_switch_Control';
1866 + break;
1867 +
1589 1868 case 'preset' :
1590 - if ( ! isset( $setting_config['choices'] ) || empty( $setting_config['choices'] ) ) {
1869 + if ( ! isset( $field_config['choices'] ) || empty( $field_config['choices'] ) ) {
1591 1870 return;
1592 1871 }
1593 1872
1594 - $control_args['choices'] = $setting_config['choices'];
1873 + $control_args['choices'] = $field_config['choices'];
1595 1874
1596 - if ( isset( $setting_config['choices_type'] ) || ! empty( $setting_config['choices_type'] ) ) {
1597 - $control_args['choices_type'] = $setting_config['choices_type'];
1875 + if ( isset( $field_config['choices_type'] ) || ! empty( $field_config['choices_type'] ) ) {
1876 + $control_args['choices_type'] = $field_config['choices_type'];
1598 1877 }
1599 1878
1600 - if ( isset( $setting_config['desc'] ) || ! empty( $setting_config['desc'] ) ) {
1601 - $control_args['description'] = $setting_config['desc'];
1879 + if ( isset( $field_config['desc'] ) || ! empty( $field_config['desc'] ) ) {
1880 + $control_args['description'] = $field_config['desc'];
1602 1881 }
1603 1882
1604 1883
1605 1884 $control_class_name = 'Pix_Customize_Preset_Control';
@@ -1605,20 +1884,20 @@
1605 1884 $control_class_name = 'Pix_Customize_Preset_Control';
1606 1885 break;
1607 1886
1608 1887 case 'radio_image' :
1609 - if ( ! isset( $setting_config['choices'] ) || empty( $setting_config['choices'] ) ) {
1888 + if ( ! isset( $field_config['choices'] ) || empty( $field_config['choices'] ) ) {
1610 1889 return;
1611 1890 }
1612 1891
1613 - $control_args['choices'] = $setting_config['choices'];
1892 + $control_args['choices'] = $field_config['choices'];
1614 1893
1615 - if ( isset( $setting_config['choices_type'] ) || ! empty( $setting_config['choices_type'] ) ) {
1616 - $control_args['choices_type'] = $setting_config['choices_type'];
1894 + if ( isset( $field_config['choices_type'] ) || ! empty( $field_config['choices_type'] ) ) {
1895 + $control_args['choices_type'] = $field_config['choices_type'];
1617 1896 }
1618 1897
1619 - if ( isset( $setting_config['desc'] ) || ! empty( $setting_config['desc'] ) ) {
1620 - $control_args['description'] = $setting_config['desc'];
1898 + if ( isset( $field_config['desc'] ) || ! empty( $field_config['desc'] ) ) {
1899 + $control_args['description'] = $field_config['desc'];
1621 1900 }
1622 1901
1623 1902
1624 1903 $control_class_name = 'Pix_Customize_Radio_Image_Control';
@@ -1624,13 +1903,13 @@
1624 1903 $control_class_name = 'Pix_Customize_Radio_Image_Control';
1625 1904 break;
1626 1905
1627 1906 case 'button' :
1628 - if ( ! isset( $setting_config['action'] ) || empty( $setting_config['action'] ) ) {
1907 + if ( ! isset( $field_config['action'] ) || empty( $field_config['action'] ) ) {
1629 1908 return;
1630 1909 }
1631 1910
1632 - $control_args['action'] = $setting_config['action'];
1911 + $control_args['action'] = $field_config['action'];
1633 1912
1634 1913 $control_class_name = 'Pix_Customize_Button_Control';
1635 1914
1636 1915 break;
@@ -1635,10 +1914,10 @@
1635 1914
1636 1915 break;
1637 1916
1638 1917 case 'html' :
1639 - if ( isset( $setting_config['html'] ) || ! empty( $setting_config['html'] ) ) {
1640 - $control_args['html'] = $setting_config['html'];
1918 + if ( isset( $field_config['html'] ) || ! empty( $field_config['html'] ) ) {
1919 + $control_args['html'] = $field_config['html'];
1641 1920 }
1642 1921
1643 1922 $control_class_name = 'Pix_Customize_HTML_Control';
1644 1923 break;
@@ -1643,20 +1922,20 @@
1643 1922 $control_class_name = 'Pix_Customize_HTML_Control';
1644 1923 break;
1645 1924
1646 1925 case 'import_demo_data' :
1647 - if ( isset( $setting_config['html'] ) || ! empty( $setting_config['html'] ) ) {
1648 - $control_args['html'] = $setting_config['html'];
1926 + if ( isset( $field_config['html'] ) || ! empty( $field_config['html'] ) ) {
1927 + $control_args['html'] = $field_config['html'];
1649 1928 }
1650 1929
1651 - if ( ! isset( $setting_config['label'] ) || empty( $setting_config['label'] ) ) {
1930 + if ( ! isset( $field_config['label'] ) || empty( $field_config['label'] ) ) {
1652 1931 $control_args['label'] = esc_html__( 'Import', 'customify' );
1653 1932 } else {
1654 - $control_args['label'] = $setting_config['label'];
1933 + $control_args['label'] = $field_config['label'];
1655 1934 }
1656 1935
1657 - if ( isset( $setting_config['notices'] ) && ! empty( $setting_config['notices'] ) ) {
1658 - $control_args['notices'] = $setting_config['notices'];
1936 + if ( isset( $field_config['notices'] ) && ! empty( $field_config['notices'] ) ) {
1937 + $control_args['notices'] = $field_config['notices'];
1659 1938 }
1660 1939
1661 1940 $control_class_name = 'Pix_Customize_Import_Demo_Data_Control';
1662 1941 break;
@@ -1702,8 +1981,99 @@
1702 1981 }
1703 1982 }
1704 1983 }
1705 1984
1985 + /**
1986 + * Print JavaScript for adding additional data to _wpCustomizeSettings.settings object of the main window (not the preview window).
1987 + */
1988 + public function customize_pane_settings_additional_data() {
1989 + /**
1990 + * @global WP_Customize_Manager $wp_customize
1991 + */
1992 + global $wp_customize;
1993 +
1994 + // Without an options name we can't do much.
1995 + if ( empty( $this->customizer_config['opt-name'] ) ) {
1996 + return;
1997 + }
1998 +
1999 + $options_name = $this->customizer_config['opt-name'];
2000 + $customizer_settings = $wp_customize->settings();
2001 + ?>
2002 + <script type="text/javascript">
2003 + if ( 'undefined' === typeof _wpCustomizeSettings.settings ) {
2004 + _wpCustomizeSettings.settings = {};
2005 + }
2006 +
2007 + <?php
2008 + echo "(function ( sAdditional ){\n";
2009 +
2010 + $options = $this->get_options();
2011 + foreach ( $options as $option_id => $option_config ) {
2012 + // If we have been explicitly given a setting ID we will use that
2013 + if ( ! empty( $option_config['setting_id'] ) ) {
2014 + $setting_id = $option_config['setting_id'];
2015 + } else {
2016 + $setting_id = $options_name . '[' . $option_id . ']';
2017 + }
2018 + // @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()
2019 + if ( ! empty( $customizer_settings[ $setting_id ] ) && ! empty( $option_config['connected_fields'] ) ) {
2020 + // Pass through all the connected fields and make sure the id is in the final format
2021 + $connected_fields = array();
2022 + foreach ( $option_config['connected_fields'] as $key => $connected_field_config ) {
2023 + $connected_field_data = array();
2024 +
2025 + if ( is_string( $connected_field_config ) ) {
2026 + $connected_field_id = $connected_field_config;
2027 + } elseif ( is_array( $connected_field_config ) ) {
2028 + // We have a full blown connected field config
2029 + if ( is_string( $key ) ) {
2030 + $connected_field_id = $key;
2031 + } else {
2032 + continue;
2033 + }
2034 +
2035 + // We will pass to JS all the configured connected field details.
2036 + $connected_field_data = $connected_field_config;
2037 + }
2038 +
2039 + // Continue if we don't have a connected field ID to work with.
2040 + if ( empty( $connected_field_id ) ) {
2041 + continue;
2042 + }
2043 +
2044 + // If the connected setting is not one of our's, we will use it's ID as it is.
2045 + if ( ! array_key_exists( $connected_field_id, $options ) ) {
2046 + $connected_field_data['setting_id'] = $connected_field_id;
2047 + }
2048 + // If the connected setting specifies a setting ID, we will not prefix it and use it as it is.
2049 + elseif ( ! empty( $options[ $connected_field_id ] ) && ! empty( $options[ $connected_field_id ]['setting_id'] ) ) {
2050 + $connected_field_data['setting_id'] = $options[ $connected_field_id ]['setting_id'];
2051 + } else {
2052 + $connected_field_data['setting_id'] = $options_name . '[' . $connected_field_id . ']';
2053 + }
2054 +
2055 + $connected_fields[] = $connected_field_data;
2056 + }
2057 +
2058 + printf(
2059 + "sAdditional[%s].%s = %s;\n",
2060 + wp_json_encode( $setting_id ),
2061 + 'connected_fields',
2062 + wp_json_encode( $connected_fields, JSON_FORCE_OBJECT )
2063 + );
2064 + }
2065 + }
2066 + echo "})( _wpCustomizeSettings.settings );\n";
2067 + ?>
2068 + </script>
2069 + <?php
2070 + }
2071 +
2072 + public function get_file() {
2073 + return $this->file;
2074 + }
2075 +
1706 2076 public function get_base_path() {
1707 2077 return plugin_dir_path( $this->file );
1708 2078 }
1709 2079
@@ -1818,40 +2188,50 @@
1818 2188
1819 2189 return $settings;
1820 2190 }
1821 2191
1822 - protected function get_value( $option, $alt_opt_name ) {
2192 + protected function get_value( $option_id, $alt_opt_name ) {
1823 2193 global $wp_customize;
1824 2194
1825 - $opt_name = $this->opt_name;
2195 + $options_name = $this->opt_name;
1826 2196 $values = $this->current_values;
1827 2197
1828 - // In case someone asked for a DB value too early but it has given us the opt_name under which to search, let's do it
1829 - if ( empty( $opt_name ) && ! empty( $alt_opt_name ) ) {
1830 - $opt_name = $alt_opt_name;
1831 - $values = $this->get_current_values( $opt_name );
2198 + // In case someone asked for a DB value too early but it has given us the options_name under which to search, let's do it
2199 + if ( empty( $options_name ) && ! empty( $alt_opt_name ) ) {
2200 + $options_name = $alt_opt_name;
2201 + $values = $this->get_current_values( $options_name );
1832 2202 }
1833 2203
1834 2204 if ( ! empty( $wp_customize ) && method_exists( $wp_customize, 'get_setting' ) ) {
2205 + // Get the field config.
2206 + $option_config = $this->get_option_customizer_config( $option_id );
1835 2207
1836 - $option_key = $opt_name . '[' . $option . ']';
1837 - $setting = $wp_customize->get_setting( $option_key );
2208 + if ( empty( $option_id ) || ! isset( $option_config['type'] ) ) {
2209 + return null;
2210 + }
2211 +
2212 + // If we have been explicitly given a setting ID we will use that
2213 + if ( ! empty( $option_config['setting_id'] ) ) {
2214 + $setting_id = $option_config['setting_id'];
2215 + } else {
2216 + $setting_id = $options_name . '[' . $option_id . ']';
2217 + }
2218 +
2219 + $setting = $wp_customize->get_setting( $setting_id );
1838 2220 if ( ! empty( $setting ) ) {
1839 - $value = $setting->value();
1840 -
1841 - return $value;
2221 + return $setting->value();
1842 2222 }
1843 2223 }
1844 2224
1845 2225 // shim
1846 - if ( strpos( $option, $opt_name . '[' ) !== false ) {
2226 + if ( strpos( $option_id, $options_name . '[' ) !== false ) {
1847 2227 // get only the setting id
1848 - $option = explode( '[', $option );
1849 - $option = rtrim( $option[1], ']' );
2228 + $option_id = explode( '[', $option_id );
2229 + $option_id = rtrim( $option_id[1], ']' );
1850 2230 }
1851 2231
1852 - if ( isset( $values[ $option ] ) ) {
1853 - return $values[ $option ];
2232 + if ( isset( $values[ $option_id ] ) ) {
2233 + return $values[ $option_id ];
1854 2234 }
1855 2235
1856 2236 return null;
1857 2237 }
@@ -1856,28 +2236,53 @@
1856 2236 return null;
1857 2237 }
1858 2238
1859 2239 /**
1860 - * A public function to retreat an option's value
1861 - * If there is a value and return it
1862 - * Otherwise try to get the default parameter or the default from config
2240 + * A public function to get an option's value.
2241 + * If there is a value and return it.
2242 + * Otherwise try to get the default parameter or the default from config.
1863 2243 *
1864 - * @param $option
2244 + * @param $option_id
1865 2245 * @param mixed $default Optional.
1866 2246 * @param string $alt_opt_name Optional. We can use this to bypass the fact that the DB values are loaded on after_setup_theme, if we know what to look for.
1867 2247 *
1868 2248 * @return bool|null|string
1869 2249 */
1870 - public function get_option( $option, $default = null, $alt_opt_name = null ) {
2250 + public function get_option( $option_id, $default = null, $alt_opt_name = null ) {
2251 + // If the development constant CUSTOMIFY_DEV_FORCE_DEFAULTS has been defined we will not retrieve anything from the database
2252 + // Always go with the default
2253 + if ( defined( 'CUSTOMIFY_DEV_FORCE_DEFAULTS' ) && true === CUSTOMIFY_DEV_FORCE_DEFAULTS && ! $this->skip_dev_mode_force_defaults( $option_id ) ) {
2254 + $return = null;
2255 + } else {
2256 + // Get the field config.
2257 + $option_config = $this->get_option_customizer_config( $option_id );
1871 2258
1872 - $return = $this->get_value( $option, $alt_opt_name );
2259 + if ( empty( $option_id ) ) {
2260 + $return = null;
2261 + } elseif ( isset( $option_config['setting_type'] ) && $option_config['setting_type'] === 'option' ) {
2262 + // We have a setting that is saved in the wp_options table, not in theme_mods.
2263 + // We will fetch it directly.
1873 2264
2265 + // If we have been explicitly given a setting ID we will use that
2266 + if ( ! empty( $option_config['setting_id'] ) ) {
2267 + $setting_id = $option_config['setting_id'];
2268 + } else {
2269 + $setting_id = $this->opt_name . '[' . $option_id . ']';
2270 + }
2271 +
2272 + $return = get_option( $setting_id, null );
2273 + } else {
2274 + // Get the value stores in theme_mods.
2275 + $return = $this->get_value( $option_id, $alt_opt_name );
2276 + }
2277 + }
2278 +
1874 2279 if ( $return !== null ) {
1875 2280 return $return;
1876 2281 } elseif ( $default !== null ) {
1877 2282 return $default;
1878 - } elseif ( isset( $this->options_list[ $option ] ) && isset( $this->options_list[ $option ]['default'] ) ) {
1879 - return $this->options_list[ $option ]['default'];
2283 + } elseif ( isset( $this->options_list[ $option_id ] ) && isset( $this->options_list[ $option_id ]['default'] ) ) {
2284 + return $this->options_list[ $option_id ]['default'];
1880 2285 }
1881 2286
1882 2287 return null;
1883 2288 }
@@ -1890,8 +2295,52 @@
1890 2295
1891 2296 return false;
1892 2297 }
1893 2298
2299 + public function get_customizer_config() {
2300 + return $this->customizer_config;
2301 + }
2302 +
2303 + /**
2304 + * Get the Customify configuration of a certain option.
2305 + *
2306 + * @param string $option_id
2307 + *
2308 + * @return array|false The option config or false on failure.
2309 + */
2310 + public function get_option_customizer_config( $option_id ) {
2311 + // We need to search for the option configured under the given id (the array key)
2312 + if ( isset ( $this->customizer_config['panels'] ) ) {
2313 + foreach ( $this->customizer_config['panels'] as $panel_id => $panel_settings ) {
2314 + if ( isset( $panel_settings['sections'] ) ) {
2315 + foreach ( $panel_settings['sections'] as $section_id => $section_settings ) {
2316 + if ( isset( $section_settings['options'] ) ) {
2317 + foreach ( $section_settings['options'] as $id => $option_config ) {
2318 + if ( $id === $option_id ) {
2319 + return $option_config;
2320 + }
2321 + }
2322 + }
2323 + }
2324 + }
2325 + }
2326 + }
2327 +
2328 + if ( isset ( $this->customizer_config['sections'] ) ) {
2329 + foreach ( $this->customizer_config['sections'] as $section_id => $section_settings ) {
2330 + if ( isset( $section_settings['options'] ) ) {
2331 + foreach ( $section_settings['options'] as $id => $option_config ) {
2332 + if ( $id === $option_id ) {
2333 + return $option_config;
2334 + }
2335 + }
2336 + }
2337 + }
2338 + }
2339 +
2340 + return false;
2341 + }
2342 +
1894 2343 protected function get_config() {
1895 2344 if ( file_exists( $this->get_base_path() . 'plugin-config.php' ) ) {
1896 2345 return include( $this->get_base_path() . 'plugin-config.php' );
1897 2346 }
@@ -1975,9 +2424,9 @@
1975 2424 $controller = new Customify_Importer_Controller();
1976 2425 $controller->init();
1977 2426 }
1978 2427
1979 - function get_options_configs() {
2428 + public function get_options_configs() {
1980 2429 return $this->options_list;
1981 2430 }
1982 2431
1983 2432 /**
@@ -2008,9 +2457,9 @@
2008 2457 *
2009 2458 * @return string
2010 2459 */
2011 2460 public static function decodeURIComponent( $str ) {
2012 - //if we get an array we just let it be
2461 + // If we get an array we just let it be
2013 2462 if ( is_string( $str ) ) {
2014 2463 $revert = array( '!' => '%21', '*' => '%2A', "'" => '%27', '(' => '%28', ')' => '%29' );
2015 2464 $str = rawurldecode( strtr( $str, $revert ) );
2016 2465 }
@@ -2032,8 +2481,90 @@
2032 2481 return true;
2033 2482 }
2034 2483
2035 2484 /**
2485 + * Prevent saving of plugin options in the Customizer
2486 + *
2487 + * @param array $data The data to save
2488 + * @param array $filter_context
2489 + *
2490 + * @return array
2491 + */
2492 + public function prevent_changeset_save_in_devmode( $data, $filter_context ) {
2493 + // Get the options key
2494 + $options_key = $this->customizer_config['opt-name'];
2495 + if ( ! empty( $options_key ) ) {
2496 + // Remove any Customify data thus preventing it from saving
2497 + foreach ( $data as $option_id => $value ) {
2498 + if ( false !== strpos( $option_id, $options_key ) && ! $this->skip_dev_mode_force_defaults( $option_id ) ) {
2499 + unset( $data[ $option_id ] );
2500 + }
2501 + }
2502 + }
2503 +
2504 + return $data;
2505 + }
2506 +
2507 + /**
2508 + * Determine if we should NOT enforce the CUSTOMIFY_DEV_FORCE_DEFAULTS behavior on a certain option.
2509 + *
2510 + * @param string $option_id
2511 + *
2512 + * @return bool
2513 + */
2514 + private function skip_dev_mode_force_defaults( $option_id ) {
2515 + // Preprocess the $option_id.
2516 + if ( false !== strpos( $option_id, '::' ) ) {
2517 + $option_id = substr( $option_id, strpos( $option_id, '::' ) + 2 );
2518 + }
2519 + if ( false !== strpos( $option_id, '[' ) ) {
2520 + $option_id = explode( '[', $option_id );
2521 + $option_id = rtrim( $option_id[1], ']' );
2522 + }
2523 +
2524 + $option_config = $this->get_option_customizer_config( $option_id );
2525 + if ( empty( $option_config ) ) {
2526 + return false;
2527 + }
2528 +
2529 + // We will skip certain field types that generally don't have a default value.
2530 + if ( ! empty( $option_config['type'] ) ) {
2531 + switch ( $option_config['type'] ) {
2532 + case 'cropped_image':
2533 + case 'cropped_media':
2534 + case 'image':
2535 + case 'media':
2536 + case 'custom_background':
2537 + case 'upload':
2538 + return true;
2539 + break;
2540 + default:
2541 + break;
2542 + }
2543 + }
2544 +
2545 + return false;
2546 + }
2547 +
2548 + public function prevent_changeset_save_in_devmode_notification() { ?>
2549 + <script type="application/javascript">
2550 + (function ( $, exports, wp ) {
2551 + 'use strict';
2552 + // when the customizer is ready add our notification
2553 + wp.customize.bind('ready', function () {
2554 + wp.customize.notifications.add( 'customify_force_defaults', new wp.customize.Notification(
2555 + 'customify_force_defaults',
2556 + {
2557 + type: 'warning',
2558 + message: '<strong style="margin-bottom: ">Customify: Development Mode</strong><p>All the options are switched to default. While they are changing in the live preview, they will not be kept when publish.</p>'
2559 + }
2560 + ) );
2561 + });
2562 + })(jQuery, window, wp);
2563 + </script>
2564 + <?php }
2565 +
2566 + /**
2036 2567 * Return an instance of this class.
2037 2568 * @since 1.0.0
2038 2569 * @return PixCustomifyPlugin A single instance of this class.
2039 2570 */
@@ -2048,9 +2579,9 @@
2048 2579 * @param string $file File.
2049 2580 * @param string $version Version.
2050 2581 *
2051 2582 * @see PixCustomifyPlugin()
2052 - * @return object Main PixCustomifyPlugin instance
2583 + * @return PixCustomifyPlugin Main PixCustomifyPlugin instance
2053 2584 */
2054 2585 public static function instance( $file = '', $version = '1.0.0' ) {
2055 2586 // If the single instance hasn't been set, set it now.
2056 2587 if ( is_null( self::$_instance ) ) {