PluginProbe
Customify / 2.3.3
Customify v2.3.3
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 +1187 -527 1.5.62.3.3 View file →
@@ -4,9 +4,9 @@
4 4 * @package PixCustomify
5 5 * @author Pixelgrade <[email protected]>
6 6 * @license GPL-2.0+
7 7 * @link https://pixelgrade.com
8 - * @copyright 2014-2017 Pixelgrade
8 + * @copyright 2014-2018 Pixelgrade
9 9 */
10 10
11 11 /**
12 12 * Plugin class.
@@ -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,24 @@
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 + /**
130 + * Gutenberg class object.
131 + * @var Customify_Gutenberg
132 + * @access public
133 + * @since 2.2.0
134 + */
135 + public $gutenberg = null;
136 +
137 + /**
129 138 * Minimal Required PHP Version
130 139 * @var string
131 140 * @access private
132 141 * @since 1.5.0
@@ -138,11 +147,8 @@
138 147 $this->file = $file;
139 148 //the current plugin version
140 149 $this->_version = $version;
141 150
142 - // Remember our base path
143 - $this->plugin_basepath = plugin_dir_path( $file );
144 -
145 151 if ( $this->php_version_check() ) {
146 152 // Only load and run the init function if we know PHP version can parse it.
147 153 $this->init();
148 154 }
@@ -151,13 +157,30 @@
151 157 /**
152 158 * Initialize plugin
153 159 */
154 160 private function init() {
161 + // We don't want to put extra load on the heartbeat AJAX request.
162 + if ( wp_doing_ajax() && isset( $_REQUEST['action'] ) && 'heartbeat' === $_REQUEST['action'] ) {
163 + return;
164 + }
165 +
155 166 // Load the config file
156 167 $this->config = $this->get_config();
157 168 // Load the plugin's settings from the DB
158 169 $this->plugin_settings = get_option( $this->config['settings-key'] );
159 170
171 + /* Initialize the Style Manager logic. */
172 + require_once( $this->get_base_path() . 'includes/class-customify-style-manager.php' );
173 + if ( is_null( $this->style_manager ) ) {
174 + $this->style_manager = Customify_Style_Manager::instance();
175 + }
176 +
177 + /* Initialize the Gutenberg logic. */
178 + require_once( $this->get_base_path() . 'includes/class-customify-gutenberg.php' );
179 + if ( is_null( $this->gutenberg ) ) {
180 + $this->gutenberg = Customify_Gutenberg::instance();
181 + }
182 +
160 183 // Register all the needed hooks
161 184 $this->register_hooks();
162 185 }
163 186
@@ -162,22 +185,20 @@
162 185 }
163 186
164 187 /**
165 188 * Register our actions and filters
166 - *
167 - * @return null
168 189 */
169 190 function register_hooks() {
191 +
170 192 /*
171 - * Register hooks that are fired when the plugin is activated, deactivated, and uninstalled, respectively.
193 + * Load plugin text domain
172 194 */
173 - register_activation_hook( $this->file, array( $this, 'activate' ) );
174 - register_deactivation_hook( $this->file, array( $this, 'deactivate' ) );
195 + add_action( 'init', array( $this, 'load_plugin_textdomain' ) );
175 196
176 197 /*
177 - * Load plugin text domain
198 + * Load the upgrade logic.
178 199 */
179 - add_action( 'init', array( $this, 'load_plugin_textdomain' ) );
200 + add_action( 'admin_init', array( $this, 'upgrade' ) );
180 201
181 202 /*
182 203 * Prepare and load the configuration
183 204 */
@@ -187,8 +208,13 @@
187 208 // We need the init hook and not after_setup_theme because there a number of plugins that fire up on init (like certain modules from Jetpack)
188 209 // We need to be able to load things like components configs depending on those firing up or not
189 210 // DO NOT TRY to use the Customify values before this!
190 211 add_action( 'init', array( $this, 'load_plugin_configs' ), 15 );
212 + // Also handle the force clearing of the cached config. Since we can't know wo can influence it, we need to be proactive.
213 + add_action( 'activated_plugin', array( $this, 'clear_customizer_config_cache' ), 10 );
214 + add_action( 'deactivated_plugin', array( $this, 'clear_customizer_config_cache' ), 10 );
215 + add_action( 'switch_theme', array( $this, 'clear_customizer_config_cache' ), 10 );
216 + add_action( 'upgrader_process_complete', array( $this, 'clear_customizer_config_cache' ), 10 );
191 217
192 218 /*
193 219 * Now setup the admin side of things
194 220 */
@@ -209,46 +235,74 @@
209 235 // Styles for the Customizer
210 236 add_action( 'customize_controls_init', array( $this, 'register_admin_customizer_styles' ), 10 );
211 237 add_action( 'customize_controls_enqueue_scripts', array( $this, 'enqueue_admin_customizer_styles' ), 10 );
212 238 // 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 );
239 + add_action( 'customize_controls_init', array( $this, 'register_admin_customizer_scripts' ), 15 );
240 + add_action( 'customize_controls_enqueue_scripts', array( $this, 'enqueue_admin_customizer_scripts' ), 15 );
215 241
216 242 // Scripts enqueued only in the theme preview
217 243 add_action( 'customize_preview_init', array( $this, 'customizer_live_preview_register_scripts' ), 10 );
218 244 add_action( 'customize_preview_init', array( $this, 'customizer_live_preview_enqueue_scripts' ), 99999 );
219 245
246 + // Add extra settings data to _wpCustomizeSettings.settings of the parent window.
247 + add_action( 'customize_controls_print_footer_scripts', array( $this, 'customize_pane_settings_additional_data' ), 10000 );
248 +
220 249 // The frontend effects of the Customizer controls
221 250 $load_location = $this->get_plugin_setting( 'style_resources_location', 'wp_head' );
222 251
223 252 add_action( $load_location, array( $this, 'output_dynamic_style' ), 99 );
253 + add_action( 'wp_head', array( $this, 'output_typography_dynamic_script' ), 10 );
224 254 add_action( 'wp_head', array( $this, 'output_typography_dynamic_style' ), 10 );
225 255
226 256 add_action( 'customize_register', array( $this, 'remove_default_sections' ), 11 );
227 257 add_action( 'customize_register', array( $this, 'register_customizer' ), 12 );
258 + // Maybe the theme has instructed us to do things like removing sections or controls.
259 + add_action( 'customize_register', array( $this, 'maybe_process_config_extras' ), 13 );
228 260
229 261 if ( $this->get_plugin_setting( 'enable_editor_style', true ) ) {
230 - add_action( 'admin_head', array( $this, 'add_customizer_settings_into_wp_editor' ) );
262 + add_action( 'admin_enqueue_scripts', array( $this, 'script_to_add_customizer_settings_into_wp_editor' ), 10, 1 );
231 263 }
232 264
265 + add_action( 'rest_api_init', array( $this, 'add_rest_routes_api' ) );
266 +
233 267 /*
234 - * Jetpack Related
268 + * Development related
235 269 */
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 );
270 + if ( defined( 'CUSTOMIFY_DEV_FORCE_DEFAULTS' ) && true === CUSTOMIFY_DEV_FORCE_DEFAULTS ) {
271 + // If the development constant CUSTOMIFY_DEV_FORCE_DEFAULTS has been defined we will not save anything in the database
272 + // Always go with the default
273 + add_filter( 'customize_changeset_save_data', array( $this, 'prevent_changeset_save_in_devmode' ), 50, 2 );
274 + // Add a JS to display a notification
275 + add_action( 'customize_controls_print_footer_scripts', array( $this, 'prevent_changeset_save_in_devmode_notification' ), 100 );
276 + }
277 + }
240 278
241 - add_action( 'rest_api_init', array( $this, 'add_rest_routes_api' ) );
279 + /**
280 + * Handle the logic to upgrade between versions. It will run only one per version change.
281 + */
282 + public function upgrade() {
283 + $customify_dbversion = get_option( 'customify_dbversion', '0.0.1' );
284 + if ( $this->get_version() === $customify_dbversion ) {
285 + return;
286 + }
287 +
288 + // For versions, previous of version 2.0.0 (the Color Palettes v2.0 release).
289 + if ( version_compare( $customify_dbversion, '2.0.0', '<' ) ) {
290 + // Delete the option holding the fact that the user offered feedback.
291 + delete_option( 'style_manager_user_feedback_provided' );
292 + }
293 +
294 + // Put the current version in the database.
295 + update_option( 'customify_dbversion', $this->get_version(), true );
242 296 }
243 297
244 298 /**
245 - * Initialize Configs, Options and Values methods
299 + * Initialize Configs, Options and Values methods.
246 300 */
247 301 function init_plugin_configs() {
248 302 $this->customizer_config = get_option( 'pixcustomify_config' );
249 303
250 - // no option so go for default
304 + // no option so go for default.
251 305 if ( empty( $this->customizer_config ) ) {
252 306 $this->customizer_config = $this->get_config_option( 'default_options' );
253 307 }
254 308
@@ -257,18 +311,18 @@
257 311 }
258 312 }
259 313
260 314 /**
261 - * Load the plugin configuration and options
315 + * Load the plugin configuration and options.
262 316 */
263 317 function load_plugin_configs() {
264 318
265 - // allow themes or other plugins to filter the config
266 - $this->customizer_config = apply_filters( 'customify_filter_fields', $this->customizer_config );
319 + $this->load_customizer_config();
320 +
267 321 $this->opt_name = $this->localized['options_name'] = $this->customizer_config['opt-name'];
268 322 $this->options_list = $this->get_options();
269 323
270 - // Load the current options values
324 + // Load the current options values.
271 325 $this->current_values = $this->get_current_values();
272 326
273 327 if ( $this->import_button_exists() ) {
274 328 $this->localized['import_rest_url'] = get_rest_url( '/customify/1.0/' );
@@ -277,90 +331,83 @@
277 331 $this->register_import_api();
278 332 }
279 333
280 334 $this->localized['theme_fonts'] = $this->theme_fonts = Customify_Font_Selector::instance()->get_theme_fonts();
281 - }
282 335
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() );
336 + $this->localized['ajax_url'] = admin_url( 'admin-ajax.php' );
337 + $this->localized['style_manager_user_feedback_nonce'] = wp_create_nonce( 'customify_style_manager_user_feedback' );
338 + $this->localized['style_manager_user_feedback_provided'] = get_option( 'style_manager_user_feedback_provided', false );
286 339 }
287 340
288 341 /**
289 - * Control the default modules that are activated in Jetpack.
290 - * Use the `customify_filter_jetpack_default_modules` to set your's.
342 + * Set the customizer configuration.
291 343 *
292 - * @param array $default The default value to return if the option does not exist
293 - * in the database.
344 + * @since 2.2.1
294 345 *
295 - * @return array
346 + * @param bool $skip_cache Optional. Whether to use the cached config or generate a new one.
296 347 */
297 - function default_jetpack_active_modules( $default ) {
298 - if ( ! is_array( $default ) ) {
299 - $default = array();
348 + protected function load_customizer_config( $skip_cache = false ) {
349 + // First try and get the cached data
350 + $data = get_option( $this->_get_customizer_config_cache_key() );
351 +
352 + // We don't force skip the cache for AJAX requests for performance reasons.
353 + if ( ! wp_doing_ajax() && defined('CUSTOMIFY_ALWAYS_GENERATE_CUSTOMIZER_CONFIG' ) && true === CUSTOMIFY_ALWAYS_GENERATE_CUSTOMIZER_CONFIG ) {
354 + $skip_cache = true;
300 355 }
301 - $jetpack_default_modules = array();
302 356
303 - $theme_default_modules = get_theme_mod( 'pixelgrade_jetpack_default_active_modules', array() );
357 + // For performance reasons, we will ONLY regenerate when in the WP ADMIN area or via an ADMIN AJAX call.
358 + if ( false !== $data && false === $skip_cache && ! is_admin() && ! is_customize_preview() ) {
359 + $this->customizer_config = $data;
360 + return;
361 + }
304 362
305 - if ( ! is_array( $theme_default_modules ) ) {
306 - return array_merge( $default, $jetpack_default_modules );
307 - }
363 + // Get the cache data expiration timestamp.
364 + $expire_timestamp = get_option( $this->_get_customizer_config_cache_key() . '_timestamp' );
308 365
309 - foreach ( $theme_default_modules as $module ) {
310 - array_push( $jetpack_default_modules, $module );
366 + // The data isn't set, is expired or we were instructed to skip the cache; we need to regenerate the config.
367 + if ( true === $skip_cache || false === $data || false === $expire_timestamp || $expire_timestamp < time() ) {
368 + // Allow themes or other plugins to filter the config.
369 + // We use $this->customizer_config so we can start from whatever default configuration it may be.
370 + $data = apply_filters( 'customify_filter_fields', $this->customizer_config );
371 + // We apply a second filter for those that wish to work with the final config and not rely on a a huge priority number.
372 + $data = apply_filters( 'customify_final_config', $data );
373 +
374 + // Cache the data in an option for 6 hours
375 + update_option( $this->_get_customizer_config_cache_key() , $data, true );
376 + update_option( $this->_get_customizer_config_cache_key() . '_timestamp' , time() + 6 * HOUR_IN_SECONDS, true );
311 377 }
312 378
313 - return array_merge( $default, $jetpack_default_modules );
379 + $this->customizer_config = $data;
380 + return;
314 381 }
315 382
316 383 /**
317 - * Control the default Jetpack Sharing options.
318 - * Use the `customify_filter_jetpack_sharing_default_options` to set your's.
384 + * Clear the customizer config cache.
319 385 *
320 - * @param array $default The default value to return if the option does not exist
321 - * in the database.
322 - *
323 - * @return array
386 + * @since 2.2.1
324 387 */
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 );
388 + public function clear_customizer_config_cache() {
389 + delete_option( $this->_get_customizer_config_cache_key() );
390 + delete_option( $this->_get_customizer_config_cache_key() . '_timestamp' );
331 391 }
332 392
333 393 /**
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.
394 + * Get the customizer config cache key.
336 395 *
337 - * @param array $modules
396 + * @since 2.2.1
338 397 *
339 - * @return array
398 + * @return string
340 399 */
341 - function jetpack_hide_blocked_modules( $modules ) {
342 - return array_diff_key( $modules, array_flip( $this->jetpack_blocked_modules ) );
400 + private function _get_customizer_config_cache_key() {
401 + return 'customify_customizer_config';
343 402 }
344 403
345 - /**
346 - * Fired when the plugin is activated.
347 - * @since 1.0.0
348 - *
349 - * @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.
350 - */
351 - public static function activate( $network_wide ) {
352 - //@todo Define activation functionality here
404 + public function get_version() {
405 + return $this->_version;
353 406 }
354 407
355 - /**
356 - * Fired when the plugin is deactivated.
357 - * @since 1.0.0
358 - *
359 - * @param boolean $network_wide True if WPMU superadmin uses "Network Deactivate" action, false if WPMU is disabled or plugin is deactivated on an individual blog.
360 - */
361 - static function deactivate( $network_wide ) {
362 - //@todo Define deactivation functionality here
408 + public function get_slug() {
409 + return $this->plugin_slug;
363 410 }
364 411
365 412 /**
366 413 * Load the plugin text domain for translation.
@@ -394,13 +441,20 @@
394 441 function register_admin_customizer_scripts() {
395 442
396 443 wp_register_script( 'customify_select2', plugins_url( 'js/select2/js/select2.js', $this->file ), array( 'jquery' ), $this->_version );
397 444 wp_register_script( 'jquery-react', plugins_url( 'js/jquery-react.js', $this->file ), array( 'jquery' ), $this->_version );
445 +
446 + wp_register_script( 'customify-scale', plugins_url( 'js/customizer/scale-iframe.js', $this->file ), array( 'jquery' ), $this->_version );
447 + wp_register_script( 'customify-fontselectfields', plugins_url( 'js/customizer/font-select-fields.js', $this->file ), array( 'jquery' ), $this->_version );
448 +
398 449 wp_register_script( $this->plugin_slug . '-customizer-scripts', plugins_url( 'js/customizer.js', $this->file ), array(
399 450 'jquery',
400 451 'customify_select2',
401 452 'underscore',
402 - 'customize-controls'
453 + 'customize-controls',
454 + 'customify-fontselectfields',
455 +
456 + 'customify-scale',
403 457 ), $this->_version );
404 458 }
405 459
406 460 /**
@@ -409,15 +463,15 @@
409 463 function enqueue_admin_customizer_scripts() {
410 464 wp_enqueue_script( 'jquery-react' );
411 465 wp_enqueue_script( $this->plugin_slug . '-customizer-scripts' );
412 466
413 - wp_localize_script( $this->plugin_slug . '-customizer-scripts', 'customify_settings', $this->localized );
467 + wp_localize_script( $this->plugin_slug . '-customizer-scripts', 'customify_settings', apply_filters( 'customify_localized_js_settings', $this->localized ) );
414 468 }
415 469
416 470 /** Register Customizer scripts loaded only on previewer page */
417 471 function customizer_live_preview_register_scripts() {
418 472 wp_register_script( $this->plugin_slug . 'CSSOM', plugins_url( 'js/CSSOM.js', $this->file ), array( 'jquery' ), $this->_version, true );
419 - wp_register_script( $this->plugin_slug . 'cssUpdate', plugins_url( 'js/jquery.cssUpdate.js', $this->file ), array(), $this->_version, true );
473 + wp_register_script( $this->plugin_slug . 'cssUpdate', plugins_url( 'js/jquery.cssUpdate.js', $this->file ), array( 'jquery' ), $this->_version, true );
420 474 wp_register_script( $this->plugin_slug . '-previewer-scripts', plugins_url( 'js/customizer_preview.js', $this->file ), array(
421 475 'jquery',
422 476 'customize-preview',
423 477 $this->plugin_slug . 'CSSOM',
@@ -482,9 +536,9 @@
482 536 ) );
483 537 }
484 538
485 539 function add_rest_routes_api(){
486 - register_rest_route( 'customfiy/v1', '/delete_theme_mod', array(
540 + register_rest_route( 'customify/v1', '/delete_theme_mod', array(
487 541 'methods' => 'POST',
488 542 'callback' => array( $this, 'delete_theme_mod' ),
489 543 'permission_callback' => array( $this, 'permission_nonce_callback' ),
490 544 ) );
@@ -490,11 +544,10 @@
490 544 ) );
491 545 }
492 546
493 547 function delete_theme_mod(){
494 - $user = wp_get_current_user();
495 - if ( ! $user->caps['administrator'] ) {
496 - wp_send_json_error('no admin');
548 + if ( ! current_user_can( 'manage_options' ) ) {
549 + wp_send_json_error('You don\'t have admin privileges.');
497 550 }
498 551
499 552 $config = apply_filters('customify_filter_fields', array() );
500 553
@@ -505,9 +558,9 @@
505 558 $key = $config['opt-name'];
506 559
507 560 remove_theme_mod( $key );
508 561
509 - wp_send_json_success('Bye bye ' . $key . '!');
562 + wp_send_json_success('Deleted ' . $key . ' theme mod!');
510 563 }
511 564
512 565 function permission_nonce_callback() {
513 566 return wp_verify_nonce( $this->get_nonce(), 'customify_settings_nonce' );
@@ -525,53 +578,16 @@
525 578 return $nonce;
526 579 }
527 580
528 581 /**
529 - * Public style generated by customizer
582 + * Output CSS style generated by customizer
530 583 */
531 - function output_dynamic_style() {
532 - $custom_css = "\n";
584 + function output_dynamic_style() { ?>
585 +<style id="customify_output_style">
586 +<?php echo $this->get_dynamic_style(); ?>
587 +</style>
588 +<?php
533 589
534 - foreach ( $this->options_list as $option_id => $option ) {
535 -
536 - if ( isset( $option['css'] ) && ! empty( $option['css'] ) ) {
537 - // now process each
538 - $custom_css .= $this->convert_setting_to_css( $option_id, $option['css'] );
539 - }
540 -
541 - if ( $option['type'] === 'custom_background' ) {
542 - $option['value'] = $this->get_option( $option_id );
543 - $custom_css .= $this->process_custom_background_field_output( $option_id, $option );
544 - }
545 - }
546 -
547 - if ( ! empty( $this->media_queries ) ) {
548 -
549 - foreach ( $this->media_queries as $media_query => $properties ) {
550 -
551 - if ( empty( $properties ) ) {
552 - continue;
553 - }
554 -
555 - $custom_css .= '@media ' . $media_query . " { ";
556 -
557 - foreach ( $properties as $key => $property ) {
558 - $property_settings = $property['property'];
559 - $property_value = $property['value'];
560 - $custom_css .= $this->proccess_css_property( $property_settings, $property_value );
561 - }
562 -
563 - $custom_css .= " }\n";
564 -
565 - }
566 - }
567 -
568 - $custom_css .= "\n";
569 - ?>
570 - <style id="customify_output_style">
571 - <?php echo apply_filters( 'customify_dynamic_style', $custom_css ); ?>
572 - </style><?php
573 -
574 590 /**
575 591 * from now on we output only style tags only for the preview purpose
576 592 * so don't cry if you see 30+ style tags for each section
577 593 */
@@ -580,15 +596,15 @@
580 596 }
581 597
582 598 foreach ( $this->options_list as $option_id => $options ) {
583 599
584 - if ( $options['type'] === 'custom_background' ) {
600 + if ( isset( $options['type'] ) && $options['type'] === 'custom_background' ) {
585 601 $options['value'] = $this->get_option( $option_id );
586 602 $custom_background_output = $this->process_custom_background_field_output( $option_id, $options ); ?>
587 603
588 - <style id="custom_background_output_for_<?php echo $option_id; ?>">
604 + <style id="custom_background_output_for_<?php echo sanitize_html_class( $option_id ); ?>">
589 605 <?php
590 - if ( isset( $custom_background_output ) && ! empty( $custom_background_output )) {
606 + if ( ! empty( $custom_background_output )) {
591 607 echo $custom_background_output;
592 608 } ?>
593 609 </style>
594 610 <?php }
@@ -597,27 +613,54 @@
597 613 continue;
598 614 }
599 615
600 616 $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
617 + if ( ! empty( $options['css'] ) ) {
618 + foreach ( $options['css'] as $key => $properties_set ) {
619 + // We need to use a class because we may have multiple <style>s with the same "ID" for example
620 + // when targeting the same property but with different selectors.
621 + $unique_class = 'dynamic_setting_' . $option_id . '_property_' . str_replace( '-', '_', $properties_set['property'] ) . '_' . $key;
604 622
623 + $inline_style = '<style class="' . sanitize_html_class( $unique_class ) . '" type="text/css">';
624 +
605 625 if ( isset( $properties_set['media'] ) && ! empty( $properties_set['media'] ) ) {
606 - echo '@media '. $properties_set['media'] . " {\n";
626 + $inline_style .= '@media '. $properties_set['media'] . ' {';
607 627 }
608 628
609 629 if ( isset( $properties_set['selector'] ) && isset( $properties_set['property'] ) ) {
610 - echo $this->proccess_css_property($properties_set, $this_value);
630 + $css_output = $this->process_css_property($properties_set, $this_value);
631 + if ( ! empty( $css_output ) ) {
632 + $inline_style .= $css_output;
633 + }
611 634 }
612 635
613 636 if ( isset( $properties_set['media'] ) && ! empty( $properties_set['media'] ) ) {
614 - echo "}\n";
615 - } ?>
616 - </style>
617 - <?php }
637 + $inline_style .= '}';
638 + }
639 + $inline_style .= '</style>';
640 +
641 + echo $inline_style;
642 + }
643 + }
618 644 }
645 + }
619 646
647 + function get_dynamic_style() {
648 + $custom_css = '';
649 +
650 + foreach ( $this->options_list as $option_id => $option ) {
651 +
652 + if ( isset( $option['css'] ) && ! empty( $option['css'] ) ) {
653 + // now process each
654 + $custom_css .= $this->convert_setting_to_css( $option_id, $option['css'] );
655 + }
656 +
657 + if ( isset( $option['type'] ) && $option['type'] === 'custom_background' ) {
658 + $option['value'] = $this->get_option( $option_id );
659 + $custom_css .= $this->process_custom_background_field_output( $option_id, $option ) . PHP_EOL;
660 + }
661 + }
662 +
620 663 if ( ! empty( $this->media_queries ) ) {
621 664
622 665 foreach ( $this->media_queries as $media_query => $properties ) {
623 666
@@ -624,32 +667,31 @@
624 667 if ( empty( $properties ) ) {
625 668 continue;
626 669 }
627 670
628 - $display = false;
629 - $media_q = '@media ' . $media_query . " {\n";
671 + $media_query_custom_css = '';
630 672
631 673 foreach ( $properties as $key => $property ) {
632 -
633 - if ( ! isset( $options['live'] ) || $options['live'] !== true ) {
634 - continue;
674 + $property_settings = $property['property'];
675 + $property_value = $property['value'];
676 + $css_output = $this->process_css_property( $property_settings, $property_value );
677 + if ( ! empty( $css_output ) ) {
678 + $media_query_custom_css .= "\t" . $css_output . PHP_EOL;
635 679 }
680 + }
636 681
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 - </style>
643 - <?php }
682 + if ( ! empty( $media_query_custom_css ) ) {
683 + $media_query_custom_css = PHP_EOL . '@media ' . $media_query . " { " . PHP_EOL . PHP_EOL . $media_query_custom_css . "}" . PHP_EOL;
684 + }
644 685
645 - $media_q .= "\n}\n";
686 + if ( ! empty( $media_query_custom_css ) ) {
687 + $custom_css .= $media_query_custom_css;
688 + }
646 689
647 - if ( $display ) {
648 - $custom_css .= $media_q;
649 - }
650 690 }
651 691 }
692 +
693 + return apply_filters( 'customify_dynamic_style', $custom_css );
652 694 }
653 695
654 696 protected function load_google_fonts() {
655 697 $fonts_path = plugin_dir_path( $this->file ) . 'features/customizer/controls/resources/google.fonts.php';
@@ -665,14 +707,154 @@
665 707 return false;
666 708 }
667 709
668 710 function output_typography_dynamic_style() {
711 + $style = $this->get_typography_dynamic_style();
712 +
713 + if ( ! empty( $style ) ) { ?>
714 + <style id="customify_typography_output_style">
715 + <?php echo $style; ?>
716 + </style>
717 + <?php }
718 + }
719 +
720 + function get_typography_dynamic_style() {
721 + $output = '';
722 +
669 723 $this->get_typography_fields( $this->options_list, 'type', 'typography', $this->typo_settings );
670 724
671 725 if ( empty( $this->typo_settings ) ) {
672 - return;
726 + return $output;
673 727 }
674 728
729 + ob_start();
730 + foreach ( $this->typo_settings as $font ) {
731 + $selector = apply_filters( 'customify_typography_css_selector', $font['selector'], $font );
732 +
733 + $load_all_weights = false;
734 + if ( isset( $font['load_all_weights'] ) && $font['load_all_weights'] == 'true' ) {
735 + $load_all_weights = true;
736 + }
737 +
738 + if ( isset( $selector ) && isset( $font['value'] ) && ! empty( $font['value'] ) ) {
739 + // Make sure that the value is in the proper format
740 + $value = PixCustomifyPlugin::decodeURIComponent( $font['value'] );
741 + if ( is_string( $value ) ) {
742 + $value = json_decode( $value, true );
743 + }
744 +
745 + // In case the value is null (most probably because the json_decode failed),
746 + // try the default value (mostly for google fonts)
747 + if ( $value === null ) {
748 + $value = $this->get_font_defaults_value( $font['value'] );
749 + }
750 +
751 + // Shim the old case when the default was only the font name
752 + if ( ! empty( $value ) && is_string( $value ) ) {
753 + $value = array( 'font_family' => $value );
754 + }
755 +
756 + // Handle special logic for when the $value array is not an associative array
757 + if ( ! $this->is_assoc( $value ) ) {
758 + $value = $this->standardize_non_associative_font_default( $value );
759 + }
760 +
761 + // Bail if empty or we don't have an array
762 + if ( empty( $value ) || ! is_array( $value ) ) {
763 + continue;
764 + }
765 +
766 + $selected_variant = '';
767 + if ( ! empty( $value['selected_variants'] ) ) {
768 + if ( is_array( $value['selected_variants'] ) ) {
769 + $selected_variant = $value['selected_variants'][0];
770 + } else {
771 + $selected_variant = $value['selected_variants'];
772 + }
773 + }
774 +
775 + // First handle the case where we have the font-family in the selected variant (usually this means a custom font from our Fonto plugin)
776 + if ( ! empty( $selected_variant ) && is_array( $selected_variant ) && ! empty( $selected_variant['font-family'] ) ) {
777 + // The variant's font-family
778 + echo $selector . " {\nfont-family: " . $selected_variant['font-family'] . ";\n";
779 +
780 + if ( ! $load_all_weights ) {
781 + // If this is a custom font (like from our plugin Fonto) with individual styles & weights - i.e. the font-family says it all
782 + // we need to "force" the font-weight and font-style
783 + if ( ! empty( $value['type'] ) && 'custom_individual' == $value['type'] ) {
784 + $selected_variant['font-weight'] = '400 !important';
785 + $selected_variant['font-style'] = 'normal !important';
786 + }
787 +
788 + // Output the font weight, if available
789 + if ( ! empty( $selected_variant['font-weight'] ) ) {
790 + echo "font-weight: " . $selected_variant['font-weight'] . ";\n";
791 + }
792 +
793 + // Output the font style, if available
794 + if ( ! empty( $selected_variant['font-style'] ) ) {
795 + echo "font-style: " . $selected_variant['font-style'] . ";\n";
796 + }
797 + }
798 +
799 + echo "}\n";
800 + } elseif ( isset( $value['font_family'] ) ) {
801 + // The selected font family
802 + echo $selector . " {\n font-family: " . $value['font_family'] . ";\n";
803 +
804 + if ( ! empty( $selected_variant ) && ! $load_all_weights ) {
805 + $weight_and_style = strtolower( $selected_variant );
806 +
807 + $italic_font = false;
808 +
809 + //determine if this is an italic font (the $weight_and_style is usually like '400' or '400italic' )
810 + if ( strpos( $weight_and_style, 'italic' ) !== false ) {
811 + $weight_and_style = str_replace( 'italic', '', $weight_and_style);
812 + $italic_font = true;
813 + }
814 +
815 + if ( ! empty( $weight_and_style ) ) {
816 + //a little bit of sanity check - in case it's not a number
817 + if( $weight_and_style === 'regular' ) {
818 + $weight_and_style = 'normal';
819 + }
820 + echo "font-weight: " . $weight_and_style . ";\n";
821 + }
822 +
823 + if ( $italic_font ) {
824 + echo "font-style: italic;\n";
825 + }
826 + }
827 +
828 + echo "}\n";
829 + }
830 + }
831 + }
832 +
833 + $output = ob_get_clean();
834 +
835 + return $output;
836 + }
837 +
838 + function output_typography_dynamic_script() {
839 +
840 + $script = $this->get_typography_dynamic_script();
841 + if ( ! empty ( $script ) ) { ?>
842 + <script type="text/javascript">
843 + <?php echo $script; ?>
844 + </script>
845 + <?php }
846 + }
847 +
848 + function get_typography_dynamic_script() {
849 + $output = '';
850 +
851 + $this->get_typography_fields( $this->options_list, 'type', 'typography', $this->typo_settings );
852 +
853 + if ( empty( $this->typo_settings ) ) {
854 + return $output;
855 + }
856 +
675 857 $families = '';
676 858
677 859 foreach ( $this->typo_settings as $id => $font ) {
678 860 if ( isset ( $font['value'] ) ) {
@@ -682,30 +864,39 @@
682 864 $load_all_weights = true;
683 865 }
684 866
685 867 // shim the time when this was an array
868 + // @todo Is this really needed? Or does it make sense?
686 869 if ( is_array( $font['value'] ) ) {
687 870 $font['value'] = stripslashes_deep( $font['value'] );
688 871 $font['value'] = json_encode( $font['value'] );
689 872 }
690 873
691 - $value = json_decode( wp_unslash( PixCustomifyPlugin::decodeURIComponent( $font['value'] ) ), true );
874 + $value = wp_unslash( PixCustomifyPlugin::decodeURIComponent( $font['value'] ) );
875 + if ( is_string( $value ) ) {
876 + $value = json_decode( $value, true );
877 + }
692 878
693 - // in case the value is still null, try default value(mostly for google fonts)
694 - if ( ! is_array( $value ) || $value === null ) {
879 + // In case the value is still null, try default value (mostly for google fonts)
880 + if ( $value === null || ! is_array( $value ) ) {
695 881 $value = $this->get_font_defaults_value( str_replace( '"', '', $font['value'] ) );
696 882 }
697 883
698 - //bail if by this time we don't have a value of some sort
884 + // Bail if by this time we don't have a value of some sort
699 885 if ( empty( $value ) ) {
700 886 continue;
701 887 }
702 888
703 - //Handle special logic for when the $value array is not an associative array
889 + // Handle special logic for when the $value array is not an associative array
704 890 if ( ! $this->is_assoc( $value ) ) {
705 - $value = $this->process_a_not_associative_font_default( $value );
891 + $value = $this->standardize_non_associative_font_default( $value );
706 892 }
707 893
894 + // Bail if empty or we don't have an array
895 + if ( empty( $value ) || ! is_array( $value ) ) {
896 + continue;
897 + }
898 +
708 899 if ( isset( $value['font_family'] ) && isset( $value['type'] ) && $value['type'] == 'google' ) {
709 900 $families .= "'" . $value['font_family'];
710 901
711 902 if ( $load_all_weights && is_array( $value['variants'] ) ) {
@@ -742,140 +933,54 @@
742 933 }
743 934 }
744 935 }
745 936
746 - if ( ! empty ( $families ) && $this->get_plugin_setting( 'typography', '1' ) && $this->get_plugin_setting( 'typography_google_fonts', 1 ) ) { ?>
747 - <script type="text/javascript">
748 - if (typeof WebFont !== 'undefined') {<?php // if there is a WebFont object, use it ?>
749 - WebFont.load({
750 - google: {families: [<?php echo( rtrim( $families, ',' ) ); ?>]},
751 - classes: false,
752 - events: false
753 - });
754 - } else {<?php // basically when we don't have the WebFont object we create the google script dynamically ?>
937 + if ( ! empty ( $families ) && $this->get_plugin_setting( 'typography', '1' ) && $this->get_plugin_setting( 'typography_google_fonts', 1 ) ) {
938 + ob_start();
939 + ?>
940 +if (typeof WebFont !== 'undefined') {<?php // if there is a WebFont object, use it ?>
941 + WebFont.load({
942 + google: {families: [<?php echo( rtrim( $families, ',' ) ); ?>]},
943 + classes: false,
944 + events: false
945 + });
946 +} else {<?php // basically when we don't have the WebFont object we create the google script dynamically ?>
755 947
756 - var tk = document.createElement('script');
757 - tk.src = '//ajax.googleapis.com/ajax/libs/webfont/1/webfont.js';
758 - tk.type = 'text/javascript';
948 + var tk = document.createElement('script');
949 + tk.src = '//ajax.googleapis.com/ajax/libs/webfont/1/webfont.js';
950 + tk.type = 'text/javascript';
759 951
760 - tk.onload = tk.onreadystatechange = function () {
761 - WebFont.load({
762 - google: {families: [<?php echo( rtrim( $families, ',' ) ); ?>]},
763 - classes: false,
764 - events: false
765 - });
766 - };
952 + tk.onload = tk.onreadystatechange = function () {
953 + WebFont.load({
954 + google: {families: [<?php echo( rtrim( $families, ',' ) ); ?>]},
955 + classes: false,
956 + events: false
957 + });
958 + };
767 959
768 - var s = document.getElementsByTagName('script')[0];
769 - s.parentNode.insertBefore(tk, s);
770 - }
771 - </script>
772 - <?php } ?>
773 - <style id="customify_typography_output_style">
774 - <?php
775 - foreach ( $this->typo_settings as $key => $font ) {
776 - $load_all_weights = false;
777 - if ( isset( $font['load_all_weights'] ) && $font['load_all_weights'] == 'true' ) {
778 - $load_all_weights = true;
779 - }
960 + var s = document.getElementsByTagName('script')[0];
961 + s.parentNode.insertBefore(tk, s);
962 +}<?php
963 + $output = ob_get_clean();
964 + }
780 965
781 - if ( isset( $font['selector'] ) && isset( $font['value'] ) && ! empty( $font['value'] ) ) {
966 + return $output;
967 + }
782 968
783 - $value = json_decode( PixCustomifyPlugin::decodeURIComponent( $font['value'] ), true );
784 - // in case the value is still null, try default value(mostly for google fonts)
785 - if ( $value === null ) {
786 - $value = $this->get_font_defaults_value( $font['value'] );
787 - }
788 -
789 - // shim the old case when the default was only the font name
790 - if ( is_string( $value ) && ! empty( $value ) ) {
791 - $value = array( 'font_family' => $value );
792 - }
793 -
794 - //Handle special logic for when the $value array is not an associative array
795 - if ( ! $this->is_assoc( $value ) ) {
796 - $value = $this->process_a_not_associative_font_default( $value );
797 - }
798 -
799 - $selected_variant = '';
800 - if ( ! empty( $value['selected_variants'] ) ) {
801 - if ( is_array( $value['selected_variants'] ) ) {
802 - $selected_variant = $value['selected_variants'][0];
803 - } else {
804 - $selected_variant = $value['selected_variants'];
805 - }
806 - }
807 -
808 - // 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 - if ( ! empty( $selected_variant ) && is_array( $selected_variant ) && ! empty( $selected_variant['font-family'] ) ) {
810 - //the variant's font-family
811 - echo $font['selector'] . " {\nfont-family: " . $selected_variant['font-family'] . ";\n";
812 -
813 - 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
815 - // we need to "force" the font-weight and font-style
816 - if ( ! empty( $value['type'] ) && 'custom_individual' == $value['type'] ) {
817 - $selected_variant['font-weight'] = '400 !important';
818 - $selected_variant['font-style'] = 'normal !important';
819 - }
820 -
821 - // output the font weight, if available
822 - if ( ! empty( $selected_variant['font-weight'] ) ) {
823 - echo "font-weight: " . $selected_variant['font-weight'] . ";\n";
824 - }
825 -
826 - // output the font style, if available
827 - if ( ! empty( $selected_variant['font-style'] ) ) {
828 - echo "font-style: " . $selected_variant['font-style'] . ";\n";
829 - }
830 - }
831 -
832 - echo "}\n";
833 - } elseif ( isset( $value['font_family'] ) ) {
834 - // the selected font family
835 - echo $font['selector'] . " {\n font-family: " . $value['font_family'] . ";\n";
836 -
837 - if ( ! empty( $selected_variant ) && ! $load_all_weights ) {
838 - $weight_and_style = strtolower( $selected_variant );
839 -
840 - $italic_font = false;
841 -
842 - //determine if this is an italic font (the $weight_and_style is usually like '400' or '400italic' )
843 - if ( strpos( $weight_and_style, 'italic' ) !== false ) {
844 - $weight_and_style = str_replace( 'italic', '', $weight_and_style);
845 - $italic_font = true;
846 - }
847 -
848 - if ( ! empty( $weight_and_style ) ) {
849 - //a little bit of sanity check - in case it's not a number
850 - if( $weight_and_style === 'regular' ) {
851 - $weight_and_style = 'normal';
852 - }
853 - echo "font-weight: " . $weight_and_style . ";\n";
854 - }
855 -
856 - if ( $italic_font ) {
857 - echo "font-style: italic;\n";
858 - }
859 - }
860 -
861 - echo "}\n";
862 - }
863 - }
864 - } ?>
865 - </style>
866 - <?php }
867 -
868 969 /**
869 970 * Handle special logic for when the $value array is not an associative array
870 971 * Return a new associative array with proper keys
871 972 */
872 - public function process_a_not_associative_font_default( $value ) {
973 + public function standardize_non_associative_font_default( $value ) {
974 + // If the value provided is not array, simply return it
975 + if ( ! is_array( $value ) ) {
976 + return $value;
977 + }
873 978
874 979 $new_value = array();
875 980
876 - //Let's determine some type of font
877 - if ( ! isset( $value[2] ) || ( isset( $value[2] ) && 'google' == $value[2] ) ) {
981 + // Let's determine some type of font
982 + if ( ! isset( $value[2] ) || 'google' == $value[2] ) {
878 983 $new_value = $this->get_font_defaults_value( $value[0] );
879 984 } else {
880 985 $new_value['type'] = $value[2];
881 986 }
@@ -883,15 +988,15 @@
883 988 if ( null == $new_value ) {
884 989 $new_value = array();
885 990 }
886 991
887 - //The first entry is the font-family
992 + // The first entry is the font-family
888 993 if ( isset( $value[0] ) ) {
889 994 $new_value['font_family'] = $value[0];
890 995 }
891 996
892 - //In case we don't have an associative array
893 - //The second entry is the variants
997 + // In case we don't have an associative array
998 + // The second entry is the variants
894 999 if ( isset( $value[1] ) ) {
895 1000 $new_value['selected_variants'] = $value[1];
896 1001 }
897 1002
@@ -954,10 +1059,10 @@
954 1059 );
955 1060 continue;
956 1061 }
957 1062
958 - if ( ! isset( $css_property['selector'] ) || isset( $css_property['property'] ) ) {
959 - $output .= $this->proccess_css_property( $css_property, $this_value );
1063 + if ( isset( $css_property['selector'] ) && isset( $css_property['property'] ) ) {
1064 + $output .= $this->process_css_property( $css_property, $this_value );
960 1065 }
961 1066 }
962 1067
963 1068 return $output;
@@ -962,9 +1067,9 @@
962 1067
963 1068 return $output;
964 1069 }
965 1070
966 - protected function proccess_css_property( $css_property, $this_value ) {
1071 + protected function process_css_property( $css_property, $this_value, $editor = false ) {
967 1072 $unit = '';
968 1073
969 1074 if ( isset( $css_property['unit'] ) ) {
970 1075 $unit = $css_property['unit'];
@@ -973,20 +1078,81 @@
973 1078 // if the unit isn't specified but the property should have a unit force 'px' as it
974 1079 if ( empty( $unit ) && in_array( $css_property['property'], self::$pixel_dependent_css_properties ) ) {
975 1080 $unit = 'px';
976 1081 }
1082 +
977 1083 // lose the tons of tabs
978 1084 $css_property['selector'] = trim( preg_replace( '/\t+/', '', $css_property['selector'] ) );
979 1085
980 - $this_property_output = $css_property['selector'] . ' { ' . $css_property['property'] . ': ' . $this_value . $unit . "; }\n";
1086 + $css_property['selector'] = apply_filters( 'customify_css_selector', $css_property['selector'], $css_property );
981 1087
982 - if ( isset( $css_property['callback_filter'] ) && function_exists( $css_property['callback_filter'] ) ) {
1088 + if ( empty( $css_property['selector'] ) ) {
1089 + return '';
1090 + }
1091 + $this_property_output = $css_property['selector'] . ' { ' . $css_property['property'] . ': ' . $this_value . $unit . "; }" . PHP_EOL;
1092 +
1093 + // Handle the value filter callback.
1094 + if ( isset( $css_property['filter_value_cb'] ) ) {
1095 + $this_value = $this->maybe_apply_filter( $css_property['filter_value_cb'], $this_value );
1096 + }
1097 +
1098 + // Handle output callback.
1099 + if ( isset( $css_property['callback_filter'] ) && is_callable( $css_property['callback_filter'] ) ) {
983 1100 $this_property_output = call_user_func( $css_property['callback_filter'], $this_value, $css_property['selector'], $css_property['property'], $unit );
984 1101 }
985 1102
1103 +// if ( ! empty( $editor ) && empty( $css_property['editor'] ) ) {
1104 +// $this_property_output = '';
1105 +// }
1106 +
986 1107 return $this_property_output;
987 1108 }
988 1109
1110 + /**
1111 + * Apply a filter (config) to a value.
1112 + *
1113 + * We currently handle filters like these:
1114 + * // Elaborate filter config
1115 + * array(
1116 + * 'callback' => 'is_post_type_archive',
1117 + * // The arguments we should pass to the check function.
1118 + * // Think post types, taxonomies, or nothing if that is the case.
1119 + * // It can be an array of values or a single value.
1120 + * 'args' => array(
1121 + * 'jetpack-portfolio',
1122 + * ),
1123 + * ),
1124 + * // Simple filter - just the function name
1125 + * 'is_404',
1126 + *
1127 + * @param array|string $filter
1128 + * @param mixed $value The value to apply the filter to.
1129 + *
1130 + * @return mixed The filtered value.
1131 + */
1132 + public function maybe_apply_filter( $filter, $value ) {
1133 + // Let's get some obvious things off the table.
1134 + // On invalid data, we just return what we've received.
1135 + if ( empty( $filter ) ) {
1136 + return $value;
1137 + }
1138 +
1139 + // First, we handle the shorthand version: just a function name
1140 + if ( is_string( $filter ) && is_callable( $filter ) ) {
1141 + $value = call_user_func( $filter );
1142 + } elseif ( is_array( $filter ) && ! empty( $filter['callback'] ) && is_callable( $filter['callback'] ) ) {
1143 + if ( empty( $filter['args'] ) ) {
1144 + $filter['args'] = array();
1145 + }
1146 + // The value is always the first argument.
1147 + $filter['args'] = array( $value ) + $filter['args'];
1148 +
1149 + $value = call_user_func_array( $filter['callback'], $filter['args'] );
1150 + }
1151 +
1152 + return $value;
1153 + }
1154 +
989 1155 protected function process_custom_background_field_output( $option_id, $options ) {
990 1156 $selector = $output = '';
991 1157
992 1158 if ( ! isset( $options['value'] ) ) {
@@ -1001,8 +1167,10 @@
1001 1167 } elseif ( is_array( $options['output'] ) ) {
1002 1168 $selector = implode( ' ', $options['output'] );
1003 1169 }
1004 1170
1171 + // Loose the ton of tabs.
1172 + $selector = trim( preg_replace( '/\t+/', '', $selector ) );
1005 1173
1006 1174 $output .= $selector . " {";
1007 1175 if ( isset( $value['background-image'] ) && ! empty( $value['background-image'] ) ) {
1008 1176 $output .= "background-image: url( " . $value['background-image'] . ");";
@@ -1032,71 +1200,77 @@
1032 1200
1033 1201 /**
1034 1202 * add our customizer styling edits into the wp_editor
1035 1203 */
1036 - function add_customizer_settings_into_wp_editor() {
1204 + function script_to_add_customizer_settings_into_wp_editor() {
1037 1205
1038 1206 ob_start();
1207 + $this->output_typography_dynamic_script();
1039 1208 $this->output_typography_dynamic_style();
1040 1209 $this->output_dynamic_style();
1041 1210
1042 - $custom_css = ob_get_clean(); ?>
1043 - <script type="text/javascript">
1044 - /* <![CDATA[ */
1045 - (function ($) {
1046 - $(window).load(function () {
1047 - /**
1048 - * @param iframe_id the id of the frame you whant to append the style
1049 - * @param style_element the style element you want to append
1050 - */
1051 - var append_script_to_iframe = function (ifrm_id, scriptEl) {
1052 - var myIframe = document.getElementById(ifrm_id);
1211 + $custom_css = ob_get_clean();
1053 1212
1054 - var script = myIframe.contentWindow.document.createElement("script");
1055 - script.type = "text/javascript";
1056 - script.innerHTML = scriptEl.innerHTML;
1213 + ob_start(); ?>
1214 + (function ($) {
1215 + $(window).load(function () {
1216 + /**
1217 + * @param iframe_id the id of the frame you want to append the style
1218 + * @param style_element the style element you want to append - boooom
1219 + */
1220 + var append_script_to_iframe = function (ifrm_id, scriptEl) {
1221 + var myIframe = document.getElementById(ifrm_id);
1057 1222
1058 - myIframe.contentWindow.document.head.appendChild(script);
1059 - };
1223 + var script = myIframe.contentWindow.document.createElement("script");
1224 + script.type = "text/javascript";
1225 + script.innerHTML = scriptEl.innerHTML;
1060 1226
1061 - var append_style_to_iframe = function (ifrm_id, styleElment) {
1062 - var ifrm = window.frames[ifrm_id];
1063 - ifrm = ( ifrm.contentDocument || ifrm.contentDocument || ifrm.document );
1064 - var head = ifrm.getElementsByTagName('head')[0];
1227 + myIframe.contentWindow.document.head.appendChild(script);
1228 + };
1065 1229
1066 - if (typeof styleElment !== "undefined") {
1067 - head.appendChild(styleElment);
1068 - }
1069 - };
1230 + var append_style_to_iframe = function (ifrm_id, styleElment) {
1231 + var ifrm = window.frames[ifrm_id];
1232 + if ( typeof ifrm === "undefined" ) {
1233 + return;
1234 + }
1235 + ifrm = ( ifrm.contentDocument || ifrm.contentDocument || ifrm.document );
1236 + var head = ifrm.getElementsByTagName('head')[0];
1070 1237
1071 - var xmlString = <?php echo json_encode( str_replace( "\n", "", $custom_css ) ); ?>,
1072 - parser = new DOMParser(),
1073 - doc = parser.parseFromString(xmlString, "text/html");
1238 + if (typeof styleElment !== "undefined") {
1239 + head.appendChild(styleElment);
1240 + }
1241 + };
1074 1242
1075 - if (typeof window.frames['content_ifr'] !== 'undefined') {
1243 + var xmlString = <?php echo json_encode( str_replace( "\n", "", $custom_css ) ); ?>,
1244 + parser = new DOMParser(),
1245 + doc = parser.parseFromString(xmlString, "text/html");
1076 1246
1077 - $.each(doc.head.childNodes, function (key, el) {
1078 - if (typeof el !== "undefined" && typeof el.tagName !== "undefined") {
1247 + if (typeof window.frames['content_ifr'] !== 'undefined') {
1079 1248
1080 - switch (el.tagName) {
1081 - case 'STYLE' :
1082 - append_style_to_iframe('content_ifr', el);
1083 - break;
1084 - case 'SCRIPT' :
1085 - append_script_to_iframe('content_ifr', el);
1086 - break;
1087 - default:
1088 - break;
1089 - }
1090 - }
1091 - });
1249 + $.each(doc.head.childNodes, function (key, el) {
1250 + if (typeof el !== "undefined" && typeof el.tagName !== "undefined") {
1251 +
1252 + switch (el.tagName) {
1253 + case 'STYLE' :
1254 + append_style_to_iframe('content_ifr', el);
1255 + break;
1256 + case 'SCRIPT' :
1257 + append_script_to_iframe('content_ifr', el);
1258 + break;
1259 + default:
1260 + break;
1261 + }
1092 1262 }
1093 1263 });
1094 - })(jQuery);
1095 - /* ]]> */
1096 - </script>
1097 - <?php }
1264 + }
1265 + });
1266 + })(jQuery);
1267 + <?php
1268 + $script = ob_get_clean();
1269 + wp_add_inline_script( 'editor', $script );
1098 1270
1271 + }
1272 +
1099 1273 /**
1100 1274 * Register the administration menu for this plugin into the WordPress Dashboard menu.
1101 1275 */
1102 1276 function add_plugin_admin_menu() {
@@ -1130,10 +1304,180 @@
1130 1304 pixcustomify::require_all( $path );
1131 1305 }
1132 1306
1133 1307 /**
1308 + * Maybe process certain "commands" from the config.
1309 + *
1310 + * Mainly things like removing sections, controls, etc.
1311 + *
1312 + * @since 1.9.0
1313 + *
1134 1314 * @param WP_Customize_Manager $wp_customize
1135 1315 */
1316 + public function maybe_process_config_extras( $wp_customize ) {
1317 + // Bail if we have no external theme config data.
1318 + if ( empty( $this->customizer_config ) || ! is_array( $this->customizer_config ) ) {
1319 + return;
1320 + }
1321 +
1322 + // Maybe remove panels
1323 + if ( ! empty( $this->customizer_config['remove_panels'] ) ) {
1324 + // Standardize it.
1325 + if ( is_string( $this->customizer_config['remove_panels'] ) ) {
1326 + $this->customizer_config['remove_panels'] = array( $this->customizer_config['remove_panels'] );
1327 + }
1328 +
1329 + foreach ( $this->customizer_config['remove_panels'] as $panel_id ) {
1330 + $wp_customize->remove_panel( $panel_id );
1331 + }
1332 + }
1333 +
1334 + // Maybe change panel props.
1335 + if ( ! empty( $this->customizer_config['change_panel_props'] ) ) {
1336 + foreach ( $this->customizer_config['change_panel_props'] as $panel_id => $panel_props ) {
1337 + if ( ! is_array( $panel_props ) ) {
1338 + continue;
1339 + }
1340 +
1341 + $panel = $wp_customize->get_panel( $panel_id );
1342 + if ( empty( $panel ) || ! $panel instanceof WP_Customize_Panel ) {
1343 + continue;
1344 + }
1345 +
1346 + $public_props = get_class_vars( get_class( $panel ) );
1347 + foreach ( $panel_props as $prop_name => $prop_value ) {
1348 +
1349 + if ( ! in_array( $prop_name, array_keys( $public_props ) ) ) {
1350 + continue;
1351 + }
1352 +
1353 + $panel->$prop_name = $prop_value;
1354 + }
1355 + }
1356 + }
1357 +
1358 + // Maybe remove sections
1359 + if ( ! empty( $this->customizer_config['remove_sections'] ) ) {
1360 + // Standardize it.
1361 + if ( is_string( $this->customizer_config['remove_sections'] ) ) {
1362 + $this->customizer_config['remove_sections'] = array( $this->customizer_config['remove_sections'] );
1363 + }
1364 +
1365 + foreach ( $this->customizer_config['remove_sections'] as $section_id ) {
1366 +
1367 + if ( 'widgets' === $section_id ) {
1368 + global $wp_registered_sidebars;
1369 +
1370 + foreach ( $wp_registered_sidebars as $widget => $settings ) {
1371 + $wp_customize->remove_section( 'sidebar-widgets-' . $widget );
1372 + }
1373 + continue;
1374 + }
1375 +
1376 + $wp_customize->remove_section( $section_id );
1377 + }
1378 + }
1379 +
1380 + // Maybe change section props.
1381 + if ( ! empty( $this->customizer_config['change_section_props'] ) ) {
1382 + foreach ( $this->customizer_config['change_section_props'] as $section_id => $section_props ) {
1383 + if ( ! is_array( $section_props ) ) {
1384 + continue;
1385 + }
1386 +
1387 + $section = $wp_customize->get_section( $section_id );
1388 + if ( empty( $section ) || ! $section instanceof WP_Customize_Section ) {
1389 + continue;
1390 + }
1391 +
1392 + $public_props = get_class_vars( get_class( $section ) );
1393 + foreach ( $section_props as $prop_name => $prop_value ) {
1394 +
1395 + if ( ! in_array( $prop_name, array_keys( $public_props ) ) ) {
1396 + continue;
1397 + }
1398 +
1399 + $section->$prop_name = $prop_value;
1400 + }
1401 + }
1402 + }
1403 +
1404 + // Maybe remove settings
1405 + if ( ! empty( $this->customizer_config['remove_settings'] ) ) {
1406 + // Standardize it.
1407 + if ( is_string( $this->customizer_config['remove_settings'] ) ) {
1408 + $this->customizer_config['remove_settings'] = array( $this->customizer_config['remove_settings'] );
1409 + }
1410 +
1411 + foreach ( $this->customizer_config['remove_settings'] as $setting_id ) {
1412 + $wp_customize->remove_setting( $setting_id );
1413 + }
1414 + }
1415 +
1416 + // Maybe change setting props.
1417 + if ( ! empty( $this->customizer_config['change_setting_props'] ) ) {
1418 + foreach ( $this->customizer_config['change_setting_props'] as $setting_id => $setting_props ) {
1419 + if ( ! is_array( $setting_props ) ) {
1420 + continue;
1421 + }
1422 +
1423 + $setting = $wp_customize->get_setting( $setting_id );
1424 + if ( empty( $setting ) || ! $setting instanceof WP_Customize_Setting ) {
1425 + continue;
1426 + }
1427 +
1428 + $public_props = get_class_vars( get_class( $setting ) );
1429 + foreach ( $setting_props as $prop_name => $prop_value ) {
1430 +
1431 + if ( ! in_array( $prop_name, array_keys( $public_props ) ) ) {
1432 + continue;
1433 + }
1434 +
1435 + $setting->$prop_name = $prop_value;
1436 + }
1437 + }
1438 + }
1439 +
1440 + // Maybe remove controls
1441 + if ( ! empty( $this->customizer_config['remove_controls'] ) ) {
1442 + // Standardize it.
1443 + if ( is_string( $this->customizer_config['remove_controls'] ) ) {
1444 + $this->customizer_config['remove_controls'] = array( $this->customizer_config['remove_controls'] );
1445 + }
1446 +
1447 + foreach ( $this->customizer_config['remove_controls'] as $control_id ) {
1448 + $wp_customize->remove_control( $control_id );
1449 + }
1450 + }
1451 +
1452 + // Maybe change control props.
1453 + if ( ! empty( $this->customizer_config['change_control_props'] ) ) {
1454 + foreach ( $this->customizer_config['change_control_props'] as $control_id => $control_props ) {
1455 + if ( ! is_array( $control_props ) ) {
1456 + continue;
1457 + }
1458 +
1459 + $control = $wp_customize->get_control( $control_id );
1460 + if ( empty( $control ) || ! $control instanceof WP_Customize_Control ) {
1461 + continue;
1462 + }
1463 +
1464 + $public_props = get_class_vars( get_class( $control ) );
1465 + foreach ( $control_props as $prop_name => $prop_value ) {
1466 +
1467 + if ( ! in_array( $prop_name, array_keys( $public_props ) ) ) {
1468 + continue;
1469 + }
1470 +
1471 + $control->$prop_name = $prop_value;
1472 + }
1473 + }
1474 + }
1475 + }
1476 +
1477 + /**
1478 + * @param WP_Customize_Manager $wp_customize
1479 + */
1136 1480 function register_customizer( $wp_customize ) {
1137 1481
1138 1482 $this->register_customizer_controls();
1139 1483
@@ -1141,9 +1485,9 @@
1141 1485
1142 1486 if ( ! empty ( $customizer_settings ) ) {
1143 1487
1144 1488 // first check the very needed options name
1145 - if ( ! isset ( $customizer_settings['opt-name'] ) || empty( $customizer_settings['opt-name'] ) ) {
1489 + if ( empty( $customizer_settings['opt-name'] ) ) {
1146 1490 return;
1147 1491 }
1148 1492 $options_name = $customizer_settings['opt-name'];
1149 1493 $wp_customize->options_key = $options_name;
@@ -1150,37 +1494,49 @@
1150 1494
1151 1495 // let's check if we have sections or panels
1152 1496 if ( isset( $customizer_settings['panels'] ) && ! empty( $customizer_settings['panels'] ) ) {
1153 1497
1154 - foreach ( $customizer_settings['panels'] as $panel_id => $panel_settings ) {
1498 + foreach ( $customizer_settings['panels'] as $panel_id => $panel_config ) {
1155 1499
1156 - if ( ! empty( $panel_id ) && isset( $panel_settings['sections'] ) && ! empty( $panel_settings['sections'] ) ) {
1500 + if ( ! empty( $panel_id ) && isset( $panel_config['sections'] ) && ! empty( $panel_config['sections'] ) ) {
1157 1501
1158 - $panel_id = $options_name . '[' . $panel_id . ']';
1502 + // If we have been explicitly given a panel ID we will use that
1503 + if ( ! empty( $panel_config['panel_id'] ) ) {
1504 + $panel_id = $panel_config['panel_id'];
1505 + } else {
1506 + $panel_id = $options_name . '[' . $panel_id . ']';
1507 + }
1508 +
1159 1509 $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' ),
1510 + 'priority' => 10,
1511 + 'capability' => 'edit_theme_options',
1512 + 'title' => __( 'Panel title is required', 'customify' ),
1513 + 'description' => __( 'Description of what this panel does.', 'customify' ),
1514 + 'auto_expand_sole_section' => false,
1164 1515 );
1165 1516
1166 - if ( isset( $panel_settings['priority'] ) && ! empty( $panel_settings['priority'] ) ) {
1167 - $panel_args['priority'] = $panel_settings['priority'];
1517 + if ( isset( $panel_config['priority'] ) && ! empty( $panel_config['priority'] ) ) {
1518 + $panel_args['priority'] = $panel_config['priority'];
1168 1519 }
1169 1520
1170 - if ( isset( $panel_settings['title'] ) && ! empty( $panel_settings['title'] ) ) {
1171 - $panel_args['title'] = $panel_settings['title'];
1521 + if ( isset( $panel_config['title'] ) && ! empty( $panel_config['title'] ) ) {
1522 + $panel_args['title'] = $panel_config['title'];
1172 1523 }
1173 1524
1174 - if ( isset( $panel_settings['description'] ) && ! empty( $panel_settings['description'] ) ) {
1175 - $panel_args[10] = $panel_settings['description'];
1525 + if ( isset( $panel_config['description'] ) && ! empty( $panel_config['description'] ) ) {
1526 + $panel_args['description'] = $panel_config['description'];
1176 1527 }
1177 1528
1529 + if ( isset( $panel_config['auto_expand_sole_section'] ) ) {
1530 + $panel_args['auto_expand_sole_section'] = $panel_config['auto_expand_sole_section'];
1531 + }
1532 +
1533 +
1178 1534 $wp_customize->add_panel( $panel_id, $panel_args );
1179 1535
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 );
1536 + foreach ( $panel_config['sections'] as $section_id => $section_config ) {
1537 + if ( ! empty( $section_id ) && isset( $section_config['options'] ) && ! empty( $section_config['options'] ) ) {
1538 + $this->register_section( $panel_id, $section_id, $options_name, $section_config, $wp_customize );
1183 1539 }
1184 1540 }
1185 1541 }
1186 1542 }
@@ -1187,11 +1543,11 @@
1187 1543 }
1188 1544
1189 1545 if ( isset( $customizer_settings['sections'] ) && ! empty( $customizer_settings['sections'] ) ) {
1190 1546
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 );
1547 + foreach ( $customizer_settings['sections'] as $section_id => $section_config ) {
1548 + if ( ! empty( $section_id ) && isset( $section_config['options'] ) && ! empty( $section_config['options'] ) ) {
1549 + $this->register_section( $panel_id = false, $section_id, $options_name, $section_config, $wp_customize );
1194 1550 }
1195 1551 }
1196 1552 }
1197 1553
@@ -1197,9 +1553,11 @@
1197 1553
1198 1554 if ( $this->plugin_settings['enable_reset_buttons'] ) {
1199 1555 // create a toolbar section which will be present all the time
1200 1556 $reset_section_settings = array(
1201 - 'title' => 'Customify toolbar',
1557 + 'title' => 'Customify Toolbox',
1558 + 'capability' => 'manage_options',
1559 + 'priority' => 999999999,
1202 1560 'options' => array(
1203 1561 'reset_all_button' => array(
1204 1562 'type' => 'button',
1205 1563 'label' => 'Reset Customify',
@@ -1210,12 +1568,9 @@
1210 1568 );
1211 1569
1212 1570 $wp_customize->add_section(
1213 1571 'customify_toolbar',
1214 - array(
1215 - 'title' => '',
1216 - 'priority' => 999999999
1217 - )
1572 + $reset_section_settings
1218 1573 );
1219 1574
1220 1575 $wp_customize->add_setting(
1221 1576 'reset_customify',
@@ -1224,9 +1579,9 @@
1224 1579 $wp_customize->add_control( new Pix_Customize_Button_Control(
1225 1580 $wp_customize,
1226 1581 'reset_customify',
1227 1582 array(
1228 - 'label' => __( 'Reset Customify to Defaults', 'customify' ),
1583 + 'label' => __( 'Reset All Customify Options to Default', 'customify' ),
1229 1584 'section' => 'customify_toolbar',
1230 1585 'settings' => 'reset_customify',
1231 1586 'action' => 'reset_customify',
1232 1587 )
@@ -1260,49 +1615,69 @@
1260 1615 /**
1261 1616 * @param string $panel_id
1262 1617 * @param string $section_key
1263 1618 * @param string $options_name
1264 - * @param array $section_settings
1619 + * @param array $section_config
1265 1620 * @param WP_Customize_Manager $wp_customize
1266 1621 */
1267 - protected function register_section( $panel_id, $section_key, $options_name, $section_settings, $wp_customize ) {
1622 + protected function register_section( $panel_id, $section_key, $options_name, $section_config, $wp_customize ) {
1268 1623
1269 1624 if ( isset( $this->plugin_settings['disable_customify_sections'] ) && isset( $this->plugin_settings['disable_customify_sections'][ $section_key ] ) ) {
1270 1625 return;
1271 1626 }
1272 1627
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 . ']';
1628 + // If we have been explicitly given a section ID we will use that
1629 + if ( ! empty( $section_config['section_id'] ) ) {
1630 + $section_id = $section_config['section_id'];
1631 + } else {
1632 + $section_id = $options_name . '[' . $section_key . ']';
1633 + }
1285 1634
1286 - // Add the new section to the Customizer
1287 - $wp_customize->add_section( $section_id, $section_args );
1635 + // Add the new section to the Customizer, but only if it is not already added.
1636 + if ( ! $wp_customize->get_section( $section_id ) ) {
1637 + // Merge the section settings with the defaults
1638 + $section_args = wp_parse_args( $section_config, array(
1639 + 'priority' => 10,
1640 + 'panel' => $panel_id,
1641 + 'capability' => 'edit_theme_options',
1642 + 'theme_supports' => '',
1643 + 'title' => esc_html__( 'Title Section is required', 'customify' ),
1644 + 'description' => '',
1645 + 'type' => 'default',
1646 + 'description_hidden' => false,
1647 + ) );
1288 1648
1649 + $wp_customize->add_section( $section_id, $section_args );
1650 + }
1651 +
1289 1652 // Now go through each section option and add the fields
1290 - foreach ( $section_settings['options'] as $option_id => $option_config ) {
1653 + foreach ( $section_config['options'] as $option_id => $option_config ) {
1291 1654
1292 1655 if ( empty( $option_id ) || ! isset( $option_config['type'] ) ) {
1293 1656 continue;
1294 1657 }
1295 1658
1296 - $option_id = $options_name . '[' . $option_id . ']';
1659 + // If we have been explicitly given a setting ID we will use that
1660 + if ( ! empty( $option_config['setting_id'] ) ) {
1661 + $setting_id = $option_config['setting_id'];
1662 + } else {
1663 + $setting_id = $options_name . '[' . $option_id . ']';
1664 + }
1297 1665
1298 - $this->register_field( $section_id, $option_id, $option_config, $wp_customize );
1666 + // Add the option config to the localized array so we can pass the info to JS.
1667 + // @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.
1668 + $this->localized['settings'][ $setting_id ] = $option_config;
1669 +
1670 + // Generate a safe option ID (not the final setting ID) to us in HTML attributes like ID or class
1671 + $this->localized['settings'][ $setting_id ]['html_safe_option_id'] = sanitize_html_class( $option_id );
1672 +
1673 + $this->register_field( $section_id, $setting_id, $option_config, $wp_customize );
1299 1674 }
1300 1675
1301 1676 }
1302 1677
1303 1678 /**
1304 - * Register a Customizer field
1679 + * Register a Customizer field (setting and control).
1305 1680 *
1306 1681 * @see WP_Customize_Setting
1307 1682 * @see WP_Customize_Control
1308 1683 *
@@ -1307,12 +1682,12 @@
1307 1682 * @see WP_Customize_Control
1308 1683 *
1309 1684 * @param string $section_id
1310 1685 * @param string $setting_id
1311 - * @param array $setting_config
1686 + * @param array $field_config
1312 1687 * @param WP_Customize_Manager $wp_customize
1313 1688 */
1314 - protected function register_field( $section_id, $setting_id, $setting_config, $wp_customize ) {
1689 + protected function register_field( $section_id, $setting_id, $field_config, $wp_customize ) {
1315 1690
1316 1691 $add_control = true;
1317 1692 // defaults
1318 1693 $setting_args = array(
@@ -1320,34 +1695,38 @@
1320 1695 'capability' => 'edit_theme_options',
1321 1696 'transport' => 'refresh',
1322 1697 );
1323 1698 $control_args = array(
1699 + 'priority' => 10,
1324 1700 'label' => '',
1325 1701 'section' => $section_id,
1326 1702 'settings' => $setting_id,
1327 1703 );
1328 1704
1329 - $this->localized['settings'][ $setting_id ] = $setting_config;
1330 -
1331 1705 // sanitize settings
1332 - if ( ( isset( $setting_config['live'] ) && $setting_config['live'] ) || $setting_config['type'] === 'font' ) {
1706 + if ( ! empty( $field_config['live'] ) || $field_config['type'] === 'font' ) {
1333 1707 $setting_args['transport'] = 'postMessage';
1334 1708 }
1335 1709
1336 - if ( isset( $setting_config['default'] ) ) {
1337 - $setting_args['default'] = $setting_config['default'];
1710 + if ( isset( $field_config['default'] ) ) {
1711 + $setting_args['default'] = $field_config['default'];
1338 1712 }
1339 1713
1340 - if ( isset( $setting_config['capability'] ) && ! empty( $setting_config['capability'] ) ) {
1341 - $setting_args['capability'] = $setting_config['capability'];
1714 + if ( ! empty( $field_config['capability'] ) ) {
1715 + $setting_args['capability'] = $field_config['capability'];
1342 1716 }
1343 1717
1344 - if ( $this->plugin_settings['values_store_mod'] == 'option' ) {
1718 + // If the setting defines it's own type we will respect that, otherwise we will follow the global plugin setting.
1719 + if ( ! empty( $field_config['setting_type'] ) ) {
1720 + if ( 'option' === $field_config['setting_type'] ) {
1721 + $setting_args['type'] = 'option';
1722 + }
1723 + } elseif ( $this->plugin_settings['values_store_mod'] === 'option' ) {
1345 1724 $setting_args['type'] = 'option';
1346 1725 }
1347 1726
1348 1727 // if we arrive here this means we have a custom field control
1349 - switch ( $setting_config['type'] ) {
1728 + switch ( $field_config['type'] ) {
1350 1729
1351 1730 case 'checkbox':
1352 1731
1353 1732 $setting_args['sanitize_callback'] = array( $this, 'setting_sanitize_checkbox' );
@@ -1356,41 +1735,41 @@
1356 1735 default:
1357 1736 break;
1358 1737 }
1359 1738
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'];
1739 + if ( ! empty( $field_config['sanitize_callback'] ) && is_callable( $field_config['sanitize_callback'] ) ) {
1740 + $setting_args['sanitize_callback'] = $field_config['sanitize_callback'];
1362 1741 }
1363 1742
1364 - // and add it
1743 + // Add the setting
1365 1744 $wp_customize->add_setting( $setting_id, $setting_args );
1366 1745
1367 1746 // now sanitize the control
1368 - if ( isset( $setting_config['label'] ) && ! empty( $setting_config['label'] ) ) {
1369 - $control_args['label'] = $setting_config['label'];
1747 + if ( ! empty( $field_config['label'] ) ) {
1748 + $control_args['label'] = $field_config['label'];
1370 1749 }
1371 1750
1372 - if ( isset( $setting_config['priority'] ) && ! empty( $setting_config['priority'] ) ) {
1373 - $control_args['priority'] = $setting_config['priority'];
1751 + if ( ! empty( $field_config['priority'] ) ) {
1752 + $control_args['priority'] = $field_config['priority'];
1374 1753 }
1375 1754
1376 - if ( isset( $setting_config['desc'] ) && ! empty( $setting_config['desc'] ) ) {
1377 - $control_args['description'] = $setting_config['desc'];
1755 + if ( ! empty( $field_config['desc'] ) ) {
1756 + $control_args['description'] = $field_config['desc'];
1378 1757 }
1379 1758
1380 - if ( isset( $setting_config['active_callback'] ) && ! empty( $setting_config['active_callback'] ) ) {
1381 - $control_args['active_callback'] = $setting_config['active_callback'];
1759 + if ( ! empty( $field_config['active_callback'] ) ) {
1760 + $control_args['active_callback'] = $field_config['active_callback'];
1382 1761 }
1383 1762
1384 1763
1385 - $control_args['type'] = $setting_config['type'];
1764 + $control_args['type'] = $field_config['type'];
1386 1765
1387 1766 // select the control type
1388 1767 // but first init a default
1389 1768 $control_class_name = 'Pix_Customize_Text_Control';
1390 1769
1391 - // if is a standard wp field type call it here and skip the rest
1392 - if ( in_array( $setting_config['type'], array(
1770 + // If is a standard wp field type call it here and skip the rest.
1771 + if ( in_array( $field_config['type'], array(
1393 1772 'checkbox',
1394 1773 'dropdown-pages',
1395 1774 'url',
1396 1775 'date',
@@ -1401,30 +1780,30 @@
1401 1780 ) ) ) {
1402 1781 $wp_customize->add_control( $setting_id . '_control', $control_args );
1403 1782
1404 1783 return;
1405 - } elseif ( in_array( $setting_config['type'], array(
1784 + } elseif ( in_array( $field_config['type'], array(
1406 1785 'radio',
1407 1786 'select'
1408 - ) ) && isset( $setting_config['choices'] ) && ! empty( $setting_config['choices'] )
1787 + ) ) && ! empty( $field_config['choices'] )
1409 1788 ) {
1410 - $control_args['choices'] = $setting_config['choices'];
1789 + $control_args['choices'] = $field_config['choices'];
1411 1790 $wp_customize->add_control( $setting_id . '_control', $control_args );
1412 1791
1413 1792 return;
1414 - } elseif ( in_array( $setting_config['type'], array( 'range' ) ) && isset( $setting_config['input_attrs'] ) && ! empty( $setting_config['input_attrs'] ) ) {
1793 + } elseif ( in_array( $field_config['type'], array( 'range' ) ) && ! empty( $field_config['input_attrs'] ) ) {
1415 1794
1416 - $control_args['input_attrs'] = $setting_config['input_attrs'];
1795 + $control_args['input_attrs'] = $field_config['input_attrs'];
1417 1796
1418 1797 $wp_customize->add_control( $setting_id . '_control', $control_args );
1419 1798 }
1420 1799
1421 - // if we arrive here this means we have a custom field control
1422 - switch ( $setting_config['type'] ) {
1800 + // If we arrive here this means we have a custom field control.
1801 + switch ( $field_config['type'] ) {
1423 1802
1424 1803 case 'text':
1425 - if ( isset( $setting_config['live'] ) ) {
1426 - $control_args['live'] = $setting_config['live'];
1804 + if ( isset( $field_config['live'] ) ) {
1805 + $control_args['live'] = $field_config['live'];
1427 1806 }
1428 1807
1429 1808 $control_class_name = 'Pix_Customize_Text_Control';
1430 1809 break;
@@ -1429,10 +1808,10 @@
1429 1808 $control_class_name = 'Pix_Customize_Text_Control';
1430 1809 break;
1431 1810
1432 1811 case 'textarea':
1433 - if ( isset( $setting_config['live'] ) ) {
1434 - $control_args['live'] = $setting_config['live'];
1812 + if ( isset( $field_config['live'] ) ) {
1813 + $control_args['live'] = $field_config['live'];
1435 1814 }
1436 1815
1437 1816 $control_class_name = 'Pix_Customize_Textarea_Control';
1438 1817 break;
@@ -1445,14 +1824,14 @@
1445 1824 $control_class_name = 'Pix_Customize_Color_Drop_Control';
1446 1825 break;
1447 1826
1448 1827 case 'ace_editor':
1449 - if ( isset( $setting_config['live'] ) ) {
1450 - $control_args['live'] = $setting_config['live'];
1828 + if ( isset( $field_config['live'] ) ) {
1829 + $control_args['live'] = $field_config['live'];
1451 1830 }
1452 1831
1453 - if ( isset( $setting_config['editor_type'] ) ) {
1454 - $control_args['editor_type'] = $setting_config['editor_type'];
1832 + if ( isset( $field_config['editor_type'] ) ) {
1833 + $control_args['editor_type'] = $field_config['editor_type'];
1455 1834 }
1456 1835
1457 1836 $control_class_name = 'Pix_Customize_Ace_Editor_Control';
1458 1837 break;
@@ -1469,32 +1848,37 @@
1469 1848 $control_class_name = 'WP_Customize_Media_Control';
1470 1849 break;
1471 1850
1472 1851 case 'custom_background':
1473 - if ( isset( $setting_config['field'] ) ) {
1474 - $control_args['field'] = $setting_config['field'];
1852 + if ( isset( $field_config['field'] ) ) {
1853 + $control_args['field'] = $field_config['field'];
1475 1854 }
1476 1855
1477 1856 $control_class_name = 'Pix_Customize_Background_Control';
1478 1857 break;
1479 1858
1480 - case 'cropped_media':
1481 - if ( isset( $setting_config['width'] ) ) {
1482 - $control_args['width'] = $setting_config['width'];
1859 + case 'cropped_image':
1860 + case 'cropped_media': // 'cropped_media' no longer works
1861 + if ( isset( $field_config['width'] ) ) {
1862 + $control_args['width'] = $field_config['width'];
1483 1863 }
1484 1864
1485 - if ( isset( $setting_config['height'] ) ) {
1486 - $control_args['height'] = $setting_config['height'];
1865 + if ( isset( $field_config['height'] ) ) {
1866 + $control_args['height'] = $field_config['height'];
1487 1867 }
1488 1868
1489 - if ( isset( $setting_config['flex_width'] ) ) {
1490 - $control_args['flex_width'] = $setting_config['flex_width'];
1869 + if ( isset( $field_config['flex_width'] ) ) {
1870 + $control_args['flex_width'] = $field_config['flex_width'];
1491 1871 }
1492 1872
1493 - if ( isset( $setting_config['flex_height'] ) ) {
1494 - $control_args['flex_height'] = $setting_config['flex_height'];
1873 + if ( isset( $field_config['flex_height'] ) ) {
1874 + $control_args['flex_height'] = $field_config['flex_height'];
1495 1875 }
1496 1876
1877 + if ( isset( $field_config['button_labels'] ) ) {
1878 + $control_args['button_labels'] = $field_config['button_labels'];
1879 + }
1880 +
1497 1881 $control_class_name = 'WP_Customize_Cropped_Image_Control';
1498 1882 break;
1499 1883
1500 1884 // Custom types
@@ -1507,35 +1891,34 @@
1507 1891 }
1508 1892
1509 1893 $control_class_name = 'Pix_Customize_Typography_Control';
1510 1894
1511 - if ( isset( $setting_config['backup'] ) ) {
1512 - $control_args['backup'] = $setting_config['backup'];
1895 + if ( isset( $field_config['backup'] ) ) {
1896 + $control_args['backup'] = $field_config['backup'];
1513 1897 }
1514 1898
1515 - if ( isset( $setting_config['font_weight'] ) ) {
1516 - $control_args['font_weight'] = $setting_config['font_weight'];
1899 + if ( isset( $field_config['font_weight'] ) ) {
1900 + $control_args['font_weight'] = $field_config['font_weight'];
1517 1901 }
1518 1902
1519 - if ( isset( $setting_config['subsets'] ) ) {
1520 - $control_args['subsets'] = $setting_config['subsets'];
1903 + if ( isset( $field_config['subsets'] ) ) {
1904 + $control_args['subsets'] = $field_config['subsets'];
1521 1905 }
1522 1906
1523 - if ( isset( $setting_config['recommended'] ) ) {
1524 - $control_args['recommended'] = array_flip( $setting_config['recommended'] );
1907 + if ( isset( $field_config['recommended'] ) ) {
1908 + $control_args['recommended'] = array_flip( $field_config['recommended'] );
1525 1909 }
1526 1910
1527 - if ( isset( $setting_config['load_all_weights'] ) ) {
1528 - $control_args['load_all_weights'] = $setting_config['load_all_weights'];
1911 + if ( isset( $field_config['load_all_weights'] ) ) {
1912 + $control_args['load_all_weights'] = $field_config['load_all_weights'];
1529 1913 }
1530 1914
1531 - if ( isset( $setting_config['default'] ) ) {
1532 - $control_args['default'] = $setting_config['default'];
1915 + if ( isset( $field_config['default'] ) ) {
1916 + $control_args['default'] = $field_config['default'];
1533 1917 }
1534 1918
1535 1919 break;
1536 1920
1537 - // Custom types
1538 1921 case 'font' :
1539 1922 $use_typography = $this->get_plugin_setting( 'typography', '1' );
1540 1923
1541 1924 if ( $use_typography === false ) {
@@ -1544,34 +1927,34 @@
1544 1927 }
1545 1928
1546 1929 $control_class_name = 'Pix_Customize_Font_Control';
1547 1930
1548 - if ( isset( $setting_config['backup'] ) ) {
1549 - $control_args['backup'] = $setting_config['backup'];
1931 + if ( isset( $field_config['backup'] ) ) {
1932 + $control_args['backup'] = $field_config['backup'];
1550 1933 }
1551 1934
1552 - if ( isset( $setting_config['font_weight'] ) ) {
1553 - $control_args['font_weight'] = $setting_config['font_weight'];
1935 + if ( isset( $field_config['font_weight'] ) ) {
1936 + $control_args['font_weight'] = $field_config['font_weight'];
1554 1937 }
1555 1938
1556 - if ( isset( $setting_config['subsets'] ) ) {
1557 - $control_args['subsets'] = $setting_config['subsets'];
1939 + if ( isset( $field_config['subsets'] ) ) {
1940 + $control_args['subsets'] = $field_config['subsets'];
1558 1941 }
1559 1942
1560 - if ( isset( $setting_config['recommended'] ) ) {
1561 - $control_args['recommended'] = array_flip( $setting_config['recommended'] );
1943 + if ( isset( $field_config['recommended'] ) ) {
1944 + $control_args['recommended'] = array_flip( $field_config['recommended'] );
1562 1945 }
1563 1946
1564 - if ( isset( $setting_config['load_all_weights'] ) ) {
1565 - $control_args['load_all_weights'] = $setting_config['load_all_weights'];
1947 + if ( isset( $field_config['load_all_weights'] ) ) {
1948 + $control_args['load_all_weights'] = $field_config['load_all_weights'];
1566 1949 }
1567 1950
1568 - if ( isset( $setting_config['default'] ) ) {
1569 - $control_args['default'] = $setting_config['default'];
1951 + if ( isset( $field_config['default'] ) ) {
1952 + $control_args['default'] = $field_config['default'];
1570 1953 }
1571 1954
1572 - if ( isset( $setting_config['fields'] ) ) {
1573 - $control_args['fields'] = $setting_config['fields'];
1955 + if ( isset( $field_config['fields'] ) ) {
1956 + $control_args['fields'] = $field_config['fields'];
1574 1957 }
1575 1958 $control_args['live'] = true;
1576 1959
1577 1960 break;
@@ -1576,30 +1959,60 @@
1576 1959
1577 1960 break;
1578 1961
1579 1962 case 'select2' :
1580 - if ( ! isset( $setting_config['choices'] ) || empty( $setting_config['choices'] ) ) {
1963 + if ( ! isset( $field_config['choices'] ) || empty( $field_config['choices'] ) ) {
1581 1964 return;
1582 1965 }
1583 1966
1584 - $control_args['choices'] = $setting_config['choices'];
1967 + $control_args['choices'] = $field_config['choices'];
1585 1968
1586 1969 $control_class_name = 'Pix_Customize_Select2_Control';
1587 1970 break;
1588 1971
1972 + case 'sm_radio' :
1973 + if ( ! isset( $field_config['choices'] ) || empty( $field_config['choices'] ) ) {
1974 + return;
1975 + }
1976 +
1977 + $control_args['choices'] = $field_config['choices'];
1978 +
1979 + $control_class_name = 'Pix_Customize_SM_radio_Control';
1980 + break;
1981 +
1982 + case 'sm_palette_filter' :
1983 + if ( ! isset( $field_config['choices'] ) || empty( $field_config['choices'] ) ) {
1984 + return;
1985 + }
1986 +
1987 + $control_args['choices'] = $field_config['choices'];
1988 +
1989 + $control_class_name = 'Pix_Customize_SM_palette_filter_Control';
1990 + break;
1991 +
1992 + case 'sm_switch' :
1993 + if ( ! isset( $field_config['choices'] ) || empty( $field_config['choices'] ) ) {
1994 + return;
1995 + }
1996 +
1997 + $control_args['choices'] = $field_config['choices'];
1998 +
1999 + $control_class_name = 'Pix_Customize_SM_switch_Control';
2000 + break;
2001 +
1589 2002 case 'preset' :
1590 - if ( ! isset( $setting_config['choices'] ) || empty( $setting_config['choices'] ) ) {
2003 + if ( ! isset( $field_config['choices'] ) || empty( $field_config['choices'] ) ) {
1591 2004 return;
1592 2005 }
1593 2006
1594 - $control_args['choices'] = $setting_config['choices'];
2007 + $control_args['choices'] = $field_config['choices'];
1595 2008
1596 - if ( isset( $setting_config['choices_type'] ) || ! empty( $setting_config['choices_type'] ) ) {
1597 - $control_args['choices_type'] = $setting_config['choices_type'];
2009 + if ( isset( $field_config['choices_type'] ) || ! empty( $field_config['choices_type'] ) ) {
2010 + $control_args['choices_type'] = $field_config['choices_type'];
1598 2011 }
1599 2012
1600 - if ( isset( $setting_config['desc'] ) || ! empty( $setting_config['desc'] ) ) {
1601 - $control_args['description'] = $setting_config['desc'];
2013 + if ( isset( $field_config['desc'] ) || ! empty( $field_config['desc'] ) ) {
2014 + $control_args['description'] = $field_config['desc'];
1602 2015 }
1603 2016
1604 2017
1605 2018 $control_class_name = 'Pix_Customize_Preset_Control';
@@ -1605,20 +2018,20 @@
1605 2018 $control_class_name = 'Pix_Customize_Preset_Control';
1606 2019 break;
1607 2020
1608 2021 case 'radio_image' :
1609 - if ( ! isset( $setting_config['choices'] ) || empty( $setting_config['choices'] ) ) {
2022 + if ( ! isset( $field_config['choices'] ) || empty( $field_config['choices'] ) ) {
1610 2023 return;
1611 2024 }
1612 2025
1613 - $control_args['choices'] = $setting_config['choices'];
2026 + $control_args['choices'] = $field_config['choices'];
1614 2027
1615 - if ( isset( $setting_config['choices_type'] ) || ! empty( $setting_config['choices_type'] ) ) {
1616 - $control_args['choices_type'] = $setting_config['choices_type'];
2028 + if ( isset( $field_config['choices_type'] ) || ! empty( $field_config['choices_type'] ) ) {
2029 + $control_args['choices_type'] = $field_config['choices_type'];
1617 2030 }
1618 2031
1619 - if ( isset( $setting_config['desc'] ) || ! empty( $setting_config['desc'] ) ) {
1620 - $control_args['description'] = $setting_config['desc'];
2032 + if ( isset( $field_config['desc'] ) || ! empty( $field_config['desc'] ) ) {
2033 + $control_args['description'] = $field_config['desc'];
1621 2034 }
1622 2035
1623 2036
1624 2037 $control_class_name = 'Pix_Customize_Radio_Image_Control';
@@ -1624,13 +2037,13 @@
1624 2037 $control_class_name = 'Pix_Customize_Radio_Image_Control';
1625 2038 break;
1626 2039
1627 2040 case 'button' :
1628 - if ( ! isset( $setting_config['action'] ) || empty( $setting_config['action'] ) ) {
2041 + if ( ! isset( $field_config['action'] ) || empty( $field_config['action'] ) ) {
1629 2042 return;
1630 2043 }
1631 2044
1632 - $control_args['action'] = $setting_config['action'];
2045 + $control_args['action'] = $field_config['action'];
1633 2046
1634 2047 $control_class_name = 'Pix_Customize_Button_Control';
1635 2048
1636 2049 break;
@@ -1635,10 +2048,10 @@
1635 2048
1636 2049 break;
1637 2050
1638 2051 case 'html' :
1639 - if ( isset( $setting_config['html'] ) || ! empty( $setting_config['html'] ) ) {
1640 - $control_args['html'] = $setting_config['html'];
2052 + if ( isset( $field_config['html'] ) || ! empty( $field_config['html'] ) ) {
2053 + $control_args['html'] = $field_config['html'];
1641 2054 }
1642 2055
1643 2056 $control_class_name = 'Pix_Customize_HTML_Control';
1644 2057 break;
@@ -1643,20 +2056,20 @@
1643 2056 $control_class_name = 'Pix_Customize_HTML_Control';
1644 2057 break;
1645 2058
1646 2059 case 'import_demo_data' :
1647 - if ( isset( $setting_config['html'] ) || ! empty( $setting_config['html'] ) ) {
1648 - $control_args['html'] = $setting_config['html'];
2060 + if ( isset( $field_config['html'] ) || ! empty( $field_config['html'] ) ) {
2061 + $control_args['html'] = $field_config['html'];
1649 2062 }
1650 2063
1651 - if ( ! isset( $setting_config['label'] ) || empty( $setting_config['label'] ) ) {
2064 + if ( ! isset( $field_config['label'] ) || empty( $field_config['label'] ) ) {
1652 2065 $control_args['label'] = esc_html__( 'Import', 'customify' );
1653 2066 } else {
1654 - $control_args['label'] = $setting_config['label'];
2067 + $control_args['label'] = $field_config['label'];
1655 2068 }
1656 2069
1657 - if ( isset( $setting_config['notices'] ) && ! empty( $setting_config['notices'] ) ) {
1658 - $control_args['notices'] = $setting_config['notices'];
2070 + if ( isset( $field_config['notices'] ) && ! empty( $field_config['notices'] ) ) {
2071 + $control_args['notices'] = $field_config['notices'];
1659 2072 }
1660 2073
1661 2074 $control_class_name = 'Pix_Customize_Import_Demo_Data_Control';
1662 2075 break;
@@ -1702,8 +2115,99 @@
1702 2115 }
1703 2116 }
1704 2117 }
1705 2118
2119 + /**
2120 + * Print JavaScript for adding additional data to _wpCustomizeSettings.settings object of the main window (not the preview window).
2121 + */
2122 + public function customize_pane_settings_additional_data() {
2123 + /**
2124 + * @global WP_Customize_Manager $wp_customize
2125 + */
2126 + global $wp_customize;
2127 +
2128 + // Without an options name we can't do much.
2129 + if ( empty( $this->customizer_config['opt-name'] ) ) {
2130 + return;
2131 + }
2132 +
2133 + $options_name = $this->customizer_config['opt-name'];
2134 + $customizer_settings = $wp_customize->settings();
2135 + ?>
2136 + <script type="text/javascript">
2137 + if ( 'undefined' === typeof _wpCustomizeSettings.settings ) {
2138 + _wpCustomizeSettings.settings = {};
2139 + }
2140 +
2141 + <?php
2142 + echo "(function ( sAdditional ){\n";
2143 +
2144 + $options = $this->get_options();
2145 + foreach ( $options as $option_id => $option_config ) {
2146 + // If we have been explicitly given a setting ID we will use that
2147 + if ( ! empty( $option_config['setting_id'] ) ) {
2148 + $setting_id = $option_config['setting_id'];
2149 + } else {
2150 + $setting_id = $options_name . '[' . $option_id . ']';
2151 + }
2152 + // @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()
2153 + if ( ! empty( $customizer_settings[ $setting_id ] ) && ! empty( $option_config['connected_fields'] ) ) {
2154 + // Pass through all the connected fields and make sure the id is in the final format
2155 + $connected_fields = array();
2156 + foreach ( $option_config['connected_fields'] as $key => $connected_field_config ) {
2157 + $connected_field_data = array();
2158 +
2159 + if ( is_string( $connected_field_config ) ) {
2160 + $connected_field_id = $connected_field_config;
2161 + } elseif ( is_array( $connected_field_config ) ) {
2162 + // We have a full blown connected field config
2163 + if ( is_string( $key ) ) {
2164 + $connected_field_id = $key;
2165 + } else {
2166 + continue;
2167 + }
2168 +
2169 + // We will pass to JS all the configured connected field details.
2170 + $connected_field_data = $connected_field_config;
2171 + }
2172 +
2173 + // Continue if we don't have a connected field ID to work with.
2174 + if ( empty( $connected_field_id ) ) {
2175 + continue;
2176 + }
2177 +
2178 + // If the connected setting is not one of our's, we will use it's ID as it is.
2179 + if ( ! array_key_exists( $connected_field_id, $options ) ) {
2180 + $connected_field_data['setting_id'] = $connected_field_id;
2181 + }
2182 + // If the connected setting specifies a setting ID, we will not prefix it and use it as it is.
2183 + elseif ( ! empty( $options[ $connected_field_id ] ) && ! empty( $options[ $connected_field_id ]['setting_id'] ) ) {
2184 + $connected_field_data['setting_id'] = $options[ $connected_field_id ]['setting_id'];
2185 + } else {
2186 + $connected_field_data['setting_id'] = $options_name . '[' . $connected_field_id . ']';
2187 + }
2188 +
2189 + $connected_fields[] = $connected_field_data;
2190 + }
2191 +
2192 + printf(
2193 + "sAdditional[%s].%s = %s;\n",
2194 + wp_json_encode( $setting_id ),
2195 + 'connected_fields',
2196 + wp_json_encode( $connected_fields, JSON_FORCE_OBJECT )
2197 + );
2198 + }
2199 + }
2200 + echo "})( _wpCustomizeSettings.settings );\n";
2201 + ?>
2202 + </script>
2203 + <?php
2204 + }
2205 +
2206 + public function get_file() {
2207 + return $this->file;
2208 + }
2209 +
1706 2210 public function get_base_path() {
1707 2211 return plugin_dir_path( $this->file );
1708 2212 }
1709 2213
@@ -1818,40 +2322,50 @@
1818 2322
1819 2323 return $settings;
1820 2324 }
1821 2325
1822 - protected function get_value( $option, $alt_opt_name ) {
2326 + protected function get_value( $option_id, $alt_opt_name ) {
1823 2327 global $wp_customize;
1824 2328
1825 - $opt_name = $this->opt_name;
2329 + $options_name = $this->opt_name;
1826 2330 $values = $this->current_values;
1827 2331
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 );
2332 + // 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
2333 + if ( empty( $options_name ) && ! empty( $alt_opt_name ) ) {
2334 + $options_name = $alt_opt_name;
2335 + $values = $this->get_current_values( $options_name );
1832 2336 }
1833 2337
1834 2338 if ( ! empty( $wp_customize ) && method_exists( $wp_customize, 'get_setting' ) ) {
2339 + // Get the field config.
2340 + $option_config = $this->get_option_customizer_config( $option_id );
1835 2341
1836 - $option_key = $opt_name . '[' . $option . ']';
1837 - $setting = $wp_customize->get_setting( $option_key );
2342 + if ( empty( $option_id ) || ! isset( $option_config['type'] ) ) {
2343 + return null;
2344 + }
2345 +
2346 + // If we have been explicitly given a setting ID we will use that
2347 + if ( ! empty( $option_config['setting_id'] ) ) {
2348 + $setting_id = $option_config['setting_id'];
2349 + } else {
2350 + $setting_id = $options_name . '[' . $option_id . ']';
2351 + }
2352 +
2353 + $setting = $wp_customize->get_setting( $setting_id );
1838 2354 if ( ! empty( $setting ) ) {
1839 - $value = $setting->value();
1840 -
1841 - return $value;
2355 + return $setting->value();
1842 2356 }
1843 2357 }
1844 2358
1845 2359 // shim
1846 - if ( strpos( $option, $opt_name . '[' ) !== false ) {
2360 + if ( strpos( $option_id, $options_name . '[' ) !== false ) {
1847 2361 // get only the setting id
1848 - $option = explode( '[', $option );
1849 - $option = rtrim( $option[1], ']' );
2362 + $option_id = explode( '[', $option_id );
2363 + $option_id = rtrim( $option_id[1], ']' );
1850 2364 }
1851 2365
1852 - if ( isset( $values[ $option ] ) ) {
1853 - return $values[ $option ];
2366 + if ( isset( $values[ $option_id ] ) ) {
2367 + return $values[ $option_id ];
1854 2368 }
1855 2369
1856 2370 return null;
1857 2371 }
@@ -1856,28 +2370,53 @@
1856 2370 return null;
1857 2371 }
1858 2372
1859 2373 /**
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
2374 + * A public function to get an option's value.
2375 + * If there is a value and return it.
2376 + * Otherwise try to get the default parameter or the default from config.
1863 2377 *
1864 - * @param $option
2378 + * @param $option_id
1865 2379 * @param mixed $default Optional.
1866 2380 * @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 2381 *
1868 2382 * @return bool|null|string
1869 2383 */
1870 - public function get_option( $option, $default = null, $alt_opt_name = null ) {
2384 + public function get_option( $option_id, $default = null, $alt_opt_name = null ) {
2385 + // If the development constant CUSTOMIFY_DEV_FORCE_DEFAULTS has been defined we will not retrieve anything from the database
2386 + // Always go with the default
2387 + if ( defined( 'CUSTOMIFY_DEV_FORCE_DEFAULTS' ) && true === CUSTOMIFY_DEV_FORCE_DEFAULTS && ! $this->skip_dev_mode_force_defaults( $option_id ) ) {
2388 + $return = null;
2389 + } else {
2390 + // Get the field config.
2391 + $option_config = $this->get_option_customizer_config( $option_id );
1871 2392
1872 - $return = $this->get_value( $option, $alt_opt_name );
2393 + if ( empty( $option_id ) ) {
2394 + $return = null;
2395 + } elseif ( isset( $option_config['setting_type'] ) && $option_config['setting_type'] === 'option' ) {
2396 + // We have a setting that is saved in the wp_options table, not in theme_mods.
2397 + // We will fetch it directly.
1873 2398
2399 + // If we have been explicitly given a setting ID we will use that
2400 + if ( ! empty( $option_config['setting_id'] ) ) {
2401 + $setting_id = $option_config['setting_id'];
2402 + } else {
2403 + $setting_id = $this->opt_name . '[' . $option_id . ']';
2404 + }
2405 +
2406 + $return = get_option( $setting_id, null );
2407 + } else {
2408 + // Get the value stores in theme_mods.
2409 + $return = $this->get_value( $option_id, $alt_opt_name );
2410 + }
2411 + }
2412 +
1874 2413 if ( $return !== null ) {
1875 2414 return $return;
1876 2415 } elseif ( $default !== null ) {
1877 2416 return $default;
1878 - } elseif ( isset( $this->options_list[ $option ] ) && isset( $this->options_list[ $option ]['default'] ) ) {
1879 - return $this->options_list[ $option ]['default'];
2417 + } elseif ( isset( $this->options_list[ $option_id ] ) && isset( $this->options_list[ $option_id ]['default'] ) ) {
2418 + return $this->options_list[ $option_id ]['default'];
1880 2419 }
1881 2420
1882 2421 return null;
1883 2422 }
@@ -1890,8 +2429,52 @@
1890 2429
1891 2430 return false;
1892 2431 }
1893 2432
2433 + public function get_customizer_config() {
2434 + return $this->customizer_config;
2435 + }
2436 +
2437 + /**
2438 + * Get the Customify configuration of a certain option.
2439 + *
2440 + * @param string $option_id
2441 + *
2442 + * @return array|false The option config or false on failure.
2443 + */
2444 + public function get_option_customizer_config( $option_id ) {
2445 + // We need to search for the option configured under the given id (the array key)
2446 + if ( isset ( $this->customizer_config['panels'] ) ) {
2447 + foreach ( $this->customizer_config['panels'] as $panel_id => $panel_settings ) {
2448 + if ( isset( $panel_settings['sections'] ) ) {
2449 + foreach ( $panel_settings['sections'] as $section_id => $section_settings ) {
2450 + if ( isset( $section_settings['options'] ) ) {
2451 + foreach ( $section_settings['options'] as $id => $option_config ) {
2452 + if ( $id === $option_id ) {
2453 + return $option_config;
2454 + }
2455 + }
2456 + }
2457 + }
2458 + }
2459 + }
2460 + }
2461 +
2462 + if ( isset ( $this->customizer_config['sections'] ) ) {
2463 + foreach ( $this->customizer_config['sections'] as $section_id => $section_settings ) {
2464 + if ( isset( $section_settings['options'] ) ) {
2465 + foreach ( $section_settings['options'] as $id => $option_config ) {
2466 + if ( $id === $option_id ) {
2467 + return $option_config;
2468 + }
2469 + }
2470 + }
2471 + }
2472 + }
2473 +
2474 + return false;
2475 + }
2476 +
1894 2477 protected function get_config() {
1895 2478 if ( file_exists( $this->get_base_path() . 'plugin-config.php' ) ) {
1896 2479 return include( $this->get_base_path() . 'plugin-config.php' );
1897 2480 }
@@ -1975,9 +2558,9 @@
1975 2558 $controller = new Customify_Importer_Controller();
1976 2559 $controller->init();
1977 2560 }
1978 2561
1979 - function get_options_configs() {
2562 + public function get_options_configs() {
1980 2563 return $this->options_list;
1981 2564 }
1982 2565
1983 2566 /**
@@ -2008,9 +2591,9 @@
2008 2591 *
2009 2592 * @return string
2010 2593 */
2011 2594 public static function decodeURIComponent( $str ) {
2012 - //if we get an array we just let it be
2595 + // If we get an array we just let it be
2013 2596 if ( is_string( $str ) ) {
2014 2597 $revert = array( '!' => '%21', '*' => '%2A', "'" => '%27', '(' => '%28', ')' => '%29' );
2015 2598 $str = rawurldecode( strtr( $str, $revert ) );
2016 2599 }
@@ -2032,13 +2615,90 @@
2032 2615 return true;
2033 2616 }
2034 2617
2035 2618 /**
2036 - * Return an instance of this class.
2037 - * @since 1.0.0
2038 - * @return PixCustomifyPlugin A single instance of this class.
2619 + * Prevent saving of plugin options in the Customizer
2620 + *
2621 + * @param array $data The data to save
2622 + * @param array $filter_context
2623 + *
2624 + * @return array
2039 2625 */
2626 + public function prevent_changeset_save_in_devmode( $data, $filter_context ) {
2627 + // Get the options key
2628 + $options_key = $this->customizer_config['opt-name'];
2629 + if ( ! empty( $options_key ) ) {
2630 + // Remove any Customify data thus preventing it from saving
2631 + foreach ( $data as $option_id => $value ) {
2632 + if ( false !== strpos( $option_id, $options_key ) && ! $this->skip_dev_mode_force_defaults( $option_id ) ) {
2633 + unset( $data[ $option_id ] );
2634 + }
2635 + }
2636 + }
2637 +
2638 + return $data;
2639 + }
2640 +
2040 2641 /**
2642 + * Determine if we should NOT enforce the CUSTOMIFY_DEV_FORCE_DEFAULTS behavior on a certain option.
2643 + *
2644 + * @param string $option_id
2645 + *
2646 + * @return bool
2647 + */
2648 + private function skip_dev_mode_force_defaults( $option_id ) {
2649 + // Preprocess the $option_id.
2650 + if ( false !== strpos( $option_id, '::' ) ) {
2651 + $option_id = substr( $option_id, strpos( $option_id, '::' ) + 2 );
2652 + }
2653 + if ( false !== strpos( $option_id, '[' ) ) {
2654 + $option_id = explode( '[', $option_id );
2655 + $option_id = rtrim( $option_id[1], ']' );
2656 + }
2657 +
2658 + $option_config = $this->get_option_customizer_config( $option_id );
2659 + if ( empty( $option_config ) ) {
2660 + return false;
2661 + }
2662 +
2663 + // We will skip certain field types that generally don't have a default value.
2664 + if ( ! empty( $option_config['type'] ) ) {
2665 + switch ( $option_config['type'] ) {
2666 + case 'cropped_image':
2667 + case 'cropped_media':
2668 + case 'image':
2669 + case 'media':
2670 + case 'custom_background':
2671 + case 'upload':
2672 + return true;
2673 + break;
2674 + default:
2675 + break;
2676 + }
2677 + }
2678 +
2679 + return false;
2680 + }
2681 +
2682 + public function prevent_changeset_save_in_devmode_notification() { ?>
2683 + <script type="application/javascript">
2684 + (function ( $, exports, wp ) {
2685 + 'use strict';
2686 + // when the customizer is ready add our notification
2687 + wp.customize.bind('ready', function () {
2688 + wp.customize.notifications.add( 'customify_force_defaults', new wp.customize.Notification(
2689 + 'customify_force_defaults',
2690 + {
2691 + type: 'warning',
2692 + 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>'
2693 + }
2694 + ) );
2695 + });
2696 + })(jQuery, window, wp);
2697 + </script>
2698 + <?php }
2699 +
2700 + /**
2041 2701 * Main PixCustomifyPlugin Instance
2042 2702 *
2043 2703 * Ensures only one instance of PixCustomifyPlugin is loaded or can be loaded.
2044 2704 *
@@ -2048,9 +2708,9 @@
2048 2708 * @param string $file File.
2049 2709 * @param string $version Version.
2050 2710 *
2051 2711 * @see PixCustomifyPlugin()
2052 - * @return object Main PixCustomifyPlugin instance
2712 + * @return PixCustomifyPlugin Main PixCustomifyPlugin instance
2053 2713 */
2054 2714 public static function instance( $file = '', $version = '1.0.0' ) {
2055 2715 // If the single instance hasn't been set, set it now.
2056 2716 if ( is_null( self::$_instance ) ) {
@@ -2078,5 +2738,5 @@
2078 2738 public function __wakeup() {
2079 2739
2080 2740 _doing_it_wrong( __FUNCTION__, esc_html( __( 'Cheatin&#8217; huh?' ) ), esc_html( $this->_version ) );
2081 2741 } // End __wakeup ()
2082 -}
2742 +}