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

extras.php in Customify 2.10.7, at includes/extras.php

593 lines 20.4 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Extra functionality.
4 */
5
6 if ( ! function_exists( 'add_customify_base_options' ) ) {
7 /**
8 * This filter is used to change the Customizer Options
9 * You can also copy this function inside your functions.php
10 * file but DO NOT FORGET TO CHANGE ITS NAME
11 *
12 * @param $config array This holds required keys for the plugin config like 'opt-name', 'panels', 'settings'
13 *
14 * @return $config
15 */
16 function add_customify_base_options( $config ) {
17
18 $config['opt-name'] = 'customify_defaults';
19
20 $config['sections'] = array(
21 /**
22 * Presets - This section will handle other options
23 */
24 'presets_section' => array(
25 'title' => esc_html__( 'Style Presets', 'customify' ),
26 'options' => array(
27 'theme_style' => array(
28 'type' => 'preset',
29 'label' => esc_html__( 'Select a style:', 'customify' ),
30 'desc' => esc_html__( 'Conveniently change the design of your site with built-in style presets. Easy as pie.', 'customify' ),
31 'default' => 'royal',
32 'choices_type' => 'awesome',
33 'choices' => array(
34 'royal' => array(
35 'label' => esc_html__( 'Royal', 'customify' ),
36 'preview' => array(
37 'color-text' => '#ffffff',
38 'background-card' => '#615375',
39 'background-label' => '#46414c',
40 'font-main' => 'Abril Fatface',
41 'font-alt' => 'PT Serif',
42 ),
43 'options' => array(
44 'links_color' => '#8eb2c5',
45 'headings_color' => '#725c92',
46 'body_color' => '#6f8089',
47 'page_background' => '#615375',
48 'headings_font' => 'Abril Fatface',
49 'body_font' => 'PT Serif',
50 ),
51 ),
52 'lovely' => array(
53 'label' => esc_html__( 'Lovely', 'customify' ),
54 'preview' => array(
55 'color-text' => '#ffffff',
56 'background-card' => '#d15c57',
57 'background-label' => '#5c374b',
58 'font-main' => 'Playfair Display',
59 'font-alt' => 'Playfair Display',
60 ),
61 'options' => array(
62 'links_color' => '#cc3747',
63 'headings_color' => '#d15c57',
64 'body_color' => '#5c374b',
65 'page_background' => '#d15c57',
66 'headings_font' => 'Playfair Display',
67 'body_font' => 'Playfair Display',
68 ),
69 ),
70 'queen' => array(
71 'label' => esc_html__( 'Queen', 'customify' ),
72 'preview' => array(
73 'color-text' => '#fbedec',
74 'background-card' => '#773347',
75 'background-label' => '#41212a',
76 'font-main' => 'Cinzel Decorative',
77 'font-alt' => 'Gentium Basic',
78 ),
79 'options' => array(
80 'links_color' => '#cd8085',
81 'headings_color' => '#54323c',
82 'body_color' => '#cd8085',
83 'page_background' => '#fff',
84 'headings_font' => 'Cinzel Decorative',
85 'body_font' => 'Gentium Basic',
86 ),
87 ),
88 'carrot' => array(
89 'label' => esc_html__( 'Carrot', 'customify' ),
90 'preview' => array(
91 'color-text' => '#ffffff',
92 'background-card' => '#df421d',
93 'background-label' => '#85210a',
94 'font-main' => 'Oswald',
95 'font-alt' => 'PT Sans Narrow',
96 ),
97 'options' => array(
98 'links_color' => '#df421d',
99 'headings_color' => '#df421d',
100 'body_color' => '#7e7e7e',
101 'page_background' => '#fff',
102 'headings_font' => 'Oswald',
103 'body_font' => 'PT Sans Narrow',
104 ),
105 ),
106
107
108 'adler' => array(
109 'label' => esc_html__( 'Adler', 'customify' ),
110 'preview' => array(
111 'color-text' => '#fff',
112 'background-card' => '#0e364f',
113 'background-label' => '#000000',
114 'font-main' => 'Permanent Marker',
115 'font-alt' => 'Droid Sans Mono',
116 ),
117 'options' => array(
118 'links_color' => '#68f3c8',
119 'headings_color' => '#0e364f',
120 'body_color' => '#45525a',
121 'page_background' => '#ffffff',
122 'headings_font' => 'Permanent Marker',
123 'body_font' => 'Droid Sans Mono',
124 ),
125 ),
126 'velvet' => array(
127 'label' => esc_html__( 'Velvet', 'customify' ),
128 'preview' => array(
129 'color-text' => '#ffffff',
130 'background-card' => '#282828',
131 'background-label' => '#000000',
132 'font-main' => 'Pinyon Script',
133 'font-alt' => 'Josefin Sans',
134 ),
135 'options' => array(
136 'links_color' => '#000000',
137 'headings_color' => '#000000',
138 'body_color' => '#000000',
139 'page_background' => '#000000',
140 'headings_font' => 'Pinyon Script',
141 'body_font' => 'Josefin Sans',
142 ),
143 ),
144
145 ),
146 ),
147 ),
148 ),
149
150 /**
151 * COLORS - This section will handle different elements colors (eg. links, headings)
152 */
153 'colors_section' => array(
154 'title' => esc_html__( 'Colors', 'customify' ),
155 'options' => array(
156 'links_color' => array(
157 'type' => 'color',
158 'label' => esc_html__( 'Links Color', 'customify' ),
159 'live' => true,
160 'default' => '#6c6e70',
161 'css' => array(
162 array(
163 'property' => 'color',
164 'selector' => 'a, .entry-meta a',
165 ),
166 ),
167 ),
168 'headings_color' => array(
169 'type' => 'color',
170 'label' => esc_html__( 'Headings Color', 'customify' ),
171 'live' => true,
172 'default' => '#0aa0d9',
173 'css' => array(
174 array(
175 'property' => 'color',
176 'selector' => '.site-title a, h1, h2, h3, h4, h5, h6,
177 h1 a, h2 a, h3 a, h4 a, h5 a, h6 a,
178 .widget-title,
179 a:hover, .entry-meta a:hover',
180 ),
181 ),
182 ),
183 'body_color' => array(
184 'type' => 'color',
185 'label' => esc_html__( 'Body Color', 'customify' ),
186 'live' => true,
187 'default' => '#2d3033',
188 'css' => array(
189 array(
190 'selector' => 'body',
191 'property' => 'color',
192 ),
193 ),
194 ),
195 ),
196 ),
197
198 /**
199 * FONTS - This section will handle different elements fonts (eg. headings, body)
200 */
201 'typography_section' => array(
202 'title' => esc_html__( 'Fonts', 'customify' ),
203 'options' => array(
204 'headings_font' => array(
205 'type' => 'font',
206 'label' => esc_html__( 'Headings', 'customify' ),
207 'default' => 'Playfair Display',
208 'selector' => '.site-title a, h1, h2, h3, h4, h5, h6,
209 h1 a, h2 a, h3 a, h4 a, h5 a, h6 a,
210 .widget-title',
211 'font_weight' => true,
212 'recommended' => array(
213 'Playfair Display',
214 'Oswald',
215 'Lato',
216 'Open Sans',
217 'Exo',
218 'PT Sans',
219 'Ubuntu',
220 'Vollkorn',
221 'Lora',
222 'Arvo',
223 'Josefin Slab',
224 'Crete Round',
225 'Kreon',
226 'Bubblegum Sans',
227 'The Girl Next Door',
228 'Pacifico',
229 'Handlee',
230 'Satify',
231 'Pompiere',
232 ),
233 ),
234 'body_font' => array(
235 'type' => 'font',
236 'label' => esc_html__( 'Body Text', 'customify' ),
237 'default' => 'Lato',
238 'selector' => 'html body',
239 'recommended' => array(
240 'Lato',
241 'Open Sans',
242 'PT Sans',
243 'Cabin',
244 'Gentium Book Basic',
245 'PT Serif',
246 'Droid Serif',
247 ),
248 ),
249 ),
250 ),
251
252 /**
253 * BACKGROUNDS - This section will handle different elements colors (eg. links, headings)
254 */
255 'backgrounds_section' => array(
256 'title' => esc_html__( 'Backgrounds', 'customify' ),
257 'options' => array(
258 'page_background' => array(
259 'type' => 'color',
260 'label' => esc_html__( 'Page Background', 'customify' ),
261 'live' => true,
262 'default' => '#ffffff',
263 'css' => array(
264 array(
265 'property' => 'background',
266 'selector' => 'body, .site',
267 ),
268 ),
269 ),
270 ),
271 ),
272 /**
273 * LAYOUTS - This section will handle different elements colors (eg. links, headings)
274 */
275 'layout_options' => array(
276 'title' => esc_html__( 'Layout', 'customify' ),
277 'options' => array(
278 'site_title_size' => array(
279 'type' => 'range',
280 'label' => esc_html__( 'Site Title Size', 'customify' ),
281 'live' => true,
282 'input_attrs' => array(
283 'min' => 24,
284 'max' => 100,
285 'step' => 1,
286 'data-preview' => true,
287 ),
288 'default' => 24,
289 'css' => array(
290 array(
291 'property' => 'font-size',
292 'selector' => '.site-title',
293 'media' => 'screen and (min-width: 1000px)',
294 'unit' => 'px',
295 ),
296 ),
297 ),
298 'page_content_spacing' => array(
299 'type' => 'range',
300 'label' => 'Page Content Spacing',
301 'live' => true,
302 'input_attrs' => array(
303 'min' => 0,
304 'max' => 100,
305 'step' => 1,
306 ),
307 'default' => 18,
308 'css' => array(
309 array(
310 'property' => 'padding',
311 'selector' => '.site-content',
312 'media' => 'screen and (min-width: 1000px)',
313 'unit' => 'px',
314 ),
315 ),
316 ),
317 ),
318 ),
319 );
320
321 return $config;
322 }
323 }
324 add_filter( 'customify_filter_fields', 'add_customify_base_options', 5, 1 );
325
326 add_action( 'after_switch_theme', function ( $old_theme_name, $old_theme ) {
327 $current_theme = wp_get_theme();
328 // If the current theme is a child theme, show a notice.
329 if ( $current_theme->exists()
330 && $old_theme->exists()
331 && $current_theme->get_template() === $old_theme->get_stylesheet() ) {
332 add_action( 'admin_notices', 'customify_child_theme_migrate_theme_mods_notice' );
333 }
334 }, 100, 2 );
335
336 /**
337 * Provide a notice allowing for theme mods migration from the parent theme to the current child theme.
338 */
339 function customify_child_theme_migrate_theme_mods_notice() {
340 global $pagenow;
341
342 // We only show the notice on the themes dashboard, and if we are allowed to.
343 if ( 'themes.php' !== $pagenow
344 || ! is_child_theme()
345 || true !== apply_filters( 'customify_allow_child_theme_mod_migrate_notice', true )
346 || ! current_user_can( 'manage_options' ) ) {
347
348 return;
349 }
350
351 $parent_theme = wp_get_theme( get_template() );
352 if ( ! $parent_theme->exists() ) {
353 return;
354 }
355
356 ob_start(); ?>
357 <div class="customify-notice__container updated notice fade is-dismissible">
358 <h3><?php echo sprintf( __( 'You have activated a child theme for "%s". Good for you!', 'customify' ), $parent_theme->get( 'Name' ) ); ?></h3>
359 <p>
360 <?php echo wp_kses_post( __( 'If you have already <strong>set up things in the Customizer,</strong> you may want to <strong>keep those customizations</strong> so you don\'t start over.', 'customify' ) ); ?>
361 </p>
362 <p>
363 <?php echo wp_kses_post( __( 'So, the question is simple: <strong>would you like to migrate all theme-specific options (theme mods) from the parent theme to the child one?</strong>', 'customify' ) ); ?>
364 </p>
365 <p>
366 <?php echo wp_kses_post( __( 'All parent theme customizations will remain in place, while those of the active child theme will be overwritten, if any.', 'customify' ) ); ?>
367 </p>
368 <form class="customify-notice-form" method="post">
369 <noscript><input type="hidden" name="customify-notice-no-js" value="1"/></noscript>
370
371 <p>
372 <button class="customify-notice-button button button-primary js-handle-customify">
373 <span
374 class="customify-notice-button__text"><?php esc_html_e( 'Yes, migrate customizations', 'customify' ); ?></span>
375 </button>
376 <button type="submit"
377 class="customify-dismiss-button button button-secondary js-dismiss-customify"><?php esc_html_e( 'No, thank you', 'customify' ); ?></button>
378 &nbsp;<span class="message js-plugin-message" style="font-style:italic"></span>
379 </p>
380
381 <?php wp_nonce_field( 'customify_migrate_customizations_from_parent_to_child_theme', 'nonce-customify_theme_mods_migrate' ); ?>
382 </form>
383 </div>
384 <script>
385 (function ($) {
386 $(function () {
387 let $noticeContainer = $('.customify-notice__container'),
388 $button = $noticeContainer.find('.js-handle-customify'),
389 $buttonText = $noticeContainer.find('.customify-notice-button__text'),
390 $dismissButton = $noticeContainer.find('.js-dismiss-customify'),
391 $statusMessage = $noticeContainer.find('.js-plugin-message')
392
393 $button.on('click', function (e) {
394 e.preventDefault()
395
396 $buttonText.html("<?php esc_html_e( 'Migrating customizations..', 'customify' ); ?>")
397 $button.attr('disabled', true)
398 $dismissButton.hide()
399
400 // Do an AJAX call to migrate the theme_mods.
401 $.ajax({
402 url: "<?php echo admin_url( 'admin-ajax.php' ); ?>",
403 type: 'post',
404 data: {
405 action: 'customify_migrate_customizations_from_parent_to_child_theme',
406 nonce_migrate: $noticeContainer.find('#nonce-customify_theme_mods_migrate').val()
407 }
408 })
409 .done(function (response) {
410 if (typeof response.success !== 'undefined' && response.success) {
411 $statusMessage.html("<?php esc_html_e( 'Successfully migrated the parent customizations! Enjoy crafting your site!', 'customify' ); ?>")
412 $buttonText.html("<?php esc_html_e( 'Finished migration', 'customify' ); ?>")
413 } else {
414 $statusMessage.html("<?php esc_html_e( 'Something went wrong and we couldn\'t migrate the customizations.', 'customify' ); ?>")
415 $buttonText.html("<?php esc_html_e( 'Migration error', 'customify' ); ?>")
416 }
417 })
418 .fail(function () {
419 $statusMessage.html("<?php esc_html_e( 'Something went wrong and we couldn\'t migrate the customizations.', 'customify' ); ?>")
420 $buttonText.html("<?php esc_html_e( 'Migration error', 'customify' ); ?>")
421 })
422 })
423
424 // Dismiss the notice.
425 $dismissButton.on('click', function (e) {
426 e.preventDefault()
427
428 $noticeContainer.slideUp()
429 })
430 })
431 })(jQuery)
432 </script>
433 <?php
434 echo ob_get_clean();
435 }
436
437 /**
438 * Process ajax call to migrate customizations from parent to current child theme.
439 */
440 function customify_migrate_customizations_from_parent_to_child_theme() {
441 // Check nonce.
442 check_ajax_referer( 'customify_migrate_customizations_from_parent_to_child_theme', 'nonce_migrate' );
443
444 if ( ! current_user_can( 'manage_options' ) ) {
445 wp_send_json_error( esc_html__( 'You do not have permission to perform this action.', 'customify' ) );
446 }
447
448 $parent_theme = wp_get_theme( get_template() );
449 if ( ! $parent_theme->exists() ) {
450 wp_send_json_error();
451 }
452
453 // Migrate theme mods
454 $parent_theme_mods = get_option( "theme_mods_" . $parent_theme->get_stylesheet() );
455 // We need to exclude certain theme_mods since they are not needed by the child theme.
456 $excluded = [
457 'pixcare_license',
458 'pixcare_new_theme_version',
459 'pixcare_install_notice_dismissed',
460 ];
461 if ( is_array( $parent_theme_mods ) ) {
462 foreach ( $excluded as $exclude ) {
463 unset( $parent_theme_mods[ $exclude ] );
464 }
465 }
466 // Finally, write the new theme mods for the active child theme.
467 if ( ! update_option( "theme_mods_" . get_option( 'stylesheet' ), $parent_theme_mods ) ) {
468 wp_send_json_error( esc_html__( 'Could not update the child theme theme_mods.', 'customify' ) );
469 }
470
471 // Redirect if this is not an ajax request.
472 if ( isset( $_POST['pixcare-notice-no-js'] ) ) {
473
474 // Go back to where we came from.
475 wp_safe_redirect( wp_get_referer() );
476 exit();
477 }
478
479 wp_send_json_success();
480 }
481
482 add_action( 'wp_ajax_customify_migrate_customizations_from_parent_to_child_theme', 'customify_migrate_customizations_from_parent_to_child_theme' );
483
484 /**
485 * Migrate data from the simple Dark Mode control to Advanced Dark Mode Control, if the current theme supports it.
486 */
487 function customify_migrate_to_advanced_dark_mode_control() {
488 // Bail if the current theme doesn't support the advanced control.
489 $supports_advanced_dark_mode = (bool) current_theme_supports( 'style_manager_advanced_dark_mode' );
490 if ( ! $supports_advanced_dark_mode ) {
491 return;
492 }
493
494 $advanced_dark_mode = get_option( 'sm_dark_mode_advanced', null );
495 // Bail if we already have advanced control data saved.
496 if ( ! is_null( $advanced_dark_mode ) ) {
497 return;
498 }
499
500 // Bail if there isn't a simple dark mode option saved.
501 $simple_dark_mode = get_option( 'sm_dark_mode', null );
502 if ( is_null( $simple_dark_mode ) ) {
503 return;
504 }
505
506 // If the simple control value was on, we have work to do.
507 if ( 'on' === $simple_dark_mode ) {
508 $old_sm_dark_primary_final = get_option( 'sm_dark_primary_final' );
509 $old_sm_dark_secondary_final = get_option( 'sm_dark_secondary_final' );
510 $old_sm_dark_tertiary_final = get_option( 'sm_dark_tertiary_final' );
511 $old_sm_light_primary_final = get_option( 'sm_light_primary_final' );
512 $old_sm_light_secondary_final = get_option( 'sm_light_secondary_final' );
513 $old_sm_light_tertiary_final = get_option( 'sm_light_tertiary_final' );
514
515 update_option( 'sm_dark_mode_advanced', 'on' );
516 update_option( 'sm_dark_mode', 'off' );
517 update_option( 'sm_dark_primary_final', $old_sm_light_primary_final );
518 update_option( 'sm_dark_secondary_final', $old_sm_light_secondary_final );
519 update_option( 'sm_dark_tertiary_final', $old_sm_light_tertiary_final );
520 update_option( 'sm_light_primary_final', $old_sm_dark_primary_final );
521 update_option( 'sm_light_secondary_final', $old_sm_dark_secondary_final );
522 update_option( 'sm_light_tertiary_final', $old_sm_dark_tertiary_final );
523 } else {
524 update_option( 'sm_dark_mode_advanced', 'off' );
525 }
526 }
527
528 add_action( 'admin_init', 'customify_migrate_to_advanced_dark_mode_control' );
529
530 if ( ! function_exists( 'pixelgrade_option' ) ) {
531 /**
532 * Get option from the database
533 *
534 * @param string $option_id The option name.
535 * @param mixed $default Optional. The default value to return when the option was not found or saved.
536 * @param bool $force_given_default Optional. When true, we will use the $default value provided for when the option was not saved at least once.
537 * When false, we will let the option's default set value (in the Customify settings) kick in first, then our $default.
538 * It basically, reverses the order of fallback, first the option's default, then our own.
539 * This is ignored when $default is null.
540 *
541 * @return mixed
542 */
543 function pixelgrade_option( $option_id, $default = null, $force_given_default = false ) {
544
545 // We need to account for the case where a option has an 'active_callback' defined in it's config
546 $options_config = PixCustomifyPlugin()->get_options_configs();
547 if ( ! empty( $options_config ) && ! empty( $options_config[ $option_id ] ) ) {
548 if ( ! empty( $options_config[ $option_id ]['active_callback'] ) ) {
549 // This option has an active callback
550 // We need to "question" it
551 //
552 // IMPORTANT NOTICE:
553 //
554 // Be extra careful when setting up the options to not end up in a circular logic
555 // due to callbacks that get an option and that option has a callback that gets the initial option - INFINITE LOOPS :(
556 if ( is_callable( $options_config[ $option_id ]['active_callback'] ) ) {
557 // Now we call the function and if it returns false, this means that the control is not active
558 // Hence it's saved value doesn't matter
559 $active = call_user_func( $options_config[ $option_id ]['active_callback'] );
560 if ( empty( $active ) ) {
561 // If we need to force the default received; we respect that
562 if ( true === $force_given_default && null !== $default ) {
563 return $default;
564 } else {
565 // Else we return false
566 // because we treat the case when the active callback returns false as if the option would be non-existent
567 // We do not return the default configured value in this case
568 return false;
569 }
570 }
571 }
572 }
573
574 // Now that the option is truly active, we need to see if we are not supposed to force over the option's default value
575 if ( $default !== null && false === $force_given_default ) {
576 // We will not pass the received $default here so Customify will fallback on the option's default value, if set
577 $customify_value = PixCustomifyPlugin()->get_option( $option_id );
578
579 // We only fallback on the $default if none was given from Customify
580 if ( null === $customify_value ) {
581 return $default;
582 }
583 } else {
584 $customify_value = PixCustomifyPlugin()->get_option( $option_id, $default );
585 }
586
587 return $customify_value;
588 }
589
590 return $default;
591 }
592 }
593