PluginProbe
King Addons for Elementor – 80+ Elementor Widgets, 4 000+ Elementor Templates, WooCommerce, Mega Menu, Popup Builder / 51.1.83
King Addons for Elementor – 80+ Elementor Widgets, 4 000+ Elementor Templates, WooCommerce, Mega Menu, Popup Builder v51.1.83
51.1.83 51.1.82 51.1.81 51.1.79 51.1.78 51.1.77 51.1.76 51.1.74 51.1.75 51.1.65 51.1.64 51.1.63 trunk 51.1.14 51.1.2 51.1.35 51.1.36 51.1.37 51.1.38 51.1.39 51.1.44 51.1.45 51.1.46 51.1.47 51.1.49 All 37 releases
king-addons / includes / widgets / Single_Product / Single_Product.php

Single_Product.php in King Addons for Elementor – 80+ Elementor Widgets, 4 000+ Elementor Templates, WooCommerce, Mega Menu, Popup Builder 51.1.83, at includes/widgets/Single_Product/Single_Product.php

959 lines 29.4 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Single Product Widget (Free).
4 *
5 * @package King_Addons
6 */
7
8 namespace King_Addons;
9
10 use Elementor\Controls_Manager;
11 use Elementor\Group_Control_Border;
12 use Elementor\Group_Control_Box_Shadow;
13 use Elementor\Group_Control_Typography;
14 use Elementor\Widget_Base;
15
16 if (!defined('ABSPATH')) {
17 exit;
18 }
19
20 /**
21 * Renders the Single Product widget.
22 */
23 class Single_Product extends Widget_Base
24 {
25 /**
26 * Widget slug.
27 *
28 * @return string
29 */
30 public function get_name(): string
31 {
32 return 'king-addons-single-product';
33 }
34
35 /**
36 * Widget title.
37 *
38 * @return string
39 */
40 public function get_title(): string
41 {
42 return esc_html__('Single Product', 'king-addons');
43 }
44
45 /**
46 * Widget icon.
47 *
48 * @return string
49 */
50 public function get_icon(): string
51 {
52 return 'king-addons-icon king-addons-single-product';
53 }
54
55 /**
56 * Script dependencies.
57 *
58 * @return array<int, string>
59 */
60 public function get_script_depends(): array
61 {
62 $deps = [
63 KING_ADDONS_ASSETS_UNIQUE_KEY . '-single-product-script',
64 ];
65
66 if (class_exists('\WooCommerce') && function_exists('wp_script_is') && wp_script_is('wc-add-to-cart', 'registered')) {
67 $deps[] = 'wc-add-to-cart';
68 }
69
70 return $deps;
71 }
72
73 /**
74 * Style dependencies.
75 *
76 * @return array<int, string>
77 */
78 public function get_style_depends(): array
79 {
80 return [
81 KING_ADDONS_ASSETS_UNIQUE_KEY . '-single-product-style',
82 ];
83 }
84
85 /**
86 * Widget categories.
87 *
88 * @return array<int, string>
89 */
90 public function get_categories(): array
91 {
92 return ['king-addons-woo'];
93 }
94
95 /**
96 * Widget keywords.
97 *
98 * @return array<int, string>
99 */
100 public function get_keywords(): array
101 {
102 return ['woocommerce', 'product', 'single', 'cart', 'shop'];
103 }
104
105 public function get_custom_help_url()
106 {
107 return 'mailto:bug@kingaddons.com?subject=Bug Report - King Addons&body=Please describe the issue';
108 }
109
110 /**
111 * Register controls.
112 *
113 * @return void
114 */
115 public function register_controls(): void
116 {
117 $this->register_content_controls();
118 $this->register_interaction_controls();
119 $this->register_style_layout_controls();
120 $this->register_style_text_controls();
121 $this->register_style_button_controls();
122 $this->register_style_view_cart_controls();
123 $this->register_pro_notice_controls();
124 }
125
126 /**
127 * Interaction controls.
128 *
129 * @return void
130 */
131 protected function register_interaction_controls(): void
132 {
133 $this->start_controls_section(
134 'kng_interaction_section',
135 [
136 'label' => KING_ADDONS_ELEMENTOR_ICON . esc_html__('Animations', 'king-addons'),
137 'tab' => Controls_Manager::TAB_CONTENT,
138 ]
139 );
140
141 $this->add_control(
142 'kng_hover_animation',
143 [
144 'label' => esc_html__('Hover Animation', 'king-addons'),
145 'type' => Controls_Manager::SELECT,
146 'default' => 'none',
147 'options' => [
148 'none' => esc_html__('None', 'king-addons'),
149 'hover-lift' => esc_html__('Lift', 'king-addons'),
150 'hover-zoom' => esc_html__('Image Zoom', 'king-addons'),
151 'hover-tilt' => esc_html__('Tilt', 'king-addons'),
152 'hover-float' => esc_html__('Float', 'king-addons'),
153 'hover-scale-fade' => esc_html__('Scale & Fade', 'king-addons'),
154 ],
155 ]
156 );
157
158 $this->end_controls_section();
159 }
160
161 /**
162 * Render widget output.
163 *
164 * @return void
165 */
166 public function render(): void
167 {
168 if (!class_exists('\WooCommerce')) {
169 return;
170 }
171
172 $settings = $this->get_settings_for_display();
173 $product_id = $this->resolve_product_id($settings);
174
175 if (!$product_id) {
176 return;
177 }
178
179 $product = wc_get_product($product_id);
180 if (!$product) {
181 return;
182 }
183
184 $this->render_output($settings, $product);
185 }
186
187 /**
188 * Content controls.
189 *
190 * @return void
191 */
192 protected function register_content_controls(): void
193 {
194 $this->start_controls_section(
195 'kng_content_section',
196 [
197 'label' => KING_ADDONS_ELEMENTOR_ICON . esc_html__('Product', 'king-addons'),
198 'tab' => Controls_Manager::TAB_CONTENT,
199 ]
200 );
201
202 $this->add_control(
203 'kng_use_current_product',
204 [
205 'label' => esc_html__('Use Current Product (Single)', 'king-addons'),
206 'type' => Controls_Manager::SWITCHER,
207 'return_value' => 'yes',
208 'default' => 'yes',
209 ]
210 );
211
212 $this->add_control(
213 'kng_product_id',
214 [
215 'label' => esc_html__('Product ID (fallback)', 'king-addons'),
216 'type' => Controls_Manager::NUMBER,
217 'min' => 1,
218 'step' => 1,
219 'condition' => [
220 'kng_use_current_product!' => 'yes',
221 ],
222 ]
223 );
224
225 $this->add_control(
226 'kng_show_image',
227 [
228 'label' => esc_html__('Show Image', 'king-addons'),
229 'type' => Controls_Manager::SWITCHER,
230 'return_value' => 'yes',
231 'default' => 'yes',
232 ]
233 );
234
235 $this->add_control(
236 'kng_show_price',
237 [
238 'label' => esc_html__('Show Price', 'king-addons'),
239 'type' => Controls_Manager::SWITCHER,
240 'return_value' => 'yes',
241 'default' => 'yes',
242 ]
243 );
244
245 $this->add_control(
246 'kng_show_excerpt',
247 [
248 'label' => esc_html__('Show Short Description', 'king-addons'),
249 'type' => Controls_Manager::SWITCHER,
250 'return_value' => 'yes',
251 'default' => 'yes',
252 ]
253 );
254
255 $this->add_control(
256 'kng_show_rating',
257 [
258 'label' => esc_html__('Show Rating', 'king-addons'),
259 'type' => Controls_Manager::SWITCHER,
260 'return_value' => 'yes',
261 'default' => 'yes',
262 ]
263 );
264
265 $this->add_control(
266 'kng_show_add_to_cart',
267 [
268 'label' => esc_html__('Show Add to Cart', 'king-addons'),
269 'type' => Controls_Manager::SWITCHER,
270 'return_value' => 'yes',
271 'default' => 'yes',
272 ]
273 );
274
275 $this->end_controls_section();
276 }
277
278 /**
279 * Layout styles.
280 *
281 * @return void
282 */
283 protected function register_style_layout_controls(): void
284 {
285 $this->start_controls_section(
286 'kng_style_layout_section',
287 [
288 'label' => KING_ADDONS_ELEMENTOR_ICON . esc_html__('Layout', 'king-addons'),
289 'tab' => Controls_Manager::TAB_STYLE,
290 ]
291 );
292
293 $this->add_control(
294 'kng_alignment',
295 [
296 'label' => esc_html__('Alignment', 'king-addons'),
297 'type' => Controls_Manager::CHOOSE,
298 'options' => [
299 'flex-start' => [
300 'title' => esc_html__('Left', 'king-addons'),
301 'icon' => 'eicon-h-align-left',
302 ],
303 'center' => [
304 'title' => esc_html__('Center', 'king-addons'),
305 'icon' => 'eicon-h-align-center',
306 ],
307 'flex-end' => [
308 'title' => esc_html__('Right', 'king-addons'),
309 'icon' => 'eicon-h-align-right',
310 ],
311 ],
312 'default' => 'flex-start',
313 'selectors' => [
314 '{{WRAPPER}} .king-addons-single-product' => 'align-items: {{VALUE}};',
315 ],
316 ]
317 );
318
319 $this->add_responsive_control(
320 'kng_gap',
321 [
322 'label' => esc_html__('Gap', 'king-addons'),
323 'type' => Controls_Manager::SLIDER,
324 'size_units' => ['px'],
325 'range' => [
326 'px' => ['min' => 0, 'max' => 60],
327 ],
328 'default' => [
329 'size' => 20,
330 'unit' => 'px',
331 ],
332 'selectors' => [
333 '{{WRAPPER}} .king-addons-single-product' => 'gap: {{SIZE}}{{UNIT}};',
334 ],
335 ]
336 );
337
338 $this->add_group_control(
339 Group_Control_Box_Shadow::get_type(),
340 [
341 'name' => 'kng_card_shadow',
342 'selector' => '{{WRAPPER}} .king-addons-single-product',
343 ]
344 );
345
346 $this->add_control(
347 'kng_disable_card_shadow',
348 [
349 'label' => esc_html__('Disable Box Shadow', 'king-addons'),
350 'type' => Controls_Manager::SWITCHER,
351 'return_value' => 'yes',
352 'default' => '',
353 'selectors' => [
354 '{{WRAPPER}} .king-addons-single-product' => 'box-shadow: none !important;',
355 ],
356 ]
357 );
358
359 $this->add_control(
360 'kng_disable_card_shadow_hover',
361 [
362 'label' => esc_html__('Disable Box Shadow on Hover', 'king-addons'),
363 'type' => Controls_Manager::SWITCHER,
364 'return_value' => 'yes',
365 'default' => '',
366 'selectors' => [
367 '{{WRAPPER}} .king-addons-single-product:hover' => 'box-shadow: none !important;',
368 ],
369 ]
370 );
371
372 $this->add_control(
373 'kng_card_radius',
374 [
375 'label' => esc_html__('Card Border Radius', 'king-addons'),
376 'type' => Controls_Manager::SLIDER,
377 'size_units' => ['px', '%'],
378 'range' => [
379 'px' => ['min' => 0, 'max' => 50],
380 '%' => ['min' => 0, 'max' => 100],
381 ],
382 'selectors' => [
383 '{{WRAPPER}} .king-addons-single-product' => 'border-radius: {{SIZE}}{{UNIT}};',
384 ],
385 ]
386 );
387
388 $this->add_control(
389 'kng_card_border',
390 [
391 'label' => esc_html__('Card Border', 'king-addons'),
392 'type' => Controls_Manager::SWITCHER,
393 'return_value' => 'yes',
394 'default' => '',
395 'selectors' => [
396 '{{WRAPPER}} .king-addons-single-product' => 'border: 1px solid #e5e7eb;',
397 ],
398 ]
399 );
400
401 $this->end_controls_section();
402 }
403
404 /**
405 * Text styles.
406 *
407 * @return void
408 */
409 protected function register_style_text_controls(): void
410 {
411 $this->start_controls_section(
412 'kng_style_text_section',
413 [
414 'label' => KING_ADDONS_ELEMENTOR_ICON . esc_html__('Text', 'king-addons'),
415 'tab' => Controls_Manager::TAB_STYLE,
416 ]
417 );
418
419 $this->add_group_control(
420 Group_Control_Typography::get_type(),
421 [
422 'name' => 'kng_title_typography',
423 'selector' => '{{WRAPPER}} .king-addons-single-product__title',
424 ]
425 );
426
427 $this->add_control(
428 'kng_title_color',
429 [
430 'label' => esc_html__('Title Color', 'king-addons'),
431 'type' => Controls_Manager::COLOR,
432 'selectors' => [
433 '{{WRAPPER}} .king-addons-single-product__title' => 'color: {{VALUE}};',
434 ],
435 ]
436 );
437
438 $this->add_group_control(
439 Group_Control_Typography::get_type(),
440 [
441 'name' => 'kng_price_typography',
442 'selector' => '{{WRAPPER}} .king-addons-single-product__price',
443 ]
444 );
445
446 $this->add_control(
447 'kng_price_color',
448 [
449 'label' => esc_html__('Price Color', 'king-addons'),
450 'type' => Controls_Manager::COLOR,
451 'selectors' => [
452 '{{WRAPPER}} .king-addons-single-product__price' => 'color: {{VALUE}};',
453 ],
454 ]
455 );
456
457 $this->add_group_control(
458 Group_Control_Typography::get_type(),
459 [
460 'name' => 'kng_excerpt_typography',
461 'selector' => '{{WRAPPER}} .king-addons-single-product__excerpt',
462 ]
463 );
464
465 $this->add_control(
466 'kng_excerpt_color',
467 [
468 'label' => esc_html__('Excerpt Color', 'king-addons'),
469 'type' => Controls_Manager::COLOR,
470 'selectors' => [
471 '{{WRAPPER}} .king-addons-single-product__excerpt' => 'color: {{VALUE}};',
472 ],
473 ]
474 );
475
476 $this->end_controls_section();
477 }
478
479 /**
480 * Button styles.
481 *
482 * @return void
483 */
484 protected function register_style_button_controls(): void
485 {
486 $this->start_controls_section(
487 'kng_style_button_section',
488 [
489 'label' => KING_ADDONS_ELEMENTOR_ICON . esc_html__('Add to Cart', 'king-addons'),
490 'tab' => Controls_Manager::TAB_STYLE,
491 ]
492 );
493
494 $this->add_group_control(
495 Group_Control_Typography::get_type(),
496 [
497 'name' => 'kng_button_typography',
498 'selector' => '{{WRAPPER}} .king-addons-single-product__cta .button',
499 ]
500 );
501
502 $this->add_responsive_control(
503 'kng_button_padding',
504 [
505 'label' => esc_html__('Padding', 'king-addons'),
506 'type' => Controls_Manager::DIMENSIONS,
507 'size_units' => ['px', 'em'],
508 'selectors' => [
509 '{{WRAPPER}} .king-addons-single-product__cta .button' => 'padding: {{TOP}}{{UNIT}} {{RIGHT}}{{UNIT}} {{BOTTOM}}{{UNIT}} {{LEFT}}{{UNIT}};',
510 ],
511 ]
512 );
513
514 $this->add_responsive_control(
515 'kng_button_indicator_size',
516 [
517 'label' => esc_html__('Indicator Size', 'king-addons'),
518 'type' => Controls_Manager::SLIDER,
519 'size_units' => ['px'],
520 'range' => [
521 'px' => ['min' => 8, 'max' => 40],
522 ],
523 'selectors' => [
524 '{{WRAPPER}} .king-addons-single-product__cta .king-addons-single-product__button' => '--king-addons-atc-indicator-size: {{SIZE}}{{UNIT}};',
525 ],
526 ]
527 );
528
529 $this->start_controls_tabs('kng_button_style_tabs');
530
531 $this->start_controls_tab(
532 'kng_button_style_tab_normal',
533 [
534 'label' => esc_html__('Normal', 'king-addons'),
535 ]
536 );
537
538 $this->add_control(
539 'kng_button_color',
540 [
541 'label' => esc_html__('Text Color', 'king-addons'),
542 'type' => Controls_Manager::COLOR,
543 'selectors' => [
544 '{{WRAPPER}} .king-addons-single-product__cta .button' => 'color: {{VALUE}};',
545 ],
546 ]
547 );
548
549 $this->add_control(
550 'kng_button_bg',
551 [
552 'label' => esc_html__('Background', 'king-addons'),
553 'type' => Controls_Manager::COLOR,
554 'selectors' => [
555 '{{WRAPPER}} .king-addons-single-product__cta .button' => 'background-color: {{VALUE}};',
556 ],
557 ]
558 );
559
560 $this->add_group_control(
561 Group_Control_Border::get_type(),
562 [
563 'name' => 'kng_button_border',
564 'selector' => '{{WRAPPER}} .king-addons-single-product__cta .button',
565 ]
566 );
567
568 $this->add_group_control(
569 Group_Control_Box_Shadow::get_type(),
570 [
571 'name' => 'kng_button_shadow',
572 'selector' => '{{WRAPPER}} .king-addons-single-product__cta .button',
573 ]
574 );
575
576 $this->end_controls_tab();
577
578 $this->start_controls_tab(
579 'kng_button_style_tab_hover',
580 [
581 'label' => esc_html__('Hover', 'king-addons'),
582 ]
583 );
584
585 $this->add_control(
586 'kng_button_color_hover',
587 [
588 'label' => esc_html__('Hover Text Color', 'king-addons'),
589 'type' => Controls_Manager::COLOR,
590 'selectors' => [
591 '{{WRAPPER}} .king-addons-single-product__cta .button:hover' => 'color: {{VALUE}};',
592 ],
593 ]
594 );
595
596 $this->add_control(
597 'kng_button_bg_hover',
598 [
599 'label' => esc_html__('Hover Background', 'king-addons'),
600 'type' => Controls_Manager::COLOR,
601 'selectors' => [
602 '{{WRAPPER}} .king-addons-single-product__cta .button:hover' => 'background-color: {{VALUE}};',
603 ],
604 ]
605 );
606
607 $this->add_group_control(
608 Group_Control_Border::get_type(),
609 [
610 'name' => 'kng_button_border_hover',
611 'selector' => '{{WRAPPER}} .king-addons-single-product__cta .button:hover',
612 ]
613 );
614
615 $this->add_group_control(
616 Group_Control_Box_Shadow::get_type(),
617 [
618 'name' => 'kng_button_shadow_hover',
619 'selector' => '{{WRAPPER}} .king-addons-single-product__cta .button:hover',
620 ]
621 );
622
623 $this->end_controls_tab();
624
625 $this->end_controls_tabs();
626
627 $this->add_control(
628 'kng_button_radius',
629 [
630 'label' => esc_html__('Border Radius', 'king-addons'),
631 'type' => Controls_Manager::SLIDER,
632 'size_units' => ['px', '%'],
633 'range' => [
634 'px' => ['min' => 0, 'max' => 40],
635 '%' => ['min' => 0, 'max' => 100],
636 ],
637 'selectors' => [
638 '{{WRAPPER}} .king-addons-single-product__cta .button' => 'border-radius: {{SIZE}}{{UNIT}};',
639 ],
640 ]
641 );
642
643 $this->end_controls_section();
644 }
645
646 /**
647 * View cart link styles (WooCommerce injects `.added_to_cart` link after AJAX add to cart).
648 *
649 * @return void
650 */
651 protected function register_style_view_cart_controls(): void
652 {
653 $this->start_controls_section(
654 'kng_style_view_cart_section',
655 [
656 'label' => KING_ADDONS_ELEMENTOR_ICON . esc_html__('View Cart Link', 'king-addons'),
657 'tab' => Controls_Manager::TAB_STYLE,
658 ]
659 );
660
661 $this->add_responsive_control(
662 'kng_view_cart_gap',
663 [
664 'label' => esc_html__('Spacing From Button', 'king-addons'),
665 'type' => Controls_Manager::SLIDER,
666 'size_units' => ['px'],
667 'range' => [
668 'px' => ['min' => 0, 'max' => 60],
669 ],
670 'selectors' => [
671 '{{WRAPPER}} .king-addons-single-product__cta .king-addons-single-product__button + .added_to_cart' => 'margin-left: {{SIZE}}{{UNIT}};',
672 ],
673 ]
674 );
675
676 $this->add_group_control(
677 Group_Control_Typography::get_type(),
678 [
679 'name' => 'kng_view_cart_typography',
680 'selector' => '{{WRAPPER}} .king-addons-single-product__cta .added_to_cart',
681 ]
682 );
683
684 $this->add_responsive_control(
685 'kng_view_cart_padding',
686 [
687 'label' => esc_html__('Padding', 'king-addons'),
688 'type' => Controls_Manager::DIMENSIONS,
689 'size_units' => ['px', 'em'],
690 'selectors' => [
691 '{{WRAPPER}} .king-addons-single-product__cta .added_to_cart' => 'padding: {{TOP}}{{UNIT}} {{RIGHT}}{{UNIT}} {{BOTTOM}}{{UNIT}} {{LEFT}}{{UNIT}};',
692 ],
693 ]
694 );
695
696 $this->start_controls_tabs('kng_view_cart_style_tabs');
697
698 $this->start_controls_tab(
699 'kng_view_cart_style_tab_normal',
700 [
701 'label' => esc_html__('Normal', 'king-addons'),
702 ]
703 );
704
705 $this->add_control(
706 'kng_view_cart_color',
707 [
708 'label' => esc_html__('Text Color', 'king-addons'),
709 'type' => Controls_Manager::COLOR,
710 'selectors' => [
711 '{{WRAPPER}} .king-addons-single-product__cta .added_to_cart' => 'color: {{VALUE}};',
712 ],
713 ]
714 );
715
716 $this->add_control(
717 'kng_view_cart_bg',
718 [
719 'label' => esc_html__('Background', 'king-addons'),
720 'type' => Controls_Manager::COLOR,
721 'selectors' => [
722 '{{WRAPPER}} .king-addons-single-product__cta .added_to_cart' => 'background-color: {{VALUE}};',
723 ],
724 ]
725 );
726
727 $this->add_group_control(
728 Group_Control_Border::get_type(),
729 [
730 'name' => 'kng_view_cart_border',
731 'selector' => '{{WRAPPER}} .king-addons-single-product__cta .added_to_cart',
732 ]
733 );
734
735 $this->add_group_control(
736 Group_Control_Box_Shadow::get_type(),
737 [
738 'name' => 'kng_view_cart_shadow',
739 'selector' => '{{WRAPPER}} .king-addons-single-product__cta .added_to_cart',
740 ]
741 );
742
743 $this->end_controls_tab();
744
745 $this->start_controls_tab(
746 'kng_view_cart_style_tab_hover',
747 [
748 'label' => esc_html__('Hover', 'king-addons'),
749 ]
750 );
751
752 $this->add_control(
753 'kng_view_cart_color_hover',
754 [
755 'label' => esc_html__('Hover Text Color', 'king-addons'),
756 'type' => Controls_Manager::COLOR,
757 'selectors' => [
758 '{{WRAPPER}} .king-addons-single-product__cta .added_to_cart:hover' => 'color: {{VALUE}};',
759 ],
760 ]
761 );
762
763 $this->add_control(
764 'kng_view_cart_bg_hover',
765 [
766 'label' => esc_html__('Hover Background', 'king-addons'),
767 'type' => Controls_Manager::COLOR,
768 'selectors' => [
769 '{{WRAPPER}} .king-addons-single-product__cta .added_to_cart:hover' => 'background-color: {{VALUE}};',
770 ],
771 ]
772 );
773
774 $this->add_group_control(
775 Group_Control_Border::get_type(),
776 [
777 'name' => 'kng_view_cart_border_hover',
778 'selector' => '{{WRAPPER}} .king-addons-single-product__cta .added_to_cart:hover',
779 ]
780 );
781
782 $this->add_group_control(
783 Group_Control_Box_Shadow::get_type(),
784 [
785 'name' => 'kng_view_cart_shadow_hover',
786 'selector' => '{{WRAPPER}} .king-addons-single-product__cta .added_to_cart:hover',
787 ]
788 );
789
790 $this->end_controls_tab();
791
792 $this->end_controls_tabs();
793
794 $this->add_control(
795 'kng_view_cart_radius',
796 [
797 'label' => esc_html__('Border Radius', 'king-addons'),
798 'type' => Controls_Manager::SLIDER,
799 'size_units' => ['px', '%'],
800 'range' => [
801 'px' => ['min' => 0, 'max' => 40],
802 '%' => ['min' => 0, 'max' => 100],
803 ],
804 'selectors' => [
805 '{{WRAPPER}} .king-addons-single-product__cta .added_to_cart' => 'border-radius: {{SIZE}}{{UNIT}};',
806 ],
807 ]
808 );
809
810 $this->end_controls_section();
811 }
812
813 /**
814 * Resolve product ID.
815 *
816 * @param array<string, mixed> $settings Settings.
817 *
818 * @return int
819 */
820 protected function resolve_product_id(array $settings): int
821 {
822 $use_current = ($settings['kng_use_current_product'] ?? 'yes') === 'yes';
823 if ($use_current && is_singular('product')) {
824 $product_id = get_the_ID();
825 if ($product_id) {
826 return (int) $product_id;
827 }
828 }
829
830 if (!empty($settings['kng_product_id'])) {
831 return (int) $settings['kng_product_id'];
832 }
833
834 return 0;
835 }
836
837 /**
838 * Render output.
839 *
840 * @param array<string, mixed> $settings Settings.
841 * @param \WC_Product $product Product object.
842 *
843 * @return void
844 */
845 protected function render_output(array $settings, \WC_Product $product): void
846 {
847 $card_classes = ['king-addons-single-product'];
848 $animation = $settings['kng_hover_animation'] ?? 'none';
849 if ($animation !== 'none') {
850 $card_classes[] = 'is-anim-' . sanitize_html_class((string) $animation);
851 }
852
853 $show_image = ($settings['kng_show_image'] ?? 'yes') === 'yes';
854 $show_price = ($settings['kng_show_price'] ?? 'yes') === 'yes';
855 $show_excerpt = ($settings['kng_show_excerpt'] ?? 'yes') === 'yes';
856 $show_rating = ($settings['kng_show_rating'] ?? 'yes') === 'yes';
857 $show_button = ($settings['kng_show_add_to_cart'] ?? 'yes') === 'yes';
858
859 ?>
860 <div class="<?php echo esc_attr(implode(' ', $card_classes)); ?>">
861 <?php if ($show_image) : ?>
862 <div class="king-addons-single-product__media">
863 <?php echo $product->get_image('medium'); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?>
864 </div>
865 <?php endif; ?>
866
867 <div class="king-addons-single-product__content">
868 <h3 class="king-addons-single-product__title"><?php echo esc_html($product->get_title()); ?></h3>
869
870 <?php if ($show_rating && wc_review_ratings_enabled()) : ?>
871 <div class="king-addons-single-product__rating">
872 <?php echo wc_get_rating_html($product->get_average_rating()); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?>
873 </div>
874 <?php endif; ?>
875
876 <?php if ($show_price) : ?>
877 <div class="king-addons-single-product__price">
878 <?php echo $product->get_price_html(); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?>
879 </div>
880 <?php endif; ?>
881
882 <?php if ($show_excerpt) : ?>
883 <div class="king-addons-single-product__excerpt">
884 <?php echo wp_kses_post(wpautop($product->get_short_description())); ?>
885 </div>
886 <?php endif; ?>
887
888 <?php if ($show_button) : ?>
889 <div class="king-addons-single-product__cta">
890 <?php echo $this->render_add_to_cart_button($product); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?>
891 </div>
892 <?php endif; ?>
893 </div>
894 </div>
895 <?php
896 }
897
898 /**
899 * Render a controlled Add to Cart button without relying on Woo shortcode.
900 *
901 * @param \WC_Product $product Product instance.
902 *
903 * @return string
904 */
905 protected function render_add_to_cart_button(\WC_Product $product): string
906 {
907 if (!$product->is_purchasable() || !$product->is_in_stock()) {
908 return '<span class="king-addons-single-product__button is-disabled">' . esc_html__('Unavailable', 'king-addons') . '</span>';
909 }
910
911 $classes = [
912 'king-addons-single-product__button',
913 'button',
914 'product_type_' . $product->get_type(),
915 ];
916
917 if ($product->supports('ajax_add_to_cart')) {
918 $classes[] = 'ajax_add_to_cart';
919 $classes[] = 'add_to_cart_button';
920 }
921
922 $attributes = [
923 'href' => $product->add_to_cart_url(),
924 'data-quantity' => 1,
925 'data-product_id' => $product->get_id(),
926 'data-product_sku' => $product->get_sku(),
927 'rel' => 'nofollow',
928 'class' => implode(' ', array_filter($classes)),
929 'aria-label' => wp_strip_all_tags($product->add_to_cart_description()),
930 ];
931
932 return '<a ' . wc_implode_html_attributes($attributes) . '><span class="king-addons-single-product__button-label">' . esc_html($product->add_to_cart_text()) . '</span></a>';
933 }
934
935 /**
936 * Pro notice.
937 *
938 * @return void
939 */
940 public function register_pro_notice_controls(): void
941 {
942 if (!king_addons_freemius()->can_use_premium_code__premium_only()) {
943 Core::renderProFeaturesSection($this, '', Controls_Manager::RAW_HTML, 'single-product', [
944 'Image badges and sale labels',
945 'Stock bar and countdown',
946 'Quantity selector and icons',
947 'Gallery thumbs and layouts',
948 ]);
949 }
950 }
951 }
952
953
954
955
956
957
958
959