PluginProbe
Ultimate Store Kit / 3.0.8
Ultimate Store Kit v3.0.8
3.0.8 3.0.9 3.1.0 3.1.2 3.1.3 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 All 92 releases
ultimate-store-kit / includes / helper.php

helper.php in Ultimate Store Kit 3.0.8, at includes/helper.php

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