PluginProbe
King Addons for Elementor – 80+ Elementor Widgets, 4 000+ Elementor Templates, WooCommerce, Mega Menu, Popup Builder / 51.1.49
King Addons for Elementor – 80+ Elementor Widgets, 4 000+ Elementor Templates, WooCommerce, Mega Menu, Popup Builder v51.1.49
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.49, at includes/widgets/Single_Product/Single_Product.php

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