PluginProbe
Customify / 1.5.3
Customify v1.5.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
customify / class-pixcustomify.php

class-pixcustomify.php in Customify 1.5.3, at class-pixcustomify.php

2,077 lines 59.6 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * PixCustomify.
4 * @package PixCustomify
5 * @author Pixelgrade <contact@pixelgrade.com>
6 * @license GPL-2.0+
7 * @link https://pixelgrade.com
8 * @copyright 2014-2017 Pixelgrade
9 */
10
11 /**
12 * Plugin class.
13 * @package PixCustomify
14 * @author Pixelgrade <contact@pixelgrade.com>
15 */
16 class PixCustomifyPlugin {
17
18 /**
19 * Plugin version, used for cache-busting of style and script file references.
20 * @since 1.5.0
21 * @const string
22 */
23 protected $_version;
24 /**
25 * Unique identifier for your plugin.
26 * Use this value (not the variable name) as the text domain when internationalizing strings of text. It should
27 * match the Text Domain file header in the main plugin file.
28 * @since 1.0.0
29 * @var string
30 */
31 protected $plugin_slug = 'customify';
32
33 /**
34 * Instance of this class.
35 * @since 1.5.0
36 * @var object
37 */
38 protected static $_instance = null;
39
40 /**
41 * Slug of the plugin screen.
42 * @since 1.0.0
43 * @var string
44 */
45 protected $plugin_screen_hook_suffix = null;
46
47 /**
48 * Path to the plugin.
49 * @since 1.0.0
50 * @var string
51 */
52 protected $plugin_basepath = null;
53
54 public $display_admin_menu = false;
55
56 private $config;
57
58 private $customizer_config;
59
60 public $plugin_settings;
61
62 protected $localized = array();
63
64 protected $current_values = array();
65
66 protected $options_list = array();
67
68 protected $media_queries = array();
69
70 protected $opt_name;
71
72 protected $typo_settings;
73
74 protected $google_fonts = null;
75
76 protected $theme_fonts = null;
77
78 // these properties will get 'px' as a default unit
79 protected static $pixel_dependent_css_properties = array(
80 'width',
81 'max-width',
82 'min-width',
83
84 'height',
85 'max-height',
86 'min-height',
87
88 'padding',
89 'padding-left',
90 'padding-right',
91 'padding-top',
92 'padding-bottom',
93
94 'margin',
95 'margin-right',
96 'margin-left',
97 'margin-top',
98 'margin-bottom',
99
100 'right',
101 'left',
102 'top',
103 'bottom',
104
105 'font-size',
106 'letter-spacing',
107
108 'border-size',
109 'border-width',
110 'border-bottom-width',
111 'border-left-width',
112 'border-right-width',
113 'border-top-width'
114 );
115
116 protected $jetpack_default_modules = array();
117 protected $jetpack_blocked_modules = array();
118 protected $jetpack_sharing_default_options = array();
119
120 /**
121 * The main plugin file.
122 * @var string
123 * @access public
124 * @since 1.5.0
125 */
126 public $file;
127
128 /**
129 * Minimal Required PHP Version
130 * @var string
131 * @access private
132 * @since 1.5.0
133 */
134 private $minimalRequiredPhpVersion = 5.2;
135
136 protected function __construct( $file, $version = '1.0.0' ) {
137 //the main plugin file (the one that loads all this)
138 $this->file = $file;
139 //the current plugin version
140 $this->_version = $version;
141
142 // Remember our base path
143 $this->plugin_basepath = plugin_dir_path( $file );
144
145 if ( $this->php_version_check() ) {
146 // Only load and run the init function if we know PHP version can parse it.
147 $this->init();
148 }
149 }
150
151 /**
152 * Initialize plugin
153 */
154 private function init() {
155 // Load the config file
156 $this->config = $this->get_config();
157 // Load the plugin's settings from the DB
158 $this->plugin_settings = get_option( $this->config['settings-key'] );
159
160 // Register all the needed hooks
161 $this->register_hooks();
162 }
163
164 /**
165 * Register our actions and filters
166 *
167 * @return null
168 */
169 function register_hooks() {
170 /*
171 * Register hooks that are fired when the plugin is activated, deactivated, and uninstalled, respectively.
172 */
173 register_activation_hook( $this->file, array( $this, 'activate' ) );
174 register_deactivation_hook( $this->file, array( $this, 'deactivate' ) );
175
176 /*
177 * Load plugin text domain
178 */
179 add_action( 'init', array( $this, 'load_plugin_textdomain' ) );
180
181 /*
182 * Prepare and load the configuration
183 */
184 $this->init_plugin_configs();
185
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
187 // DO NOT TRY to use the Customify values before this!
188 add_action( 'after_setup_theme', array( $this, 'load_plugin_configs' ), 5 );
189
190 /*
191 * Now setup the admin side of things
192 */
193 // Starting with the menu item for this plugin
194 add_action( 'admin_menu', array( $this, 'add_plugin_admin_menu' ) );
195
196 // Add an action link pointing to the options page.
197 $plugin_basename = plugin_basename( plugin_dir_path( $this->file ) . 'pixcustomify.php' );
198 add_filter( 'plugin_action_links_' . $plugin_basename, array( $this, 'add_action_links' ) );
199
200 // Load admin style sheet and JavaScript.
201 add_action( 'admin_enqueue_scripts', array( $this, 'enqueue_admin_styles' ) );
202 add_action( 'admin_enqueue_scripts', array( $this, 'enqueue_admin_scripts' ) );
203
204 /*
205 * Now it's time for the Customizer logic to kick in
206 */
207 // Styles for the Customizer
208 add_action( 'customize_controls_init', array( $this, 'register_admin_customizer_styles' ), 10 );
209 add_action( 'customize_controls_enqueue_scripts', array( $this, 'enqueue_admin_customizer_styles' ), 10 );
210 // 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 );
213
214 // Scripts enqueued only in the theme preview
215 add_action( 'customize_preview_init', array( $this, 'customizer_live_preview_register_scripts' ), 10 );
216 add_action( 'customize_preview_init', array( $this, 'customizer_live_preview_enqueue_scripts' ), 99999 );
217
218 // The frontend effects of the Customizer controls
219 $load_location = $this->get_plugin_setting( 'style_resources_location', 'wp_head' );
220
221 add_action( $load_location, array( $this, 'output_dynamic_style' ), 99999 );
222 add_action( 'wp_head', array( $this, 'output_typography_dynamic_style' ), 10 );
223
224 add_action( 'customize_register', array( $this, 'remove_default_sections' ), 11 );
225 add_action( 'customize_register', array( $this, 'register_customizer' ), 12 );
226
227 if ( $this->get_plugin_setting( 'enable_editor_style', true ) ) {
228 add_action( 'admin_head', array( $this, 'add_customizer_settings_into_wp_editor' ) );
229 }
230
231 /*
232 * Jetpack Related
233 */
234 add_action( 'init', array( $this, 'set_jetpack_sharing_config') );
235 add_filter( 'default_option_jetpack_active_modules', array( $this, 'default_jetpack_active_modules' ), 10, 1 );
236 add_filter( 'jetpack_get_available_modules', array( $this, 'jetpack_hide_blocked_modules' ), 10, 1 );
237 add_filter( 'default_option_sharing-options', array( $this, 'default_jetpack_sharing_options' ), 10, 1 );
238
239 add_action( 'rest_api_init', array( $this, 'add_rest_routes_api' ) );
240 }
241
242 /**
243 * Initialize Configs, Options and Values methods
244 */
245 function init_plugin_configs() {
246 $this->customizer_config = get_option( 'pixcustomify_config' );
247
248 // no option so go for default
249 if ( empty( $this->customizer_config ) ) {
250 $this->customizer_config = $this->get_config_option( 'default_options' );
251 }
252
253 if ( empty( $this->customizer_config ) ) {
254 $this->customizer_config = array();
255 }
256 }
257
258 /**
259 * Load the plugin configuration and options
260 */
261 function load_plugin_configs() {
262
263 // allow themes or other plugins to filter the config
264 $this->customizer_config = apply_filters( 'customify_filter_fields', $this->customizer_config );
265 $this->opt_name = $this->localized['options_name'] = $this->customizer_config['opt-name'];
266 $this->options_list = $this->get_options();
267
268 // Load the current options values
269 $this->current_values = $this->get_current_values();
270
271 if ( $this->import_button_exists() ) {
272 $this->localized['import_rest_url'] = get_rest_url( '/customify/1.0/' );
273 $this->localized['import_rest_nonce'] = wp_create_nonce( 'wp_rest' );
274
275 $this->register_import_api();
276 }
277
278 $this->localized['theme_fonts'] = $this->theme_fonts = Customify_Font_Selector::instance()->get_theme_fonts();
279 }
280
281 function set_jetpack_sharing_config() {
282 // Allow others to change the sharing config here
283 $this->jetpack_sharing_default_options = apply_filters ( 'customify_filter_jetpack_sharing_default_options', array() );
284 }
285
286 /**
287 * Control the default modules that are activated in Jetpack.
288 * Use the `customify_filter_jetpack_default_modules` to set your's.
289 *
290 * @param array $default The default value to return if the option does not exist
291 * in the database.
292 *
293 * @return array
294 */
295 function default_jetpack_active_modules( $default ) {
296 if ( ! is_array( $default ) ) {
297 $default = array();
298 }
299 $jetpack_default_modules = array();
300
301 $theme_default_modules = get_theme_mod( 'pixelgrade_jetpack_default_active_modules', array() );
302
303 if ( ! is_array( $theme_default_modules ) ) {
304 return array_merge( $default, $jetpack_default_modules );
305 }
306
307 foreach ( $theme_default_modules as $module ) {
308 array_push( $jetpack_default_modules, $module );
309 }
310
311 return array_merge( $default, $jetpack_default_modules );
312 }
313
314 /**
315 * Control the default Jetpack Sharing options.
316 * Use the `customify_filter_jetpack_sharing_default_options` to set your's.
317 *
318 * @param array $default The default value to return if the option does not exist
319 * in the database.
320 *
321 * @return array
322 */
323 function default_jetpack_sharing_options( $default ) {
324 if ( ! is_array( $default ) ) {
325 $default = array();
326 }
327
328 return array_merge( $default, $this->jetpack_sharing_default_options );
329 }
330
331 /**
332 * Control the modules that are available in Jetpack (hide some of them).
333 * Use the `customify_filter_jetpack_blocked_modules` filter to set your's.
334 *
335 * @param array $modules
336 *
337 * @return array
338 */
339 function jetpack_hide_blocked_modules( $modules ) {
340 return array_diff_key( $modules, array_flip( $this->jetpack_blocked_modules ) );
341 }
342
343 /**
344 * Fired when the plugin is activated.
345 * @since 1.0.0
346 *
347 * @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.
348 */
349 public static function activate( $network_wide ) {
350 //@todo Define activation functionality here
351 }
352
353 /**
354 * Fired when the plugin is deactivated.
355 * @since 1.0.0
356 *
357 * @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.
358 */
359 static function deactivate( $network_wide ) {
360 //@todo Define deactivation functionality here
361 }
362
363 /**
364 * Load the plugin text domain for translation.
365 * @since 1.0.0
366 */
367 function load_plugin_textdomain() {
368 $domain = $this->plugin_slug;
369 load_plugin_textdomain( $domain, false, basename( dirname( $this->file ) ) . '/languages/' );
370 }
371
372 /** === RESOURCES === **/
373
374 /**
375 * Register Customizer admin styles
376 */
377 function register_admin_customizer_styles() {
378 wp_register_style( 'customify_select2', plugins_url( 'js/select2/css/select2.css', $this->file ), array(), $this->_version );
379 wp_register_style( 'customify_style', plugins_url( 'css/customizer.css', $this->file ), array( 'customify_select2' ), $this->_version );
380 }
381
382 /**
383 * Enqueue Customizer admin styles
384 */
385 function enqueue_admin_customizer_styles() {
386 wp_enqueue_style( 'customify_style' );
387 }
388
389 /**
390 * Register Customizer admin scripts
391 */
392 function register_admin_customizer_scripts() {
393
394 wp_register_script( 'customify_select2', plugins_url( 'js/select2/js/select2.js', $this->file ), array( 'jquery' ), $this->_version );
395 wp_register_script( 'jquery-react', plugins_url( 'js/jquery-react.js', $this->file ), array( 'jquery' ), $this->_version );
396 wp_register_script( $this->plugin_slug . '-customizer-scripts', plugins_url( 'js/customizer.js', $this->file ), array(
397 'jquery',
398 'customify_select2',
399 'underscore',
400 'customize-controls'
401 ), $this->_version );
402 }
403
404 /**
405 * Enqueue Customizer admin scripts
406 */
407 function enqueue_admin_customizer_scripts() {
408 wp_enqueue_script( 'jquery-react' );
409 wp_enqueue_script( $this->plugin_slug . '-customizer-scripts' );
410
411 wp_localize_script( $this->plugin_slug . '-customizer-scripts', 'customify_settings', $this->localized );
412 }
413
414 /** Register Customizer scripts loaded only on previewer page */
415 function customizer_live_preview_register_scripts() {
416 wp_register_script( $this->plugin_slug . 'CSSOM', plugins_url( 'js/CSSOM.js', $this->file ), array( 'jquery' ), $this->_version, true );
417 wp_register_script( $this->plugin_slug . 'cssUpdate', plugins_url( 'js/jquery.cssUpdate.js', $this->file ), array(), $this->_version, true );
418 wp_register_script( $this->plugin_slug . '-previewer-scripts', plugins_url( 'js/customizer_preview.js', $this->file ), array(
419 'jquery',
420 'customize-preview',
421 $this->plugin_slug . 'CSSOM',
422 $this->plugin_slug . 'cssUpdate'
423 ), $this->_version, true );
424 }
425
426 /** Enqueue Customizer scripts loaded only on previewer page */
427 function customizer_live_preview_enqueue_scripts() {
428 wp_enqueue_script( $this->plugin_slug . '-previewer-scripts' );
429
430 // when a live preview field is in action we need to know which props need 'px' as defaults
431 $this->localized['px_dependent_css_props'] = self::$pixel_dependent_css_properties;
432
433 wp_localize_script( $this->plugin_slug . '-previewer-scripts', 'customify_settings', $this->localized );
434 }
435
436 /**
437 * Add dynamic style only on the previewer page
438 */
439
440 /**
441 * Settings page styles
442 */
443 function enqueue_admin_styles() {
444
445 if ( ! isset( $this->plugin_screen_hook_suffix ) ) {
446 return;
447 }
448
449 $screen = get_current_screen();
450 if ( $screen->id == $this->plugin_screen_hook_suffix ) {
451 wp_enqueue_style( $this->plugin_slug . '-admin-styles', plugins_url( 'css/admin.css', $this->file ), array(), $this->_version );
452 }
453 }
454
455 /**
456 * Settings page scripts
457 */
458 function enqueue_admin_scripts() {
459
460 if ( ! isset( $this->plugin_screen_hook_suffix ) ) {
461 return;
462 }
463
464 $screen = get_current_screen();
465 if ( $screen->id == $this->plugin_screen_hook_suffix ) {
466 wp_enqueue_script( $this->plugin_slug . '-admin-script', plugins_url( 'js/admin.js', $this->file ), array( 'jquery' ), $this->_version );
467 wp_localize_script( $this->plugin_slug . '-admin-script', 'customify_settings', array(
468 'ajax_url' => admin_url( 'admin-ajax.php' ),
469 'wp_rest' => array(
470 'root' => esc_url_raw( rest_url() ),
471 'nonce' => wp_create_nonce( 'wp_rest' ),
472 'customify_settings_nonce' => wp_create_nonce( 'customify_settings_nonce' )
473 ),
474 ) );
475 }
476
477 wp_localize_script( $this->plugin_slug . '-customizer-scripts', 'WP_API_Settings', array(
478 'root' => esc_url_raw( rest_url() ),
479 'nonce' => wp_create_nonce( 'wp_rest' )
480 ) );
481 }
482
483 function add_rest_routes_api(){
484 register_rest_route( 'customfiy/v1', '/delete_theme_mod', array(
485 'methods' => 'POST',
486 'callback' => array( $this, 'delete_theme_mod' ),
487 'permission_callback' => array( $this, 'permission_nonce_callback' ),
488 ) );
489 }
490
491 function delete_theme_mod(){
492 $user = wp_get_current_user();
493 if ( ! $user->caps['administrator'] ) {
494 wp_send_json_error('no admin');
495 }
496
497 $config = apply_filters('customify_filter_fields', array() );
498
499 if ( empty( $config['opt-name'] ) ) {
500 wp_send_json_error('no option key');
501 }
502
503 $key = $config['opt-name'];
504
505 remove_theme_mod( $key );
506
507 wp_send_json_success('Bby ' . $key . '!');
508 }
509
510 function permission_nonce_callback() {
511 return wp_verify_nonce( $this->get_nonce(), 'customify_settings_nonce' );
512 }
513
514 private function get_nonce() {
515 $nonce = null;
516
517 if ( isset( $_REQUEST['customify_settings_nonce'] ) ) {
518 $nonce = wp_unslash( $_REQUEST['customify_settings_nonce'] );
519 } elseif ( isset( $_POST['customify_settings_nonce'] ) ) {
520 $nonce = wp_unslash( $_POST['customify_settings_nonce'] );
521 }
522
523 return $nonce;
524 }
525
526 /**
527 * Public style generated by customizer
528 */
529 function output_dynamic_style() {
530 $custom_css = "\n";
531
532 foreach ( $this->options_list as $option_id => $option ) {
533
534 if ( isset( $option['css'] ) && ! empty( $option['css'] ) ) {
535 // now process each
536 $custom_css .= $this->convert_setting_to_css( $option_id, $option['css'] );
537 }
538
539 if ( $option['type'] === 'custom_background' ) {
540 $option['value'] = $this->get_option( $option_id );
541 $custom_css .= $this->process_custom_background_field_output( $option_id, $option );
542 }
543 }
544
545 if ( ! empty( $this->media_queries ) ) {
546
547 foreach ( $this->media_queries as $media_query => $properties ) {
548
549 if ( empty( $properties ) ) {
550 continue;
551 }
552
553 $custom_css .= '@media ' . $media_query . " { ";
554
555 foreach ( $properties as $key => $property ) {
556 $property_settings = $property['property'];
557 $property_value = $property['value'];
558 $custom_css .= $this->proccess_css_property( $property_settings, $property_value );
559 }
560
561 $custom_css .= " }\n";
562
563 }
564 }
565
566 $custom_css .= "\n";
567 ?>
568 <style id="customify_output_style">
569 <?php echo apply_filters( 'customify_dynamic_style', $custom_css ); ?>
570 </style><?php
571
572 /**
573 * from now on we output only style tags only for the preview purpose
574 * so don't cry if you see 30+ style tags for each section
575 */
576 if ( ! isset( $GLOBALS['wp_customize'] ) ) {
577 return;
578 }
579
580 foreach ( $this->options_list as $option_id => $options ) {
581
582 if ( $options['type'] === 'custom_background' ) {
583 $options['value'] = $this->get_option( $option_id );
584 $custom_background_output = $this->process_custom_background_field_output( $option_id, $options ); ?>
585
586 <style id="custom_backgorund_output_for_<?php echo $option_id; ?>">
587 <?php
588 if ( isset( $custom_background_output ) && ! empty( $custom_background_output )) {
589 echo $custom_background_output;
590 } ?>
591 </style>
592 <?php }
593
594 if ( ! isset( $options['live'] ) || $options['live'] !== true ) {
595 continue;
596 }
597
598 $this_value = $this->get_option( $option_id );
599 foreach ( $options['css'] as $key => $properties_set ) { ?>
600 <style id="dynamic_setting_<?php echo $option_id . '_property_' . str_replace( '-', '_', $properties_set['property'] ); ?>"
601 type="text/css"><?php
602
603 if ( isset( $properties_set['media'] ) && ! empty( $properties_set['media'] ) ) {
604 echo '@media '. $properties_set['media'] . " {\n";
605 }
606
607 if ( isset( $properties_set['selector'] ) && isset( $properties_set['property'] ) ) {
608 echo $this->proccess_css_property($properties_set, $this_value);
609 }
610
611 if ( isset( $properties_set['media'] ) && ! empty( $properties_set['media'] ) ) {
612 echo "}\n";
613 } ?>
614 </style>
615 <?php }
616 }
617
618 if ( ! empty( $this->media_queries ) ) {
619
620 foreach ( $this->media_queries as $media_query => $properties ) {
621
622 if ( empty( $properties ) ) {
623 continue;
624 }
625
626 $display = false;
627 $media_q = '@media ' . $media_query . " {\n";
628
629 foreach ( $properties as $key => $property ) {
630
631 if ( ! isset( $options['live'] ) || $options['live'] !== true ) {
632 continue;
633 }
634
635 $display = true; ?>
636 <style id="dynamic_setting_<?php echo $key; ?>" type="text/css"><?php
637 $property_settings = $property['property'];
638 $property_value = $property['value'];
639 $media_q .= "\t" . $this->proccess_css_property( $property_settings, $property_value );?>
640 </style>
641 <?php }
642
643 $media_q .= "\n}\n";
644
645 if ( $display ) {
646 $custom_css .= $media_q;
647 }
648 }
649 }
650 }
651
652 protected function load_google_fonts() {
653 $fonts_path = plugin_dir_path( $this->file ) . 'features/customizer/controls/resources/google.fonts.php';
654
655 if ( file_exists( $fonts_path ) ) {
656 $this->google_fonts = require( $fonts_path );
657 }
658
659 if ( ! empty( $this->google_fonts ) ) {
660 return $this->google_fonts;
661 }
662
663 return false;
664 }
665
666 function output_typography_dynamic_style() {
667 $this->get_typography_fields( $this->options_list, 'type', 'typography', $this->typo_settings );
668
669 if ( empty( $this->typo_settings ) ) {
670 return;
671 }
672
673 $families = '';
674
675 foreach ( $this->typo_settings as $id => $font ) {
676 if ( isset ( $font['value'] ) ) {
677
678 $load_all_weights = false;
679 if ( isset( $font['load_all_weights'] ) && $font['load_all_weights'] == 'true' ) {
680 $load_all_weights = true;
681 }
682
683 // shim the time when this was an array
684 if ( is_array( $font['value'] ) ) {
685 $font['value'] = stripslashes_deep( $font['value'] );
686 $font['value'] = json_encode( $font['value'] );
687 }
688
689 $value = json_decode( wp_unslash( PixCustomifyPlugin::decodeURIComponent( $font['value'] ) ), true );
690
691 // in case the value is still null, try default value(mostly for google fonts)
692 if ( ! is_array( $value ) || $value === null ) {
693 $value = $this->get_font_defaults_value( str_replace( '"', '', $font['value'] ) );
694 }
695
696 //bail if by this time we don't have a value of some sort
697 if ( empty( $value ) ) {
698 continue;
699 }
700
701 //Handle special logic for when the $value array is not an associative array
702 if ( ! $this->is_assoc( $value ) ) {
703 $value = $this->process_a_not_associative_font_default( $value );
704 }
705
706 if ( isset( $value['font_family'] ) && isset( $value['type'] ) && $value['type'] == 'google' ) {
707 $families .= "'" . $value['font_family'];
708
709 if ( $load_all_weights && is_array( $value['variants'] ) ) {
710 $families .= ":" . implode( ',', $value['variants'] );
711 } elseif ( isset( $value['selected_variants'] ) && ! empty( $value['selected_variants'] ) ) {
712 if ( is_array( $value['selected_variants'] ) ) {
713 $families .= ":" . implode( ',', $value['selected_variants'] );
714 } elseif ( is_string( $value['selected_variants'] ) || is_numeric( $value['selected_variants'] ) ) {
715 $families .= ":" . $value['selected_variants'];
716 }
717 } elseif ( isset( $value['variants'] ) && ! empty( $value['variants'] ) ) {
718 if ( is_array( $value['variants'] ) ) {
719 $families .= ":" . implode( ',', $value['variants'] );
720 } else {
721 $families .= ":" . $value['variants'];
722 }
723 }
724
725 if ( isset( $value['selected_subsets'] ) && ! empty( $value['selected_subsets'] ) ) {
726 if ( is_array( $value['selected_subsets'] ) ) {
727 $families .= ":" . implode( ',', $value['selected_subsets'] );
728 } else {
729 $families .= ":" . $value['selected_subsets'];
730 }
731 } elseif ( isset( $value['subsets'] ) && ! empty( $value['subsets'] ) ) {
732 if ( is_array( $value['subsets'] ) ) {
733 $families .= ":" . implode( ',', $value['subsets'] );
734 } else {
735 $families .= ":" . $value['subsets'];
736 }
737 }
738
739 $families .= '\',';
740 }
741 }
742 }
743
744 if ( ! empty ( $families ) && $this->get_plugin_setting( 'typography', '1' ) && $this->get_plugin_setting( 'typography_google_fonts', 1 ) ) { ?>
745 <script type="text/javascript">
746 if (typeof WebFont !== 'undefined') {<?php // if there is a WebFont object, use it ?>
747 WebFont.load({
748 google: {families: [<?php echo( rtrim( $families, ',' ) ); ?>]},
749 classes: false,
750 events: false
751 });
752 } else {<?php // basically when we don't have the WebFont object we create the google script dynamically ?>
753
754 var tk = document.createElement('script');
755 tk.src = '//ajax.googleapis.com/ajax/libs/webfont/1/webfont.js';
756 tk.type = 'text/javascript';
757
758 tk.onload = tk.onreadystatechange = function () {
759 WebFont.load({
760 google: {families: [<?php echo( rtrim( $families, ',' ) ); ?>]},
761 classes: false,
762 events: false
763 });
764 };
765
766 var s = document.getElementsByTagName('script')[0];
767 s.parentNode.insertBefore(tk, s);
768 }
769 </script>
770 <?php } ?>
771 <style id="customify_typography_output_style">
772 <?php
773 foreach ( $this->typo_settings as $key => $font ) {
774 $load_all_weights = false;
775 if ( isset( $font['load_all_weights'] ) && $font['load_all_weights'] == 'true' ) {
776 $load_all_weights = true;
777 }
778
779 if ( isset( $font['selector'] ) && isset( $font['value'] ) && ! empty( $font['value'] ) ) {
780
781 $value = json_decode( PixCustomifyPlugin::decodeURIComponent( $font['value'] ), true );
782 // in case the value is still null, try default value(mostly for google fonts)
783 if ( $value === null ) {
784 $value = $this->get_font_defaults_value( $font['value'] );
785 }
786
787 // shim the old case when the default was only the font name
788 if ( is_string( $value ) && ! empty( $value ) ) {
789 $value = array( 'font_family' => $value );
790 }
791
792 //Handle special logic for when the $value array is not an associative array
793 if ( ! $this->is_assoc( $value ) ) {
794 $value = $this->process_a_not_associative_font_default( $value );
795 }
796
797 $selected_variant = '';
798 if ( ! empty( $value['selected_variants'] ) ) {
799 if ( is_array( $value['selected_variants'] ) ) {
800 $selected_variant = $value['selected_variants'][0];
801 } else {
802 $selected_variant = $value['selected_variants'];
803 }
804 }
805
806 // First handle the case where we have the font-family in the selected variant (usually this means a custom font from our Fonto plugin)
807 if ( ! empty( $selected_variant ) && is_array( $selected_variant ) && ! empty( $selected_variant['font-family'] ) ) {
808 //the variant's font-family
809 echo $font['selector'] . " {\nfont-family: " . $selected_variant['font-family'] . ";\n";
810
811 if ( ! $load_all_weights ) {
812 // if this is a custom font (like from our plugin Fonto) with individual styles & weights - i.e. the font-family says it all
813 // we need to "force" the font-weight and font-style
814 if ( ! empty( $value['type'] ) && 'custom_individual' == $value['type'] ) {
815 $selected_variant['font-weight'] = '400 !important';
816 $selected_variant['font-style'] = 'normal !important';
817 }
818
819 // output the font weight, if available
820 if ( ! empty( $selected_variant['font-weight'] ) ) {
821 echo "font-weight: " . $selected_variant['font-weight'] . ";\n";
822 }
823
824 // output the font style, if available
825 if ( ! empty( $selected_variant['font-style'] ) ) {
826 echo "font-style: " . $selected_variant['font-style'] . ";\n";
827 }
828 }
829
830 echo "}\n";
831 } elseif ( isset( $value['font_family'] ) ) {
832 // the selected font family
833 echo $font['selector'] . " {\n font-family: " . $value['font_family'] . ";\n";
834
835 if ( ! empty( $selected_variant ) && ! $load_all_weights ) {
836 $weight_and_style = strtolower( $selected_variant );
837
838 $italic_font = false;
839
840 //determine if this is an italic font (the $weight_and_style is usually like '400' or '400italic' )
841 if ( strpos( $weight_and_style, 'italic' ) !== false ) {
842 $weight_and_style = str_replace( 'italic', '', $weight_and_style);
843 $italic_font = true;
844 }
845
846 if ( ! empty( $weight_and_style ) ) {
847 //a little bit of sanity check - in case it's not a number
848 if( $weight_and_style === 'regular' ) {
849 $weight_and_style = 'normal';
850 }
851 echo "font-weight: " . $weight_and_style . ";\n";
852 }
853
854 if ( $italic_font ) {
855 echo "font-style: italic;\n";
856 }
857 }
858
859 echo "}\n";
860 }
861 }
862 } ?>
863 </style>
864 <?php }
865
866 /**
867 * Handle special logic for when the $value array is not an associative array
868 * Return a new associative array with proper keys
869 */
870 public function process_a_not_associative_font_default( $value ) {
871
872 $new_value = array();
873
874 //Let's determine some type of font
875 if ( ! isset( $value[2] ) || ( isset( $value[2] ) && 'google' == $value[2] ) ) {
876 $new_value = $this->get_font_defaults_value( $value[0] );
877 } else {
878 $new_value['type'] = $value[2];
879 }
880
881 if ( null == $new_value ) {
882 $new_value = array();
883 }
884
885 //The first entry is the font-family
886 if ( isset( $value[0] ) ) {
887 $new_value['font_family'] = $value[0];
888 }
889
890 //In case we don't have an associative array
891 //The second entry is the variants
892 if ( isset( $value[1] ) ) {
893 $new_value['selected_variants'] = $value[1];
894 }
895
896 return $new_value;
897 }
898
899 /**
900 *
901 * @param $font_name
902 *
903 * @return null
904 */
905 public function get_font_defaults_value( $font_name ) {
906
907 if ( empty( $this->google_fonts ) ) {
908 $this->load_google_fonts();
909 }
910
911 if ( isset( $this->google_fonts[ $font_name ] ) ) {
912 $value = $this->google_fonts[ $font_name ];
913 $value['font_family'] = $font_name;
914 $value['type'] = 'google';
915
916 return $value;
917 } elseif ( isset( $this->theme_fonts[ $font_name ] ) ) {
918 $value['type'] = 'theme_font';
919 $value['src'] = $this->theme_fonts[ $font_name ]['src'];
920 $value['variants'] = $this->theme_fonts[ $font_name ]['variants'];
921 $value['font_family'] = $this->theme_fonts[ $font_name ]['family'];
922
923 return $value;
924 }
925
926 return null;
927 }
928
929 /**
930 * Turn css options into a valid CSS output
931 *
932 * @param $option_id
933 * @param array $css_config
934 *
935 * @return string
936 */
937 protected function convert_setting_to_css( $option_id, $css_config = array() ) {
938 $output = '';
939
940 $this_value = $this->get_option( $option_id );
941
942 if ( empty( $css_config ) ) {
943 return $output;
944 }
945
946 foreach ( $css_config as $css_property ) {
947
948 if ( isset( $css_property['media'] ) && ! empty( $css_property['media'] ) ) {
949 $this->media_queries[ $css_property['media'] ][ $option_id ] = array(
950 'property' => $css_property,
951 'value' => $this_value
952 );
953 continue;
954 }
955
956 if ( ! isset( $css_property['selector'] ) || isset( $css_property['property'] ) ) {
957 $output .= $this->proccess_css_property( $css_property, $this_value );
958 }
959 }
960
961 return $output;
962 }
963
964 protected function proccess_css_property( $css_property, $this_value ) {
965 $unit = '';
966
967 if ( isset( $css_property['unit'] ) ) {
968 $unit = $css_property['unit'];
969 }
970
971 // if the unit isn't specified but the property should have a unit force 'px' as it
972 if ( empty( $unit ) && in_array( $css_property['property'], self::$pixel_dependent_css_properties ) ) {
973 $unit = 'px';
974 }
975 // lose the tons of tabs
976 $css_property['selector'] = trim( preg_replace( '/\t+/', '', $css_property['selector'] ) );
977
978 $this_property_output = $css_property['selector'] . ' { ' . $css_property['property'] . ': ' . $this_value . $unit . "; }\n";
979
980 if ( isset( $css_property['callback_filter'] ) && function_exists( $css_property['callback_filter'] ) ) {
981 $this_property_output = call_user_func( $css_property['callback_filter'], $this_value, $css_property['selector'], $css_property['property'], $unit );
982 }
983
984 return $this_property_output;
985 }
986
987 protected function process_custom_background_field_output( $option_id, $options ) {
988 $selector = $output = '';
989
990 if ( ! isset( $options['value'] ) ) {
991 return false;
992 }
993 $value = $options['value'];
994
995 if ( ! isset( $options['output'] ) ) {
996 return $selector;
997 } elseif ( is_string( $options['output'] ) ) {
998 $selector = $options['output'];
999 } elseif ( is_array( $options['output'] ) ) {
1000 $selector = implode( ' ', $options['output'] );
1001 }
1002
1003
1004 $output .= $selector . " {";
1005 if ( isset( $value['background-image'] ) && ! empty( $value['background-image'] ) ) {
1006 $output .= "background-image: url( " . $value['background-image'] . ");";
1007 } else {
1008 $output .= "background-image: none;";
1009 }
1010
1011 if ( isset( $value['background-repeat'] ) && ! empty( $value['background-repeat'] ) ) {
1012 $output .= "background-repeat:" . $value['background-repeat'] . ";";
1013 }
1014
1015 if ( isset( $value['background-position'] ) && ! empty( $value['background-position'] ) ) {
1016 $output .= "background-position:" . $value['background-position'] . ";";
1017 }
1018
1019 if ( isset( $value['background-size'] ) && ! empty( $value['background-size'] ) ) {
1020 $output .= "background-size:" . $value['background-size'] . ";";
1021 }
1022
1023 if ( isset( $value['background-attachment'] ) && ! empty( $value['background-attachment'] ) ) {
1024 $output .= "background-attachment:" . $value['background-attachment'] . ";";
1025 }
1026 $output .= "}\n";
1027
1028 return $output;
1029 }
1030
1031 /**
1032 * add our customizer styling edits into the wp_editor
1033 */
1034 function add_customizer_settings_into_wp_editor() {
1035
1036 ob_start();
1037 $this->output_typography_dynamic_style();
1038 $this->output_dynamic_style();
1039
1040 $custom_css = ob_get_clean(); ?>
1041 <script type="text/javascript">
1042 /* <![CDATA[ */
1043 (function ($) {
1044 $(window).load(function () {
1045 /**
1046 * @param iframe_id the id of the frame you whant to append the style
1047 * @param style_element the style element you want to append
1048 */
1049 var append_script_to_iframe = function (ifrm_id, scriptEl) {
1050 var myIframe = document.getElementById(ifrm_id);
1051
1052 var script = myIframe.contentWindow.document.createElement("script");
1053 script.type = "text/javascript";
1054 script.innerHTML = scriptEl.innerHTML;
1055
1056 myIframe.contentWindow.document.head.appendChild(script);
1057 };
1058
1059 var append_style_to_iframe = function (ifrm_id, styleElment) {
1060 var ifrm = window.frames[ifrm_id];
1061 ifrm = ( ifrm.contentDocument || ifrm.contentDocument || ifrm.document );
1062 var head = ifrm.getElementsByTagName('head')[0];
1063
1064 if (typeof styleElment !== "undefined") {
1065 head.appendChild(styleElment);
1066 }
1067 };
1068
1069 var xmlString = <?php echo json_encode( str_replace( "\n", "", $custom_css ) ); ?>,
1070 parser = new DOMParser(),
1071 doc = parser.parseFromString(xmlString, "text/html");
1072
1073 if (typeof window.frames['content_ifr'] !== 'undefined') {
1074
1075 $.each(doc.head.childNodes, function (key, el) {
1076 if (typeof el !== "undefined" && typeof el.tagName !== "undefined") {
1077
1078 switch (el.tagName) {
1079 case 'STYLE' :
1080 append_style_to_iframe('content_ifr', el);
1081 break;
1082 case 'SCRIPT' :
1083 append_script_to_iframe('content_ifr', el);
1084 break;
1085 default:
1086 break;
1087 }
1088 }
1089 });
1090 }
1091 });
1092 })(jQuery);
1093 /* ]]> */
1094 </script>
1095 <?php }
1096
1097 /**
1098 * Register the administration menu for this plugin into the WordPress Dashboard menu.
1099 */
1100 function add_plugin_admin_menu() {
1101 $this->plugin_screen_hook_suffix = add_options_page( __( 'Customify', $this->plugin_slug ), __( 'Customify', $this->plugin_slug ), 'edit_plugins', $this->plugin_slug, array(
1102 $this,
1103 'display_plugin_admin_page'
1104 ) );
1105 }
1106
1107 /**
1108 * Render the settings page for this plugin.
1109 */
1110 function display_plugin_admin_page() {
1111 include_once( 'views/admin.php' );
1112 }
1113
1114 /**
1115 * Add settings action link to the plugins page.
1116 */
1117 function add_action_links( $links ) {
1118 return array_merge( array( 'settings' => '<a href="' . admin_url( 'options-general.php?page=pixcustomify' ) . '">' . __( 'Settings', $this->plugin_slug ) . '</a>' ), $links );
1119 }
1120
1121 protected function register_customizer_controls() {
1122
1123 // first get the base customizer extend class
1124 require_once( $this->get_base_path() . '/features/customizer/class-Pix_Customize_Control.php' );
1125
1126 // now get all the controls
1127 $path = $this->get_base_path() . '/features/customizer/controls/';
1128 pixcustomify::require_all( $path );
1129 }
1130
1131 /**
1132 * @param WP_Customize_Manager $wp_customize
1133 */
1134 function register_customizer( $wp_customize ) {
1135
1136 $this->register_customizer_controls();
1137
1138 $customizer_settings = $this->customizer_config;
1139
1140 if ( ! empty ( $customizer_settings ) ) {
1141
1142 // first check the very needed options name
1143 if ( ! isset ( $customizer_settings['opt-name'] ) || empty( $customizer_settings['opt-name'] ) ) {
1144 return;
1145 }
1146 $options_name = $customizer_settings['opt-name'];
1147 $wp_customize->options_key = $options_name;
1148
1149 // let's check if we have sections or panels
1150 if ( isset( $customizer_settings['panels'] ) && ! empty( $customizer_settings['panels'] ) ) {
1151
1152 foreach ( $customizer_settings['panels'] as $panel_id => $panel_settings ) {
1153
1154 if ( ! empty( $panel_id ) && isset( $panel_settings['sections'] ) && ! empty( $panel_settings['sections'] ) ) {
1155
1156 $panel_id = $options_name . '[' . $panel_id . ']';
1157 $panel_args = array(
1158 'priority' => 10,
1159 'capability' => 'edit_theme_options',
1160 'title' => __( 'Panel title is required', 'pixcustomify' ),
1161 'description' => __( 'Description of what this panel does.', 'pixcustomify' ),
1162 );
1163
1164 if ( isset( $panel_settings['priority'] ) && ! empty( $panel_settings['priority'] ) ) {
1165 $panel_args['priority'] = $panel_settings['priority'];
1166 }
1167
1168 if ( isset( $panel_settings['title'] ) && ! empty( $panel_settings['title'] ) ) {
1169 $panel_args['title'] = $panel_settings['title'];
1170 }
1171
1172 if ( isset( $panel_settings['description'] ) && ! empty( $panel_settings['description'] ) ) {
1173 $panel_args[10] = $panel_settings['description'];
1174 }
1175
1176 $wp_customize->add_panel( $panel_id, $panel_args );
1177
1178 foreach ( $panel_settings['sections'] as $section_id => $section_settings ) {
1179 if ( ! empty( $section_id ) && isset( $section_settings['options'] ) && ! empty( $section_settings['options'] ) ) {
1180 $this->register_section( $panel_id, $section_id, $options_name, $section_settings, $wp_customize );
1181 }
1182 }
1183 }
1184 }
1185 }
1186
1187 if ( isset( $customizer_settings['sections'] ) && ! empty( $customizer_settings['sections'] ) ) {
1188
1189 foreach ( $customizer_settings['sections'] as $section_id => $section_settings ) {
1190 if ( ! empty( $section_id ) && isset( $section_settings['options'] ) && ! empty( $section_settings['options'] ) ) {
1191 $this->register_section( $panel_id = false, $section_id, $options_name, $section_settings, $wp_customize );
1192 }
1193 }
1194 }
1195
1196 if ( $this->plugin_settings['enable_reset_buttons'] ) {
1197 // create a toolbar section which will be present all the time
1198 $reset_section_settings = array(
1199 'title' => 'Customify toolbar',
1200 'options' => array(
1201 'reset_all_button' => array(
1202 'type' => 'button',
1203 'label' => 'Reset Customify',
1204 'action' => 'reset_customify',
1205 'value' => 'Reset'
1206 ),
1207 )
1208 );
1209
1210 $wp_customize->add_section(
1211 'customify_toolbar',
1212 array(
1213 'title' => '',
1214 'priority' => 999999999
1215 )
1216 );
1217
1218 $wp_customize->add_setting(
1219 'reset_customify',
1220 array()
1221 );
1222 $wp_customize->add_control( new Pix_Customize_Button_Control(
1223 $wp_customize,
1224 'reset_customify',
1225 array(
1226 'label' => __( 'Reset Customify to Defaults', 'customify' ),
1227 'section' => 'customify_toolbar',
1228 'settings' => 'reset_customify',
1229 'action' => 'reset_customify',
1230 )
1231 ) );
1232 }
1233
1234 // register typekit options
1235 if ( isset( $customizer_settings['typekit_options'] ) ) {
1236
1237 // create a toolbar section which will be present all the time
1238 $reset_section_settings = array(
1239 'title' => 'Customify Typekit Options',
1240 'capability' => 'manage_options',
1241 'options' => array(
1242 'typkit_user' => array(
1243 'type' => 'text',
1244 'label' => 'Typekit Username',
1245 ),
1246 'typkit_password' => array(
1247 'type' => 'text',
1248 'label' => 'Typekit Username',
1249 ),
1250 )
1251 );
1252 }
1253 }
1254
1255 do_action( 'customify_create_custom_control', $wp_customize );
1256 }
1257
1258 protected function register_section( $panel_id, $section_key, $options_name, $section_settings, $wp_customize ) {
1259
1260 if ( isset( $this->plugin_settings['disable_customify_sections'] ) && isset( $this->plugin_settings['disable_customify_sections'][ $section_key ] ) ) {
1261 return;
1262 }
1263
1264 $section_args = array(
1265 'priority' => 10,
1266 'capability' => 'edit_theme_options',
1267 'title' => __( 'Title Section is required', '' ),
1268 'panel' => $panel_id,
1269 );
1270 $section_id = $options_name . '[' . $section_key . ']';
1271
1272 if ( isset( $section_settings['priority'] ) && ! empty( $section_settings['priority'] ) ) {
1273 $section_args['priority'] = $section_settings['priority'];
1274 }
1275
1276 if ( isset( $section_settings['title'] ) && ! empty( $section_settings['title'] ) ) {
1277 $section_args['title'] = $section_settings['title'];
1278 }
1279
1280 if ( isset( $section_settings['theme_supports'] ) && ! empty( $section_settings['theme_supports'] ) ) {
1281 $section_args['theme_supports'] = $section_settings['theme_supports'];
1282 }
1283
1284 if ( isset( $section_settings['description'] ) && ! empty( $section_settings['description'] ) ) {
1285 $section_args['description'] = $section_settings['description'];
1286 }
1287
1288 $wp_customize->add_section( $section_id, $section_args );
1289
1290 foreach ( $section_settings['options'] as $option_id => $option_config ) {
1291
1292 if ( empty( $option_id ) || ! isset( $option_config['type'] ) ) {
1293 continue;
1294 }
1295
1296 $option_id = $options_name . '[' . $option_id . ']';
1297
1298 $this->register_field( $section_id, $option_id, $option_config, $wp_customize );
1299 }
1300
1301 }
1302
1303 /**
1304 * @param string $section_id
1305 * @param string $setting_id
1306 * @param array $setting_config
1307 * @param WP_Customize_Manager $wp_customize
1308 */
1309 protected function register_field( $section_id, $setting_id, $setting_config, $wp_customize ) {
1310
1311 $add_control = true;
1312 // defaults
1313 $setting_args = array(
1314 'default' => '',
1315 'capability' => 'edit_theme_options',
1316 'transport' => 'refresh',
1317 );
1318 $control_args = array(
1319 'label' => '',
1320 'section' => $section_id,
1321 'settings' => $setting_id,
1322 );
1323
1324 $this->localized['settings'][ $setting_id ] = $setting_config;
1325
1326 // sanitize settings
1327 if ( ( isset( $setting_config['live'] ) && $setting_config['live'] ) || $setting_config['type'] === 'font' ) {
1328 $setting_args['transport'] = 'postMessage';
1329 }
1330
1331 if ( isset( $setting_config['default'] ) ) {
1332 $setting_args['default'] = $setting_config['default'];
1333 }
1334
1335 if ( isset( $setting_config['capability'] ) && ! empty( $setting_config['capability'] ) ) {
1336 $setting_args['capability'] = $setting_config['capability'];
1337 }
1338
1339 if ( $this->plugin_settings['values_store_mod'] == 'option' ) {
1340 $setting_args['type'] = 'option';
1341 }
1342
1343 // if we arrive here this means we have a custom field control
1344 switch ( $setting_config['type'] ) {
1345
1346 case 'checkbox':
1347
1348 $setting_args['sanitize_callback'] = array( $this, 'setting_sanitize_checkbox' );
1349 break;
1350
1351 default:
1352 break;
1353 }
1354
1355 if ( isset( $setting_config['sanitize_callback'] ) && ! empty( $setting_config['sanitize_callback'] ) && function_exists( $setting_config['sanitize_callback'] ) ) {
1356 $setting_args['sanitize_callback'] = $setting_config['sanitize_callback'];
1357 }
1358
1359 // and add it
1360 $wp_customize->add_setting( $setting_id, $setting_args );
1361
1362 // now sanitize the control
1363 if ( isset( $setting_config['label'] ) && ! empty( $setting_config['label'] ) ) {
1364 $control_args['label'] = $setting_config['label'];
1365 }
1366
1367 if ( isset( $setting_config['priority'] ) && ! empty( $setting_config['priority'] ) ) {
1368 $control_args['priority'] = $setting_config['priority'];
1369 }
1370
1371 if ( isset( $setting_config['desc'] ) && ! empty( $setting_config['desc'] ) ) {
1372 $control_args['description'] = $setting_config['desc'];
1373 }
1374
1375 if ( isset( $setting_config['active_callback'] ) && ! empty( $setting_config['active_callback'] ) ) {
1376 $control_args['active_callback'] = $setting_config['active_callback'];
1377 }
1378
1379
1380 $control_args['type'] = $setting_config['type'];
1381
1382 // select the control type
1383 // but first init a default
1384 $control_class_name = 'Pix_Customize_Text_Control';
1385
1386 // if is a standard wp field type call it here and skip the rest
1387 if ( in_array( $setting_config['type'], array(
1388 'checkbox',
1389 'dropdown-pages',
1390 'url',
1391 'date',
1392 'time',
1393 'datetime',
1394 'week',
1395 'search'
1396 ) ) ) {
1397 $wp_customize->add_control( $setting_id . '_control', $control_args );
1398
1399 return;
1400 } elseif ( in_array( $setting_config['type'], array(
1401 'radio',
1402 'select'
1403 ) ) && isset( $setting_config['choices'] ) && ! empty( $setting_config['choices'] )
1404 ) {
1405 $control_args['choices'] = $setting_config['choices'];
1406 $wp_customize->add_control( $setting_id . '_control', $control_args );
1407
1408 return;
1409 } elseif ( in_array( $setting_config['type'], array( 'range' ) ) && isset( $setting_config['input_attrs'] ) && ! empty( $setting_config['input_attrs'] ) ) {
1410
1411 $control_args['input_attrs'] = $setting_config['input_attrs'];
1412
1413 $wp_customize->add_control( $setting_id . '_control', $control_args );
1414 }
1415
1416 // if we arrive here this means we have a custom field control
1417 switch ( $setting_config['type'] ) {
1418
1419 case 'text':
1420 if ( isset( $setting_config['live'] ) ) {
1421 $control_args['live'] = $setting_config['live'];
1422 }
1423
1424 $control_class_name = 'Pix_Customize_Text_Control';
1425 break;
1426
1427 case 'textarea':
1428 if ( isset( $setting_config['live'] ) ) {
1429 $control_args['live'] = $setting_config['live'];
1430 }
1431
1432 $control_class_name = 'Pix_Customize_Textarea_Control';
1433 break;
1434
1435 case 'color':
1436 $control_class_name = 'WP_Customize_Color_Control';
1437 break;
1438
1439 case 'color_drop':
1440 $control_class_name = 'Pix_Customize_Color_Drop_Control';
1441 break;
1442
1443 case 'ace_editor':
1444 if ( isset( $setting_config['live'] ) ) {
1445 $control_args['live'] = $setting_config['live'];
1446 }
1447
1448 if ( isset( $setting_config['editor_type'] ) ) {
1449 $control_args['editor_type'] = $setting_config['editor_type'];
1450 }
1451
1452 $control_class_name = 'Pix_Customize_Ace_Editor_Control';
1453 break;
1454
1455 case 'upload':
1456 $control_class_name = 'WP_Customize_Upload_Control';
1457 break;
1458
1459 case 'image':
1460 $control_class_name = 'WP_Customize_Image_Control';
1461 break;
1462
1463 case 'media':
1464 $control_class_name = 'WP_Customize_Media_Control';
1465 break;
1466
1467 case 'custom_background':
1468 if ( isset( $setting_config['field'] ) ) {
1469 $control_args['field'] = $setting_config['field'];
1470 }
1471
1472 $control_class_name = 'Pix_Customize_Background_Control';
1473 break;
1474
1475 case 'cropped_media':
1476 if ( isset( $setting_config['width'] ) ) {
1477 $control_args['width'] = $setting_config['width'];
1478 }
1479
1480 if ( isset( $setting_config['height'] ) ) {
1481 $control_args['height'] = $setting_config['height'];
1482 }
1483
1484 if ( isset( $setting_config['flex_width'] ) ) {
1485 $control_args['flex_width'] = $setting_config['flex_width'];
1486 }
1487
1488 if ( isset( $setting_config['flex_height'] ) ) {
1489 $control_args['flex_height'] = $setting_config['flex_height'];
1490 }
1491
1492 $control_class_name = 'WP_Customize_Cropped_Image_Control';
1493 break;
1494
1495 // Custom types
1496 case 'typography' :
1497 $use_typography = $this->get_plugin_setting( 'typography', '1' );
1498
1499 if ( $use_typography === false ) {
1500 $add_control = false;
1501 continue;
1502 }
1503
1504 $control_class_name = 'Pix_Customize_Typography_Control';
1505
1506 if ( isset( $setting_config['backup'] ) ) {
1507 $control_args['backup'] = $setting_config['backup'];
1508 }
1509
1510 if ( isset( $setting_config['font_weight'] ) ) {
1511 $control_args['font_weight'] = $setting_config['font_weight'];
1512 }
1513
1514 if ( isset( $setting_config['subsets'] ) ) {
1515 $control_args['subsets'] = $setting_config['subsets'];
1516 }
1517
1518 if ( isset( $setting_config['recommended'] ) ) {
1519 $control_args['recommended'] = array_flip( $setting_config['recommended'] );
1520 }
1521
1522 if ( isset( $setting_config['load_all_weights'] ) ) {
1523 $control_args['load_all_weights'] = $setting_config['load_all_weights'];
1524 }
1525
1526 if ( isset( $setting_config['default'] ) ) {
1527 $control_args['default'] = $setting_config['default'];
1528 }
1529
1530 break;
1531
1532 // Custom types
1533 case 'font' :
1534 $use_typography = $this->get_plugin_setting( 'typography', '1' );
1535
1536 if ( $use_typography === false ) {
1537 $add_control = false;
1538 continue;
1539 }
1540
1541 $control_class_name = 'Pix_Customize_Font_Control';
1542
1543 if ( isset( $setting_config['backup'] ) ) {
1544 $control_args['backup'] = $setting_config['backup'];
1545 }
1546
1547 if ( isset( $setting_config['font_weight'] ) ) {
1548 $control_args['font_weight'] = $setting_config['font_weight'];
1549 }
1550
1551 if ( isset( $setting_config['subsets'] ) ) {
1552 $control_args['subsets'] = $setting_config['subsets'];
1553 }
1554
1555 if ( isset( $setting_config['recommended'] ) ) {
1556 $control_args['recommended'] = array_flip( $setting_config['recommended'] );
1557 }
1558
1559 if ( isset( $setting_config['load_all_weights'] ) ) {
1560 $control_args['load_all_weights'] = $setting_config['load_all_weights'];
1561 }
1562
1563 if ( isset( $setting_config['default'] ) ) {
1564 $control_args['default'] = $setting_config['default'];
1565 }
1566
1567 if ( isset( $setting_config['fields'] ) ) {
1568 $control_args['fields'] = $setting_config['fields'];
1569 }
1570 $control_args['live'] = true;
1571
1572 break;
1573
1574 case 'select2' :
1575 if ( ! isset( $setting_config['choices'] ) || empty( $setting_config['choices'] ) ) {
1576 return;
1577 }
1578
1579 $control_args['choices'] = $setting_config['choices'];
1580
1581 $control_class_name = 'Pix_Customize_Select2_Control';
1582 break;
1583
1584 case 'preset' :
1585 if ( ! isset( $setting_config['choices'] ) || empty( $setting_config['choices'] ) ) {
1586 return;
1587 }
1588
1589 $control_args['choices'] = $setting_config['choices'];
1590
1591 if ( isset( $setting_config['choices_type'] ) || ! empty( $setting_config['choices_type'] ) ) {
1592 $control_args['choices_type'] = $setting_config['choices_type'];
1593 }
1594
1595 if ( isset( $setting_config['desc'] ) || ! empty( $setting_config['desc'] ) ) {
1596 $control_args['description'] = $setting_config['desc'];
1597 }
1598
1599
1600 $control_class_name = 'Pix_Customize_Preset_Control';
1601 break;
1602
1603 case 'radio_image' :
1604 if ( ! isset( $setting_config['choices'] ) || empty( $setting_config['choices'] ) ) {
1605 return;
1606 }
1607
1608 $control_args['choices'] = $setting_config['choices'];
1609
1610 if ( isset( $setting_config['choices_type'] ) || ! empty( $setting_config['choices_type'] ) ) {
1611 $control_args['choices_type'] = $setting_config['choices_type'];
1612 }
1613
1614 if ( isset( $setting_config['desc'] ) || ! empty( $setting_config['desc'] ) ) {
1615 $control_args['description'] = $setting_config['desc'];
1616 }
1617
1618
1619 $control_class_name = 'Pix_Customize_Radio_Image_Control';
1620 break;
1621
1622 case 'button' :
1623 if ( ! isset( $setting_config['action'] ) || empty( $setting_config['action'] ) ) {
1624 return;
1625 }
1626
1627 $control_args['action'] = $setting_config['action'];
1628
1629 $control_class_name = 'Pix_Customize_Button_Control';
1630
1631 break;
1632
1633 case 'html' :
1634 if ( isset( $setting_config['html'] ) || ! empty( $setting_config['html'] ) ) {
1635 $control_args['html'] = $setting_config['html'];
1636 }
1637
1638 $control_class_name = 'Pix_Customize_HTML_Control';
1639 break;
1640
1641 case 'import_demo_data' :
1642 if ( isset( $setting_config['html'] ) || ! empty( $setting_config['html'] ) ) {
1643 $control_args['html'] = $setting_config['html'];
1644 }
1645
1646 if ( ! isset( $setting_config['label'] ) || empty( $setting_config['label'] ) ) {
1647 $control_args['label'] = esc_html__( 'Import', 'customify' );
1648 } else {
1649 $control_args['label'] = $setting_config['label'];
1650 }
1651
1652 if ( isset( $setting_config['notices'] ) && ! empty( $setting_config['notices'] ) ) {
1653 $control_args['notices'] = $setting_config['notices'];
1654 }
1655
1656 $control_class_name = 'Pix_Customize_Import_Demo_Data_Control';
1657 break;
1658
1659 default:
1660 // if we don't have a real control just quit, it doesn't even matter
1661 return;
1662 break;
1663 }
1664
1665 $this_control = new $control_class_name(
1666 $wp_customize,
1667 $setting_id . '_control',
1668 $control_args
1669 );
1670
1671 if ( $add_control ) {
1672 $wp_customize->add_control( $this_control );
1673 }
1674 }
1675
1676 /**
1677 * Remove the sections selected by user
1678 *
1679 * @param WP_Customize_Manager $wp_customize
1680 */
1681 function remove_default_sections( $wp_customize ) {
1682 global $wp_registered_sidebars;
1683
1684 $to_remove = $this->get_plugin_setting( 'disable_default_sections' );
1685
1686 if ( ! empty( $to_remove ) ) {
1687 foreach ( $to_remove as $section => $nothing ) {
1688
1689 if ( $section === 'widgets' ) {
1690 foreach ( $wp_registered_sidebars as $widget => $settings ) {
1691 $wp_customize->remove_section( 'sidebar-widgets-' . $widget );
1692 }
1693 continue;
1694 }
1695
1696 $wp_customize->remove_section( $section );
1697 }
1698 }
1699 }
1700
1701 public function get_base_path() {
1702 return plugin_dir_path( $this->file );
1703 }
1704
1705 public function get_typography_fields( $array, $key, $value, &$results, $input_key = 0 ) {
1706 if ( ! is_array( $array ) ) {
1707 return;
1708 }
1709
1710 if ( isset( $array[ $key ] ) && $array[ $key ] == $value ) {
1711 $results[ $input_key ] = $array;
1712
1713 $default = null;
1714
1715 if ( isset( $array['default'] ) && is_array( $array['default'] ) ) {
1716 $default = json_encode( $array['default'] );
1717 }
1718
1719 $results[ $input_key ]['value'] = $this->get_option( $input_key, $default );
1720 }
1721
1722 foreach ( $array as $i => $subarray ) {
1723 $this->get_typography_fields( $subarray, $key, $value, $results, $i );
1724 }
1725 }
1726
1727 function get_options_key() {
1728 if ( ! empty( $this->opt_name ) ) {
1729 return $this->opt_name;
1730 }
1731
1732 return false;
1733 }
1734
1735 /**
1736 * Use this function when you need to know if an import button is used
1737 * @return bool
1738 */
1739 function import_button_exists() {
1740
1741 if ( empty( $this->options_list ) ) {
1742 $this->options_list = $this->get_options();
1743 }
1744
1745 foreach ( $this->options_list as $option ) {
1746 if ( isset( $option['type'] ) && 'import_demo_data' === $option['type'] ) {
1747 return true;
1748 break;
1749 }
1750 }
1751
1752 return false;
1753 }
1754
1755 /** == Helpers == */
1756
1757 protected function get_current_values( $opt_name = null ) {
1758 // Fallback to the global $opt_name
1759 if ( empty( $opt_name ) ) {
1760 $opt_name = $this->opt_name;
1761 }
1762
1763 // Bail as we have nothing to work with
1764 if ( empty( $opt_name ) ) {
1765 return false;
1766 }
1767
1768 $store_type = $this->get_plugin_setting( 'values_store_mod', 'option' );
1769 if ( $store_type === 'option' ) {
1770 return get_option( $opt_name );
1771 } elseif ( $store_type === 'theme_mod' ) {
1772 return get_theme_mod( $opt_name );
1773 }
1774
1775 return false;
1776 }
1777
1778 public function get_options() {
1779
1780 $settings = array();
1781
1782 if ( isset ( $this->customizer_config['panels'] ) ) {
1783
1784 foreach ( $this->customizer_config['panels'] as $pane_id => $panel_settings ) {
1785
1786 if ( isset( $panel_settings['sections'] ) ) {
1787 foreach ( $panel_settings['sections'] as $section_id => $section_settings ) {
1788 if ( isset( $section_settings['options'] ) ) {
1789 foreach ( $section_settings['options'] as $option_id => $option ) {
1790 $settings[ $option_id ] = $option;
1791 if ( isset( $this->current_values[ $option_id ] ) ) {
1792 $settings[ $option_id ]['value'] = $this->current_values[ $option_id ];
1793 }
1794 }
1795 }
1796 }
1797 }
1798 }
1799 }
1800
1801 if ( isset ( $this->customizer_config['sections'] ) ) {
1802 foreach ( $this->customizer_config['sections'] as $section_id => $section_settings ) {
1803 if ( isset( $section_settings['options'] ) ) {
1804 foreach ( $section_settings['options'] as $option_id => $option ) {
1805 $settings[ $option_id ] = $option;
1806 if ( isset( $this->current_values[ $option_id ] ) ) {
1807 $settings[ $option_id ]['value'] = $this->current_values[ $option_id ];
1808 }
1809 }
1810 }
1811 }
1812 }
1813
1814 return $settings;
1815 }
1816
1817 protected function get_value( $option, $alt_opt_name ) {
1818 global $wp_customize;
1819
1820 $opt_name = $this->opt_name;
1821 $values = $this->current_values;
1822
1823 // 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
1824 if ( empty( $opt_name ) && ! empty( $alt_opt_name ) ) {
1825 $opt_name = $alt_opt_name;
1826 $values = $this->get_current_values( $opt_name );
1827 }
1828
1829 if ( ! empty( $wp_customize ) && method_exists( $wp_customize, 'get_setting' ) ) {
1830
1831 $option_key = $opt_name . '[' . $option . ']';
1832 $setting = $wp_customize->get_setting( $option_key );
1833 if ( ! empty( $setting ) ) {
1834 $value = $setting->value();
1835
1836 return $value;
1837 }
1838 }
1839
1840 // shim
1841 if ( strpos( $option, $opt_name . '[' ) !== false ) {
1842 // get only the setting id
1843 $option = explode( '[', $option );
1844 $option = rtrim( $option[1], ']' );
1845 }
1846
1847 if ( isset( $values[ $option ] ) ) {
1848 return $values[ $option ];
1849 }
1850
1851 return null;
1852 }
1853
1854 /**
1855 * A public function to retreat an option's value
1856 * If there is a value and return it
1857 * Otherwise try to get the default parameter or the default from config
1858 *
1859 * @param $option
1860 * @param mixed $default Optional.
1861 * @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.
1862 *
1863 * @return bool|null|string
1864 */
1865 public function get_option( $option, $default = null, $alt_opt_name = null ) {
1866
1867 $return = $this->get_value( $option, $alt_opt_name );
1868
1869 if ( $return !== null ) {
1870 return $return;
1871 } elseif ( $default !== null ) {
1872 return $default;
1873 } elseif ( isset( $this->options_list[ $option ] ) && isset( $this->options_list[ $option ]['default'] ) ) {
1874 return $this->options_list[ $option ]['default'];
1875 }
1876
1877 return null;
1878 }
1879
1880 public function has_option( $option ) {
1881
1882 if ( isset( $this->options_list[ $option ] ) ) {
1883 return true;
1884 }
1885
1886 return false;
1887 }
1888
1889 protected function get_config() {
1890 if ( file_exists( $this->get_base_path() . 'plugin-config.php' ) ) {
1891 return include( $this->get_base_path() . 'plugin-config.php' );
1892 }
1893
1894 return false;
1895 }
1896
1897 /**
1898 * Get an option's value from the config file
1899 *
1900 * @param $option
1901 * @param null $default
1902 *
1903 * @return bool|null
1904 */
1905 public function get_config_option( $option, $default = null ) {
1906
1907 if ( isset( $this->config[ $option ] ) ) {
1908 return $this->config[ $option ];
1909 } elseif ( $default !== null ) {
1910 return $default;
1911 }
1912
1913 return false;
1914 }
1915
1916 public function get_plugin_setting( $option, $default = null ) {
1917
1918 if ( isset( $this->plugin_settings[ $option ] ) ) {
1919 return $this->plugin_settings[ $option ];
1920 } elseif ( $default !== null ) {
1921 return $default;
1922 }
1923
1924 return false;
1925 }
1926
1927 /**
1928 * Sanitize functions
1929 */
1930
1931 /**
1932 * Sanitize the checkbox.
1933 *
1934 * @param boolean $input .
1935 *
1936 * @return boolean true if is 1 or '1', false if anything else
1937 */
1938 function setting_sanitize_checkbox( $input ) {
1939 if ( 1 == $input ) {
1940 return true;
1941 } else {
1942 return false;
1943 }
1944 }
1945
1946 /**
1947 * Checks whether an array is associative or not
1948 *
1949 * @param array $array
1950 *
1951 * @return bool
1952 */
1953 public function is_assoc( $array ) {
1954
1955 if ( ! is_array( $array ) ) {
1956 return false;
1957 }
1958
1959 // Keys of the array
1960 $keys = array_keys( $array );
1961
1962 // If the array keys of the keys match the keys, then the array must
1963 // not be associative (e.g. the keys array looked like {0:0, 1:1...}).
1964 return array_keys( $keys ) !== $keys;
1965 }
1966
1967 function register_import_api() {
1968
1969 include_once( $this->get_base_path() . '/features/class-Customify_Importer.php' );
1970 $controller = new Customify_Importer_Controller();
1971 $controller->init();
1972 }
1973
1974 function get_options_configs() {
1975 return $this->options_list;
1976 }
1977
1978 /**
1979 * Does the same thing the JS encodeURIComponent() does
1980 *
1981 * @param string $str
1982 *
1983 * @return string
1984 */
1985 public static function encodeURIComponent( $str ) {
1986 //if we get an array we just let it be
1987 if ( is_string( $str ) ) {
1988 $revert = array( '%21' => '!', '%2A' => '*', '%27' => "'", '%28' => '(', '%29' => ')' );
1989
1990 $str = strtr( rawurlencode( $str ), $revert );
1991 } else {
1992 var_dump( 'boooom' );
1993 die;
1994 }
1995
1996 return $str;
1997 }
1998
1999 /**
2000 * Does the same thing the JS decodeURIComponent() does
2001 *
2002 * @param string $str
2003 *
2004 * @return string
2005 */
2006 public static function decodeURIComponent( $str ) {
2007 //if we get an array we just let it be
2008 if ( is_string( $str ) ) {
2009 $revert = array( '!' => '%21', '*' => '%2A', "'" => '%27', '(' => '%28', ')' => '%29' );
2010 $str = rawurldecode( strtr( $str, $revert ) );
2011 }
2012
2013 return $str;
2014 }
2015
2016 /**
2017 * PHP version check
2018 */
2019 protected function php_version_check() {
2020
2021 if ( version_compare( phpversion(), $this->minimalRequiredPhpVersion ) < 0 ) {
2022 add_action( 'admin_notices', array( $this, 'notice_php_version_wrong' ) );
2023
2024 return false;
2025 }
2026
2027 return true;
2028 }
2029
2030 /**
2031 * Return an instance of this class.
2032 * @since 1.0.0
2033 * @return PixCustomifyPlugin A single instance of this class.
2034 */
2035 /**
2036 * Main PixCustomifyPlugin Instance
2037 *
2038 * Ensures only one instance of PixCustomifyPlugin is loaded or can be loaded.
2039 *
2040 * @since 1.0.0
2041 * @static
2042 *
2043 * @param string $file File.
2044 * @param string $version Version.
2045 *
2046 * @see PixCustomifyPlugin()
2047 * @return object Main PixCustomifyPlugin instance
2048 */
2049 public static function instance( $file = '', $version = '1.0.0' ) {
2050 // If the single instance hasn't been set, set it now.
2051 if ( is_null( self::$_instance ) ) {
2052 self::$_instance = new self( $file, $version );
2053 }
2054
2055 return self::$_instance;
2056 }
2057
2058 /**
2059 * Cloning is forbidden.
2060 *
2061 * @since 1.5.0
2062 */
2063 public function __clone() {
2064
2065 _doing_it_wrong( __FUNCTION__, esc_html( __( 'Cheatin&#8217; huh?' ) ), esc_html( $this->_version ) );
2066 } // End __clone ()
2067
2068 /**
2069 * Unserializing instances of this class is forbidden.
2070 *
2071 * @since 1.5.0
2072 */
2073 public function __wakeup() {
2074
2075 _doing_it_wrong( __FUNCTION__, esc_html( __( 'Cheatin&#8217; huh?' ) ), esc_html( $this->_version ) );
2076 } // End __wakeup ()
2077 }