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 +1248 -527 1.5.1 → 2.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 */
@@ -182,11 +203,18 @@
182 203 * Prepare and load the configuration
183 204 */
184 205 $this->init_plugin_configs();
185 206
186 - // We can load the actual plugins config only on after_setup_theme so we can give the themes a change to have their say
207 + // We need to load the configuration as late as possible so we allow all that want to influence it
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)
209 + // We need to be able to load things like components configs depending on those firing up or not
187 210 // DO NOT TRY to use the Customify values before this!
188 - add_action( 'after_setup_theme', array( $this, 'load_plugin_configs' ), 5 );
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 );
189 217
190 218 /*
191 219 * Now setup the admin side of things
192 220 */
@@ -207,43 +235,74 @@
207 235 // Styles for the Customizer
208 236 add_action( 'customize_controls_init', array( $this, 'register_admin_customizer_styles' ), 10 );
209 237 add_action( 'customize_controls_enqueue_scripts', array( $this, 'enqueue_admin_customizer_styles' ), 10 );
210 238 // Scripts enqueued in the Customizer
211 - add_action( 'customize_controls_init', array( $this, 'register_admin_customizer_scripts' ), 10 );
212 - 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 );
213 241
214 242 // Scripts enqueued only in the theme preview
215 243 add_action( 'customize_preview_init', array( $this, 'customizer_live_preview_register_scripts' ), 10 );
216 244 add_action( 'customize_preview_init', array( $this, 'customizer_live_preview_enqueue_scripts' ), 99999 );
217 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 +
218 249 // The frontend effects of the Customizer controls
219 250 $load_location = $this->get_plugin_setting( 'style_resources_location', 'wp_head' );
220 251
221 - add_action( $load_location, array( $this, 'output_dynamic_style' ), 99999 );
252 + add_action( $load_location, array( $this, 'output_dynamic_style' ), 99 );
253 + add_action( 'wp_head', array( $this, 'output_typography_dynamic_script' ), 10 );
222 254 add_action( 'wp_head', array( $this, 'output_typography_dynamic_style' ), 10 );
223 255
224 256 add_action( 'customize_register', array( $this, 'remove_default_sections' ), 11 );
225 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 );
226 260
227 261 if ( $this->get_plugin_setting( 'enable_editor_style', true ) ) {
228 - 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 );
229 263 }
230 264
265 + add_action( 'rest_api_init', array( $this, 'add_rest_routes_api' ) );
266 +
231 267 /*
232 - * Jetpack Related
268 + * Development related
233 269 */
234 - add_filter( 'default_option_jetpack_active_modules', array( $this, 'default_jetpack_active_modules' ), 10, 1 );
235 - add_filter( 'jetpack_get_available_modules', array( $this, 'jetpack_hide_blocked_modules' ), 10, 1 );
236 - 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 + }
237 277 }
238 278
239 279 /**
240 - * Initialize Configs, Options and Values methods
280 + * Handle the logic to upgrade between versions. It will run only one per version change.
241 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 );
296 + }
297 +
298 + /**
299 + * Initialize Configs, Options and Values methods.
300 + */
242 301 function init_plugin_configs() {
243 302 $this->customizer_config = get_option( 'pixcustomify_config' );
244 303
245 - // no option so go for default
304 + // no option so go for default.
246 305 if ( empty( $this->customizer_config ) ) {
247 306 $this->customizer_config = $this->get_config_option( 'default_options' );
248 307 }
249 308
@@ -252,18 +311,18 @@
252 311 }
253 312 }
254 313
255 314 /**
256 - * Load the plugin configuration and options
315 + * Load the plugin configuration and options.
257 316 */
258 317 function load_plugin_configs() {
259 318
260 - // allow themes or other plugins to filter the config
261 - $this->customizer_config = apply_filters( 'customify_filter_fields', $this->customizer_config );
319 + $this->load_customizer_config();
320 +
262 321 $this->opt_name = $this->localized['options_name'] = $this->customizer_config['opt-name'];
263 322 $this->options_list = $this->get_options();
264 323
265 - // Load the current options values
324 + // Load the current options values.
266 325 $this->current_values = $this->get_current_values();
267 326
268 327 if ( $this->import_button_exists() ) {
269 328 $this->localized['import_rest_url'] = get_rest_url( '/customify/1.0/' );
@@ -272,85 +331,83 @@
272 331 $this->register_import_api();
273 332 }
274 333
275 334 $this->localized['theme_fonts'] = $this->theme_fonts = Customify_Font_Selector::instance()->get_theme_fonts();
335 +
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 );
276 339 }
277 340
278 341 /**
279 - * Control the default modules that are activated in Jetpack.
280 - * Use the `customify_filter_jetpack_default_modules` to set your's.
342 + * Set the customizer configuration.
281 343 *
282 - * @param array $default The default value to return if the option does not exist
283 - * in the database.
344 + * @since 2.2.1
284 345 *
285 - * @return array
346 + * @param bool $skip_cache Optional. Whether to use the cached config or generate a new one.
286 347 */
287 - function default_jetpack_active_modules( $default ) {
288 - if ( ! is_array( $default ) ) {
289 - $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;
290 355 }
291 - $jetpack_default_modules = array();
292 356
293 - $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 + }
294 362
295 - if ( ! is_array( $theme_default_modules ) ) {
296 - return array_merge( $default, $jetpack_default_modules );
297 - }
363 + // Get the cache data expiration timestamp.
364 + $expire_timestamp = get_option( $this->_get_customizer_config_cache_key() . '_timestamp' );
298 365
299 - foreach ( $theme_default_modules as $module ) {
300 - 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 );
301 377 }
302 378
303 - return array_merge( $default, $jetpack_default_modules );
379 + $this->customizer_config = $data;
380 + return;
304 381 }
305 382
306 383 /**
307 - * Control the default Jetpack Sharing options.
308 - * Use the `customify_filter_jetpack_sharing_default_options` to set your's.
384 + * Clear the customizer config cache.
309 385 *
310 - * @param array $default The default value to return if the option does not exist
311 - * in the database.
312 - *
313 - * @return array
386 + * @since 2.2.1
314 387 */
315 - function default_jetpack_sharing_options( $default ) {
316 - if ( ! is_array( $default ) ) {
317 - $default = array();
318 - }
319 -
320 - 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' );
321 391 }
322 392
323 393 /**
324 - * Control the modules that are available in Jetpack (hide some of them).
325 - * Use the `customify_filter_jetpack_blocked_modules` filter to set your's.
394 + * Get the customizer config cache key.
326 395 *
327 - * @param array $modules
396 + * @since 2.2.1
328 397 *
329 - * @return array
398 + * @return string
330 399 */
331 - function jetpack_hide_blocked_modules( $modules ) {
332 - return array_diff_key( $modules, array_flip( $this->jetpack_blocked_modules ) );
400 + private function _get_customizer_config_cache_key() {
401 + return 'customify_customizer_config';
333 402 }
334 403
335 - /**
336 - * Fired when the plugin is activated.
337 - * @since 1.0.0
338 - *
339 - * @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.
340 - */
341 - public static function activate( $network_wide ) {
342 - //@todo Define activation functionality here
404 + public function get_version() {
405 + return $this->_version;
343 406 }
344 407
345 - /**
346 - * Fired when the plugin is deactivated.
347 - * @since 1.0.0
348 - *
349 - * @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.
350 - */
351 - static function deactivate( $network_wide ) {
352 - //@todo Define deactivation functionality here
408 + public function get_slug() {
409 + return $this->plugin_slug;
353 410 }
354 411
355 412 /**
356 413 * Load the plugin text domain for translation.
@@ -384,13 +441,20 @@
384 441 function register_admin_customizer_scripts() {
385 442
386 443 wp_register_script( 'customify_select2', plugins_url( 'js/select2/js/select2.js', $this->file ), array( 'jquery' ), $this->_version );
387 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 +
388 449 wp_register_script( $this->plugin_slug . '-customizer-scripts', plugins_url( 'js/customizer.js', $this->file ), array(
389 450 'jquery',
390 451 'customify_select2',
391 452 'underscore',
392 - 'customize-controls'
453 + 'customize-controls',
454 + 'customify-fontselectfields',
455 +
456 + 'customify-scale',
393 457 ), $this->_version );
394 458 }
395 459
396 460 /**
@@ -399,15 +463,15 @@
399 463 function enqueue_admin_customizer_scripts() {
400 464 wp_enqueue_script( 'jquery-react' );
401 465 wp_enqueue_script( $this->plugin_slug . '-customizer-scripts' );
402 466
403 - 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 ) );
404 468 }
405 469
406 470 /** Register Customizer scripts loaded only on previewer page */
407 471 function customizer_live_preview_register_scripts() {
408 472 wp_register_script( $this->plugin_slug . 'CSSOM', plugins_url( 'js/CSSOM.js', $this->file ), array( 'jquery' ), $this->_version, true );
409 - 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 );
410 474 wp_register_script( $this->plugin_slug . '-previewer-scripts', plugins_url( 'js/customizer_preview.js', $this->file ), array(
411 475 'jquery',
412 476 'customize-preview',
413 477 $this->plugin_slug . 'CSSOM',
@@ -455,14 +519,18 @@
455 519
456 520 $screen = get_current_screen();
457 521 if ( $screen->id == $this->plugin_screen_hook_suffix ) {
458 522 wp_enqueue_script( $this->plugin_slug . '-admin-script', plugins_url( 'js/admin.js', $this->file ), array( 'jquery' ), $this->_version );
459 - wp_localize_script( $this->plugin_slug . '-admin-script', 'locals', array(
460 - 'ajax_url' => admin_url( 'admin-ajax.php' )
523 + wp_localize_script( $this->plugin_slug . '-admin-script', 'customify_settings', array(
524 + 'ajax_url' => admin_url( 'admin-ajax.php' ),
525 + 'wp_rest' => array(
526 + 'root' => esc_url_raw( rest_url() ),
527 + 'nonce' => wp_create_nonce( 'wp_rest' ),
528 + 'customify_settings_nonce' => wp_create_nonce( 'customify_settings_nonce' )
529 + ),
461 530 ) );
462 531 }
463 532
464 -
465 533 wp_localize_script( $this->plugin_slug . '-customizer-scripts', 'WP_API_Settings', array(
466 534 'root' => esc_url_raw( rest_url() ),
467 535 'nonce' => wp_create_nonce( 'wp_rest' )
468 536 ) );
@@ -467,52 +535,58 @@
467 535 'nonce' => wp_create_nonce( 'wp_rest' )
468 536 ) );
469 537 }
470 538
471 - /**
472 - * Public style generated by customizer
473 - */
474 - function output_dynamic_style() {
475 - $custom_css = "\n";
539 + function add_rest_routes_api(){
540 + register_rest_route( 'customify/v1', '/delete_theme_mod', array(
541 + 'methods' => 'POST',
542 + 'callback' => array( $this, 'delete_theme_mod' ),
543 + 'permission_callback' => array( $this, 'permission_nonce_callback' ),
544 + ) );
545 + }
476 546
477 - foreach ( $this->options_list as $option_id => $option ) {
547 + function delete_theme_mod(){
548 + if ( ! current_user_can( 'manage_options' ) ) {
549 + wp_send_json_error('You don\'t have admin privileges.');
550 + }
478 551
479 - if ( isset( $option['css'] ) && ! empty( $option['css'] ) ) {
480 - // now process each
481 - $custom_css .= $this->convert_setting_to_css( $option_id, $option['css'] );
482 - }
552 + $config = apply_filters('customify_filter_fields', array() );
483 553
484 - if ( $option['type'] === 'custom_background' ) {
485 - $custom_css .= $this->process_custom_background_field_output( $option_id, $option );
486 - }
554 + if ( empty( $config['opt-name'] ) ) {
555 + wp_send_json_error('no option key');
487 556 }
488 557
489 - if ( ! empty( $this->media_queries ) ) {
558 + $key = $config['opt-name'];
490 559
491 - foreach ( $this->media_queries as $media_query => $properties ) {
560 + remove_theme_mod( $key );
492 561
493 - if ( empty( $properties ) ) {
494 - continue;
495 - }
562 + wp_send_json_success('Deleted ' . $key . ' theme mod!');
563 + }
496 564
497 - $custom_css .= '@media ' . $media_query . " { ";
565 + function permission_nonce_callback() {
566 + return wp_verify_nonce( $this->get_nonce(), 'customify_settings_nonce' );
567 + }
498 568
499 - foreach ( $properties as $key => $property ) {
500 - $property_settings = $property['property'];
501 - $property_value = $property['value'];
502 - $custom_css .= $this->proccess_css_property( $property_settings, $property_value );
503 - }
569 + private function get_nonce() {
570 + $nonce = null;
504 571
505 - $custom_css .= " }\n";
572 + if ( isset( $_REQUEST['customify_settings_nonce'] ) ) {
573 + $nonce = wp_unslash( $_REQUEST['customify_settings_nonce'] );
574 + } elseif ( isset( $_POST['customify_settings_nonce'] ) ) {
575 + $nonce = wp_unslash( $_POST['customify_settings_nonce'] );
576 + }
506 577
507 - }
508 - }
578 + return $nonce;
579 + }
509 580
510 - $custom_css .= "\n";
511 - ?>
512 - <style id="customify_output_style">
513 - <?php echo apply_filters( 'customify_dynamic_style', $custom_css ); ?>
514 - </style><?php
581 + /**
582 + * Output CSS style generated by customizer
583 + */
584 + function output_dynamic_style() { ?>
585 +<style id="customify_output_style">
586 +<?php echo $this->get_dynamic_style(); ?>
587 +</style>
588 +<?php
515 589
516 590 /**
517 591 * from now on we output only style tags only for the preview purpose
518 592 * so don't cry if you see 30+ style tags for each section
@@ -522,15 +596,15 @@
522 596 }
523 597
524 598 foreach ( $this->options_list as $option_id => $options ) {
525 599
526 - if ( $options['type'] === 'custom_background' ) {
600 + if ( isset( $options['type'] ) && $options['type'] === 'custom_background' ) {
527 601 $options['value'] = $this->get_option( $option_id );
528 602 $custom_background_output = $this->process_custom_background_field_output( $option_id, $options ); ?>
529 603
530 - <style id="custom_backgorund_output_for_<?php echo $option_id; ?>">
604 + <style id="custom_background_output_for_<?php echo sanitize_html_class( $option_id ); ?>">
531 605 <?php
532 - if ( isset( $custom_background_output ) && ! empty( $custom_background_output )) {
606 + if ( ! empty( $custom_background_output )) {
533 607 echo $custom_background_output;
534 608 } ?>
535 609 </style>
536 610 <?php }
@@ -539,27 +613,54 @@
539 613 continue;
540 614 }
541 615
542 616 $this_value = $this->get_option( $option_id );
543 - foreach ( $options['css'] as $key => $properties_set ) { ?>
544 - <style id="dynamic_setting_<?php echo $option_id . '_property_' . str_replace( '-', '_', $properties_set['property'] ); ?>"
545 - 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;
546 622
623 + $inline_style = '<style class="' . sanitize_html_class( $unique_class ) . '" type="text/css">';
624 +
547 625 if ( isset( $properties_set['media'] ) && ! empty( $properties_set['media'] ) ) {
548 - echo '@media '. $properties_set['media'] . " {\n";
626 + $inline_style .= '@media '. $properties_set['media'] . ' {';
549 627 }
550 628
551 629 if ( isset( $properties_set['selector'] ) && isset( $properties_set['property'] ) ) {
552 - 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 + }
553 634 }
554 635
555 636 if ( isset( $properties_set['media'] ) && ! empty( $properties_set['media'] ) ) {
556 - echo "}\n";
557 - } ?>
558 - </style>
559 - <?php }
637 + $inline_style .= '}';
638 + }
639 + $inline_style .= '</style>';
640 +
641 + echo $inline_style;
642 + }
643 + }
560 644 }
645 + }
561 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 +
562 663 if ( ! empty( $this->media_queries ) ) {
563 664
564 665 foreach ( $this->media_queries as $media_query => $properties ) {
565 666
@@ -566,32 +667,31 @@
566 667 if ( empty( $properties ) ) {
567 668 continue;
568 669 }
569 670
570 - $display = false;
571 - $media_q = '@media ' . $media_query . " {\n";
671 + $media_query_custom_css = '';
572 672
573 673 foreach ( $properties as $key => $property ) {
574 -
575 - if ( ! isset( $options['live'] ) || $options['live'] !== true ) {
576 - 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;
577 679 }
680 + }
578 681
579 - $display = true; ?>
580 - <style id="dynamic_setting_<?php echo $key; ?>" type="text/css"><?php
581 - $property_settings = $property['property'];
582 - $property_value = $property['value'];
583 - $media_q .= "\t" . $this->proccess_css_property( $property_settings, $property_value );?>
584 - </style>
585 - <?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 + }
586 685
587 - $media_q .= "\n}\n";
686 + if ( ! empty( $media_query_custom_css ) ) {
687 + $custom_css .= $media_query_custom_css;
688 + }
588 689
589 - if ( $display ) {
590 - $custom_css .= $media_q;
591 - }
592 690 }
593 691 }
692 +
693 + return apply_filters( 'customify_dynamic_style', $custom_css );
594 694 }
595 695
596 696 protected function load_google_fonts() {
597 697 $fonts_path = plugin_dir_path( $this->file ) . 'features/customizer/controls/resources/google.fonts.php';
@@ -607,14 +707,154 @@
607 707 return false;
608 708 }
609 709
610 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 +
611 723 $this->get_typography_fields( $this->options_list, 'type', 'typography', $this->typo_settings );
612 724
613 725 if ( empty( $this->typo_settings ) ) {
614 - return;
726 + return $output;
615 727 }
616 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 +
617 857 $families = '';
618 858
619 859 foreach ( $this->typo_settings as $id => $font ) {
620 860 if ( isset ( $font['value'] ) ) {
@@ -624,30 +864,39 @@
624 864 $load_all_weights = true;
625 865 }
626 866
627 867 // shim the time when this was an array
868 + // @todo Is this really needed? Or does it make sense?
628 869 if ( is_array( $font['value'] ) ) {
629 870 $font['value'] = stripslashes_deep( $font['value'] );
630 871 $font['value'] = json_encode( $font['value'] );
631 872 }
632 873
633 - $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 + }
634 878
635 - // in case the value is still null, try default value(mostly for google fonts)
636 - 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 ) ) {
637 881 $value = $this->get_font_defaults_value( str_replace( '"', '', $font['value'] ) );
638 882 }
639 883
640 - //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
641 885 if ( empty( $value ) ) {
642 886 continue;
643 887 }
644 888
645 - //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
646 890 if ( ! $this->is_assoc( $value ) ) {
647 - $value = $this->process_a_not_associative_font_default( $value );
891 + $value = $this->standardize_non_associative_font_default( $value );
648 892 }
649 893
894 + // Bail if empty or we don't have an array
895 + if ( empty( $value ) || ! is_array( $value ) ) {
896 + continue;
897 + }
898 +
650 899 if ( isset( $value['font_family'] ) && isset( $value['type'] ) && $value['type'] == 'google' ) {
651 900 $families .= "'" . $value['font_family'];
652 901
653 902 if ( $load_all_weights && is_array( $value['variants'] ) ) {
@@ -684,140 +933,54 @@
684 933 }
685 934 }
686 935 }
687 936
688 - if ( ! empty ( $families ) && $this->get_plugin_setting( 'typography', '1' ) && $this->get_plugin_setting( 'typography_google_fonts', 1 ) ) { ?>
689 - <script type="text/javascript">
690 - if (typeof WebFont !== 'undefined') {<?php // if there is a WebFont object, use it ?>
691 - WebFont.load({
692 - google: {families: [<?php echo( rtrim( $families, ',' ) ); ?>]},
693 - classes: false,
694 - events: false
695 - });
696 - } 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 ?>
697 947
698 - var tk = document.createElement('script');
699 - tk.src = '//ajax.googleapis.com/ajax/libs/webfont/1/webfont.js';
700 - 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';
701 951
702 - tk.onload = tk.onreadystatechange = function () {
703 - WebFont.load({
704 - google: {families: [<?php echo( rtrim( $families, ',' ) ); ?>]},
705 - classes: false,
706 - events: false
707 - });
708 - };
952 + tk.onload = tk.onreadystatechange = function () {
953 + WebFont.load({
954 + google: {families: [<?php echo( rtrim( $families, ',' ) ); ?>]},
955 + classes: false,
956 + events: false
957 + });
958 + };
709 959
710 - var s = document.getElementsByTagName('script')[0];
711 - s.parentNode.insertBefore(tk, s);
712 - }
713 - </script>
714 - <?php } ?>
715 - <style id="customify_typography_output_style">
716 - <?php
717 - foreach ( $this->typo_settings as $key => $font ) {
718 - $load_all_weights = false;
719 - if ( isset( $font['load_all_weights'] ) && $font['load_all_weights'] == 'true' ) {
720 - $load_all_weights = true;
721 - }
960 + var s = document.getElementsByTagName('script')[0];
961 + s.parentNode.insertBefore(tk, s);
962 +}<?php
963 + $output = ob_get_clean();
964 + }
722 965
723 - if ( isset( $font['selector'] ) && isset( $font['value'] ) && ! empty( $font['value'] ) ) {
966 + return $output;
967 + }
724 968
725 - $value = json_decode( PixCustomifyPlugin::decodeURIComponent( $font['value'] ), true );
726 - // in case the value is still null, try default value(mostly for google fonts)
727 - if ( $value === null ) {
728 - $value = $this->get_font_defaults_value( $font['value'] );
729 - }
730 -
731 - // shim the old case when the default was only the font name
732 - if ( is_string( $value ) && ! empty( $value ) ) {
733 - $value = array( 'font_family' => $value );
734 - }
735 -
736 - //Handle special logic for when the $value array is not an associative array
737 - if ( ! $this->is_assoc( $value ) ) {
738 - $value = $this->process_a_not_associative_font_default( $value );
739 - }
740 -
741 - $selected_variant = '';
742 - if ( ! empty( $value['selected_variants'] ) ) {
743 - if ( is_array( $value['selected_variants'] ) ) {
744 - $selected_variant = $value['selected_variants'][0];
745 - } else {
746 - $selected_variant = $value['selected_variants'];
747 - }
748 - }
749 -
750 - // First handle the case where we have the font-family in the selected variant (usually this means a custom font from our Fonto plugin)
751 - if ( ! empty( $selected_variant ) && is_array( $selected_variant ) && ! empty( $selected_variant['font-family'] ) ) {
752 - //the variant's font-family
753 - echo $font['selector'] . " {\nfont-family: " . $selected_variant['font-family'] . ";\n";
754 -
755 - if ( ! $load_all_weights ) {
756 - // if this is a custom font (like from our plugin Fonto) with individual styles & weights - i.e. the font-family says it all
757 - // we need to "force" the font-weight and font-style
758 - if ( ! empty( $value['type'] ) && 'custom_individual' == $value['type'] ) {
759 - $selected_variant['font-weight'] = '400 !important';
760 - $selected_variant['font-style'] = 'normal !important';
761 - }
762 -
763 - // output the font weight, if available
764 - if ( ! empty( $selected_variant['font-weight'] ) ) {
765 - echo "font-weight: " . $selected_variant['font-weight'] . ";\n";
766 - }
767 -
768 - // output the font style, if available
769 - if ( ! empty( $selected_variant['font-style'] ) ) {
770 - echo "font-style: " . $selected_variant['font-style'] . ";\n";
771 - }
772 - }
773 -
774 - echo "}\n";
775 - } elseif ( isset( $value['font_family'] ) ) {
776 - // the selected font family
777 - echo $font['selector'] . " {\n font-family: " . $value['font_family'] . ";\n";
778 -
779 - if ( ! empty( $selected_variant ) && ! $load_all_weights ) {
780 - $weight_and_style = strtolower( $selected_variant );
781 -
782 - $italic_font = false;
783 -
784 - //determine if this is an italic font (the $weight_and_style is usually like '400' or '400italic' )
785 - if ( strpos( $weight_and_style, 'italic' ) !== false ) {
786 - $weight_and_style = str_replace( 'italic', '', $weight_and_style);
787 - $italic_font = true;
788 - }
789 -
790 - if ( ! empty( $weight_and_style ) ) {
791 - //a little bit of sanity check - in case it's not a number
792 - if( $weight_and_style === 'regular' ) {
793 - $weight_and_style = 'normal';
794 - }
795 - echo "font-weight: " . $weight_and_style . ";\n";
796 - }
797 -
798 - if ( $italic_font ) {
799 - echo "font-style: italic;\n";
800 - }
801 - }
802 -
803 - echo "}\n";
804 - }
805 - }
806 - } ?>
807 - </style>
808 - <?php }
809 -
810 969 /**
811 970 * Handle special logic for when the $value array is not an associative array
812 971 * Return a new associative array with proper keys
813 972 */
814 - 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 + }
815 978
816 979 $new_value = array();
817 980
818 - //Let's determine some type of font
819 - 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] ) {
820 983 $new_value = $this->get_font_defaults_value( $value[0] );
821 984 } else {
822 985 $new_value['type'] = $value[2];
823 986 }
@@ -825,15 +988,15 @@
825 988 if ( null == $new_value ) {
826 989 $new_value = array();
827 990 }
828 991
829 - //The first entry is the font-family
992 + // The first entry is the font-family
830 993 if ( isset( $value[0] ) ) {
831 994 $new_value['font_family'] = $value[0];
832 995 }
833 996
834 - //In case we don't have an associative array
835 - //The second entry is the variants
997 + // In case we don't have an associative array
998 + // The second entry is the variants
836 999 if ( isset( $value[1] ) ) {
837 1000 $new_value['selected_variants'] = $value[1];
838 1001 }
839 1002
@@ -896,10 +1059,10 @@
896 1059 );
897 1060 continue;
898 1061 }
899 1062
900 - if ( ! isset( $css_property['selector'] ) || isset( $css_property['property'] ) ) {
901 - $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 );
902 1065 }
903 1066 }
904 1067
905 1068 return $output;
@@ -904,9 +1067,9 @@
904 1067
905 1068 return $output;
906 1069 }
907 1070
908 - protected function proccess_css_property( $css_property, $this_value ) {
1071 + protected function process_css_property( $css_property, $this_value, $editor = false ) {
909 1072 $unit = '';
910 1073
911 1074 if ( isset( $css_property['unit'] ) ) {
912 1075 $unit = $css_property['unit'];
@@ -915,22 +1078,83 @@
915 1078 // if the unit isn't specified but the property should have a unit force 'px' as it
916 1079 if ( empty( $unit ) && in_array( $css_property['property'], self::$pixel_dependent_css_properties ) ) {
917 1080 $unit = 'px';
918 1081 }
1082 +
919 1083 // lose the tons of tabs
920 1084 $css_property['selector'] = trim( preg_replace( '/\t+/', '', $css_property['selector'] ) );
921 1085
922 - $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 );
923 1087
924 - 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'] ) ) {
925 1100 $this_property_output = call_user_func( $css_property['callback_filter'], $this_value, $css_property['selector'], $css_property['property'], $unit );
926 1101 }
927 1102
1103 +// if ( ! empty( $editor ) && empty( $css_property['editor'] ) ) {
1104 +// $this_property_output = '';
1105 +// }
1106 +
928 1107 return $this_property_output;
929 1108 }
930 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 +
931 1155 protected function process_custom_background_field_output( $option_id, $options ) {
932 - $selector = '';
1156 + $selector = $output = '';
933 1157
934 1158 if ( ! isset( $options['value'] ) ) {
935 1159 return false;
936 1160 }
@@ -942,103 +1166,111 @@
942 1166 $selector = $options['output'];
943 1167 } elseif ( is_array( $options['output'] ) ) {
944 1168 $selector = implode( ' ', $options['output'] );
945 1169 }
946 - ob_start();
947 1170
948 - echo $selector . " {";
1171 + // Loose the ton of tabs.
1172 + $selector = trim( preg_replace( '/\t+/', '', $selector ) );
1173 +
1174 + $output .= $selector . " {";
949 1175 if ( isset( $value['background-image'] ) && ! empty( $value['background-image'] ) ) {
950 - echo "background-image: url( " . $value['background-image'] . ");";
1176 + $output .= "background-image: url( " . $value['background-image'] . ");";
951 1177 } else {
952 - echo "background-image: none;";
1178 + $output .= "background-image: none;";
953 1179 }
954 1180
955 1181 if ( isset( $value['background-repeat'] ) && ! empty( $value['background-repeat'] ) ) {
956 - echo "background-repeat:" . $value['background-repeat'] . ";";
1182 + $output .= "background-repeat:" . $value['background-repeat'] . ";";
957 1183 }
958 1184
959 1185 if ( isset( $value['background-position'] ) && ! empty( $value['background-position'] ) ) {
960 - echo "background-position:" . $value['background-position'] . ";";
1186 + $output .= "background-position:" . $value['background-position'] . ";";
961 1187 }
962 1188
963 1189 if ( isset( $value['background-size'] ) && ! empty( $value['background-size'] ) ) {
964 - echo "background-size:" . $value['background-size'] . ";";
1190 + $output .= "background-size:" . $value['background-size'] . ";";
965 1191 }
966 1192
967 1193 if ( isset( $value['background-attachment'] ) && ! empty( $value['background-attachment'] ) ) {
968 - echo "background-attachment:" . $value['background-attachment'] . ";";
1194 + $output .= "background-attachment:" . $value['background-attachment'] . ";";
969 1195 }
970 - echo "}\n";
1196 + $output .= "}\n";
971 1197
972 - return ob_get_clean();
1198 + return $output;
973 1199 }
974 1200
975 1201 /**
976 1202 * add our customizer styling edits into the wp_editor
977 1203 */
978 - function add_customizer_settings_into_wp_editor() {
1204 + function script_to_add_customizer_settings_into_wp_editor() {
979 1205
980 1206 ob_start();
1207 + $this->output_typography_dynamic_script();
981 1208 $this->output_typography_dynamic_style();
982 1209 $this->output_dynamic_style();
983 1210
984 - $custom_css = ob_get_clean(); ?>
985 - <script type="text/javascript">
986 - /* <![CDATA[ */
987 - (function ($) {
988 - $(window).load(function () {
989 - /**
990 - * @param iframe_id the id of the frame you whant to append the style
991 - * @param style_element the style element you want to append
992 - */
993 - var append_script_to_iframe = function (ifrm_id, scriptEl) {
994 - var myIframe = document.getElementById(ifrm_id);
1211 + $custom_css = ob_get_clean();
995 1212
996 - var script = myIframe.contentWindow.document.createElement("script");
997 - script.type = "text/javascript";
998 - 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);
999 1222
1000 - myIframe.contentWindow.document.head.appendChild(script);
1001 - };
1223 + var script = myIframe.contentWindow.document.createElement("script");
1224 + script.type = "text/javascript";
1225 + script.innerHTML = scriptEl.innerHTML;
1002 1226
1003 - var append_style_to_iframe = function (ifrm_id, styleElment) {
1004 - var ifrm = window.frames[ifrm_id];
1005 - ifrm = ( ifrm.contentDocument || ifrm.contentDocument || ifrm.document );
1006 - var head = ifrm.getElementsByTagName('head')[0];
1227 + myIframe.contentWindow.document.head.appendChild(script);
1228 + };
1007 1229
1008 - if (typeof styleElment !== "undefined") {
1009 - head.appendChild(styleElment);
1010 - }
1011 - };
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];
1012 1237
1013 - var xmlString = <?php echo json_encode( str_replace( "\n", "", $custom_css ) ); ?>,
1014 - parser = new DOMParser(),
1015 - doc = parser.parseFromString(xmlString, "text/html");
1238 + if (typeof styleElment !== "undefined") {
1239 + head.appendChild(styleElment);
1240 + }
1241 + };
1016 1242
1017 - 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");
1018 1246
1019 - $.each(doc.head.childNodes, function (key, el) {
1020 - if (typeof el !== "undefined" && typeof el.tagName !== "undefined") {
1247 + if (typeof window.frames['content_ifr'] !== 'undefined') {
1021 1248
1022 - switch (el.tagName) {
1023 - case 'STYLE' :
1024 - append_style_to_iframe('content_ifr', el);
1025 - break;
1026 - case 'SCRIPT' :
1027 - append_script_to_iframe('content_ifr', el);
1028 - break;
1029 - default:
1030 - break;
1031 - }
1032 - }
1033 - });
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 + }
1034 1262 }
1035 1263 });
1036 - })(jQuery);
1037 - /* ]]> */
1038 - </script>
1039 - <?php }
1264 + }
1265 + });
1266 + })(jQuery);
1267 + <?php
1268 + $script = ob_get_clean();
1269 + wp_add_inline_script( 'editor', $script );
1040 1270
1271 + }
1272 +
1041 1273 /**
1042 1274 * Register the administration menu for this plugin into the WordPress Dashboard menu.
1043 1275 */
1044 1276 function add_plugin_admin_menu() {
@@ -1072,10 +1304,180 @@
1072 1304 pixcustomify::require_all( $path );
1073 1305 }
1074 1306
1075 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 + *
1076 1314 * @param WP_Customize_Manager $wp_customize
1077 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 + */
1078 1480 function register_customizer( $wp_customize ) {
1079 1481
1080 1482 $this->register_customizer_controls();
1081 1483
@@ -1083,9 +1485,9 @@
1083 1485
1084 1486 if ( ! empty ( $customizer_settings ) ) {
1085 1487
1086 1488 // first check the very needed options name
1087 - if ( ! isset ( $customizer_settings['opt-name'] ) || empty( $customizer_settings['opt-name'] ) ) {
1489 + if ( empty( $customizer_settings['opt-name'] ) ) {
1088 1490 return;
1089 1491 }
1090 1492 $options_name = $customizer_settings['opt-name'];
1091 1493 $wp_customize->options_key = $options_name;
@@ -1092,37 +1494,49 @@
1092 1494
1093 1495 // let's check if we have sections or panels
1094 1496 if ( isset( $customizer_settings['panels'] ) && ! empty( $customizer_settings['panels'] ) ) {
1095 1497
1096 - foreach ( $customizer_settings['panels'] as $panel_id => $panel_settings ) {
1498 + foreach ( $customizer_settings['panels'] as $panel_id => $panel_config ) {
1097 1499
1098 - 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'] ) ) {
1099 1501
1100 - $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 +
1101 1509 $panel_args = array(
1102 - 'priority' => 10,
1103 - 'capability' => 'edit_theme_options',
1104 - 'title' => __( 'Panel title is required', 'pixcustomify' ),
1105 - '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,
1106 1515 );
1107 1516
1108 - if ( isset( $panel_settings['priority'] ) && ! empty( $panel_settings['priority'] ) ) {
1109 - $panel_args['priority'] = $panel_settings['priority'];
1517 + if ( isset( $panel_config['priority'] ) && ! empty( $panel_config['priority'] ) ) {
1518 + $panel_args['priority'] = $panel_config['priority'];
1110 1519 }
1111 1520
1112 - if ( isset( $panel_settings['title'] ) && ! empty( $panel_settings['title'] ) ) {
1113 - $panel_args['title'] = $panel_settings['title'];
1521 + if ( isset( $panel_config['title'] ) && ! empty( $panel_config['title'] ) ) {
1522 + $panel_args['title'] = $panel_config['title'];
1114 1523 }
1115 1524
1116 - if ( isset( $panel_settings['description'] ) && ! empty( $panel_settings['description'] ) ) {
1117 - $panel_args[10] = $panel_settings['description'];
1525 + if ( isset( $panel_config['description'] ) && ! empty( $panel_config['description'] ) ) {
1526 + $panel_args['description'] = $panel_config['description'];
1118 1527 }
1119 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 +
1120 1534 $wp_customize->add_panel( $panel_id, $panel_args );
1121 1535
1122 - foreach ( $panel_settings['sections'] as $section_id => $section_settings ) {
1123 - if ( ! empty( $section_id ) && isset( $section_settings['options'] ) && ! empty( $section_settings['options'] ) ) {
1124 - $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 );
1125 1539 }
1126 1540 }
1127 1541 }
1128 1542 }
@@ -1129,11 +1543,11 @@
1129 1543 }
1130 1544
1131 1545 if ( isset( $customizer_settings['sections'] ) && ! empty( $customizer_settings['sections'] ) ) {
1132 1546
1133 - foreach ( $customizer_settings['sections'] as $section_id => $section_settings ) {
1134 - if ( ! empty( $section_id ) && isset( $section_settings['options'] ) && ! empty( $section_settings['options'] ) ) {
1135 - $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 );
1136 1550 }
1137 1551 }
1138 1552 }
1139 1553
@@ -1139,9 +1553,11 @@
1139 1553
1140 1554 if ( $this->plugin_settings['enable_reset_buttons'] ) {
1141 1555 // create a toolbar section which will be present all the time
1142 1556 $reset_section_settings = array(
1143 - 'title' => 'Customify toolbar',
1557 + 'title' => 'Customify Toolbox',
1558 + 'capability' => 'manage_options',
1559 + 'priority' => 999999999,
1144 1560 'options' => array(
1145 1561 'reset_all_button' => array(
1146 1562 'type' => 'button',
1147 1563 'label' => 'Reset Customify',
@@ -1152,12 +1568,9 @@
1152 1568 );
1153 1569
1154 1570 $wp_customize->add_section(
1155 1571 'customify_toolbar',
1156 - array(
1157 - 'title' => '',
1158 - 'priority' => 999999999
1159 - )
1572 + $reset_section_settings
1160 1573 );
1161 1574
1162 1575 $wp_customize->add_setting(
1163 1576 'reset_customify',
@@ -1166,9 +1579,9 @@
1166 1579 $wp_customize->add_control( new Pix_Customize_Button_Control(
1167 1580 $wp_customize,
1168 1581 'reset_customify',
1169 1582 array(
1170 - 'label' => __( 'Reset Customify to Defaults', 'customify' ),
1583 + 'label' => __( 'Reset All Customify Options to Default', 'customify' ),
1171 1584 'section' => 'customify_toolbar',
1172 1585 'settings' => 'reset_customify',
1173 1586 'action' => 'reset_customify',
1174 1587 )
@@ -1198,60 +1611,83 @@
1198 1611
1199 1612 do_action( 'customify_create_custom_control', $wp_customize );
1200 1613 }
1201 1614
1202 - protected function register_section( $panel_id, $section_key, $options_name, $section_settings, $wp_customize ) {
1615 + /**
1616 + * @param string $panel_id
1617 + * @param string $section_key
1618 + * @param string $options_name
1619 + * @param array $section_config
1620 + * @param WP_Customize_Manager $wp_customize
1621 + */
1622 + protected function register_section( $panel_id, $section_key, $options_name, $section_config, $wp_customize ) {
1203 1623
1204 1624 if ( isset( $this->plugin_settings['disable_customify_sections'] ) && isset( $this->plugin_settings['disable_customify_sections'][ $section_key ] ) ) {
1205 1625 return;
1206 1626 }
1207 1627
1208 - $section_args = array(
1209 - 'priority' => 10,
1210 - 'capability' => 'edit_theme_options',
1211 - 'title' => __( 'Title Section is required', '' ),
1212 - 'panel' => $panel_id,
1213 - );
1214 - $section_id = $options_name . '[' . $section_key . ']';
1215 -
1216 - if ( isset( $section_settings['priority'] ) && ! empty( $section_settings['priority'] ) ) {
1217 - $section_args['priority'] = $section_settings['priority'];
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 . ']';
1218 1633 }
1219 1634
1220 - if ( isset( $section_settings['title'] ) && ! empty( $section_settings['title'] ) ) {
1221 - $section_args['title'] = $section_settings['title'];
1222 - }
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 + ) );
1223 1648
1224 - if ( isset( $section_settings['theme_supports'] ) && ! empty( $section_settings['theme_supports'] ) ) {
1225 - $section_args['theme_supports'] = $section_settings['theme_supports'];
1649 + $wp_customize->add_section( $section_id, $section_args );
1226 1650 }
1227 1651
1228 - if ( isset( $section_settings['description'] ) && ! empty( $section_settings['description'] ) ) {
1229 - $section_args['description'] = $section_settings['description'];
1230 - }
1652 + // Now go through each section option and add the fields
1653 + foreach ( $section_config['options'] as $option_id => $option_config ) {
1231 1654
1232 - $wp_customize->add_section( $section_id, $section_args );
1233 -
1234 - foreach ( $section_settings['options'] as $option_id => $option_config ) {
1235 -
1236 1655 if ( empty( $option_id ) || ! isset( $option_config['type'] ) ) {
1237 1656 continue;
1238 1657 }
1239 1658
1240 - $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 + }
1241 1665
1242 - $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 );
1243 1674 }
1244 1675
1245 1676 }
1246 1677
1247 1678 /**
1679 + * Register a Customizer field (setting and control).
1680 + *
1681 + * @see WP_Customize_Setting
1682 + * @see WP_Customize_Control
1683 + *
1248 1684 * @param string $section_id
1249 1685 * @param string $setting_id
1250 - * @param array $setting_config
1686 + * @param array $field_config
1251 1687 * @param WP_Customize_Manager $wp_customize
1252 1688 */
1253 - 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 ) {
1254 1690
1255 1691 $add_control = true;
1256 1692 // defaults
1257 1693 $setting_args = array(
@@ -1259,34 +1695,38 @@
1259 1695 'capability' => 'edit_theme_options',
1260 1696 'transport' => 'refresh',
1261 1697 );
1262 1698 $control_args = array(
1699 + 'priority' => 10,
1263 1700 'label' => '',
1264 1701 'section' => $section_id,
1265 1702 'settings' => $setting_id,
1266 1703 );
1267 1704
1268 - $this->localized['settings'][ $setting_id ] = $setting_config;
1269 -
1270 1705 // sanitize settings
1271 - if ( ( isset( $setting_config['live'] ) && $setting_config['live'] ) || $setting_config['type'] === 'font' ) {
1706 + if ( ! empty( $field_config['live'] ) || $field_config['type'] === 'font' ) {
1272 1707 $setting_args['transport'] = 'postMessage';
1273 1708 }
1274 1709
1275 - if ( isset( $setting_config['default'] ) ) {
1276 - $setting_args['default'] = $setting_config['default'];
1710 + if ( isset( $field_config['default'] ) ) {
1711 + $setting_args['default'] = $field_config['default'];
1277 1712 }
1278 1713
1279 - if ( isset( $setting_config['capability'] ) && ! empty( $setting_config['capability'] ) ) {
1280 - $setting_args['capability'] = $setting_config['capability'];
1714 + if ( ! empty( $field_config['capability'] ) ) {
1715 + $setting_args['capability'] = $field_config['capability'];
1281 1716 }
1282 1717
1283 - 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' ) {
1284 1724 $setting_args['type'] = 'option';
1285 1725 }
1286 1726
1287 1727 // if we arrive here this means we have a custom field control
1288 - switch ( $setting_config['type'] ) {
1728 + switch ( $field_config['type'] ) {
1289 1729
1290 1730 case 'checkbox':
1291 1731
1292 1732 $setting_args['sanitize_callback'] = array( $this, 'setting_sanitize_checkbox' );
@@ -1295,41 +1735,41 @@
1295 1735 default:
1296 1736 break;
1297 1737 }
1298 1738
1299 - if ( isset( $setting_config['sanitize_callback'] ) && ! empty( $setting_config['sanitize_callback'] ) && function_exists( $setting_config['sanitize_callback'] ) ) {
1300 - $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'];
1301 1741 }
1302 1742
1303 - // and add it
1743 + // Add the setting
1304 1744 $wp_customize->add_setting( $setting_id, $setting_args );
1305 1745
1306 1746 // now sanitize the control
1307 - if ( isset( $setting_config['label'] ) && ! empty( $setting_config['label'] ) ) {
1308 - $control_args['label'] = $setting_config['label'];
1747 + if ( ! empty( $field_config['label'] ) ) {
1748 + $control_args['label'] = $field_config['label'];
1309 1749 }
1310 1750
1311 - if ( isset( $setting_config['priority'] ) && ! empty( $setting_config['priority'] ) ) {
1312 - $control_args['priority'] = $setting_config['priority'];
1751 + if ( ! empty( $field_config['priority'] ) ) {
1752 + $control_args['priority'] = $field_config['priority'];
1313 1753 }
1314 1754
1315 - if ( isset( $setting_config['desc'] ) && ! empty( $setting_config['desc'] ) ) {
1316 - $control_args['description'] = $setting_config['desc'];
1755 + if ( ! empty( $field_config['desc'] ) ) {
1756 + $control_args['description'] = $field_config['desc'];
1317 1757 }
1318 1758
1319 - if ( isset( $setting_config['active_callback'] ) && ! empty( $setting_config['active_callback'] ) ) {
1320 - $control_args['active_callback'] = $setting_config['active_callback'];
1759 + if ( ! empty( $field_config['active_callback'] ) ) {
1760 + $control_args['active_callback'] = $field_config['active_callback'];
1321 1761 }
1322 1762
1323 1763
1324 - $control_args['type'] = $setting_config['type'];
1764 + $control_args['type'] = $field_config['type'];
1325 1765
1326 1766 // select the control type
1327 1767 // but first init a default
1328 1768 $control_class_name = 'Pix_Customize_Text_Control';
1329 1769
1330 - // if is a standard wp field type call it here and skip the rest
1331 - 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(
1332 1772 'checkbox',
1333 1773 'dropdown-pages',
1334 1774 'url',
1335 1775 'date',
@@ -1340,30 +1780,30 @@
1340 1780 ) ) ) {
1341 1781 $wp_customize->add_control( $setting_id . '_control', $control_args );
1342 1782
1343 1783 return;
1344 - } elseif ( in_array( $setting_config['type'], array(
1784 + } elseif ( in_array( $field_config['type'], array(
1345 1785 'radio',
1346 1786 'select'
1347 - ) ) && isset( $setting_config['choices'] ) && ! empty( $setting_config['choices'] )
1787 + ) ) && ! empty( $field_config['choices'] )
1348 1788 ) {
1349 - $control_args['choices'] = $setting_config['choices'];
1789 + $control_args['choices'] = $field_config['choices'];
1350 1790 $wp_customize->add_control( $setting_id . '_control', $control_args );
1351 1791
1352 1792 return;
1353 - } 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'] ) ) {
1354 1794
1355 - $control_args['input_attrs'] = $setting_config['input_attrs'];
1795 + $control_args['input_attrs'] = $field_config['input_attrs'];
1356 1796
1357 1797 $wp_customize->add_control( $setting_id . '_control', $control_args );
1358 1798 }
1359 1799
1360 - // if we arrive here this means we have a custom field control
1361 - switch ( $setting_config['type'] ) {
1800 + // If we arrive here this means we have a custom field control.
1801 + switch ( $field_config['type'] ) {
1362 1802
1363 1803 case 'text':
1364 - if ( isset( $setting_config['live'] ) ) {
1365 - $control_args['live'] = $setting_config['live'];
1804 + if ( isset( $field_config['live'] ) ) {
1805 + $control_args['live'] = $field_config['live'];
1366 1806 }
1367 1807
1368 1808 $control_class_name = 'Pix_Customize_Text_Control';
1369 1809 break;
@@ -1368,10 +1808,10 @@
1368 1808 $control_class_name = 'Pix_Customize_Text_Control';
1369 1809 break;
1370 1810
1371 1811 case 'textarea':
1372 - if ( isset( $setting_config['live'] ) ) {
1373 - $control_args['live'] = $setting_config['live'];
1812 + if ( isset( $field_config['live'] ) ) {
1813 + $control_args['live'] = $field_config['live'];
1374 1814 }
1375 1815
1376 1816 $control_class_name = 'Pix_Customize_Textarea_Control';
1377 1817 break;
@@ -1384,14 +1824,14 @@
1384 1824 $control_class_name = 'Pix_Customize_Color_Drop_Control';
1385 1825 break;
1386 1826
1387 1827 case 'ace_editor':
1388 - if ( isset( $setting_config['live'] ) ) {
1389 - $control_args['live'] = $setting_config['live'];
1828 + if ( isset( $field_config['live'] ) ) {
1829 + $control_args['live'] = $field_config['live'];
1390 1830 }
1391 1831
1392 - if ( isset( $setting_config['editor_type'] ) ) {
1393 - $control_args['editor_type'] = $setting_config['editor_type'];
1832 + if ( isset( $field_config['editor_type'] ) ) {
1833 + $control_args['editor_type'] = $field_config['editor_type'];
1394 1834 }
1395 1835
1396 1836 $control_class_name = 'Pix_Customize_Ace_Editor_Control';
1397 1837 break;
@@ -1408,32 +1848,37 @@
1408 1848 $control_class_name = 'WP_Customize_Media_Control';
1409 1849 break;
1410 1850
1411 1851 case 'custom_background':
1412 - if ( isset( $setting_config['field'] ) ) {
1413 - $control_args['field'] = $setting_config['field'];
1852 + if ( isset( $field_config['field'] ) ) {
1853 + $control_args['field'] = $field_config['field'];
1414 1854 }
1415 1855
1416 1856 $control_class_name = 'Pix_Customize_Background_Control';
1417 1857 break;
1418 1858
1419 - case 'cropped_media':
1420 - if ( isset( $setting_config['width'] ) ) {
1421 - $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'];
1422 1863 }
1423 1864
1424 - if ( isset( $setting_config['height'] ) ) {
1425 - $control_args['height'] = $setting_config['height'];
1865 + if ( isset( $field_config['height'] ) ) {
1866 + $control_args['height'] = $field_config['height'];
1426 1867 }
1427 1868
1428 - if ( isset( $setting_config['flex_width'] ) ) {
1429 - $control_args['flex_width'] = $setting_config['flex_width'];
1869 + if ( isset( $field_config['flex_width'] ) ) {
1870 + $control_args['flex_width'] = $field_config['flex_width'];
1430 1871 }
1431 1872
1432 - if ( isset( $setting_config['flex_height'] ) ) {
1433 - $control_args['flex_height'] = $setting_config['flex_height'];
1873 + if ( isset( $field_config['flex_height'] ) ) {
1874 + $control_args['flex_height'] = $field_config['flex_height'];
1434 1875 }
1435 1876
1877 + if ( isset( $field_config['button_labels'] ) ) {
1878 + $control_args['button_labels'] = $field_config['button_labels'];
1879 + }
1880 +
1436 1881 $control_class_name = 'WP_Customize_Cropped_Image_Control';
1437 1882 break;
1438 1883
1439 1884 // Custom types
@@ -1446,35 +1891,34 @@
1446 1891 }
1447 1892
1448 1893 $control_class_name = 'Pix_Customize_Typography_Control';
1449 1894
1450 - if ( isset( $setting_config['backup'] ) ) {
1451 - $control_args['backup'] = $setting_config['backup'];
1895 + if ( isset( $field_config['backup'] ) ) {
1896 + $control_args['backup'] = $field_config['backup'];
1452 1897 }
1453 1898
1454 - if ( isset( $setting_config['font_weight'] ) ) {
1455 - $control_args['font_weight'] = $setting_config['font_weight'];
1899 + if ( isset( $field_config['font_weight'] ) ) {
1900 + $control_args['font_weight'] = $field_config['font_weight'];
1456 1901 }
1457 1902
1458 - if ( isset( $setting_config['subsets'] ) ) {
1459 - $control_args['subsets'] = $setting_config['subsets'];
1903 + if ( isset( $field_config['subsets'] ) ) {
1904 + $control_args['subsets'] = $field_config['subsets'];
1460 1905 }
1461 1906
1462 - if ( isset( $setting_config['recommended'] ) ) {
1463 - $control_args['recommended'] = array_flip( $setting_config['recommended'] );
1907 + if ( isset( $field_config['recommended'] ) ) {
1908 + $control_args['recommended'] = array_flip( $field_config['recommended'] );
1464 1909 }
1465 1910
1466 - if ( isset( $setting_config['load_all_weights'] ) ) {
1467 - $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'];
1468 1913 }
1469 1914
1470 - if ( isset( $setting_config['default'] ) ) {
1471 - $control_args['default'] = $setting_config['default'];
1915 + if ( isset( $field_config['default'] ) ) {
1916 + $control_args['default'] = $field_config['default'];
1472 1917 }
1473 1918
1474 1919 break;
1475 1920
1476 - // Custom types
1477 1921 case 'font' :
1478 1922 $use_typography = $this->get_plugin_setting( 'typography', '1' );
1479 1923
1480 1924 if ( $use_typography === false ) {
@@ -1483,34 +1927,34 @@
1483 1927 }
1484 1928
1485 1929 $control_class_name = 'Pix_Customize_Font_Control';
1486 1930
1487 - if ( isset( $setting_config['backup'] ) ) {
1488 - $control_args['backup'] = $setting_config['backup'];
1931 + if ( isset( $field_config['backup'] ) ) {
1932 + $control_args['backup'] = $field_config['backup'];
1489 1933 }
1490 1934
1491 - if ( isset( $setting_config['font_weight'] ) ) {
1492 - $control_args['font_weight'] = $setting_config['font_weight'];
1935 + if ( isset( $field_config['font_weight'] ) ) {
1936 + $control_args['font_weight'] = $field_config['font_weight'];
1493 1937 }
1494 1938
1495 - if ( isset( $setting_config['subsets'] ) ) {
1496 - $control_args['subsets'] = $setting_config['subsets'];
1939 + if ( isset( $field_config['subsets'] ) ) {
1940 + $control_args['subsets'] = $field_config['subsets'];
1497 1941 }
1498 1942
1499 - if ( isset( $setting_config['recommended'] ) ) {
1500 - $control_args['recommended'] = array_flip( $setting_config['recommended'] );
1943 + if ( isset( $field_config['recommended'] ) ) {
1944 + $control_args['recommended'] = array_flip( $field_config['recommended'] );
1501 1945 }
1502 1946
1503 - if ( isset( $setting_config['load_all_weights'] ) ) {
1504 - $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'];
1505 1949 }
1506 1950
1507 - if ( isset( $setting_config['default'] ) ) {
1508 - $control_args['default'] = $setting_config['default'];
1951 + if ( isset( $field_config['default'] ) ) {
1952 + $control_args['default'] = $field_config['default'];
1509 1953 }
1510 1954
1511 - if ( isset( $setting_config['fields'] ) ) {
1512 - $control_args['fields'] = $setting_config['fields'];
1955 + if ( isset( $field_config['fields'] ) ) {
1956 + $control_args['fields'] = $field_config['fields'];
1513 1957 }
1514 1958 $control_args['live'] = true;
1515 1959
1516 1960 break;
@@ -1515,30 +1959,60 @@
1515 1959
1516 1960 break;
1517 1961
1518 1962 case 'select2' :
1519 - if ( ! isset( $setting_config['choices'] ) || empty( $setting_config['choices'] ) ) {
1963 + if ( ! isset( $field_config['choices'] ) || empty( $field_config['choices'] ) ) {
1520 1964 return;
1521 1965 }
1522 1966
1523 - $control_args['choices'] = $setting_config['choices'];
1967 + $control_args['choices'] = $field_config['choices'];
1524 1968
1525 1969 $control_class_name = 'Pix_Customize_Select2_Control';
1526 1970 break;
1527 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 +
1528 2002 case 'preset' :
1529 - if ( ! isset( $setting_config['choices'] ) || empty( $setting_config['choices'] ) ) {
2003 + if ( ! isset( $field_config['choices'] ) || empty( $field_config['choices'] ) ) {
1530 2004 return;
1531 2005 }
1532 2006
1533 - $control_args['choices'] = $setting_config['choices'];
2007 + $control_args['choices'] = $field_config['choices'];
1534 2008
1535 - if ( isset( $setting_config['choices_type'] ) || ! empty( $setting_config['choices_type'] ) ) {
1536 - $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'];
1537 2011 }
1538 2012
1539 - if ( isset( $setting_config['desc'] ) || ! empty( $setting_config['desc'] ) ) {
1540 - $control_args['description'] = $setting_config['desc'];
2013 + if ( isset( $field_config['desc'] ) || ! empty( $field_config['desc'] ) ) {
2014 + $control_args['description'] = $field_config['desc'];
1541 2015 }
1542 2016
1543 2017
1544 2018 $control_class_name = 'Pix_Customize_Preset_Control';
@@ -1544,20 +2018,20 @@
1544 2018 $control_class_name = 'Pix_Customize_Preset_Control';
1545 2019 break;
1546 2020
1547 2021 case 'radio_image' :
1548 - if ( ! isset( $setting_config['choices'] ) || empty( $setting_config['choices'] ) ) {
2022 + if ( ! isset( $field_config['choices'] ) || empty( $field_config['choices'] ) ) {
1549 2023 return;
1550 2024 }
1551 2025
1552 - $control_args['choices'] = $setting_config['choices'];
2026 + $control_args['choices'] = $field_config['choices'];
1553 2027
1554 - if ( isset( $setting_config['choices_type'] ) || ! empty( $setting_config['choices_type'] ) ) {
1555 - $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'];
1556 2030 }
1557 2031
1558 - if ( isset( $setting_config['desc'] ) || ! empty( $setting_config['desc'] ) ) {
1559 - $control_args['description'] = $setting_config['desc'];
2032 + if ( isset( $field_config['desc'] ) || ! empty( $field_config['desc'] ) ) {
2033 + $control_args['description'] = $field_config['desc'];
1560 2034 }
1561 2035
1562 2036
1563 2037 $control_class_name = 'Pix_Customize_Radio_Image_Control';
@@ -1563,13 +2037,13 @@
1563 2037 $control_class_name = 'Pix_Customize_Radio_Image_Control';
1564 2038 break;
1565 2039
1566 2040 case 'button' :
1567 - if ( ! isset( $setting_config['action'] ) || empty( $setting_config['action'] ) ) {
2041 + if ( ! isset( $field_config['action'] ) || empty( $field_config['action'] ) ) {
1568 2042 return;
1569 2043 }
1570 2044
1571 - $control_args['action'] = $setting_config['action'];
2045 + $control_args['action'] = $field_config['action'];
1572 2046
1573 2047 $control_class_name = 'Pix_Customize_Button_Control';
1574 2048
1575 2049 break;
@@ -1574,10 +2048,10 @@
1574 2048
1575 2049 break;
1576 2050
1577 2051 case 'html' :
1578 - if ( isset( $setting_config['html'] ) || ! empty( $setting_config['html'] ) ) {
1579 - $control_args['html'] = $setting_config['html'];
2052 + if ( isset( $field_config['html'] ) || ! empty( $field_config['html'] ) ) {
2053 + $control_args['html'] = $field_config['html'];
1580 2054 }
1581 2055
1582 2056 $control_class_name = 'Pix_Customize_HTML_Control';
1583 2057 break;
@@ -1582,20 +2056,20 @@
1582 2056 $control_class_name = 'Pix_Customize_HTML_Control';
1583 2057 break;
1584 2058
1585 2059 case 'import_demo_data' :
1586 - if ( isset( $setting_config['html'] ) || ! empty( $setting_config['html'] ) ) {
1587 - $control_args['html'] = $setting_config['html'];
2060 + if ( isset( $field_config['html'] ) || ! empty( $field_config['html'] ) ) {
2061 + $control_args['html'] = $field_config['html'];
1588 2062 }
1589 2063
1590 - if ( ! isset( $setting_config['label'] ) || empty( $setting_config['label'] ) ) {
2064 + if ( ! isset( $field_config['label'] ) || empty( $field_config['label'] ) ) {
1591 2065 $control_args['label'] = esc_html__( 'Import', 'customify' );
1592 2066 } else {
1593 - $control_args['label'] = $setting_config['label'];
2067 + $control_args['label'] = $field_config['label'];
1594 2068 }
1595 2069
1596 - if ( isset( $setting_config['notices'] ) && ! empty( $setting_config['notices'] ) ) {
1597 - $control_args['notices'] = $setting_config['notices'];
2070 + if ( isset( $field_config['notices'] ) && ! empty( $field_config['notices'] ) ) {
2071 + $control_args['notices'] = $field_config['notices'];
1598 2072 }
1599 2073
1600 2074 $control_class_name = 'Pix_Customize_Import_Demo_Data_Control';
1601 2075 break;
@@ -1641,8 +2115,99 @@
1641 2115 }
1642 2116 }
1643 2117 }
1644 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 +
1645 2210 public function get_base_path() {
1646 2211 return plugin_dir_path( $this->file );
1647 2212 }
1648 2213
@@ -1757,40 +2322,50 @@
1757 2322
1758 2323 return $settings;
1759 2324 }
1760 2325
1761 - protected function get_value( $option, $alt_opt_name ) {
2326 + protected function get_value( $option_id, $alt_opt_name ) {
1762 2327 global $wp_customize;
1763 2328
1764 - $opt_name = $this->opt_name;
2329 + $options_name = $this->opt_name;
1765 2330 $values = $this->current_values;
1766 2331
1767 - // 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
1768 - if ( empty( $opt_name ) && ! empty( $alt_opt_name ) ) {
1769 - $opt_name = $alt_opt_name;
1770 - $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 );
1771 2336 }
1772 2337
1773 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 );
1774 2341
1775 - $option_key = $opt_name . '[' . $option . ']';
1776 - $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 );
1777 2354 if ( ! empty( $setting ) ) {
1778 - $value = $setting->value();
1779 -
1780 - return $value;
2355 + return $setting->value();
1781 2356 }
1782 2357 }
1783 2358
1784 2359 // shim
1785 - if ( strpos( $option, $opt_name . '[' ) !== false ) {
2360 + if ( strpos( $option_id, $options_name . '[' ) !== false ) {
1786 2361 // get only the setting id
1787 - $option = explode( '[', $option );
1788 - $option = rtrim( $option[1], ']' );
2362 + $option_id = explode( '[', $option_id );
2363 + $option_id = rtrim( $option_id[1], ']' );
1789 2364 }
1790 2365
1791 - if ( isset( $values[ $option ] ) ) {
1792 - return $values[ $option ];
2366 + if ( isset( $values[ $option_id ] ) ) {
2367 + return $values[ $option_id ];
1793 2368 }
1794 2369
1795 2370 return null;
1796 2371 }
@@ -1795,28 +2370,53 @@
1795 2370 return null;
1796 2371 }
1797 2372
1798 2373 /**
1799 - * A public function to retreat an option's value
1800 - * If there is a value and return it
1801 - * 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.
1802 2377 *
1803 - * @param $option
2378 + * @param $option_id
1804 2379 * @param mixed $default Optional.
1805 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.
1806 2381 *
1807 2382 * @return bool|null|string
1808 2383 */
1809 - 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 );
1810 2392
1811 - $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.
1812 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 +
1813 2413 if ( $return !== null ) {
1814 2414 return $return;
1815 2415 } elseif ( $default !== null ) {
1816 2416 return $default;
1817 - } elseif ( isset( $this->options_list[ $option ] ) && isset( $this->options_list[ $option ]['default'] ) ) {
1818 - 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'];
1819 2419 }
1820 2420
1821 2421 return null;
1822 2422 }
@@ -1829,8 +2429,52 @@
1829 2429
1830 2430 return false;
1831 2431 }
1832 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 +
1833 2477 protected function get_config() {
1834 2478 if ( file_exists( $this->get_base_path() . 'plugin-config.php' ) ) {
1835 2479 return include( $this->get_base_path() . 'plugin-config.php' );
1836 2480 }
@@ -1914,9 +2558,9 @@
1914 2558 $controller = new Customify_Importer_Controller();
1915 2559 $controller->init();
1916 2560 }
1917 2561
1918 - function get_options_configs() {
2562 + public function get_options_configs() {
1919 2563 return $this->options_list;
1920 2564 }
1921 2565
1922 2566 /**
@@ -1947,9 +2591,9 @@
1947 2591 *
1948 2592 * @return string
1949 2593 */
1950 2594 public static function decodeURIComponent( $str ) {
1951 - //if we get an array we just let it be
2595 + // If we get an array we just let it be
1952 2596 if ( is_string( $str ) ) {
1953 2597 $revert = array( '!' => '%21', '*' => '%2A', "'" => '%27', '(' => '%28', ')' => '%29' );
1954 2598 $str = rawurldecode( strtr( $str, $revert ) );
1955 2599 }
@@ -1971,13 +2615,90 @@
1971 2615 return true;
1972 2616 }
1973 2617
1974 2618 /**
1975 - * Return an instance of this class.
1976 - * @since 1.0.0
1977 - * @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
1978 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 +
1979 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 + /**
1980 2701 * Main PixCustomifyPlugin Instance
1981 2702 *
1982 2703 * Ensures only one instance of PixCustomifyPlugin is loaded or can be loaded.
1983 2704 *
@@ -1987,9 +2708,9 @@
1987 2708 * @param string $file File.
1988 2709 * @param string $version Version.
1989 2710 *
1990 2711 * @see PixCustomifyPlugin()
1991 - * @return object Main PixCustomifyPlugin instance
2712 + * @return PixCustomifyPlugin Main PixCustomifyPlugin instance
1992 2713 */
1993 2714 public static function instance( $file = '', $version = '1.0.0' ) {
1994 2715 // If the single instance hasn't been set, set it now.
1995 2716 if ( is_null( self::$_instance ) ) {
@@ -2017,5 +2738,5 @@
2017 2738 public function __wakeup() {
2018 2739
2019 2740 _doing_it_wrong( __FUNCTION__, esc_html( __( 'Cheatin&#8217; huh?' ) ), esc_html( $this->_version ) );
2020 2741 } // End __wakeup ()
2021 -}
2742 +}