PluginProbe
Customify / trunk
Customify vtrunk
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 trunk, at includes/extras.php

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