Passed
Push — master ( 4b094a...bf7929 )
by Brian
05:29 queued 53s
created

AyeCode_UI_Settings::css_secondary()   F

Complexity

Conditions 23
Paths > 20000

Size

Total Lines 114
Code Lines 70

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 1
Metric Value
cc 23
eloc 70
c 1
b 0
f 1
nc 557569
nop 2
dl 0
loc 114
rs 0

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
/**
3
 * A class for adjusting AyeCode UI settings on WordPress
4
 *
5
 * This class can be added to any plugin or theme and will add a settings screen to WordPress to control Bootstrap settings.
6
 *
7
 * @link https://github.com/AyeCode/wp-ayecode-ui
8
 *
9
 * @internal This file should not be edited directly but pulled from the github repo above.
10
 */
11
12
/**
13
 * Bail if we are not in WP.
14
 */
15
if ( ! defined( 'ABSPATH' ) ) {
16
	exit;
17
}
18
19
/**
20
 * Only add if the class does not already exist.
21
 */
22
if ( ! class_exists( 'AyeCode_UI_Settings' ) ) {
23
24
	/**
25
	 * A Class to be able to change settings for Font Awesome.
26
	 *
27
	 * Class AyeCode_UI_Settings
28
	 * @ver 1.0.0
29
	 * @todo decide how to implement textdomain
30
	 */
31
	class AyeCode_UI_Settings {
32
33
		/**
34
		 * Class version version.
35
		 *
36
		 * @var string
37
		 */
38
		public $version = '1.0.1';
39
40
		/**
41
		 * Class textdomain.
42
		 *
43
		 * @var string
44
		 */
45
		public $textdomain = 'aui';
46
47
		/**
48
		 * Latest version of Bootstrap at time of publish published.
49
		 *
50
		 * @var string
51
		 */
52
		public $latest = "4.5.3";
53
54
		/**
55
		 * Current version of select2 being used.
56
		 *
57
		 * @var string
58
		 */
59
		public $select2_version = "4.0.11";
60
61
		/**
62
		 * The title.
63
		 *
64
		 * @var string
65
		 */
66
		public $name = 'AyeCode UI';
67
68
		/**
69
		 * The relative url to the assets.
70
		 *
71
		 * @var string
72
		 */
73
		public $url = '';
74
75
		/**
76
		 * Holds the settings values.
77
		 *
78
		 * @var array
79
		 */
80
		private $settings;
81
82
		/**
83
		 * AyeCode_UI_Settings instance.
84
		 *
85
		 * @access private
86
		 * @since  1.0.0
87
		 * @var    AyeCode_UI_Settings There can be only one!
88
		 */
89
		private static $instance = null;
90
91
		/**
92
		 * Main AyeCode_UI_Settings Instance.
93
		 *
94
		 * Ensures only one instance of AyeCode_UI_Settings is loaded or can be loaded.
95
		 *
96
		 * @since 1.0.0
97
		 * @static
98
		 * @return AyeCode_UI_Settings - Main instance.
99
		 */
100
		public static function instance() {
101
			if ( ! isset( self::$instance ) && ! ( self::$instance instanceof AyeCode_UI_Settings ) ) {
102
103
				self::$instance = new AyeCode_UI_Settings;
104
105
				add_action( 'init', array( self::$instance, 'init' ) ); // set settings
106
107
				if ( is_admin() ) {
108
					add_action( 'admin_menu', array( self::$instance, 'menu_item' ) );
109
					add_action( 'admin_init', array( self::$instance, 'register_settings' ) );
110
111
					// Maybe show example page
112
					add_action( 'template_redirect', array( self::$instance,'maybe_show_examples' ) );
113
				}
114
115
				add_action( 'customize_register', array( self::$instance, 'customizer_settings' ));
116
117
				do_action( 'ayecode_ui_settings_loaded' );
118
			}
119
120
			return self::$instance;
121
		}
122
123
		/**
124
		 * Setup some constants.
125
		 */
126
		public function constants(){
127
			define('AUI_PRIMARY_COLOR_ORIGINAL', "#1e73be");
128
			define('AUI_SECONDARY_COLOR_ORIGINAL', '#6c757d');
129
			if (!defined('AUI_PRIMARY_COLOR')) define('AUI_PRIMARY_COLOR', AUI_PRIMARY_COLOR_ORIGINAL);
130
			if (!defined('AUI_SECONDARY_COLOR')) define('AUI_SECONDARY_COLOR', AUI_SECONDARY_COLOR_ORIGINAL);
131
		}
132
133
		/**
134
		 * Initiate the settings and add the required action hooks.
135
		 */
136
		public function init() {
137
			$this->constants();
138
			$this->settings = $this->get_settings();
139
			$this->url = $this->get_url();
140
141
			/**
142
			 * Maybe load CSS
143
			 *
144
			 * We load super early in case there is a theme version that might change the colors
145
			 */
146
			if ( $this->settings['css'] ) {
147
				add_action( 'wp_enqueue_scripts', array( $this, 'enqueue_style' ), 1 );
148
			}
149
			if ( $this->settings['css_backend'] && $this->load_admin_scripts() ) {
150
				add_action( 'admin_enqueue_scripts', array( $this, 'enqueue_style' ), 1 );
151
			}
152
153
			// maybe load JS
154
			if ( $this->settings['js'] ) {
155
				$priority = $this->is_bs3_compat() ? 100 : 1;
156
				add_action( 'wp_enqueue_scripts', array( $this, 'enqueue_scripts' ), $priority );
157
			}
158
			if ( $this->settings['js_backend'] && $this->load_admin_scripts() ) {
159
				add_action( 'admin_enqueue_scripts', array( $this, 'enqueue_scripts' ), 1 );
160
			}
161
162
			// Maybe set the HTML font size
163
			if ( $this->settings['html_font_size'] ) {
164
				add_action( 'wp_footer', array( $this, 'html_font_size' ), 10 );
165
			}
166
167
168
		}
169
170
		/**
171
		 * Check if we should load the admin scripts or not.
172
		 *
173
		 * @return bool
174
		 */
175
		public function load_admin_scripts(){
176
			$result = true;
177
178
			if(!empty($this->settings['disable_admin'])){
179
				$url_parts = explode("\n",$this->settings['disable_admin']);
180
				foreach($url_parts as $part){
181
					if( strpos($_SERVER['REQUEST_URI'], trim($part)) !== false ){
182
						return false; // return early, no point checking further
183
					}
184
				}
185
			}
186
187
			return $result;
188
		}
189
190
		/**
191
		 * Add a html font size to the footer.
192
		 */
193
		public function html_font_size(){
194
			$this->settings = $this->get_settings();
195
			echo "<style>html{font-size:".absint($this->settings['html_font_size'])."px;}</style>";
196
		}
197
198
		/**
199
		 * Adds the styles.
200
		 */
201
		public function enqueue_style() {
202
203
			$css_setting = current_action() == 'wp_enqueue_scripts' ? 'css' : 'css_backend';
204
205
			$rtl = is_rtl() ? '-rtl' : '';
206
207
			if($this->settings[$css_setting]){
208
				$compatibility = $this->settings[$css_setting]=='core' ? false : true;
209
				$url = $this->settings[$css_setting]=='core' ? $this->url.'assets/css/ayecode-ui'.$rtl.'.css' : $this->url.'assets/css/ayecode-ui-compatibility'.$rtl.'.css';
210
				wp_register_style( 'ayecode-ui', $url, array(), $this->latest );
211
				wp_enqueue_style( 'ayecode-ui' );
212
213
				// flatpickr
214
				wp_register_style( 'flatpickr', $this->url.'assets/css/flatpickr.min.css', array(), $this->latest );
215
216
217
				// fix some wp-admin issues
218
				if(is_admin()){
219
					$custom_css = "
220
                body{
221
                    background-color: #f1f1f1;
222
                    font-family: -apple-system,BlinkMacSystemFont,\"Segoe UI\",Roboto,Oxygen-Sans,Ubuntu,Cantarell,\"Helvetica Neue\",sans-serif;
223
                    font-size:13px;
224
                }
225
                a {
226
				    color: #0073aa;
227
				    text-decoration: underline;
228
				}
229
                label {
230
				    display: initial;
231
				    margin-bottom: 0;
232
				}
233
				input, select {
234
				    margin: 1px;
235
				    line-height: initial;
236
				}
237
				th, td, div, h2 {
238
				    box-sizing: content-box;
239
				}
240
				p {
241
				    font-size: 13px;
242
				    line-height: 1.5;
243
				    margin: 1em 0;
244
				}
245
				h1, h2, h3, h4, h5, h6 {
246
				    display: block;
247
				    font-weight: 600;
248
				}
249
				h2,h3 {
250
				    font-size: 1.3em;
251
				    margin: 1em 0
252
				}
253
                ";
254
255
					// @todo, remove once fixed :: fix for this bug https://github.com/WordPress/gutenberg/issues/14377
256
					$custom_css .= "
257
						.edit-post-sidebar input[type=color].components-text-control__input{
258
						    padding: 0;
259
						}
260
					";
261
					wp_add_inline_style( 'ayecode-ui', $custom_css );
262
				}
263
264
				// custom changes
265
				wp_add_inline_style( 'ayecode-ui', self::custom_css($compatibility) );
266
267
			}
268
		}
269
270
		/**
271
		 * Get inline script used if bootstrap enqueued
272
		 *
273
		 * If this remains small then its best to use this than to add another JS file.
274
		 */
275
		public function inline_script(){
276
			ob_start();
277
			?>
278
			<script>
279
				
280
				/**
281
				 * An AUI bootstrap adaptation of GreedyNav.js ( by Luke Jackson ).
282
				 *
283
				 * Simply add the class `greedy` to any <nav> menu and it will do the rest.
284
				 * Licensed under the MIT license - http://opensource.org/licenses/MIT
285
				 * @ver 0.0.1
286
				 */
287
				function aui_init_greedy_nav(){
288
					jQuery('nav.greedy').each(function(i, obj) {
289
290
						// Check if already initialized, if so continue.
291
						if(jQuery(this).hasClass("being-greedy")){return true;}
292
293
						// Make sure its always expanded
294
						jQuery(this).addClass('navbar-expand');
295
296
						// vars
297
						var $vlinks = '';
298
						var $dDownClass = '';
299
						if(jQuery(this).find('.navbar-nav').length){
300
							if(jQuery(this).find('.navbar-nav').hasClass("being-greedy")){return true;}
301
							$vlinks = jQuery(this).find('.navbar-nav').addClass("being-greedy w-100").removeClass('overflow-hidden');
302
						}else if(jQuery(this).find('.nav').length){
303
							if(jQuery(this).find('.nav').hasClass("being-greedy")){return true;}
304
							$vlinks = jQuery(this).find('.nav').addClass("being-greedy w-100").removeClass('overflow-hidden');
305
							$dDownClass = ' mt-2 ';
306
						}else{
307
							return false;
308
						}
309
310
						jQuery($vlinks).append('<li class="nav-item list-unstyled ml-auto greedy-btn d-none dropdown ">' +
311
							'<a href="javascript:void(0)" data-toggle="dropdown" class="nav-link"><i class="fas fa-ellipsis-h"></i> <span class="greedy-count badge badge-dark badge-pill"></span></a>' +
312
							'<ul class="greedy-links dropdown-menu  dropdown-menu-right '+$dDownClass+'"></ul>' +
313
							'</li>');
314
315
						var $hlinks = jQuery(this).find('.greedy-links');
316
						var $btn = jQuery(this).find('.greedy-btn');
317
318
						var numOfItems = 0;
319
						var totalSpace = 0;
320
						var closingTime = 1000;
321
						var breakWidths = [];
322
323
						// Get initial state
324
						$vlinks.children().outerWidth(function(i, w) {
325
							totalSpace += w;
326
							numOfItems += 1;
327
							breakWidths.push(totalSpace);
328
						});
329
330
						var availableSpace, numOfVisibleItems, requiredSpace, buttonSpace ,timer;
331
332
						/*
333
						 The check function.
334
						 */
335
						function check() {
336
337
							// Get instant state
338
							buttonSpace = $btn.width();
339
							availableSpace = $vlinks.width() - 10;
340
							numOfVisibleItems = $vlinks.children().length;
341
							requiredSpace = breakWidths[numOfVisibleItems - 1];
342
343
							// There is not enough space
344
							if (numOfVisibleItems > 1 && requiredSpace > availableSpace) {
345
								$vlinks.children().last().prev().prependTo($hlinks);
346
								numOfVisibleItems -= 1;
347
								check();
348
								// There is more than enough space
349
							} else if (availableSpace > breakWidths[numOfVisibleItems]) {
350
								$hlinks.children().first().insertBefore($btn);
351
								numOfVisibleItems += 1;
352
								check();
353
							}
354
							// Update the button accordingly
355
							jQuery($btn).find(".greedy-count").html( numOfItems - numOfVisibleItems);
356
							if (numOfVisibleItems === numOfItems) {
357
								$btn.addClass('d-none');
358
							} else $btn.removeClass('d-none');
359
						}
360
361
						// Window listeners
362
						jQuery(window).resize(function() {
363
							check();
364
						});
365
366
						// do initial check
367
						check();
368
					});
369
				}
370
371
				/**
372
				 * Initiate Select2 items.
373
				 */
374
				function aui_init_select2(){
375
					jQuery("select.aui-select2").select2();
376
				}
377
378
				/**
379
				 * A function to convert a time value to a "ago" time text.
380
				 *
381
				 * @param selector string The .class selector
382
				 */
383
				function aui_time_ago(selector) {
384
385
					var templates = {
386
						prefix: "",
387
						suffix: " ago",
388
						seconds: "less than a minute",
389
						minute: "about a minute",
390
						minutes: "%d minutes",
391
						hour: "about an hour",
392
						hours: "about %d hours",
393
						day: "a day",
394
						days: "%d days",
395
						month: "about a month",
396
						months: "%d months",
397
						year: "about a year",
398
						years: "%d years"
399
					};
400
					var template = function (t, n) {
401
						return templates[t] && templates[t].replace(/%d/i, Math.abs(Math.round(n)));
402
					};
403
404
					var timer = function (time) {
405
						if (!time)
406
							return;
407
						time = time.replace(/\.\d+/, ""); // remove milliseconds
408
						time = time.replace(/-/, "/").replace(/-/, "/");
409
						time = time.replace(/T/, " ").replace(/Z/, " UTC");
410
						time = time.replace(/([\+\-]\d\d)\:?(\d\d)/, " $1$2"); // -04:00 -> -0400
411
						time = new Date(time * 1000 || time);
412
413
						var now = new Date();
414
						var seconds = ((now.getTime() - time) * .001) >> 0;
415
						var minutes = seconds / 60;
416
						var hours = minutes / 60;
417
						var days = hours / 24;
418
						var years = days / 365;
419
420
						return templates.prefix + (
421
								seconds < 45 && template('seconds', seconds) ||
422
								seconds < 90 && template('minute', 1) ||
423
								minutes < 45 && template('minutes', minutes) ||
424
								minutes < 90 && template('hour', 1) ||
425
								hours < 24 && template('hours', hours) ||
426
								hours < 42 && template('day', 1) ||
427
								days < 30 && template('days', days) ||
428
								days < 45 && template('month', 1) ||
429
								days < 365 && template('months', days / 30) ||
430
								years < 1.5 && template('year', 1) ||
431
								template('years', years)
432
							) + templates.suffix;
433
					};
434
435
					var elements = document.getElementsByClassName(selector);
436
					if (selector && elements && elements.length) {
437
						for (var i in elements) {
438
							var $el = elements[i];
439
							if (typeof $el === 'object') {
440
								$el.innerHTML = '<i class="far fa-clock"></i> ' + timer($el.getAttribute('title') || $el.getAttribute('datetime'));
441
							}
442
						}
443
					}
444
445
					// update time every minute
446
					setTimeout(function() {
447
						aui_time_ago(selector);
448
					}, 60000);
449
450
				}
451
452
				/**
453
				 * Initiate tooltips on the page.
454
				 */
455
				function aui_init_tooltips(){
456
					jQuery('[data-toggle="tooltip"]').tooltip();
457
					jQuery('[data-toggle="popover"]').popover();
458
					jQuery('[data-toggle="popover-html"]').popover({
459
						html: true
460
					});
461
462
					// fix popover container compatibility
463
					jQuery('[data-toggle="popover"],[data-toggle="popover-html"]').on('inserted.bs.popover', function () {
464
						jQuery('body > .popover').wrapAll("<div class='bsui' />");
465
					});
466
				}
467
468
				/**
469
				 * Initiate flatpickrs on the page.
470
				 */
471
				$aui_doing_init_flatpickr = false;
472
				function aui_init_flatpickr(){
473
					if ( jQuery.isFunction(jQuery.fn.flatpickr) && !$aui_doing_init_flatpickr) {
474
						$aui_doing_init_flatpickr = true;
475
						jQuery('input[data-aui-init="flatpickr"]:not(.flatpickr-input)').flatpickr();
476
					}
477
					$aui_doing_init_flatpickr = false;
478
				}
479
480
				function aui_modal($title,$body,$footer,$dismissible,$class,$dialog_class) {
481
					if(!$class){$class = '';}
482
					if(!$dialog_class){$dialog_class = '';}
483
					if(!$body){$body = '<div class="text-center"><div class="spinner-border" role="status"></div></div>';}
484
					// remove it first
485
					jQuery('.aui-modal').modal('hide').modal('dispose').remove();
486
					jQuery('.modal-backdrop').remove();
487
488
					var $modal = '';
489
490
					$modal += '<div class="modal aui-modal fade shadow bsui '+$class+'" tabindex="-1">'+
491
						'<div class="modal-dialog modal-dialog-centered '+$dialog_class+'">'+
492
							'<div class="modal-content">';
493
494
					if($title) {
495
						$modal += '<div class="modal-header">' +
496
						'<h5 class="modal-title">' + $title + '</h5>';
497
498
						if ($dismissible) {
499
							$modal += '<button type="button" class="close" data-dismiss="modal" aria-label="Close">' +
500
								'<span aria-hidden="true">&times;</span>' +
501
								'</button>';
502
						}
503
504
						$modal += '</div>';
505
					}
506
					$modal += '<div class="modal-body">'+
507
									$body+
508
								'</div>';
509
510
					if($footer){
511
						$modal += '<div class="modal-footer">'+
512
							$footer +
513
							'</div>';
514
					}
515
516
					$modal +='</div>'+
517
						'</div>'+
518
					'</div>';
519
520
					jQuery('body').append($modal);
521
522
					jQuery('.aui-modal').modal('hide').modal({
523
						//backdrop: 'static'
524
					});
525
				}
526
527
				/**
528
				 * Show / hide fields depending on conditions.
529
				 */
530
				function aui_conditional_fields(form){
531
					jQuery(form).find(".aui-conditional-field").each(function () {
532
533
						var $element_require = jQuery(this).data('element-require');
534
535
						if ($element_require) {
536
537
							$element_require = $element_require.replace("&#039;", "'"); // replace single quotes
538
							$element_require = $element_require.replace("&quot;", '"'); // replace double quotes
539
540
							if (aui_check_form_condition($element_require,form)) {
541
								jQuery(this).removeClass('d-none');
542
							} else {
543
								jQuery(this).addClass('d-none');
544
							}
545
						}
546
					});
547
				}
548
549
				/**
550
				 * Check form condition
551
				 */
552
				function aui_check_form_condition(condition,form) {
553
					if (form) {
554
						condition = condition.replace(/\(form\)/g, "('"+form+"')");
555
					}
556
					return new Function("return " + condition+";")();
557
				}
558
559
				/**
560
				 * A function to determine if a element is on screen.
561
				 */
562
				jQuery.fn.aui_isOnScreen = function(){
563
564
					var win = jQuery(window);
565
566
					var viewport = {
567
						top : win.scrollTop(),
568
						left : win.scrollLeft()
569
					};
570
					viewport.right = viewport.left + win.width();
571
					viewport.bottom = viewport.top + win.height();
572
573
					var bounds = this.offset();
574
					bounds.right = bounds.left + this.outerWidth();
575
					bounds.bottom = bounds.top + this.outerHeight();
576
577
					return (!(viewport.right < bounds.left || viewport.left > bounds.right || viewport.bottom < bounds.top || viewport.top > bounds.bottom));
578
579
				};
580
581
				/**
582
				 * Maybe show multiple carousel items if set to do so.
583
				 */ 
584
				function aui_carousel_maybe_show_multiple_items($carousel){
585
					var $items = {};
586
					var $item_count = 0;
587
588
					// maybe backup
589
					if(!jQuery($carousel).find('.carousel-inner-original').length){
590
						jQuery($carousel).append('<div class="carousel-inner-original d-none">'+jQuery($carousel).find('.carousel-inner').html()+'</div>');
591
					}
592
593
					// Get the original items html
594
					jQuery($carousel).find('.carousel-inner-original .carousel-item').each(function () {
595
						$items[$item_count] = jQuery(this).html();
596
						$item_count++;
597
					});
598
599
					// bail if no items
600
					if(!$item_count){return;}
601
602
					if(jQuery(window).width() <= 576){
603
						// maybe restore original
604
						if(jQuery($carousel).find('.carousel-inner').hasClass('aui-multiple-items') && jQuery($carousel).find('.carousel-inner-original').length){
605
							jQuery($carousel).find('.carousel-inner').removeClass('aui-multiple-items').html(jQuery($carousel).find('.carousel-inner-original').html());
606
							jQuery($carousel).find(".carousel-indicators li").removeClass("d-none");
607
						}
608
609
					}else{
610
						// new items
611
						var $md_count = jQuery($carousel).data('limit_show');
612
						var $new_items = '';
613
						var $new_items_count = 0;
614
						var $new_item_count = 0;
615
						var $closed = true;
616
						Object.keys($items).forEach(function(key,index) {
617
618
							// close
619
							if(index != 0 && Number.isInteger(index/$md_count) ){
620
								$new_items += '</div></div>';
621
								$closed = true;
622
							}
623
624
							// open
625
							if(index == 0 || Number.isInteger(index/$md_count) ){
626
								$active = index == 0 ? 'active' : '';
627
								$new_items += '<div class="carousel-item '+$active+'"><div class="row m-0">';
628
								$closed = false;
629
								$new_items_count++;
630
								$new_item_count = 0;
631
							}
632
633
							// content
634
							$new_items += '<div class="col pr-1 pl-0">'+$items[index]+'</div>';
635
							$new_item_count++;
636
637
638
						});
639
640
						// close if not closed in the loop
641
						if(!$closed){
642
							// check for spares
643
							if($md_count-$new_item_count > 0){
644
								$placeholder_count = $md_count-$new_item_count;
645
								while($placeholder_count > 0){
646
									$new_items += '<div class="col pr-1 pl-0"></div>';
647
									$placeholder_count--;
648
								}
649
650
							}
651
652
							$new_items += '</div></div>';
653
						}
654
655
						// insert the new items
656
						jQuery($carousel).find('.carousel-inner').addClass('aui-multiple-items').html($new_items);
657
658
						// fix any lazyload images in the active slider
659
						jQuery($carousel).find('.carousel-item.active img').each(function () {
660
							// fix the srcset
661
							if(real_srcset = jQuery(this).attr("data-srcset")){
662
								if(!jQuery(this).attr("srcset")) jQuery(this).attr("srcset",real_srcset);
663
							}
664
							// fix the src
665
							if(real_src = jQuery(this).attr("data-src")){
666
								if(!jQuery(this).attr("srcset"))  jQuery(this).attr("src",real_src);
667
							}
668
						});
669
670
						// maybe fix carousel indicators
671
						$hide_count = $new_items_count-1;
672
						jQuery($carousel).find(".carousel-indicators li:gt("+$hide_count+")").addClass("d-none");
673
					}
674
675
					// trigger a global action to say we have
676
					jQuery( window ).trigger( "aui_carousel_multiple" );
677
				}
678
679
				/**
680
				 * Init Multiple item carousels.
681
				 */ 
682
				function aui_init_carousel_multiple_items(){
683
					jQuery(window).resize(function(){
684
						jQuery('.carousel-multiple-items').each(function () {
685
							aui_carousel_maybe_show_multiple_items(this);
686
						});
687
					});
688
689
					// run now
690
					jQuery('.carousel-multiple-items').each(function () {
691
						aui_carousel_maybe_show_multiple_items(this);
692
					});
693
				}
694
695
				/**
696
				 * Allow navs to use multiple sub menus.
697
				 */
698
				function init_nav_sub_menus(){
699
700
					jQuery('.navbar-multi-sub-menus').each(function(i, obj) {
701
						// Check if already initialized, if so continue.
702
						if(jQuery(this).hasClass("has-sub-sub-menus")){return true;}
703
704
						// Make sure its always expanded
705
						jQuery(this).addClass('has-sub-sub-menus');
706
707
						jQuery(this).find( '.dropdown-menu a.dropdown-toggle' ).on( 'click', function ( e ) {
708
							var $el = jQuery( this );
709
							$el.toggleClass('active-dropdown');
710
							var $parent = jQuery( this ).offsetParent( ".dropdown-menu" );
711
							if ( !jQuery( this ).next().hasClass( 'show' ) ) {
712
								jQuery( this ).parents( '.dropdown-menu' ).first().find( '.show' ).removeClass( "show" );
713
							}
714
							var $subMenu = jQuery( this ).next( ".dropdown-menu" );
715
							$subMenu.toggleClass( 'show' );
716
717
							jQuery( this ).parent( "li" ).toggleClass( 'show' );
718
719
							jQuery( this ).parents( 'li.nav-item.dropdown.show' ).on( 'hidden.bs.dropdown', function ( e ) {
720
								jQuery( '.dropdown-menu .show' ).removeClass( "show" );
721
								$el.removeClass('active-dropdown');
722
							} );
723
724
							if ( !$parent.parent().hasClass( 'navbar-nav' ) ) {
725
								$el.next().addClass('position-relative border-top border-bottom');
726
							}
727
728
							return false;
729
						} );
730
731
					});
732
733
				}
734
				
735
736
				/**
737
				 * Initiate all AUI JS.
738
				 */
739
				function aui_init(){
740
					// nav menu submenus
741
					init_nav_sub_menus();
742
					
743
					// init tooltips
744
					aui_init_tooltips();
745
746
					// init select2
747
					aui_init_select2();
748
749
					// init flatpickr
750
					aui_init_flatpickr();
751
752
					// init Greedy nav
753
					aui_init_greedy_nav();
754
755
					// Set times to time ago
756
					aui_time_ago('timeago');
757
					
758
					// init multiple item carousels
759
					aui_init_carousel_multiple_items();
760
				}
761
762
				// run on window loaded
763
				jQuery(window).on("load",function() {
764
					aui_init();
765
				});
766
				
767
			</script>
768
			<?php
769
			$output = ob_get_clean();
770
771
			/*
772
			 * We only add the <script> tags for code highlighting, so we strip them from the output.
773
			 */
774
			return str_replace( array(
775
				'<script>',
776
				'</script>'
777
			), '', $output );
778
		}
779
780
781
		/**
782
		 * JS to help with conflict issues with other plugins and themes using bootstrap v3.
783
		 * 
784
		 * @TODO we may need this when other conflicts arrise.
785
		 * @return mixed
786
		 */
787
		public static function bs3_compat_js() {
788
			ob_start();
789
			?>
790
			<script>
791
				<?php if( defined( 'FUSION_BUILDER_VERSION' ) ){ ?>
792
				/* With Avada builder */
793
794
				<?php } ?>
795
			</script>
796
			<?php
797
			return str_replace( array(
798
				'<script>',
799
				'</script>'
800
			), '', ob_get_clean());
801
		}
802
803
		/**
804
		 * Get inline script used if bootstrap file browser enqueued.
805
		 *
806
		 * If this remains small then its best to use this than to add another JS file.
807
		 */
808
		public function inline_script_file_browser(){
809
			ob_start();
810
			?>
811
			<script>
812
				// run on doc ready
813
				jQuery(document).ready(function () {
814
					bsCustomFileInput.init();
815
				});
816
			</script>
817
			<?php
818
			$output = ob_get_clean();
819
820
			/*
821
			 * We only add the <script> tags for code highlighting, so we strip them from the output.
822
			 */
823
			return str_replace( array(
824
				'<script>',
825
				'</script>'
826
			), '', $output );
827
		}
828
829
		/**
830
		 * Adds the Font Awesome JS.
831
		 */
832
		public function enqueue_scripts() {
833
834
			$js_setting = current_action() == 'wp_enqueue_scripts' ? 'js' : 'js_backend';
835
836
			// select2
837
			wp_register_script( 'select2', $this->url.'assets/js/select2.min.js', array('jquery'), $this->select2_version );
838
839
			// flatpickr
840
			wp_register_script( 'flatpickr', $this->url.'assets/js/flatpickr.min.js', array(), $this->latest );
841
842
			// Bootstrap file browser
843
			wp_register_script( 'aui-custom-file-input', $url = $this->url.'assets/js/bs-custom-file-input.min.js', array('jquery'), $this->select2_version );
844
			wp_add_inline_script( 'aui-custom-file-input', $this->inline_script_file_browser() );
845
846
			$load_inline = false;
847
848
			if($this->settings[$js_setting]=='core-popper'){
849
				// Bootstrap bundle
850
				$url = $this->url.'assets/js/bootstrap.bundle.min.js';
851
				wp_register_script( 'bootstrap-js-bundle', $url, array('select2','jquery'), $this->latest, $this->is_bs3_compat() );
852
				// if in admin then add to footer for compatibility.
853
				is_admin() ? wp_enqueue_script( 'bootstrap-js-bundle', '', null, null, true ) : wp_enqueue_script( 'bootstrap-js-bundle');
854
				$script = $this->inline_script();
855
				wp_add_inline_script( 'bootstrap-js-bundle', $script );
856
			}elseif($this->settings[$js_setting]=='popper'){
857
				$url = $this->url.'assets/js/popper.min.js';
858
				wp_register_script( 'bootstrap-js-popper', $url, array('select2','jquery'), $this->latest );
859
				wp_enqueue_script( 'bootstrap-js-popper' );
860
				$load_inline = true;
861
			}else{
862
				$load_inline = true;
863
			}
864
865
			// Load needed inline scripts by faking the loading of a script if the main script is not being loaded
866
			if($load_inline){
867
				wp_register_script( 'bootstrap-dummy', '',array('select2','jquery') );
868
				wp_enqueue_script( 'bootstrap-dummy' );
869
				$script = $this->inline_script();
870
				wp_add_inline_script( 'bootstrap-dummy', $script  );
871
			}
872
873
		}
874
875
		/**
876
		 * Enqueue flatpickr if called.
877
		 */
878
		public function enqueue_flatpickr(){
879
			wp_enqueue_style( 'flatpickr' );
880
			wp_enqueue_script( 'flatpickr' );
881
		}
882
883
		/**
884
		 * Get the url path to the current folder.
885
		 *
886
		 * @return string
887
		 */
888
		public function get_url() {
889
890
			$url = '';
891
			// check if we are inside a plugin
892
			$file_dir = str_replace( "/includes","", wp_normalize_path( dirname( __FILE__ ) ) );
893
894
			// add check in-case user has changed wp-content dir name.
895
			$wp_content_folder_name = basename(WP_CONTENT_DIR);
896
			$dir_parts = explode("/$wp_content_folder_name/",$file_dir);
897
			$url_parts = explode("/$wp_content_folder_name/",plugins_url());
898
899
			if(!empty($url_parts[0]) && !empty($dir_parts[1])){
900
				$url = trailingslashit( $url_parts[0]."/$wp_content_folder_name/".$dir_parts[1] );
901
			}
902
903
			return $url;
904
		}
905
906
		/**
907
		 * Register the database settings with WordPress.
908
		 */
909
		public function register_settings() {
910
			register_setting( 'ayecode-ui-settings', 'ayecode-ui-settings' );
911
		}
912
913
		/**
914
		 * Add the WordPress settings menu item.
915
		 * @since 1.0.10 Calling function name direct will fail theme check so we don't.
916
		 */
917
		public function menu_item() {
918
			$menu_function = 'add' . '_' . 'options' . '_' . 'page'; // won't pass theme check if function name present in theme
919
			call_user_func( $menu_function, $this->name, $this->name, 'manage_options', 'ayecode-ui-settings', array(
920
				$this,
921
				'settings_page'
922
			) );
923
		}
924
925
		/**
926
		 * Get a list of themes and their default JS settings.
927
		 *
928
		 * @return array
929
		 */
930
		public function theme_js_settings(){
931
			return array(
932
				'ayetheme' => 'popper',
933
				'listimia' => 'required',
934
				'listimia_backend' => 'core-popper',
935
				'avada'    => 'required',
936
			);
937
		}
938
939
		/**
940
		 * Get the current Font Awesome output settings.
941
		 *
942
		 * @return array The array of settings.
943
		 */
944
		public function get_settings() {
945
946
			$db_settings = get_option( 'ayecode-ui-settings' );
947
			$js_default = 'core-popper';
948
			$js_default_backend = $js_default;
949
950
			// maybe set defaults (if no settings set)
951
			if(empty($db_settings)){
952
				$active_theme = strtolower( get_template() ); // active parent theme.
953
				$theme_js_settings = self::theme_js_settings();
0 ignored issues
show
Bug Best Practice introduced by
The method AyeCode_UI_Settings::theme_js_settings() is not static, but was called statically. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

953
				/** @scrutinizer ignore-call */ 
954
    $theme_js_settings = self::theme_js_settings();
Loading history...
954
				if(isset($theme_js_settings[$active_theme])){
955
					$js_default = $theme_js_settings[$active_theme];
956
					$js_default_backend = isset($theme_js_settings[$active_theme."_backend"]) ? $theme_js_settings[$active_theme."_backend"] : $js_default;
957
				}
958
			}
959
960
			$defaults = array(
961
				'css'       => 'compatibility', // core, compatibility
962
				'js'        => $js_default, // js to load, core-popper, popper
963
				'html_font_size'        => '16', // js to load, core-popper, popper
964
				'css_backend'       => 'compatibility', // core, compatibility
965
				'js_backend'        => $js_default_backend, // js to load, core-popper, popper
966
				'disable_admin'     =>  '', // URL snippets to disable loading on admin
967
			);
968
969
			$settings = wp_parse_args( $db_settings, $defaults );
970
971
			/**
972
			 * Filter the Bootstrap settings.
973
			 *
974
			 * @todo if we add this filer people might use it and then it defeates the purpose of this class :/
975
			 */
976
			return $this->settings = apply_filters( 'ayecode-ui-settings', $settings, $db_settings, $defaults );
977
		}
978
979
980
		/**
981
		 * The settings page html output.
982
		 */
983
		public function settings_page() {
984
			if ( ! current_user_can( 'manage_options' ) ) {
985
				wp_die( __( 'You do not have sufficient permissions to access this page.', 'aui' ) );
986
			}
987
			?>
988
			<div class="wrap">
989
				<h1><?php echo $this->name; ?></h1>
990
				<p><?php _e("Here you can adjust settings if you are having compatibility issues.","aui");?></p>
991
				<form method="post" action="options.php">
992
					<?php
993
					settings_fields( 'ayecode-ui-settings' );
994
					do_settings_sections( 'ayecode-ui-settings' );
995
					?>
996
997
					<h2><?php _e( 'Frontend', 'aui' ); ?></h2>
998
					<table class="form-table wpbs-table-settings">
999
						<tr valign="top">
1000
							<th scope="row"><label
1001
									for="wpbs-css"><?php _e( 'Load CSS', 'aui' ); ?></label></th>
1002
							<td>
1003
								<select name="ayecode-ui-settings[css]" id="wpbs-css">
1004
									<option	value="compatibility" <?php selected( $this->settings['css'], 'compatibility' ); ?>><?php _e( 'Compatibility Mode (default)', 'aui' ); ?></option>
1005
									<option value="core" <?php selected( $this->settings['css'], 'core' ); ?>><?php _e( 'Full Mode', 'aui' ); ?></option>
1006
									<option	value="" <?php selected( $this->settings['css'], '' ); ?>><?php _e( 'Disabled', 'aui' ); ?></option>
1007
								</select>
1008
							</td>
1009
						</tr>
1010
1011
						<tr valign="top">
1012
							<th scope="row"><label
1013
									for="wpbs-js"><?php _e( 'Load JS', 'aui' ); ?></label></th>
1014
							<td>
1015
								<select name="ayecode-ui-settings[js]" id="wpbs-js">
1016
									<option	value="core-popper" <?php selected( $this->settings['js'], 'core-popper' ); ?>><?php _e( 'Core + Popper (default)', 'aui' ); ?></option>
1017
									<option value="popper" <?php selected( $this->settings['js'], 'popper' ); ?>><?php _e( 'Popper', 'aui' ); ?></option>
1018
									<option value="required" <?php selected( $this->settings['js'], 'required' ); ?>><?php _e( 'Required functions only', 'aui' ); ?></option>
1019
									<option	value="" <?php selected( $this->settings['js'], '' ); ?>><?php _e( 'Disabled (not recommended)', 'aui' ); ?></option>
1020
								</select>
1021
							</td>
1022
						</tr>
1023
1024
						<tr valign="top">
1025
							<th scope="row"><label
1026
									for="wpbs-font_size"><?php _e( 'HTML Font Size (px)', 'aui' ); ?></label></th>
1027
							<td>
1028
								<input type="number" name="ayecode-ui-settings[html_font_size]" id="wpbs-font_size" value="<?php echo absint( $this->settings['html_font_size']); ?>" placeholder="16" />
1029
								<p class="description" ><?php _e("Our font sizing is rem (responsive based) here you can set the html font size in-case your theme is setting it too low.","aui");?></p>
1030
							</td>
1031
						</tr>
1032
1033
					</table>
1034
1035
					<h2><?php _e( 'Backend', 'aui' ); ?> (wp-admin)</h2>
1036
					<table class="form-table wpbs-table-settings">
1037
						<tr valign="top">
1038
							<th scope="row"><label
1039
									for="wpbs-css-admin"><?php _e( 'Load CSS', 'aui' ); ?></label></th>
1040
							<td>
1041
								<select name="ayecode-ui-settings[css_backend]" id="wpbs-css-admin">
1042
									<option	value="compatibility" <?php selected( $this->settings['css_backend'], 'compatibility' ); ?>><?php _e( 'Compatibility Mode (default)', 'aui' ); ?></option>
1043
									<option value="core" <?php selected( $this->settings['css_backend'], 'core' ); ?>><?php _e( 'Full Mode (will cause style issues)', 'aui' ); ?></option>
1044
									<option	value="" <?php selected( $this->settings['css_backend'], '' ); ?>><?php _e( 'Disabled', 'aui' ); ?></option>
1045
								</select>
1046
							</td>
1047
						</tr>
1048
1049
						<tr valign="top">
1050
							<th scope="row"><label
1051
									for="wpbs-js-admin"><?php _e( 'Load JS', 'aui' ); ?></label></th>
1052
							<td>
1053
								<select name="ayecode-ui-settings[js_backend]" id="wpbs-js-admin">
1054
									<option	value="core-popper" <?php selected( $this->settings['js_backend'], 'core-popper' ); ?>><?php _e( 'Core + Popper (default)', 'aui' ); ?></option>
1055
									<option value="popper" <?php selected( $this->settings['js_backend'], 'popper' ); ?>><?php _e( 'Popper', 'aui' ); ?></option>
1056
									<option value="required" <?php selected( $this->settings['js_backend'], 'required' ); ?>><?php _e( 'Required functions only', 'aui' ); ?></option>
1057
									<option	value="" <?php selected( $this->settings['js_backend'], '' ); ?>><?php _e( 'Disabled (not recommended)', 'aui' ); ?></option>
1058
								</select>
1059
							</td>
1060
						</tr>
1061
1062
						<tr valign="top">
1063
							<th scope="row"><label
1064
									for="wpbs-disable-admin"><?php _e( 'Disable load on URL', 'aui' ); ?></label></th>
1065
							<td>
1066
								<p><?php _e( 'If you have backend conflict you can enter a partial URL argument that will disable the loading of AUI on those pages. Add each argument on a new line.', 'aui' ); ?></p>
1067
								<textarea name="ayecode-ui-settings[disable_admin]" rows="10" cols="50" id="wpbs-disable-admin" class="large-text code" spellcheck="false" placeholder="myplugin.php &#10;action=go"><?php echo $this->settings['disable_admin'];?></textarea>
1068
1069
							</td>
1070
						</tr>
1071
1072
					</table>
1073
1074
					<?php
1075
					submit_button();
1076
					?>
1077
				</form>
1078
1079
				<div id="wpbs-version"><?php echo $this->version; ?></div>
1080
			</div>
1081
1082
			<?php
1083
		}
1084
1085
		public function customizer_settings($wp_customize){
1086
			$wp_customize->add_section('aui_settings', array(
1087
				'title'    => __('AyeCode UI','aui'),
1088
				'priority' => 120,
1089
			));
1090
1091
			//  =============================
1092
			//  = Color Picker              =
1093
			//  =============================
1094
			$wp_customize->add_setting('aui_options[color_primary]', array(
1095
				'default'           => AUI_PRIMARY_COLOR,
1096
				'sanitize_callback' => 'sanitize_hex_color',
1097
				'capability'        => 'edit_theme_options',
1098
				'type'              => 'option',
1099
				'transport'         => 'refresh',
1100
			));
1101
			$wp_customize->add_control( new WP_Customize_Color_Control($wp_customize, 'color_primary', array(
1102
				'label'    => __('Primary Color','aui'),
1103
				'section'  => 'aui_settings',
1104
				'settings' => 'aui_options[color_primary]',
1105
			)));
1106
1107
			$wp_customize->add_setting('aui_options[color_secondary]', array(
1108
				'default'           => '#6c757d',
1109
				'sanitize_callback' => 'sanitize_hex_color',
1110
				'capability'        => 'edit_theme_options',
1111
				'type'              => 'option',
1112
				'transport'         => 'refresh',
1113
			));
1114
			$wp_customize->add_control( new WP_Customize_Color_Control($wp_customize, 'color_secondary', array(
1115
				'label'    => __('Secondary Color','aui'),
1116
				'section'  => 'aui_settings',
1117
				'settings' => 'aui_options[color_secondary]',
1118
			)));
1119
		}
1120
1121
		/**
1122
		 * CSS to help with conflict issues with other plugins and themes using bootstrap v3.
1123
		 *
1124
		 * @return mixed
1125
		 */
1126
		public static function bs3_compat_css() {
1127
			ob_start();
1128
			?>
1129
			<style>
1130
			/* Bootstrap 3 compatibility */
1131
			body.modal-open .modal-backdrop.show:not(.in) {opacity:0.5;}
1132
			body.modal-open .modal.show:not(.in)  {opacity:1;z-index: 99999}
1133
			body.modal-open .modal.show:not(.in) .modal-content  {box-shadow: none;}
1134
			body.modal-open .modal.show:not(.in)  .modal-dialog {transform: initial;}
1135
1136
			body.modal-open .modal.bsui .modal-dialog{left: auto;}
1137
1138
			.collapse.show:not(.in){display: inherit;}
1139
			.fade.show{opacity: 1;}
1140
1141
			<?php if( defined( 'SVQ_THEME_VERSION' ) ){ ?>
1142
			/* KLEO theme specific */
1143
			.kleo-main-header .navbar-collapse.collapse.show:not(.in){display: inherit !important;}
1144
			<?php } ?>
1145
1146
			<?php if( defined( 'FUSION_BUILDER_VERSION' ) ){ ?>
1147
			/* With Avada builder */
1148
			body.modal-open .modal.in  {opacity:1;z-index: 99999}
1149
			body.modal-open .modal.bsui.in .modal-content  {box-shadow: none;}
1150
			.bsui .collapse.in{display: inherit;}
1151
			<?php } ?>
1152
			</style>
1153
			<?php
1154
			return str_replace( array(
1155
				'<style>',
1156
				'</style>'
1157
			), '', ob_get_clean());
1158
		}
1159
1160
1161
		public static function custom_css($compatibility = true) {
1162
			$settings = get_option('aui_options');
1163
1164
			ob_start();
1165
1166
			$primary_color = !empty($settings['color_primary']) ? $settings['color_primary'] : AUI_PRIMARY_COLOR;
1167
			$secondary_color = !empty($settings['color_secondary']) ? $settings['color_secondary'] : AUI_SECONDARY_COLOR;
1168
				//AUI_PRIMARY_COLOR_ORIGINAL
1169
			?>
1170
			<style>
1171
				<?php
1172
1173
					// BS v3 compat
1174
					if( self::is_bs3_compat() ){
1175
					    echo self::bs3_compat_css();
1176
					}
1177
1178
					if(!is_admin() && $primary_color != AUI_PRIMARY_COLOR_ORIGINAL){
1179
						echo self::css_primary($primary_color,$compatibility);
1180
					}
1181
1182
					if(!is_admin() && $secondary_color != AUI_SECONDARY_COLOR_ORIGINAL){
1183
						echo self::css_secondary($settings['color_secondary'],$compatibility);
1184
					}
1185
                ?>
1186
			</style>
1187
			<?php
1188
1189
1190
			/*
1191
			 * We only add the <script> tags for code highlighting, so we strip them from the output.
1192
			 */
1193
			return str_replace( array(
1194
				'<style>',
1195
				'</style>'
1196
			), '', ob_get_clean());
1197
		}
1198
1199
		/**
1200
		 * Check if we should add booststrap 3 compatibility changes.
1201
		 *
1202
		 * @return bool
1203
		 */
1204
		public static function is_bs3_compat(){
1205
			return defined('AYECODE_UI_BS3_COMPAT') || defined('SVQ_THEME_VERSION') || defined('FUSION_BUILDER_VERSION');
1206
		}
1207
1208
		public static function css_primary($color_code,$compatibility){;
1209
			$color_code = sanitize_hex_color($color_code);
1210
			if(!$color_code){return '';}
1211
			/**
1212
			 * c = color, b = background color, o = border-color, f = fill
1213
			 */
1214
			$selectors = array(
1215
				'a' => array('c'),
1216
				'.btn-primary' => array('b','o'),
1217
				'.btn-primary.disabled' => array('b','o'),
1218
				'.btn-primary:disabled' => array('b','o'),
1219
				'.btn-outline-primary' => array('c','o'),
1220
				'.btn-outline-primary:hover' => array('b','o'),
1221
				'.btn-outline-primary:not(:disabled):not(.disabled).active' => array('b','o'),
1222
				'.btn-outline-primary:not(:disabled):not(.disabled):active' => array('b','o'),
1223
				'.show>.btn-outline-primary.dropdown-toggle' => array('b','o'),
1224
				'.btn-link' => array('c'),
1225
				'.dropdown-item.active' => array('b'),
1226
				'.custom-control-input:checked~.custom-control-label::before' => array('b','o'),
1227
				'.custom-checkbox .custom-control-input:indeterminate~.custom-control-label::before' => array('b','o'),
1228
//				'.custom-range::-webkit-slider-thumb' => array('b'), // these break the inline rules...
1229
//				'.custom-range::-moz-range-thumb' => array('b'),
1230
//				'.custom-range::-ms-thumb' => array('b'),
1231
				'.nav-pills .nav-link.active' => array('b'),
1232
				'.nav-pills .show>.nav-link' => array('b'),
1233
				'.page-link' => array('c'),
1234
				'.page-item.active .page-link' => array('b','o'),
1235
				'.badge-primary' => array('b'),
1236
				'.alert-primary' => array('b','o'),
1237
				'.progress-bar' => array('b'),
1238
				'.list-group-item.active' => array('b','o'),
1239
				'.bg-primary' => array('b','f'),
1240
				'.btn-link.btn-primary' => array('c'),
1241
				'.select2-container .select2-results__option--highlighted.select2-results__option[aria-selected=true]' => array('b'),
1242
			);
1243
1244
			$important_selectors = array(
1245
				'.bg-primary' => array('b','f'),
1246
				'.border-primary' => array('o'),
1247
				'.text-primary' => array('c'),
1248
			);
1249
1250
			$color = array();
1251
			$color_i = array();
1252
			$background = array();
1253
			$background_i = array();
1254
			$border = array();
1255
			$border_i = array();
1256
			$fill = array();
1257
			$fill_i = array();
1258
1259
			$output = '';
1260
1261
			// build rules into each type
1262
			foreach($selectors as $selector => $types){
1263
				$selector = $compatibility ? ".bsui ".$selector : $selector;
1264
				$types = array_combine($types,$types);
1265
				if(isset($types['c'])){$color[] = $selector;}
1266
				if(isset($types['b'])){$background[] = $selector;}
1267
				if(isset($types['o'])){$border[] = $selector;}
1268
				if(isset($types['f'])){$fill[] = $selector;}
1269
			}
1270
1271
			// build rules into each type
1272
			foreach($important_selectors as $selector => $types){
1273
				$selector = $compatibility ? ".bsui ".$selector : $selector;
1274
				$types = array_combine($types,$types);
1275
				if(isset($types['c'])){$color_i[] = $selector;}
1276
				if(isset($types['b'])){$background_i[] = $selector;}
1277
				if(isset($types['o'])){$border_i[] = $selector;}
1278
				if(isset($types['f'])){$fill_i[] = $selector;}
1279
			}
1280
1281
			// add any color rules
1282
			if(!empty($color)){
1283
				$output .= implode(",",$color) . "{color: $color_code;} ";
1284
			}
1285
			if(!empty($color_i)){
1286
				$output .= implode(",",$color_i) . "{color: $color_code !important;} ";
1287
			}
1288
1289
			// add any background color rules
1290
			if(!empty($background)){
1291
				$output .= implode(",",$background) . "{background-color: $color_code;} ";
1292
			}
1293
			if(!empty($background_i)){
1294
				$output .= implode(",",$background_i) . "{background-color: $color_code !important;} ";
1295
			}
1296
1297
			// add any border color rules
1298
			if(!empty($border)){
1299
				$output .= implode(",",$border) . "{border-color: $color_code;} ";
1300
			}
1301
			if(!empty($border_i)){
1302
				$output .= implode(",",$border_i) . "{border-color: $color_code !important;} ";
1303
			}
1304
1305
			// add any fill color rules
1306
			if(!empty($fill)){
1307
				$output .= implode(",",$fill) . "{fill: $color_code;} ";
1308
			}
1309
			if(!empty($fill_i)){
1310
				$output .= implode(",",$fill_i) . "{fill: $color_code !important;} ";
1311
			}
1312
1313
1314
			$prefix = $compatibility ? ".bsui " : "";
1315
1316
			// darken
1317
			$darker_075 = self::css_hex_lighten_darken($color_code,"-0.075");
0 ignored issues
show
Bug introduced by
'-0.075' of type string is incompatible with the type double expected by parameter $adjustPercent of AyeCode_UI_Settings::css_hex_lighten_darken(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

1317
			$darker_075 = self::css_hex_lighten_darken($color_code,/** @scrutinizer ignore-type */ "-0.075");
Loading history...
1318
			$darker_10 = self::css_hex_lighten_darken($color_code,"-0.10");
1319
			$darker_125 = self::css_hex_lighten_darken($color_code,"-0.125");
1320
1321
			// lighten
1322
			$lighten_25 = self::css_hex_lighten_darken($color_code,"0.25");
1323
1324
			// opacity see https://css-tricks.com/8-digit-hex-codes/
1325
			$op_25 = $color_code."40"; // 25% opacity
1326
1327
1328
			// button states
1329
			$output .= $prefix ." .btn-primary:hover{background-color: ".$darker_075.";    border-color: ".$darker_10.";} ";
1330
			$output .= $prefix ." .btn-outline-primary:not(:disabled):not(.disabled):active:focus, $prefix .btn-outline-primary:not(:disabled):not(.disabled).active:focus, .show>$prefix .btn-outline-primary.dropdown-toggle:focus{box-shadow: 0 0 0 0.2rem $op_25;} ";
1331
			$output .= $prefix ." .btn-primary:not(:disabled):not(.disabled):active, $prefix .btn-primary:not(:disabled):not(.disabled).active, .show>$prefix .btn-primary.dropdown-toggle{background-color: ".$darker_10.";    border-color: ".$darker_125.";} ";
1332
			$output .= $prefix ." .btn-primary:not(:disabled):not(.disabled):active:focus, $prefix .btn-primary:not(:disabled):not(.disabled).active:focus, .show>$prefix .btn-primary.dropdown-toggle:focus {box-shadow: 0 0 0 0.2rem $op_25;} ";
1333
1334
1335
			// dropdown's
1336
			$output .= $prefix ." .dropdown-item.active, $prefix .dropdown-item:active{background-color: $color_code;} ";
1337
1338
1339
			// input states
1340
			$output .= $prefix ." .form-control:focus{border-color: ".$lighten_25.";box-shadow: 0 0 0 0.2rem $op_25;} ";
1341
1342
			// page link
1343
			$output .= $prefix ." .page-link:focus{box-shadow: 0 0 0 0.2rem $op_25;} ";
1344
1345
			return $output;
1346
		}
1347
1348
		public static function css_secondary($color_code,$compatibility){;
1349
			$color_code = sanitize_hex_color($color_code);
1350
			if(!$color_code){return '';}
1351
			/**
1352
			 * c = color, b = background color, o = border-color, f = fill
1353
			 */
1354
			$selectors = array(
1355
				'.btn-secondary' => array('b','o'),
1356
				'.btn-secondary.disabled' => array('b','o'),
1357
				'.btn-secondary:disabled' => array('b','o'),
1358
				'.btn-outline-secondary' => array('c','o'),
1359
				'.btn-outline-secondary:hover' => array('b','o'),
1360
				'.btn-outline-secondary.disabled' => array('c'),
1361
				'.btn-outline-secondary:disabled' => array('c'),
1362
				'.btn-outline-secondary:not(:disabled):not(.disabled):active' => array('b','o'),
1363
				'.btn-outline-secondary:not(:disabled):not(.disabled).active' => array('b','o'),
1364
				'.btn-outline-secondary.dropdown-toggle' => array('b','o'),
1365
				'.badge-secondary' => array('b'),
1366
				'.alert-secondary' => array('b','o'),
1367
				'.btn-link.btn-secondary' => array('c'),
1368
			);
1369
1370
			$important_selectors = array(
1371
				'.bg-secondary' => array('b','f'),
1372
				'.border-secondary' => array('o'),
1373
				'.text-secondary' => array('c'),
1374
			);
1375
1376
			$color = array();
1377
			$color_i = array();
1378
			$background = array();
1379
			$background_i = array();
1380
			$border = array();
1381
			$border_i = array();
1382
			$fill = array();
1383
			$fill_i = array();
1384
1385
			$output = '';
1386
1387
			// build rules into each type
1388
			foreach($selectors as $selector => $types){
1389
				$selector = $compatibility ? ".bsui ".$selector : $selector;
1390
				$types = array_combine($types,$types);
1391
				if(isset($types['c'])){$color[] = $selector;}
1392
				if(isset($types['b'])){$background[] = $selector;}
1393
				if(isset($types['o'])){$border[] = $selector;}
1394
				if(isset($types['f'])){$fill[] = $selector;}
1395
			}
1396
1397
			// build rules into each type
1398
			foreach($important_selectors as $selector => $types){
1399
				$selector = $compatibility ? ".bsui ".$selector : $selector;
1400
				$types = array_combine($types,$types);
1401
				if(isset($types['c'])){$color_i[] = $selector;}
1402
				if(isset($types['b'])){$background_i[] = $selector;}
1403
				if(isset($types['o'])){$border_i[] = $selector;}
1404
				if(isset($types['f'])){$fill_i[] = $selector;}
1405
			}
1406
1407
			// add any color rules
1408
			if(!empty($color)){
1409
				$output .= implode(",",$color) . "{color: $color_code;} ";
1410
			}
1411
			if(!empty($color_i)){
1412
				$output .= implode(",",$color_i) . "{color: $color_code !important;} ";
1413
			}
1414
1415
			// add any background color rules
1416
			if(!empty($background)){
1417
				$output .= implode(",",$background) . "{background-color: $color_code;} ";
1418
			}
1419
			if(!empty($background_i)){
1420
				$output .= implode(",",$background_i) . "{background-color: $color_code !important;} ";
1421
			}
1422
1423
			// add any border color rules
1424
			if(!empty($border)){
1425
				$output .= implode(",",$border) . "{border-color: $color_code;} ";
1426
			}
1427
			if(!empty($border_i)){
1428
				$output .= implode(",",$border_i) . "{border-color: $color_code !important;} ";
1429
			}
1430
1431
			// add any fill color rules
1432
			if(!empty($fill)){
1433
				$output .= implode(",",$fill) . "{fill: $color_code;} ";
1434
			}
1435
			if(!empty($fill_i)){
1436
				$output .= implode(",",$fill_i) . "{fill: $color_code !important;} ";
1437
			}
1438
1439
1440
			$prefix = $compatibility ? ".bsui " : "";
1441
1442
			// darken
1443
			$darker_075 = self::css_hex_lighten_darken($color_code,"-0.075");
0 ignored issues
show
Bug introduced by
'-0.075' of type string is incompatible with the type double expected by parameter $adjustPercent of AyeCode_UI_Settings::css_hex_lighten_darken(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

1443
			$darker_075 = self::css_hex_lighten_darken($color_code,/** @scrutinizer ignore-type */ "-0.075");
Loading history...
1444
			$darker_10 = self::css_hex_lighten_darken($color_code,"-0.10");
1445
			$darker_125 = self::css_hex_lighten_darken($color_code,"-0.125");
1446
1447
			// lighten
1448
			$lighten_25 = self::css_hex_lighten_darken($color_code,"0.25");
0 ignored issues
show
Unused Code introduced by
The assignment to $lighten_25 is dead and can be removed.
Loading history...
1449
1450
			// opacity see https://css-tricks.com/8-digit-hex-codes/
1451
			$op_25 = $color_code."40"; // 25% opacity
1452
1453
1454
			// button states
1455
			$output .= $prefix ." .btn-secondary:hover{background-color: ".$darker_075.";    border-color: ".$darker_10.";} ";
1456
			$output .= $prefix ." .btn-outline-secondary:not(:disabled):not(.disabled):active:focus, $prefix .btn-outline-secondary:not(:disabled):not(.disabled).active:focus, .show>$prefix .btn-outline-secondary.dropdown-toggle:focus{box-shadow: 0 0 0 0.2rem $op_25;} ";
1457
			$output .= $prefix ." .btn-secondary:not(:disabled):not(.disabled):active, $prefix .btn-secondary:not(:disabled):not(.disabled).active, .show>$prefix .btn-secondary.dropdown-toggle{background-color: ".$darker_10.";    border-color: ".$darker_125.";} ";
1458
			$output .= $prefix ." .btn-secondary:not(:disabled):not(.disabled):active:focus, $prefix .btn-secondary:not(:disabled):not(.disabled).active:focus, .show>$prefix .btn-secondary.dropdown-toggle:focus {box-shadow: 0 0 0 0.2rem $op_25;} ";
1459
1460
1461
			return $output;
1462
		}
1463
1464
		/**
1465
		 * Increases or decreases the brightness of a color by a percentage of the current brightness.
1466
		 *
1467
		 * @param   string  $hexCode        Supported formats: `#FFF`, `#FFFFFF`, `FFF`, `FFFFFF`
1468
		 * @param   float   $adjustPercent  A number between -1 and 1. E.g. 0.3 = 30% lighter; -0.4 = 40% darker.
1469
		 *
1470
		 * @return  string
1471
		 */
1472
		public static function css_hex_lighten_darken($hexCode, $adjustPercent) {
1473
			$hexCode = ltrim($hexCode, '#');
1474
1475
			if (strlen($hexCode) == 3) {
1476
				$hexCode = $hexCode[0] . $hexCode[0] . $hexCode[1] . $hexCode[1] . $hexCode[2] . $hexCode[2];
1477
			}
1478
1479
			$hexCode = array_map('hexdec', str_split($hexCode, 2));
0 ignored issues
show
Bug introduced by
It seems like str_split($hexCode, 2) can also be of type true; however, parameter $array of array_map() does only seem to accept array, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

1479
			$hexCode = array_map('hexdec', /** @scrutinizer ignore-type */ str_split($hexCode, 2));
Loading history...
1480
1481
			foreach ($hexCode as & $color) {
1482
				$adjustableLimit = $adjustPercent < 0 ? $color : 255 - $color;
1483
				$adjustAmount = ceil($adjustableLimit * $adjustPercent);
1484
1485
				$color = str_pad(dechex($color + $adjustAmount), 2, '0', STR_PAD_LEFT);
0 ignored issues
show
Bug introduced by
$color + $adjustAmount of type double is incompatible with the type integer expected by parameter $num of dechex(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

1485
				$color = str_pad(dechex(/** @scrutinizer ignore-type */ $color + $adjustAmount), 2, '0', STR_PAD_LEFT);
Loading history...
1486
			}
1487
1488
			return '#' . implode($hexCode);
1489
		}
1490
1491
		/**
1492
		 * Check if we should display examples.
1493
		 */
1494
		public function maybe_show_examples(){
1495
			if(current_user_can('manage_options') && isset($_REQUEST['preview-aui'])){
1496
				echo "<head>";
1497
				wp_head();
1498
				echo "</head>";
1499
				echo "<body>";
1500
				echo $this->get_examples();
1501
				echo "</body>";
1502
				exit;
0 ignored issues
show
Best Practice introduced by
Using exit here is not recommended.

In general, usage of exit should be done with care and only when running in a scripting context like a CLI script.

Loading history...
1503
			}
1504
		}
1505
1506
		/**
1507
		 * Get developer examples.
1508
		 *
1509
		 * @return string
1510
		 */
1511
		public function get_examples(){
1512
			$output = '';
1513
1514
1515
			// open form
1516
			$output .= "<form class='p-5 m-5 border rounded'>";
1517
1518
			// input example
1519
			$output .= aui()->input(array(
1520
				'type'  =>  'text',
1521
				'id'    =>  'text-example',
1522
				'name'    =>  'text-example',
1523
				'placeholder'   => 'text placeholder',
1524
				'title'   => 'Text input example',
1525
				'value' =>  '',
1526
				'required'  => false,
1527
				'help_text' => 'help text',
1528
				'label' => 'Text input example label'
1529
			));
1530
1531
			// input example
1532
			$output .= aui()->input(array(
1533
				'type'  =>  'url',
1534
				'id'    =>  'text-example2',
1535
				'name'    =>  'text-example',
1536
				'placeholder'   => 'url placeholder',
1537
				'title'   => 'Text input example',
1538
				'value' =>  '',
1539
				'required'  => false,
1540
				'help_text' => 'help text',
1541
				'label' => 'Text input example label'
1542
			));
1543
1544
			// checkbox example
1545
			$output .= aui()->input(array(
1546
				'type'  =>  'checkbox',
1547
				'id'    =>  'checkbox-example',
1548
				'name'    =>  'checkbox-example',
1549
				'placeholder'   => 'checkbox-example',
1550
				'title'   => 'Checkbox example',
1551
				'value' =>  '1',
1552
				'checked'   => true,
1553
				'required'  => false,
1554
				'help_text' => 'help text',
1555
				'label' => 'Checkbox checked'
1556
			));
1557
1558
			// checkbox example
1559
			$output .= aui()->input(array(
1560
				'type'  =>  'checkbox',
1561
				'id'    =>  'checkbox-example2',
1562
				'name'    =>  'checkbox-example2',
1563
				'placeholder'   => 'checkbox-example',
1564
				'title'   => 'Checkbox example',
1565
				'value' =>  '1',
1566
				'checked'   => false,
1567
				'required'  => false,
1568
				'help_text' => 'help text',
1569
				'label' => 'Checkbox un-checked'
1570
			));
1571
1572
			// switch example
1573
			$output .= aui()->input(array(
1574
				'type'  =>  'checkbox',
1575
				'id'    =>  'switch-example',
1576
				'name'    =>  'switch-example',
1577
				'placeholder'   => 'checkbox-example',
1578
				'title'   => 'Switch example',
1579
				'value' =>  '1',
1580
				'checked'   => true,
1581
				'switch'    => true,
1582
				'required'  => false,
1583
				'help_text' => 'help text',
1584
				'label' => 'Switch on'
1585
			));
1586
1587
			// switch example
1588
			$output .= aui()->input(array(
1589
				'type'  =>  'checkbox',
1590
				'id'    =>  'switch-example2',
1591
				'name'    =>  'switch-example2',
1592
				'placeholder'   => 'checkbox-example',
1593
				'title'   => 'Switch example',
1594
				'value' =>  '1',
1595
				'checked'   => false,
1596
				'switch'    => true,
1597
				'required'  => false,
1598
				'help_text' => 'help text',
1599
				'label' => 'Switch off'
1600
			));
1601
1602
			// close form
1603
			$output .= "</form>";
1604
1605
			return $output;
1606
		}
1607
1608
	}
1609
1610
	/**
1611
	 * Run the class if found.
1612
	 */
1613
	AyeCode_UI_Settings::instance();
1614
}