PluginProbe
Ultimate Store Kit – Addon For WooCommerce, EDD and Elementor / trunk
Ultimate Store Kit – Addon For WooCommerce, EDD and Elementor vtrunk
3.0.7 3.0.5 3.0.4 3.0.3 3.0.2 trunk 1.5.0 1.5.1 1.5.2 1.6.1 1.6.2 1.6.3 1.6.4 2.0.0 2.0.1 2.0.2 2.0.3 2.0.4 2.0.5 2.0.6 2.1.0 2.1.1 2.1.10 2.1.2 2.1.3 All 87 releases
ultimate-store-kit / includes / helper.php

helper.php in Ultimate Store Kit – Addon For WooCommerce, EDD and Elementor trunk, at includes/helper.php

1,464 lines 41.1 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 if (! defined('ABSPATH')) {
4 exit; // Exit if accessed directly
5 }
6
7 // phpcs:disable WordPress.NamingConventions.PrefixAllGlobals -- BDTUSK_ / ultimate_store_kit_ / ultimate-store-kit- are this plugin's established public prefixes.
8
9 use UltimateStoreKit\Ultimate_Store_Kit_Loader;
10 use Elementor\Plugin;
11
12 /**
13 * You can easily add white label branding for for extended license or multi site license.
14 * Don't try for regular license otherwise your license will be invalid.
15 * return white label
16 */
17
18 if (! defined('BDTUSK')) {
19 define('BDTUSK', '');
20 }
21
22 //Add prefix for all widgets <span class="usk-widget-badge"></span>
23 if (! defined('BDTUSK_CP')) {
24 define('BDTUSK_CP', '<span class="usk-widget-badge"></span>');
25 }
26
27 //Add prefix for all widgets <span class="usk-widget-badge"></span>
28 if (! defined('BDTUSK_NC')) {
29 define('BDTUSK_NC', '<span class="usk-new-control"></span>');
30 }
31
32 // if you have any custom style
33 if (! defined('BDTUSK_SLUG')) {
34 define('BDTUSK_SLUG', 'ultimate-store-kit');
35 }
36
37 // set your own alias
38 if (! defined('BDTUSK_VER')) {
39 define('BDTUSK_VER', 'Ultimate Store Kit');
40 }
41
42 // Set your own name for plugin
43
44 if (! defined('BDTUSK_NAME')) {
45 define('BDTUSK_NAME', 'Ultimate Store Kit');
46 }
47
48 if (ultimate_store_kit_is_pro_activated()) {
49 if (! defined('BDTUSK_PC')) {
50 define('BDTUSK_PC', '');
51 } // pro control badge
52 define('BDTUSK_IS_PC', '');
53 } else {
54 if (! defined('BDTUSK_PC')) {
55 define('BDTUSK_PC', '<span class="usk-pro-control"></span>');
56 } // pro control badge
57 define('BDTUSK_IS_PC', 'usk-disabled-control');
58 }
59
60 /**
61 * Show any alert by this function
62 *
63 * @param mixed $message [description]
64 * @param class prefix $type [description]
65 * @param boolean $close [description]
66 *
67 * @return helper [description]
68 */
69
70
71 function ultimate_store_kit_is_edit() {
72 return Plugin::$instance->editor->is_edit_mode();
73 }
74
75 function ultimate_store_kit_is_preview() {
76 return Plugin::$instance->preview->is_preview_mode();
77 }
78
79 function ultimate_store_kit_alert($message, $type = 'warning', $close = true) {
80 ?>
81 <div class="usk-alert-<?php echo esc_attr('$type'); ?>" usk-alert>
82 <?php if ($close) : ?>
83 <a class="usk-alert-close" usk-close></a>
84 <?php endif; ?>
85 <?php echo wp_kses_post($message); ?>
86 </div>
87 <?php
88 }
89
90 function ultimate_store_kit_get_alert($message, $type = 'warning', $close = true) {
91
92 $output = '<div class="usk-alert-' . $type . '" usk-alert>';
93 if ($close) :
94 $output .= '<a class="usk-alert-close" usk-close></a>';
95 endif;
96 $output .= wp_kses_post($message);
97 $output .= '</div>';
98
99 return $output;
100 }
101
102 /**
103 * all array css classes will output as proper space
104 *
105 * @param array $classes shortcode css class as array
106 *
107 * @return proper string
108 */
109
110 function ultimate_store_kit_get_post_types($args = []) {
111
112 $post_type_args = [
113 'show_in_nav_menus' => true,
114 ];
115
116 if (! empty($args['post_type'])) {
117 $post_type_args['name'] = $args['post_type'];
118 }
119
120 $_post_types = get_post_types($post_type_args, 'objects');
121
122 $post_types = ['0' => esc_html__('Select Type', 'ultimate-store-kit')];
123
124 foreach ($_post_types as $post_type => $object) {
125 $post_types[$post_type] = $object->label;
126 }
127
128 return $post_types;
129 }
130
131 /**
132 * Add REST API support to an already registered post type.
133 */
134
135 // function bdt_custom_post_type_rest_support() {
136
137 // global $wp_post_types;
138
139 // $post_types = ultimate_store_kit_get_post_types();
140
141 // foreach( $post_types as $post_type ) {
142
143 // $post_type_name = $post_type;
144
145 // if( isset( $wp_post_types[ $post_type_name ] ) ) {
146
147 // $wp_post_types[$post_type_name]->show_in_rest = true;
148
149 // $wp_post_types[$post_type_name]->rest_base = $post_type_name;
150
151 // $wp_post_types[$post_type_name]->rest_controller_class = 'WP_REST_Posts_Controller';
152
153 // }
154
155 // }
156
157 // }
158
159 // add_action( 'init', 'bdt_custom_post_type_rest_support', 25 );
160
161 function ultimate_store_kit_allow_tags($tag = null) {
162 $tag_allowed = wp_kses_allowed_html('post');
163
164 $tag_allowed['input'] = [
165 'class' => [],
166 'id' => [],
167 'name' => [],
168 'value' => [],
169 'checked' => [],
170 'type' => [],
171 ];
172 $tag_allowed['select'] = [
173 'class' => [],
174 'id' => [],
175 'name' => [],
176 'value' => [],
177 'multiple' => [],
178 'type' => [],
179 ];
180 $tag_allowed['option'] = [
181 'value' => [],
182 'selected' => [],
183 ];
184
185 $tag_allowed['title'] = [
186 'a' => [
187 'href' => [],
188 'title' => [],
189 'class' => [],
190 ],
191 'br' => [],
192 'em' => [],
193 'strong' => [],
194 'hr' => [],
195 ];
196
197 $tag_allowed['text'] = [
198 'a' => [
199 'href' => [],
200 'title' => [],
201 'class' => [],
202 ],
203 'br' => [],
204 'em' => [],
205 'strong' => [],
206 'hr' => [],
207 'i' => [
208 'class' => [],
209 ],
210 'span' => [
211 'class' => [],
212 ],
213 ];
214
215 $tag_allowed['svg'] = [
216 'svg' => [
217 'version' => [],
218 'xmlns' => [],
219 'viewbox' => [],
220 'xml:space' => [],
221 'xmlns:xlink' => [],
222 'x' => [],
223 'y' => [],
224 'style' => [],
225 ],
226 'g' => [],
227 'path' => [
228 'class' => [],
229 'd' => [],
230 ],
231 'ellipse' => [
232 'class' => [],
233 'cx' => [],
234 'cy' => [],
235 'rx' => [],
236 'ry' => [],
237 ],
238 'circle' => [
239 'class' => [],
240 'cx' => [],
241 'cy' => [],
242 'r' => [],
243 ],
244 'rect' => [
245 'x' => [],
246 'y' => [],
247 'transform' => [],
248 'height' => [],
249 'width' => [],
250 'class' => [],
251 ],
252 'line' => [
253 'class' => [],
254 'x1' => [],
255 'x2' => [],
256 'y1' => [],
257 'y2' => [],
258 ],
259 'style' => [],
260
261 ];
262
263 if ($tag == null) {
264 return $tag_allowed;
265 } elseif (is_array($tag)) {
266 $new_tag_allow = [];
267
268 foreach ($tag as $_tag) {
269 $new_tag_allow[$_tag] = $tag_allowed[$_tag];
270 }
271
272 return $new_tag_allow;
273 } else {
274 return isset($tag_allowed[$tag]) ? $tag_allowed[$tag] : [];
275 }
276 }
277
278 /**
279 * Build a pagination link for widget grids or standard WordPress queries.
280 *
281 * @param int $page Page number.
282 * @param string $query_arg Optional custom query arg (e.g. product-page).
283 * @param string $current_url Base URL when using a custom query arg.
284 * @return string
285 */
286 function ultimate_store_kit_get_pagination_link($page, $query_arg = '', $current_url = '') {
287 $page = absint($page);
288
289 if (! empty($query_arg)) {
290 if ($page <= 1) {
291 return remove_query_arg($query_arg, $current_url);
292 }
293
294 return add_query_arg($query_arg, $page, $current_url);
295 }
296
297 return get_pagenum_link($page);
298 }
299
300 /**
301 * Whether pagination should use the product-page query arg.
302 *
303 * WooCommerce product grids read the page from ?product-page= so widget
304 * pagination does not conflict with WordPress paged/page on embedded pages.
305 *
306 * @param WP_Query|object $wp_query Query object.
307 * @return bool
308 */
309 function ultimate_store_kit_pagination_uses_product_page($wp_query) {
310 if (! $wp_query instanceof \WP_Query) {
311 return false;
312 }
313
314 $post_type = $wp_query->get('post_type');
315
316 if (empty($post_type) && isset($wp_query->query_vars['post_type'])) {
317 $post_type = $wp_query->query_vars['post_type'];
318 }
319
320 if (is_array($post_type)) {
321 return in_array('product', $post_type, true);
322 }
323
324 return 'product' === $post_type;
325 }
326
327 /**
328 * Post pagination.
329 *
330 * Auto-detects WooCommerce product grids and uses the product-page query arg.
331 * EDD grids, product reviews, and other queries use standard WordPress pagination.
332 *
333 * @param WP_Query|object $wp_query Query object with max_num_pages.
334 * @param array $args Optional. 'query_arg' => 'product-page' to force custom arg mode.
335 */
336 function ultimate_store_kit_post_pagination($wp_query, $args = []) {
337 $args = wp_parse_args($args, [
338 'query_arg' => '',
339 ]);
340
341 if ($wp_query->max_num_pages <= 1) {
342 return;
343 }
344
345 $query_arg = sanitize_key($args['query_arg']);
346
347 if ('' === $query_arg && ultimate_store_kit_pagination_uses_product_page($wp_query)) {
348 $query_arg = 'product-page';
349 }
350
351 $use_custom_arg = ! empty($query_arg);
352
353 if ($use_custom_arg) {
354 $page = max(1, absint(get_query_var('paged')), absint(get_query_var('page')));
355 $custom_page = filter_input(INPUT_GET, $query_arg, FILTER_VALIDATE_INT);
356
357 if ($custom_page && $custom_page >= 1) {
358 $page = absint($custom_page);
359 }
360
361 $paged = absint($page);
362 } elseif (is_front_page()) {
363 $paged = absint(get_query_var('page')) ?: 1;
364 } else {
365 $paged = absint(get_query_var('paged')) ?: 1;
366 }
367
368 $max = absint($wp_query->max_num_pages);
369 $links = [];
370
371 if ($paged >= 1) {
372 $links[] = $paged;
373 }
374
375 if ($paged >= 3) {
376 $links[] = $paged - 1;
377 $links[] = $paged - 2;
378 }
379
380 if (($paged + 2) <= $max) {
381 $links[] = $paged + 2;
382 $links[] = $paged + 1;
383 }
384
385 $current_url = '';
386
387 if ($use_custom_arg) {
388 $current_url = remove_query_arg(['paged', 'page', $query_arg]);
389
390 if (is_post_type_archive() || is_tax()) {
391 $current_url = remove_query_arg(
392 ['paged', 'page', $query_arg],
393 get_pagenum_link(1, false)
394 );
395 }
396 }
397
398 echo '<ul class="usk-pagination" aria-label="' . esc_attr__('Pagination', 'ultimate-store-kit') . '">' . "\n";
399
400 if ($paged > 1) {
401 printf(
402 '<li class="usk-pagination-previous">
403 <a href="%s" aria-label="%s">
404 <span class="usk-icon-arrow-left-5" aria-hidden="true"></span>
405 </a>
406 </li>' . "\n",
407 esc_url(ultimate_store_kit_get_pagination_link($paged - 1, $query_arg, $current_url)),
408 esc_attr__('Previous Page', 'ultimate-store-kit')
409 );
410 }
411
412 if (! in_array(1, $links, true)) {
413 $class = (1 === $paged) ? 'usk-active' : '';
414
415 printf(
416 '<li class="%s"><a href="%s" target="_self">%s</a></li>' . "\n",
417 esc_attr($class),
418 esc_url(ultimate_store_kit_get_pagination_link(1, $query_arg, $current_url)),
419 esc_html('1')
420 );
421
422 if (! in_array(2, $links, true)) {
423 echo '<li class="usk-pagination-dot-dot"><span>...</span></li>' . "\n";
424 }
425 }
426
427 sort($links);
428
429 foreach ($links as $link) {
430 $class = ($paged === (int) $link) ? 'usk-active' : '';
431
432 printf(
433 '<li class="%s"><a href="%s" target="_self">%s</a></li>' . "\n",
434 esc_attr($class),
435 esc_url(ultimate_store_kit_get_pagination_link($link, $query_arg, $current_url)),
436 esc_html($link)
437 );
438 }
439
440 if (! in_array($max, $links, true)) {
441 if (! in_array($max - 1, $links, true)) {
442 echo '<li class="usk-pagination-dot-dot"><span>...</span></li>' . "\n";
443 }
444
445 $class = ($paged === $max) ? 'usk-active' : '';
446
447 printf(
448 '<li class="%s"><a href="%s" target="_self">%s</a></li>' . "\n",
449 esc_attr($class),
450 esc_url(ultimate_store_kit_get_pagination_link($max, $query_arg, $current_url)),
451 esc_html($max)
452 );
453 }
454
455 if ($paged < $max) {
456 printf(
457 '<li class="usk-pagination-next">
458 <a href="%s" aria-label="%s">
459 <span class="usk-icon-arrow-right-5" aria-hidden="true"></span>
460 </a>
461 </li>' . "\n",
462 esc_url(ultimate_store_kit_get_pagination_link($paged + 1, $query_arg, $current_url)),
463 esc_attr__('Next Page', 'ultimate-store-kit')
464 );
465 }
466
467 echo '</ul>' . "\n";
468 }
469
470 function ultimate_store_kit_template_edit_link($template_id) {
471
472 if (Ultimate_Store_Kit_Loader::elementor()->editor->is_edit_mode()) {
473
474 $final_url = add_query_arg(['elementor' => ''], get_permalink($template_id));
475
476 $output = sprintf('<a class="usk-elementor-template-edit-link" href="%s" title="%s" target="_blank"><i class="usk-icon-edit"></i></a>', esc_url($final_url), esc_html__('Edit Template', 'ultimate-store-kit'));
477
478 return $output;
479 }
480 }
481
482 function ultimate_store_kit_iso_time($time) {
483 $current_offset = (float) get_option('gmt_offset');
484 $timezone_string = get_option('timezone_string');
485
486 // Create a UTC+- zone if no timezone string exists.
487
488 //if ( empty( $timezone_string ) ) {
489 if (0 === $current_offset) {
490 $timezone_string = '+00:00';
491 } elseif ($current_offset < 0) {
492 $timezone_string = $current_offset . ':00';
493 } else {
494 $timezone_string = '+0' . $current_offset . ':00';
495 }
496
497 //}
498
499 $sub_time = [];
500 $sub_time = explode(" ", $time);
501 $final_time = $sub_time[0] . 'T' . $sub_time[1] . ':00' . $timezone_string;
502
503 return $final_time;
504 }
505
506 /**
507 * @param $currency
508 * @param int $precision
509 *
510 * @return false|string
511 */
512 function ultimate_store_kit_currency_format($currency, $precision = 1) {
513
514 if ($currency > 0) {
515
516 if ($currency < 900) {
517 // 0 - 900
518 $currency_format = number_format($currency, $precision);
519 $suffix = '';
520 } else
521
522 if ($currency < 900000) {
523 // 0.9k-850k
524 $currency_format = number_format($currency / 1000, $precision);
525 $suffix = 'K';
526 } else
527
528 if ($currency < 900000000) {
529 // 0.9m-850m
530 $currency_format = number_format($currency / 1000000, $precision);
531 $suffix = 'M';
532 } else
533
534 if ($currency < 900000000000) {
535 // 0.9b-850b
536 $currency_format = number_format($currency / 1000000000, $precision);
537 $suffix = 'B';
538 } else {
539 // 0.9t+
540 $currency_format = number_format($currency / 1000000000000, $precision);
541 $suffix = 'T';
542 }
543
544 // Remove unecessary zeroes after decimal. "1.0" -> "1"; "1.00" -> "1"
545
546 // Intentionally does not affect partials, eg "1.50" -> "1.50"
547 if ($precision > 0) {
548 $dotzero = '.' . str_repeat('0', $precision);
549 $currency_format = str_replace($dotzero, '', $currency_format);
550 }
551
552 return $currency_format . $suffix;
553 }
554
555 return false;
556 }
557
558 /**
559 * @return array
560 */
561 function ultimate_store_kit_get_menu() {
562
563 $menus = wp_get_nav_menus();
564 $items = [0 => esc_html__('Select Menu', 'ultimate-store-kit')];
565 foreach ($menus as $menu) {
566 $items[$menu->slug] = $menu->name;
567 }
568
569 return $items;
570 }
571
572 /**
573 * default get_option() default value check
574 *
575 * @param string $option settings field name
576 * @param string $section the section name this field belongs to
577 * @param string $default default text if it's not found
578 *
579 * @return mixed
580 */
581 function ultimate_store_kit_option($option, $section, $default = '') {
582
583 $options = get_option($section);
584
585 if (isset($options[$option])) {
586 return $options[$option];
587 }
588
589 return $default;
590 }
591
592 /**
593 * @return array of elementor template
594 */
595 function ultimate_store_kit_et_options() {
596
597 $templates = Ultimate_Store_Kit_Loader::elementor()->templates_manager->get_source('local')->get_items();
598 $types = [];
599
600 if (empty($templates)) {
601 $template_options = ['0' => __('Template Not Found!', 'ultimate-store-kit')];
602 } else {
603 $template_options = ['0' => __('Select Template', 'ultimate-store-kit')];
604
605 foreach ($templates as $template) {
606 $template_options[$template['template_id']] = $template['title'] . ' (' . $template['type'] . ')';
607 $types[$template['template_id']] = $template['type'];
608 }
609 }
610
611 return $template_options;
612 }
613
614 /**
615 * @return array of wp default sidebars
616 */
617 function ultimate_store_kit_sidebar_options() {
618
619 global $wp_registered_sidebars;
620 $sidebar_options = [];
621
622 if (! $wp_registered_sidebars) {
623 $sidebar_options[0] = esc_html__('No sidebars were found', 'ultimate-store-kit');
624 } else {
625 $sidebar_options[0] = esc_html__('Select Sidebar', 'ultimate-store-kit');
626
627 foreach ($wp_registered_sidebars as $sidebar_id => $sidebar) {
628 $sidebar_options[$sidebar_id] = $sidebar['name'];
629 }
630 }
631
632 return $sidebar_options;
633 }
634
635 /**
636 * @param string category name
637 *
638 * @return array of category
639 */
640 function ultimate_store_kit_get_category($taxonomy = 'product_cat') {
641
642 $post_options = [];
643
644 $post_categories = get_terms([
645 'taxonomy' => $taxonomy,
646 'hide_empty' => false,
647 ]);
648
649 if (is_wp_error($post_categories)) {
650 return $post_options;
651 }
652
653 if (false !== $post_categories and is_array($post_categories)) {
654 foreach ($post_categories as $category) {
655 // Ensure $category is an object, not an array
656 if (is_object($category) && isset($category->term_id, $category->name)) {
657 $post_options[$category->term_id] = $category->name;
658 }
659 }
660 }
661
662 return $post_options;
663 }
664
665 /**
666 * @param string parent category name
667 * @return array of parent category
668 */
669 function ultimate_store_kit_get_only_parent_cats($taxonomy = 'category') {
670
671 $parent_categories = ['none' => __('None', 'ultimate-store-kit')];
672 $args = ['taxonomy' => $taxonomy, 'parent' => 0];
673 $parent_cats = get_terms($args);
674
675 foreach ($parent_cats as $parent_cat) {
676 // Ensure $parent_cat is an object, not an array
677 if (is_object($parent_cat) && isset($parent_cat->term_id, $parent_cat->name)) {
678 $parent_categories[$parent_cat->term_id] = ucfirst($parent_cat->name);
679 }
680 }
681
682 return $parent_categories;
683 }
684
685 /**
686 * @param array all ajax posted array there
687 *
688 * @return array return all setting as array
689 */
690 function ultimate_store_kit_ajax_settings($settings) {
691
692 $required_settings = [
693 'show_date' => true,
694 'show_comment' => true,
695 'show_link' => true,
696 'show_meta' => true,
697 'show_title' => true,
698 'show_excerpt' => true,
699 'show_lightbox' => true,
700 'show_thumbnail' => true,
701 'show_category' => false,
702 'show_tags' => false,
703 ];
704
705 foreach ($settings as $key => $value) {
706 if (in_array($key, $required_settings)) {
707 $required_settings[$key] = $value;
708 }
709 }
710
711 return $required_settings;
712 }
713
714 /**
715 * @return array of all transition names
716 */
717 function ultimate_store_kit_transition_options() {
718
719 $transition_options = [
720 '' => esc_html__('None', 'ultimate-store-kit'),
721 'fade' => esc_html__('Fade', 'ultimate-store-kit'),
722 'scale-up' => esc_html__('Scale Up', 'ultimate-store-kit'),
723 'scale-down' => esc_html__('Scale Down', 'ultimate-store-kit'),
724 'slide-top' => esc_html__('Slide Top', 'ultimate-store-kit'),
725 'slide-bottom' => esc_html__('Slide Bottom', 'ultimate-store-kit'),
726 'slide-left' => esc_html__('Slide Left', 'ultimate-store-kit'),
727 'slide-right' => esc_html__('Slide Right', 'ultimate-store-kit'),
728 'slide-top-small' => esc_html__('Slide Top Small', 'ultimate-store-kit'),
729 'slide-bottom-small' => esc_html__('Slide Bottom Small', 'ultimate-store-kit'),
730 'slide-left-small' => esc_html__('Slide Left Small', 'ultimate-store-kit'),
731 'slide-right-small' => esc_html__('Slide Right Small', 'ultimate-store-kit'),
732 'slide-top-medium' => esc_html__('Slide Top Medium', 'ultimate-store-kit'),
733 'slide-bottom-medium' => esc_html__('Slide Bottom Medium', 'ultimate-store-kit'),
734 'slide-left-medium' => esc_html__('Slide Left Medium', 'ultimate-store-kit'),
735 'slide-right-medium' => esc_html__('Slide Right Medium', 'ultimate-store-kit'),
736 ];
737
738 return $transition_options;
739 }
740
741 // BDT Blend Type
742 function ultimate_store_kit_blend_options() {
743 $blend_options = [
744 'multiply' => esc_html__('Multiply', 'ultimate-store-kit'),
745 'screen' => esc_html__('Screen', 'ultimate-store-kit'),
746 'overlay' => esc_html__('Overlay', 'ultimate-store-kit'),
747 'darken' => esc_html__('Darken', 'ultimate-store-kit'),
748 'lighten' => esc_html__('Lighten', 'ultimate-store-kit'),
749 'color-dodge' => esc_html__('Color-Dodge', 'ultimate-store-kit'),
750 'color-burn' => esc_html__('Color-Burn', 'ultimate-store-kit'),
751 'hard-light' => esc_html__('Hard-Light', 'ultimate-store-kit'),
752 'soft-light' => esc_html__('Soft-Light', 'ultimate-store-kit'),
753 'difference' => esc_html__('Difference', 'ultimate-store-kit'),
754 'exclusion' => esc_html__('Exclusion', 'ultimate-store-kit'),
755 'hue' => esc_html__('Hue', 'ultimate-store-kit'),
756 'saturation' => esc_html__('Saturation', 'ultimate-store-kit'),
757 'color' => esc_html__('Color', 'ultimate-store-kit'),
758 'luminosity' => esc_html__('Luminosity', 'ultimate-store-kit'),
759 ];
760
761 return $blend_options;
762 }
763
764 // BDT Position
765 function ultimate_store_kit_position() {
766 $position_options = [
767 '' => esc_html__('Default', 'ultimate-store-kit'),
768 'top-left' => esc_html__('Top Left', 'ultimate-store-kit'),
769 'top-center' => esc_html__('Top Center', 'ultimate-store-kit'),
770 'top-right' => esc_html__('Top Right', 'ultimate-store-kit'),
771 'center' => esc_html__('Center', 'ultimate-store-kit'),
772 'center-left' => esc_html__('Center Left', 'ultimate-store-kit'),
773 'center-right' => esc_html__('Center Right', 'ultimate-store-kit'),
774 'bottom-left' => esc_html__('Bottom Left', 'ultimate-store-kit'),
775 'bottom-center' => esc_html__('Bottom Center', 'ultimate-store-kit'),
776 'bottom-right' => esc_html__('Bottom Right', 'ultimate-store-kit'),
777 ];
778
779 return $position_options;
780 }
781
782 // BDT Thumbnavs Position
783 function ultimate_store_kit_thumbnavs_position() {
784 $position_options = [
785 'top-left' => esc_html__('Top Left', 'ultimate-store-kit'),
786 'top-center' => esc_html__('Top Center', 'ultimate-store-kit'),
787 'top-right' => esc_html__('Top Right', 'ultimate-store-kit'),
788 'center-left' => esc_html__('Center Left', 'ultimate-store-kit'),
789 'center-right' => esc_html__('Center Right', 'ultimate-store-kit'),
790 'bottom-left' => esc_html__('Bottom Left', 'ultimate-store-kit'),
791 'bottom-center' => esc_html__('Bottom Center', 'ultimate-store-kit'),
792 'bottom-right' => esc_html__('Bottom Right', 'ultimate-store-kit'),
793 ];
794
795 return $position_options;
796 }
797
798 function ultimate_store_kit_navigation_position() {
799 $position_options = [
800 'top-left' => esc_html__('Top Left', 'ultimate-store-kit'),
801 'top-center' => esc_html__('Top Center', 'ultimate-store-kit'),
802 'top-right' => esc_html__('Top Right', 'ultimate-store-kit'),
803 'center' => esc_html__('Center', 'ultimate-store-kit'),
804 'bottom-left' => esc_html__('Bottom Left', 'ultimate-store-kit'),
805 'bottom-center' => esc_html__('Bottom Center', 'ultimate-store-kit'),
806 'bottom-right' => esc_html__('Bottom Right', 'ultimate-store-kit'),
807 ];
808
809 return $position_options;
810 }
811
812 function ultimate_store_kit_pagination_position() {
813 $position_options = [
814 'top-left' => esc_html__('Top Left', 'ultimate-store-kit'),
815 'top-center' => esc_html__('Top Center', 'ultimate-store-kit'),
816 'top-right' => esc_html__('Top Right', 'ultimate-store-kit'),
817 'bottom-left' => esc_html__('Bottom Left', 'ultimate-store-kit'),
818 'bottom-center' => esc_html__('Bottom Center', 'ultimate-store-kit'),
819 'bottom-right' => esc_html__('Bottom Right', 'ultimate-store-kit'),
820 ];
821
822 return $position_options;
823 }
824
825 // BDT Drop Position
826 function ultimate_store_kit_drop_position() {
827 $drop_position_options = [
828 'bottom-left' => esc_html__('Bottom Left', 'ultimate-store-kit'),
829 'bottom-center' => esc_html__('Bottom Center', 'ultimate-store-kit'),
830 'bottom-right' => esc_html__('Bottom Right', 'ultimate-store-kit'),
831 'bottom-justify' => esc_html__('Bottom Justify', 'ultimate-store-kit'),
832 'top-left' => esc_html__('Top Left', 'ultimate-store-kit'),
833 'top-center' => esc_html__('Top Center', 'ultimate-store-kit'),
834 'top-right' => esc_html__('Top Right', 'ultimate-store-kit'),
835 'top-justify' => esc_html__('Top Justify', 'ultimate-store-kit'),
836 'left-top' => esc_html__('Left Top', 'ultimate-store-kit'),
837 'left-center' => esc_html__('Left Center', 'ultimate-store-kit'),
838 'left-bottom' => esc_html__('Left Bottom', 'ultimate-store-kit'),
839 'right-top' => esc_html__('Right Top', 'ultimate-store-kit'),
840 'right-center' => esc_html__('Right Center', 'ultimate-store-kit'),
841 'right-bottom' => esc_html__('Right Bottom', 'ultimate-store-kit'),
842 ];
843
844 return $drop_position_options;
845 }
846
847 // Button Size
848 function ultimate_store_kit_button_sizes() {
849 $button_sizes = [
850 'xs' => esc_html__('Extra Small', 'ultimate-store-kit'),
851 'sm' => esc_html__('Small', 'ultimate-store-kit'),
852 'md' => esc_html__('Medium', 'ultimate-store-kit'),
853 'lg' => esc_html__('Large', 'ultimate-store-kit'),
854 'xl' => esc_html__('Extra Large', 'ultimate-store-kit'),
855 ];
856
857 return $button_sizes;
858 }
859
860 // Button Size
861 function ultimate_store_kit_heading_size() {
862 $heading_sizes = [
863 'h1' => 'H1',
864 'h2' => 'H2',
865 'h3' => 'H3',
866 'h4' => 'H4',
867 'h5' => 'H5',
868 'h6' => 'H6',
869 ];
870
871 return $heading_sizes;
872 }
873
874 // Title Tags
875 function ultimate_store_kit_title_tags() {
876 $title_tags = [
877 'h1' => 'H1',
878 'h2' => 'H2',
879 'h3' => 'H3',
880 'h4' => 'H4',
881 'h5' => 'H5',
882 'h6' => 'H6',
883 'div' => 'div',
884 'span' => 'span',
885 'p' => 'p',
886 ];
887
888 return $title_tags;
889 }
890
891 function ultimate_store_kit_mask_shapes() {
892 $path = BDTUSK_ASSETS_URL . 'images/mask/';
893 $shape_name = 'shape';
894 $extension = '.svg';
895 $list = [0 => esc_html__('Select Mask', 'ultimate-store-kit')];
896
897 for ($i = 1; $i <= 20; $i++) {
898 $list[$path . $shape_name . '-' . $i . $extension] = ucwords($shape_name . ' ' . $i);
899 }
900
901 return $list;
902 }
903
904 /**
905 * This is a svg file converter function which return a svg content
906 *
907 * @param svg file
908 *
909 * @return svg content
910 */
911 function ultimate_store_kit_svg_icon($icon) {
912
913 $icon_path = BDTUSK_ASSETS_PATH . "images/svg/{$icon}.svg";
914
915 if (! file_exists($icon_path)) {
916 return false;
917 }
918
919 ob_start();
920
921 include $icon_path;
922
923 $svg = ob_get_clean();
924
925 return $svg;
926 }
927
928 /**
929 * @param array CSV file data
930 * @param string $delimiter
931 * @param false $header
932 *
933 * @return string
934 */
935 function ultimate_store_kit_parse_csv($csv, $delimiter = ';', $header = true) {
936
937 if (! is_string($csv)) {
938 return '';
939 }
940
941 if (! function_exists('str_getcsv')) {
942 return $csv;
943 }
944
945 $html = '';
946 $rows = explode(PHP_EOL, $csv);
947 $headRow = 1;
948
949 foreach ($rows as $row) {
950
951 if ($headRow == 1 and $header) {
952 $html .= '<thead><tr>';
953 } else {
954 $html .= '<tr>';
955 }
956
957 foreach (str_getcsv($row, $delimiter) as $cell) {
958
959 $cell = trim($cell);
960
961 $html .= $header
962 ? '<th>' . $cell . '</th>'
963 : '<td>' . $cell . '</td>';
964 }
965
966 if ($headRow == 1 and $header) {
967 $html .= '</tr></thead><tbody>';
968 } else {
969 $html .= '</tr>';
970 }
971
972 $headRow++;
973 $header = false;
974 }
975
976 return '<table>' . $html . '</tbody></table>';
977 }
978
979 function ultimate_store_kit_dashboard_link($suffix = '') {
980 return add_query_arg(['page' => 'ultimate-store-kit' . $suffix], admin_url('admin.php'));
981 }
982
983 /**
984 * @param int $limit default limit is 25 word
985 * @param bool $strip_shortcode if you want to strip shortcode from excert text
986 * @param string $trail trail string default is ...
987 *
988 * @return string return custom limited excerpt text
989 */
990 function ultimate_store_kit_custom_excerpt($limit = 25, $strip_shortcode = false, $trail = '') {
991
992 $output = get_the_content();
993
994 if ($limit) {
995 $output = wp_trim_words($output, $limit, $trail);
996 }
997
998 if ($strip_shortcode) {
999 $output = strip_shortcodes($output);
1000 }
1001
1002 return wpautop($output);
1003 }
1004
1005 //wishlist
1006 function ultimate_store_kit_get_wishlist($user_id = 0) {
1007 $_wishlist_key = '_ultimate_store_kit_wishlist';
1008 $_wishlist = [];
1009
1010 if (isset($_COOKIE[$_wishlist_key])) {
1011 // The cookie is visitor-controlled, so it is sanitized before decoding and
1012 // every decoded entry is forced to a product id — nothing else is kept.
1013 $cookie_data = sanitize_text_field(wp_unslash($_COOKIE[$_wishlist_key]));
1014 $decoded_data = json_decode($cookie_data, true);
1015
1016 if (json_last_error() === JSON_ERROR_NONE && is_array($decoded_data)) {
1017 $_wishlist = array_values(array_filter(array_map('absint', array_filter($decoded_data, 'is_scalar'))));
1018 }
1019 }
1020
1021 return apply_filters('ultimate_store_kit_wishlist', array_unique($_wishlist));
1022 }
1023
1024 function ultimate_store_kit_hide_on_class($selectors) {
1025 $element_hide_on = '';
1026
1027 if (! empty($selectors)) {
1028
1029 foreach ($selectors as $element) {
1030
1031 if ($element == 'desktop') {
1032 $element_hide_on .= ' usk-hide-desktop';
1033 }
1034
1035 if ($element == 'tablet') {
1036 $element_hide_on .= ' usk-hide-tablet';
1037 }
1038
1039 if ($element == 'mobile') {
1040 $element_hide_on .= ' usk-hide-mobile';
1041 }
1042 }
1043 }
1044
1045 return $element_hide_on;
1046 }
1047
1048 function ultimate_store_kit_wc_product_quick_view_content($product_id) {
1049 // This renders on an unauthenticated endpoint, so the gate is on the product
1050 // rather than on a nonce: nothing is written, and only a product the visitor
1051 // could already open on the shop is allowed through. The previous
1052 // wp_verify_nonce() call here had its arguments reversed and its result
1053 // discarded, so it checked nothing.
1054 if (! ultimate_store_kit_is_public_product($product_id)) {
1055 return;
1056 }
1057
1058 global $woocommerce;
1059 global $post;
1060
1061 if (intval($product_id)) {
1062 $post = get_post($product_id);
1063 $next_post = get_next_post();
1064 $prev_post = get_previous_post();
1065
1066 wp('p=' . $product_id . '&post_type=product');
1067 ob_start();
1068 ?>
1069 <div class="usk-modal-page">
1070 <?php
1071 while (have_posts()) :
1072 the_post(); ?>
1073 <div class="usk-modal-product">
1074 <div id="product-<?php the_ID(); ?>" <?php post_class('product'); ?>>
1075 <div class="usk-modal-image-wrapper">
1076 <?php do_action('ultimate_store_kit_quick_florence_grid_view_product_images'); ?>
1077 <div class="usk-onsale">
1078 <?php do_action('ultimate_store_kit_wc_product_quick_view_product_sale_flash'); ?>
1079 </div>
1080 </div>
1081 <div class="usk-modal-content-box">
1082 <a href="<?php echo esc_url(get_permalink()); ?>" class="usk-product-title">
1083 <?php do_action('ultimate_store_kit_quick_view_product_title'); ?>
1084 </a>
1085 <div class="usk-rating">
1086 <?php do_action('ultimate_store_kit_quick_view_product_single_rating'); ?>
1087 </div>
1088 <div class="usk-product-price">
1089 <?php do_action('ultimate_store_kit_quick_view_product_single_price'); ?>
1090 </div>
1091 <div class="usk-product-meta">
1092 <div class="usk-sku-wrapper">
1093 <?php do_action('ultimate_store_kit_quick_view_product_single_meta'); ?>
1094 </div>
1095 </div>
1096 <div class="usk-product-desc">
1097 <?php do_action('ultimate_store_kit_quick_view_product_single_excerpt'); ?>
1098 </div>
1099
1100 <div class="usk-quick-action-wrap">
1101 <?php do_action('ultimate_store_kit_quick_view_product_single_add_to_cart'); ?>
1102 </div>
1103 </div>
1104 </div>
1105 </div>
1106 <?php endwhile; ?>
1107 </div>
1108
1109 <?php
1110 $content = ob_get_clean();
1111 echo wp_kses_post($content);
1112 ?>
1113 <script type="text/javascript">
1114 jQuery(document).ready(function($) {
1115 // Load required WooCommerce scripts
1116 var scripts = [
1117 '<?php echo esc_url(plugins_url('assets/js/prettyPhoto/jquery.prettyPhoto.init.js', WC_PLUGIN_FILE)); ?>',
1118 '<?php echo esc_url(plugins_url('assets/js/frontend/add-to-cart-variation.min.js', WC_PLUGIN_FILE)); ?>',
1119 '<?php echo esc_url(plugins_url('assets/js/frontend/add-to-cart.min.js', WC_PLUGIN_FILE)); ?>',
1120 '<?php echo esc_url(plugins_url('assets/js/frontend/single-product.min.js', WC_PLUGIN_FILE)); ?>'
1121 ];
1122
1123 // Load scripts sequentially
1124 function loadScript(index) {
1125 if (index >= scripts.length) {
1126 initializeWooCommerce();
1127 return;
1128 }
1129
1130 $.getScript(scripts[index], function() {
1131 loadScript(index + 1);
1132 });
1133 }
1134
1135 function initializeWooCommerce() {
1136 // Initialize WooCommerce add to cart functionality
1137 var wc_add_to_cart_variation_params = {
1138 "ajax_url": "<?php echo esc_url(admin_url('admin-ajax.php')); ?>",
1139 "i18n_view_cart": "<?php echo esc_js(__('View cart', 'ultimate-store-kit')); ?>",
1140 "cart_url": "<?php echo esc_url(wc_get_cart_url()); ?>",
1141 "is_cart": "<?php echo is_cart() ? '1' : '0'; ?>",
1142 "cart_redirect_after_add": "<?php echo get_option('woocommerce_cart_redirect_after_add') ? '1' : '0'; ?>"
1143 };
1144
1145 // Initialize variation forms
1146 $(document.body).trigger('wc_variation_form');
1147
1148 // Initialize add to cart buttons
1149 $(document.body).trigger('wc_fragments_refreshed');
1150 $(document.body).trigger('wc_fragments_loaded');
1151 $(document.body).trigger('added_to_cart');
1152 }
1153
1154 // Start loading scripts
1155 // loadScript(0);
1156 });
1157 </script>
1158 <?php
1159 exit();
1160 }
1161 }
1162
1163 function ultimate_store_kit_quick_view_product_images() {
1164 global $post, $product; ?>
1165 <div class="images">
1166 <?php
1167
1168 if (has_post_thumbnail()) {
1169 $attachment_count = count($product->get_gallery_image_ids());
1170 $gallery = $attachment_count > 0 ? '[product-gallery]' : '';
1171 $props = wc_get_product_attachment_props(get_post_thumbnail_id(), $post);
1172 $image = get_the_post_thumbnail($post->ID, apply_filters('single_product_large_thumbnail_size', 'shop_single'), [
1173 'title' => $props['title'],
1174 'alt' => $props['alt'],
1175 ]);
1176 echo wp_kses_post(apply_filters('woocommerce_single_product_image_html', sprintf('<a href="%s" itemprop="image" class="usk-product woocommerce-main-image zoom" title="%s" data-rel="prettyPhoto' . $gallery . '">%s</a>', $props['url'], $props['caption'], $image), $post->ID));
1177 } else {
1178 echo wp_kses_post(apply_filters('woocommerce_single_product_image_html', sprintf('<img src="%s" alt="%s" />', wc_placeholder_img_src(), esc_html__('Placeholder', 'ultimate-store-kit')), $post->ID));
1179 }
1180
1181 $attachment_ids = $product->get_gallery_image_ids();
1182
1183 if ($attachment_ids) :
1184 $loop = 0;
1185 $columns = apply_filters('woocommerce_product_thumbnails_columns', 3);
1186 ?>
1187 <div class="thumbnails columns-<?php echo esc_attr($columns); ?>">
1188 <?php
1189
1190 foreach ($attachment_ids as $attachment_id) {
1191 $classes = ['thumbnail'];
1192
1193 if ($loop === 0 || $loop % $columns === 0) {
1194 $classes[] = 'first';
1195 }
1196
1197 if (($loop + 1) % $columns === 0) {
1198 $classes[] = 'last';
1199 }
1200
1201 $image_link = wp_get_attachment_url($attachment_id);
1202
1203 if (! $image_link) {
1204 continue;
1205 }
1206
1207 $image_title = esc_attr(get_the_title($attachment_id));
1208 $image_caption = esc_attr(get_post_field('post_excerpt', $attachment_id));
1209 $image = wp_get_attachment_image($attachment_id, apply_filters('single_product_small_thumbnail_size', 'shop_thumbnail'), 0, $attr = [
1210 'title' => $image_title,
1211 'alt' => $image_title,
1212 ]);
1213 $image_class = esc_attr(implode(' ', $classes));
1214 echo wp_kses_post(apply_filters('woocommerce_single_product_image_thumbnail_html', sprintf('<a href="%s" class="%s" title="%s" >%s</a>', $image_link, $image_class, $image_caption, $image), $attachment_id, $post->ID, $image_class));
1215 $loop++;
1216 }
1217
1218 ?>
1219 </div>
1220 <?php endif; ?>
1221 </div>
1222 <?php
1223 }
1224
1225
1226 /**
1227 * License Validation
1228 */
1229 if (! function_exists('ultimate_store_kit_license_validation')) {
1230 function ultimate_store_kit_license_validation() {
1231
1232 if (function_exists('ultimate_store_kit_is_pro_activated') && false === ultimate_store_kit_is_pro_activated()) {
1233 return false;
1234 }
1235
1236 $license_key = trim(get_option('ultimate_store_kit_license_key'));
1237
1238 if (isset($license_key) && ! empty($license_key)) {
1239 return true;
1240 } else {
1241 return false;
1242 }
1243 return false;
1244 }
1245 }
1246
1247
1248
1249
1250 if (! function_exists('ultimate_store_kit_is_public_product')) {
1251 /**
1252 * Whether a product id may be read or acted on by the current request.
1253 *
1254 * wc_get_product() resolves an id regardless of post status, so any endpoint
1255 * reachable by untrusted users must run the id through here before it reads
1256 * product data or stores the id against the visitor.
1257 *
1258 * @param mixed $product_id Raw product id, typically straight off $_POST.
1259 * @return bool
1260 */
1261 function ultimate_store_kit_is_public_product($product_id) {
1262 $product_id = absint($product_id);
1263
1264 // Fail closed when WooCommerce is absent — helper.php also loads on EDD-only sites.
1265 if (! $product_id || ! function_exists('wc_get_product')) {
1266 return false;
1267 }
1268
1269 $product = wc_get_product($product_id);
1270
1271 if (! $product) {
1272 return false;
1273 }
1274
1275 // Private, draft, pending and trashed products stay invisible unless the
1276 // current user could read the post anyway (shop managers, the editor).
1277 if ('publish' !== $product->get_status() && ! current_user_can('read_post', $product_id)) {
1278 return false;
1279 }
1280
1281 if (post_password_required($product_id)) {
1282 return false;
1283 }
1284
1285 return true;
1286 }
1287 }
1288
1289 /**
1290 * Maximum number of items kept in a wishlist or compare list.
1291 *
1292 * Both lists are written from unauthenticated endpoints, so they need an upper
1293 * bound — a cookie that outgrows ~4KB is silently dropped by the browser, and an
1294 * unbounded list against a logged-in user means unbounded user meta.
1295 */
1296 if (! function_exists('ultimate_store_kit_get_list_item_limit')) {
1297 function ultimate_store_kit_get_list_item_limit() {
1298 return (int) apply_filters('ultimate_store_kit_list_item_limit', 50);
1299 }
1300 }
1301
1302 function ultimate_store_kit_get_compare_products($user_id = 0) {
1303 $_compare_products_key = '_ultimate_store_kit_compare_products';
1304 $_compare_products = [];
1305 if ($user_id != 0) {
1306 $_compare_products = get_user_meta($user_id, $_compare_products_key, true) ?: [];
1307 } elseif (isset($_COOKIE[$_compare_products_key])) {
1308 // Same treatment as the wishlist cookie: sanitize the visitor-supplied value
1309 // before decoding, then keep nothing but product ids.
1310 $cookie_value = sanitize_text_field(wp_unslash($_COOKIE[$_compare_products_key]));
1311 $_compare_products = json_decode($cookie_value, true);
1312
1313 // Check if JSON decoding failed
1314 if (! is_array($_compare_products)) {
1315 $_compare_products = [];
1316 } else {
1317 $_compare_products = array_values(array_filter(array_map('absint', array_filter($_compare_products, 'is_scalar'))));
1318 }
1319 }
1320
1321 return apply_filters('ultimate_store_kit_compare_products', array_unique($_compare_products));
1322 }
1323
1324
1325 //if (!function_exists('ultimate_store_kit_get_compare_product_slug')) {
1326 // function ultimate_store_kit_compare_product_slug() {
1327 // return 'compare-products';
1328 // }
1329 //}
1330
1331 if (! function_exists('ultimate_store_kit_get_compare_page_option')) {
1332 /**
1333 * Read the compare-products page id, migrating it off the old "bdt_"-prefixed
1334 * option key the first time it is seen.
1335 *
1336 * The option is written by Ultimate Store Kit Pro on activation and read by
1337 * both plugins, so it is stored user data: a bare rename would detach an
1338 * existing site's compare page.
1339 *
1340 * @return int Page id, or 0 when unset.
1341 */
1342 function ultimate_store_kit_get_compare_page_option() {
1343 $value = get_option('ultimate_store_kit_compare_products_page_id', null);
1344
1345 if (null === $value) {
1346 $legacy = get_option('bdt_usk_compare_products_page_id', null);
1347
1348 if (null !== $legacy) {
1349 update_option('ultimate_store_kit_compare_products_page_id', $legacy, true);
1350 delete_option('bdt_usk_compare_products_page_id');
1351 $value = $legacy;
1352 }
1353 }
1354
1355 return intval($value);
1356 }
1357 }
1358
1359 if (! function_exists('ultimate_store_kit_compare_product_page')) {
1360 function ultimate_store_kit_compare_product_page() {
1361 if ($postId = ultimate_store_kit_get_compare_page_option()) {
1362 $post = get_post($postId);
1363 if ($post && $post->post_status == 'publish') {
1364 return $post->ID;
1365 }
1366 }
1367 }
1368 }
1369
1370 if (! function_exists('ultimate_store_kit_is_compare_product_page')) {
1371 function ultimate_store_kit_is_compare_product_page() {
1372 if ($page = ultimate_store_kit_compare_product_page()) {
1373 // return is_page( $page->ID );
1374 return is_page($page);
1375 }
1376 }
1377 }
1378
1379
1380 /**
1381 * Helper function to load variation swatches scripts and styles
1382 */
1383 function ultimate_store_kit_load_variation_swatches_assets() {
1384 // Always load the grid variations script for variation support
1385 wp_register_script('usk-grid-variations', BDTUSK_ASSETS_URL . 'js/modules/grid-variations.js', ['jquery'], BDTUSK_VER, true);
1386 wp_localize_script('usk-grid-variations', 'usk_vars', array(
1387 'ajax_url' => admin_url('admin-ajax.php'),
1388 'nonce' => wp_create_nonce('usk_variations')
1389 ));
1390 }
1391 add_action('wp_enqueue_scripts', 'ultimate_store_kit_load_variation_swatches_assets', 20);
1392
1393
1394 // Start: Add to cart quantity buttons conversion
1395 if (! function_exists('ultimate_store_kit_display_quantity_minus')) {
1396 function ultimate_store_kit_display_quantity_minus() {
1397 if (! is_product()) return;
1398 echo '<button type="button" class="bdt-add-to-cart-qty-minus" ><i class="usk-icon-minus3"></i></button>';
1399 }
1400 }
1401
1402 if (! function_exists('ultimate_store_kit_display_quantity_plus')) {
1403 function ultimate_store_kit_display_quantity_plus() {
1404 if (! is_product()) return;
1405 echo '<button type="button" class="bdt-add-to-cart-qty-plus" ><i class="usk-icon-plus3"></i></button>';
1406 }
1407 }
1408
1409 if (! function_exists('ultimate_store_kit_add_cart_quantity_plus_minus')) {
1410 function ultimate_store_kit_add_cart_quantity_plus_minus() {
1411
1412 echo '<style>
1413 input[type="number"]::-webkit-outer-spin-button,
1414 input[type="number"]::-webkit-inner-spin-button {
1415 -webkit-appearance: none;
1416 margin: 0;
1417 }
1418
1419 input[type="number"] {
1420 -moz-appearance: textfield; /* Firefox */
1421 }
1422 </style>';
1423
1424 wc_enqueue_js("
1425 $(document).off('click.bdtQtyHandler'); // Remove previous handler
1426 $(document).on('click.bdtQtyHandler', 'button.bdt-add-to-cart-qty-plus, button.bdt-add-to-cart-qty-minus', function(e) {
1427 e.preventDefault();
1428 var qty = $(this).closest('form.cart').find('.qty');
1429 var val = parseFloat(qty.val()) || 0;
1430 var max = parseFloat(qty.attr('max')) || Infinity;
1431 var min = parseFloat(qty.attr('min')) || 0;
1432 var step = parseFloat(qty.attr( 'step' ));
1433
1434 if ($(this).is('.bdt-add-to-cart-qty-plus')) {
1435 qty.val(Math.min(val + step, max)).trigger('change');
1436 } else {
1437 qty.val(Math.max(val - step, min)).trigger('change');
1438 }
1439 });
1440 ");
1441 }
1442 }
1443
1444 if (! function_exists('ultimate_store_kit_setup_quantity_buttons')) {
1445 function ultimate_store_kit_setup_quantity_buttons() {
1446 if (function_exists('is_product')) {
1447 // Element Pack renders its own quantity buttons on these hooks. Remove
1448 // only those callbacks: the previous remove_all_actions() also stripped
1449 // WooCommerce core's own handlers on woocommerce_before_single_product
1450 // (notably woocommerce_output_all_notices), suppressing store notices.
1451 remove_action('woocommerce_before_quantity_input_field', 'ep_display_quantity_minus');
1452 remove_action('woocommerce_after_quantity_input_field', 'ep_display_quantity_plus');
1453 remove_action('woocommerce_before_single_product', 'ep_add_cart_quantity_plus_minus');
1454
1455 // Add our version
1456 add_action('woocommerce_before_quantity_input_field', 'ultimate_store_kit_display_quantity_minus');
1457 add_action('woocommerce_after_quantity_input_field', 'ultimate_store_kit_display_quantity_plus');
1458 add_action('woocommerce_after_single_product', 'ultimate_store_kit_add_cart_quantity_plus_minus');
1459 }
1460 }
1461 }
1462
1463 // End: Add to cart quantity buttons conversion
1464