PluginProbe
ShopBuilder – WooCommerce Builder For Elementor / 2.6.4
ShopBuilder – WooCommerce Builder For Elementor v2.6.4
3.4.2 3.4.1 3.4.0 2.0.1 2.0.2 2.0.3 2.1.0 2.1.1 2.1.10 2.1.11 2.1.12 2.1.13 2.1.14 2.1.15 2.1.2 2.1.3 2.1.4 2.1.5 2.1.6 2.1.7 2.1.8 2.1.9 2.2.0 2.2.1 2.2.2 All 63 releases
shopbuilder / app / Abstracts / ElementorWidgetBase.php

ElementorWidgetBase.php in ShopBuilder – WooCommerce Builder For Elementor 2.6.4, at app/Abstracts/ElementorWidgetBase.php

803 lines 19.2 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Main ElementorWidgetBase class.
4 *
5 * @package RadiusTheme\SB
6 */
7
8 namespace RadiusTheme\SB\Abstracts;
9
10 use Elementor\Group_Control_Css_Filter;
11 use Elementor\Plugin;
12 use Elementor\Repeater;
13 use Elementor\Widget_Base;
14 use Elementor\Controls_Manager;
15 use Elementor\Group_Control_Border;
16 use RadiusTheme\SB\Controllers\Hooks\FilterHooks;
17 use RadiusTheme\SB\Helpers\BuilderFns;
18 use Elementor\Group_Control_Typography;
19 use Elementor\Group_Control_Background;
20 use Elementor\Group_Control_Box_Shadow;
21 use Elementor\Group_Control_Text_Shadow;
22 use Elementor\Group_Control_Text_Stroke;
23 use RadiusTheme\SB\Elementor\Helper\ControlSelectors;
24
25
26 // Do not allow directly accessing this file.
27 if ( ! defined( 'ABSPATH' ) ) {
28 exit( 'This script cannot be accessed directly.' );
29 }
30
31 /**
32 * Abstract ElementorWidgetBase Class
33 *
34 * Implemented by classes for elementor addons development.
35 *
36 * @version 1.0.0
37 * @package RadiusTheme\SB
38 */
39 abstract class ElementorWidgetBase extends Widget_Base {
40
41 /**
42 * Widget Title.
43 *
44 * @var String
45 */
46 public $rtsb_name;
47
48 /**
49 * Widget name.
50 *
51 * @var String
52 */
53 public $rtsb_base;
54
55 /**
56 * Widget categories.
57 *
58 * @var String
59 */
60 public $rtsb_category;
61
62 /**
63 * Widget icon class
64 *
65 * @var String
66 */
67 public $rtsb_icon;
68
69 /**
70 * PRO Label HTML.
71 *
72 * @var String
73 */
74 public $pro_label = '';
75
76 /**
77 * PRO content tab.
78 *
79 * @var String
80 */
81 public $pro_tab;
82
83 /**
84 * Widget prefix.
85 *
86 * @var String
87 */
88 public $el_prefix;
89
90 /**
91 * Widget controls.
92 *
93 * @var array
94 */
95 public $selectors = [];
96
97 /**
98 * Class Constructor
99 *
100 * @param array $data default data.
101 * @param array $args default arg.
102 */
103 public function __construct( $data = [], $args = null ) {
104 $this->apply_hooks_before_render();
105 parent::__construct( $data, $args );
106 $this->rtsb_category = 'rtsb-shopbuilder';
107 $this->rtsb_icon = 'rtsb-el-custom rtsb-element icon-' . $this->rtsb_base;
108 $this->el_prefix = 'rtsb_el_';
109 $this->pro_label = sprintf(
110 '<span class="rtsb-pro-label">%s</span>',
111 esc_html__( 'Pro', 'shopbuilder' )
112 );
113 $this->selectors = ControlSelectors::get_widget_selectors( $this );
114 }
115
116
117 /**
118 * Elementor controls marge all settings
119 *
120 * @return array
121 */
122 abstract public function widget_fields();
123
124 /**
125 * Get widget name.
126 *
127 * Retrieve widget name.
128 *
129 * @access public
130 *
131 * @return string Widget name.
132 */
133 public function get_name() {
134 return $this->rtsb_base;
135 }
136
137 /**
138 * Set Widget Keyword.
139 *
140 * @return array
141 */
142 public function get_keywords() {
143 return [ 'woocommerce', 'shopbuilder' ];
144 }
145
146 /**
147 * Get widget title.
148 *
149 * Retrieve widget title.
150 *
151 * @access public
152 *
153 * @return string Widget title.
154 */
155 public function get_title() {
156 return $this->rtsb_name;
157 }
158
159 /**
160 * Get widget icon.
161 *
162 * Retrieve widget icon.
163 *
164 * @return string Widget icon.
165 * @since 1.0.0
166 * @access public
167 */
168 public function get_icon() {
169 return $this->rtsb_icon;
170 }
171
172 /**
173 * Get widget categories.
174 *
175 * Retrieve the list of categories widget belongs to.
176 *
177 * @return array Widget categories.
178 * @since 1.0.0
179 * @access public
180 */
181 public function get_categories() {
182 return [ $this->rtsb_category ];
183 }
184
185 /**
186 * Elementor Promotional section controls.
187 *
188 * @return array
189 */
190 public function promo_content() {
191 if ( rtsb()->has_pro() || $this->widget_exceptions() ) {
192 return [];
193 }
194
195 $promo_fields = [];
196
197 $promo_fields['pro_alert'] = [
198 'mode' => 'section_start',
199 'label' => sprintf(
200 '<span style="color: #f54">%s</span>',
201 esc_html__( 'Go Premium for More Features', 'shopbuilder' )
202 ),
203 ];
204
205 if ( $this->pro_tab ) {
206 $promo_fields['pro_alert']['tab'] = $this->pro_tab;
207 }
208
209 $promo_fields['get_pro'] = [
210 'type' => 'html',
211 'raw' => '<div class="elementor-nerd-box rtsb-promo"><div class="elementor-nerd-box-title" style="margin-top: 0; margin-bottom: 20px;">Unlock more possibilities</div><div class="elementor-nerd-box-message"><span class="pro-feature" style="font-size: 13px;"> Get the <a href="' . esc_url( rtsb()->pro_version_link() ) . '" target="_blank" style="color: #f54">Pro version</a> for more stunning layouts and customization options.</span></div><a class="elementor-nerd-box-link elementor-button elementor-button-default elementor-button-go-pro" href="' . esc_url( rtsb()->pro_version_link() ) . '" target="_blank">Get Pro</a></div>',
212 'separator' => 'default',
213 ];
214
215 $promo_fields['pro_alert_end'] = [
216 'mode' => 'section_end',
217 ];
218
219 return $promo_fields;
220 }
221
222 /**
223 * Register widget controls.
224 *
225 * Adds different input fields to allow the user to change and customize the widget settings.
226 *
227 * @since 1.0.0
228 * @access protected
229 */
230 protected function register_controls() {
231 $this->theme_support( 'widget_controls' );
232 $the_widget = $this->widget_fields();
233 if ( ! is_array( $the_widget ) ) {
234 return;
235 }
236 $fields = array_merge( $the_widget, $this->promo_content() );
237
238 $fields = apply_filters( 'rtsb/elements/elementor/widgets/controls/' . $this->rtsb_base, $fields, $this );
239
240 foreach ( $fields as $id => $field ) {
241 $field['classes'] = ! empty( $field['classes'] ) ? $field['classes'] . ' elementor-control-rtsb_el' : ' elementor-control-rtsb_el';
242
243 if ( ! empty( $field['type'] ) ) {
244 $field['type'] = self::el_fields( $field['type'] );
245 }
246
247 if ( ! empty( $field['tab'] ) ) {
248 $field['tab'] = self::el_tabs( $field['tab'] );
249 }
250
251 if ( isset( $field['mode'] ) && 'section_start' === $field['mode'] ) {
252 unset( $field['mode'] );
253 unset( $field['separator'] );
254
255 $this->start_controls_section( $id, $field );
256 } elseif ( isset( $field['mode'] ) && 'section_end' === $field['mode'] ) {
257 $this->end_controls_section();
258 } elseif ( isset( $field['mode'] ) && 'tabs_start' === $field['mode'] ) {
259 unset( $field['mode'] );
260 unset( $field['separator'] );
261
262 $this->start_controls_tabs( $id );
263 } elseif ( isset( $field['mode'] ) && 'tabs_end' === $field['mode'] ) {
264 $this->end_controls_tabs();
265 } elseif ( isset( $field['mode'] ) && 'tab_start' === $field['mode'] ) {
266 unset( $field['mode'] );
267 unset( $field['separator'] );
268
269 $this->start_controls_tab( $id, $field );
270 } elseif ( isset( $field['mode'] ) && 'tab_end' === $field['mode'] ) {
271 $this->end_controls_tab();
272 } elseif ( isset( $field['mode'] ) && 'group' === $field['mode'] ) {
273 $type = $field['type'];
274 $field['name'] = $id;
275 unset( $field['mode'] );
276 unset( $field['type'] );
277 $this->add_group_control( $type, $field );
278 } elseif ( isset( $field['mode'] ) && 'responsive' === $field['mode'] ) {
279 unset( $field['mode'] );
280
281 $this->add_responsive_control( $id, $field );
282 } elseif ( isset( $field['mode'] ) && 'popover_start' === $field['mode'] ) {
283 unset( $field['mode'] );
284 unset( $field['separator'] );
285
286 $this->add_control( $id, $field );
287 $this->start_popover();
288 } elseif ( isset( $field['mode'] ) && 'popover_end' === $field['mode'] ) {
289 $this->end_popover();
290 } elseif ( isset( $field['mode'] ) && 'repeater' === $field['mode'] ) {
291 $repeater = new Repeater();
292 $repeater_fields = $field['fields'];
293
294 foreach ( $repeater_fields as $rf_id => $value ) {
295 if ( ! empty( $value['type'] ) ) {
296 $value['type'] = self::el_fields( $value['type'] );
297 }
298 if ( isset( $value['mode'] ) && 'responsive' === $value['mode'] ) {
299 unset( $value['mode'] );
300 $repeater->add_responsive_control( $rf_id, $value );
301 } elseif ( isset( $value['mode'] ) && 'group' === $value['mode'] ) {
302 $type = $value['type'];
303 $value['name'] = $rf_id;
304 unset( $value['mode'] );
305 unset( $value['type'] );
306 $repeater->add_group_control( $type, $value );
307 } else {
308 $repeater->add_control( $rf_id, $value );
309 }
310 }
311
312 $field['fields'] = $repeater->get_controls();
313
314 $this->add_control( $id, $field );
315 } else {
316 $this->add_control( $id, $field );
317 }
318 }
319
320 do_action( 'rtsb/after/register/controls' );
321 }
322
323 /**
324 * Elementor Edit mode.
325 *
326 * @return mixed
327 */
328 public function is_edit_mode() {
329 return Plugin::$instance->preview->is_preview_mode() || Plugin::$instance->editor->is_edit_mode();
330 }
331
332 /**
333 * Elementor Edit preview.
334 *
335 * @return mixed
336 */
337 public function is_builder_mode() {
338 return BuilderFns::is_builder_preview() || $this->is_edit_mode();
339 }
340
341 /**
342 * Elementor Edit mode need some extra js for isotop reinitialize
343 *
344 * @return void
345 */
346 public function editor_slider_script() {
347 if ( \Elementor\Plugin::$instance->editor->is_edit_mode() ) {
348 $selector = $this->get_unique_selector() . ' .rtsb-carousel-slider';
349 ?>
350 <script>
351 jQuery('<?php echo esc_attr( $selector ); ?>').rtsb_slider();
352 </script>
353 <?php
354 }
355 }
356
357 /**
358 * Elementor Edit mode need some extra js for isotop reinitialize
359 *
360 * @return void
361 */
362 public function editor_cart_icon_script() {
363 if ( $this->is_edit_mode() ) {
364 $selector = $this->get_unique_selector() . ' .has-cart-button';
365 ?>
366 <script type="text/javascript">
367 // Product Archive Catelog
368 (function ($) {
369 setTimeout( function (){
370 var cartWrpper = $('body').find('<?php echo esc_attr( $selector ); ?>');
371 var cartIcon = cartWrpper.attr('data-cart-icon');
372 var cartButton = cartWrpper.find(
373 '.product_type_grouped, .add_to_cart_button, .single_add_to_cart_button '
374 );
375 if (cartIcon) {
376 //console.log( cartButton.find('svg') )
377 cartButton.find('i').remove();
378 cartButton.find('svg').remove();
379 cartButton.find('img').remove();
380 cartButton.prepend(cartIcon);
381 }
382 }, 2000);
383 })(jQuery);
384 </script>
385 <?php
386 }
387 }
388
389 /**
390 * Elementor Edit mode script
391 *
392 * @return void
393 */
394 public function edit_mode_script() {
395 if ( ! $this->is_edit_mode() ) {
396 return;
397 }
398 $ajaxurl = admin_url( 'admin-ajax.php' );
399
400 if ( in_array( 'sitepress-multilingual-cms/sitepress.php', get_option( 'active_plugins' ) ) ) {
401 $ajaxurl = admin_url( 'admin-ajax.php?lang=' . ICL_LANGUAGE_CODE );
402 }
403 ?>
404 <script>
405 var rtsb = {
406 ajaxurl: '<?php echo esc_url( $ajaxurl ); ?>',
407 nonce: '<?php echo esc_attr( wp_create_nonce( rtsb()->nonceId ) ); ?>',
408 is_pro: '<?php echo esc_attr( rtsb()->has_pro() ? 'true' : 'false' ); ?>'
409 };
410
411 rtsbElFrontend();
412
413 setTimeout(function() {
414 rtsbProductPageInit();
415 }, 1000);
416 <?php if ( rtsb()->has_pro() ) { ?>
417 var isMasonry = jQuery('.rtsb-elementor-container .rtsb-masonry');
418
419 if(isMasonry.length > 0) {
420 isMasonry.masonry();
421 }
422
423 if (typeof rtsbFilters === 'function') {
424 rtsbFilters();
425 }
426
427 setTimeout( function (){
428 window.rtsbCountdownApply();
429 }, 1000 );
430 <?php } ?>
431 </script>
432
433 <?php
434 }
435
436 /**
437 * Starts an Elementor Section
438 *
439 * @param string $label Section label.
440 * @param object $tab Tab ID.
441 * @param array $conditions Section Condition.
442 * @param array $condition Section Conditions.
443 * @return array
444 */
445 public function start_section( $label, $tab, $conditions = [], $condition = [] ) {
446 $start = [
447 'mode' => 'section_start',
448 'tab' => $tab,
449 'label' => $label,
450 ];
451 if ( ! empty( $condition ) ) {
452 $start['condition'] = $condition;
453 }
454 if ( ! empty( $conditions ) ) {
455 $start['conditions'] = $conditions;
456 }
457 return $start;
458 }
459
460 /**
461 * Ends an Elementor Section
462 *
463 * @return array
464 */
465 public function end_section() {
466 return [
467 'mode' => 'section_end',
468 ];
469 }
470
471 /**
472 * Theme Support for render/widget_controls
473 *
474 * @param string $support Support for render/widget_controls.
475 * @return void
476 */
477 public function theme_support( $support = 'render' ) {
478
479 if ( empty( $support ) ) {
480 return;
481 }
482 $theme = ucwords( str_replace( [ '_', '-', ' ' ], '', rtsb()->current_theme ) );
483
484 $supportClass = apply_filters(
485 'radiustheme/sb/widgetsupport/class',
486 [
487 'ShopbuilderPlugin' => 'RadiusTheme\SB\Controllers\ThemesSupport\\' . $theme . '\\WidgetsSupport',
488 'TheTheme' => \WidgetSupport::class,
489 ]
490 );
491
492 foreach ( $supportClass as $key => $theClass ) {
493 $themeWidgetSupport = get_theme_file_path( '/shopbuilder/WidgetSupport.php' );
494 if ( 'TheTheme' === $key && file_exists( $themeWidgetSupport ) ) {
495 require_once $themeWidgetSupport;
496 }
497 if ( class_exists( $theClass ) ) {
498 $method = $support . '_' . str_replace( [ '-', ' ' ], '_', $this->rtsb_base );
499 if ( method_exists( $theClass, $method ) ) {
500 $theClass::instance( $this )->$method();
501 }
502 }
503 }
504 }
505
506 /**
507 * Starts an Elementor tab group.
508 *
509 * @param array $conditions Tab condition.
510 * @param array $condition Tab condition.
511 * @return array
512 */
513 public function start_tab_group( $conditions = [], $condition = [] ) {
514 return [
515 'mode' => 'tabs_start',
516 'conditions' => $conditions,
517 'condition' => $condition,
518 ];
519 }
520
521 /**
522 * Ends an Elementor tab group.
523 *
524 * @param array $conditions Tab condition.
525 * @param array $condition Tab condition.
526 * @return array
527 */
528 public function end_tab_group( $conditions = [], $condition = [] ) {
529 return [
530 'mode' => 'tabs_end',
531 'conditions' => $conditions,
532 'condition' => $condition,
533 ];
534 }
535
536 /**
537 * Starts an Elementor tab
538 *
539 * @param string $label Section label.
540 * @param array $conditions Tab condition.
541 * @param array $condition Tab condition.
542 * @return array
543 */
544 public function start_tab( $label, $conditions = [], $condition = [] ) {
545 return [
546 'mode' => 'tab_start',
547 'label' => $label,
548 'conditions' => $conditions,
549 'condition' => $condition,
550 ];
551 }
552
553 /**
554 * Ends an Elementor tab.
555 *
556 * @param array $conditions Tab condition.
557 * @param array $condition Tab condition.
558 * @return array
559 */
560 public function end_tab( $conditions = [], $condition = [] ) {
561 return [
562 'mode' => 'tab_end',
563 'conditions' => $conditions,
564 'condition' => $condition,
565 ];
566 }
567
568 /**
569 * Starts an Elementor Section Heading
570 *
571 * @param string $label Heading label.
572 * @param string $separator Section separator.
573 * @param array $conditions Section Condition.
574 * @param array $condition Section Conditions.
575 * @return array
576 */
577 public function el_heading( $label, $separator = null, $conditions = [], $condition = [] ) {
578 return [
579 'type' => 'html',
580 'raw' => sprintf(
581 '<h3 class="rtsb-elementor-group-heading">%s</h3>',
582 $label
583 ),
584 'separator' => $separator,
585 'content_classes' => 'elementor-panel-heading-title',
586 'conditions' => $conditions,
587 'condition' => $condition,
588 ];
589 }
590
591 /**
592 * Prints a control notification.
593 *
594 * @param string $label Field label.
595 * @return string
596 */
597 public function is_pro_control( $label ) {
598 if ( rtsb()->has_pro() ) {
599 return $label;
600 }
601
602 return $label . $this->pro_label;
603 }
604
605 /**
606 * Adds a class.
607 *
608 * @return string
609 */
610 public function pro_class() {
611 return ! rtsb()->has_pro() ? 'rtsb-pro-field' : '';
612 }
613
614 /**
615 * Elementor Fields.
616 *
617 * @param string $type Control type.
618 *
619 * @return string
620 */
621 private static function el_fields( $type ) {
622
623 $controls = Controls_Manager::class;
624
625 switch ( $type ) {
626 case 'link':
627 $type = $controls::URL;
628 break;
629
630 case 'image-dimensions':
631 $type = $controls::IMAGE_DIMENSIONS;
632 break;
633
634 case 'html':
635 $type = $controls::RAW_HTML;
636 break;
637
638 case 'switch':
639 $type = $controls::SWITCHER;
640 break;
641
642 case 'popover':
643 $type = $controls::POPOVER_TOGGLE;
644 break;
645
646 case 'rtsb-image-selector':
647 $type = \RadiusTheme\SB\Elementor\Controls\ImageSelectorControl::$controlName;
648 break;
649
650 case 'rt-select2':
651 $type = \RadiusTheme\SB\Elementor\Controls\Select2AjaxControl::$controlName;
652 break;
653
654 case 'typography':
655 $type = Group_Control_Typography::get_type();
656 break;
657
658 case 'border':
659 $type = Group_Control_Border::get_type();
660 break;
661
662 case 'background':
663 $type = Group_Control_Background::get_type();
664 break;
665
666 case 'box-shadow':
667 $type = Group_Control_Box_Shadow::get_type();
668 break;
669
670 case 'text-shadow':
671 $type = Group_Control_Text_Shadow::get_type();
672 break;
673
674 case 'text-stroke':
675 $type = Group_Control_Text_Stroke::get_type();
676 break;
677
678 case 'css-filter':
679 $type = Group_Control_Css_Filter::get_type();
680 break;
681 default:
682 $type = constant( 'Elementor\Controls_Manager::' . strtoupper( $type ) );
683
684 }
685 return $type;
686 }
687
688 /**
689 * Elementor Fields.
690 *
691 * @param string $tab Tab.
692 *
693 * @return string
694 */
695 private static function el_tabs( $tab ) {
696 return constant( 'Elementor\Controls_Manager::TAB_' . strtoupper( $tab ) );
697 }
698
699
700 /**
701 * Init render hooks & functions.
702 *
703 * @return void
704 */
705 protected function render_start() {
706 add_filter( 'rtsb/countdown/campaign/parent/class', [ $this, 'countdown_campaign_parent_class' ], 15 );
707 do_action( 'rtsb/custom/products/before/template/load', $this );
708 $this->theme_support();
709
710 if ( $this->is_builder_mode() ) {
711 add_filter( 'wp_kses_allowed_html', [ FilterHooks::class, 'custom_wpkses_post_tags' ], 10, 2 );
712 }
713 }
714 /**
715 * Archive Custom Layout Widget Rendering.
716 *
717 * @return void
718 */
719 public function countdown_campaign_parent_class( $classes ) {
720 $settings = $this->get_settings_for_display();
721 $layout = $settings['countdown_layout'] ?? 'horizontal';
722 $v_position = $settings['countdown_vertical_position'] ?? '';
723 $countdown_preset = $settings['countdown_preset'] ?? '';
724 $vertical_center = $settings['countdown_vertical_center'] ?? false;
725
726 $remove = [
727 'rtsb-countdown-horizontal',
728 'rtsb-countdown-vertical',
729 'rtsb-vertical-position-top-left',
730 'rtsb-vertical-position-top-right',
731 ];
732 $classes = array_filter(
733 $classes,
734 function ( $item ) use ( $remove ) {
735 return ! in_array( $item, $remove );
736 }
737 );
738 $new_class = 'rtsb-countdown-' . esc_attr( $countdown_preset );
739 $new_class .= ' rtsb-countdown-' . esc_attr( $layout );
740
741 if ( $v_position && 'horizontal' !== $layout ) {
742 $vertical_class = 'rtsb-vertical-position-top-' . esc_attr( $v_position );
743 $classes[] = $vertical_class;
744 if ( 'yes' === $vertical_center ) {
745 $classes[] = 'rtsb-countdown-vertical-middle';
746 }
747 }
748
749 $classes[] = $new_class;
750
751 return $classes;
752 }
753 /**
754 * End render hooks & functions.
755 *
756 * @return void
757 */
758 protected function render_end() {
759 $this->edit_mode_script();
760 do_action( 'rtsb/custom/products/after/template/load', $this );
761 $this->theme_support( 'render_reset' );
762 remove_filter( 'rtsb/countdown/campaign/parent/class', [ $this, 'countdown_campaign_parent_class' ], 15 );
763 }
764
765 /**
766 * Elementor controls marge all settings
767 *
768 * @return void
769 */
770 protected function apply_hooks_before_render() {
771 if ( $this->is_edit_mode() ) {
772 add_filter( 'wp_calculate_image_srcset_meta', '__return_null' );
773 }
774 }
775
776 /**
777 * If checkout registration is disabled and not logged in,
778 * the user cannot check out.
779 *
780 * @return bool
781 */
782 protected function has_checkout_restriction() {
783 $checkout = WC()->checkout();
784
785 return ! $checkout->is_registration_enabled() && $checkout->is_registration_required() && ! is_user_logged_in();
786 }
787
788 /**
789 * Widget Exceptions.
790 *
791 * @return bool
792 */
793 private function widget_exceptions() {
794 $exceptions = [
795 'rtsb-product-filters',
796 'rtsb-wishlist',
797 'rtsb-product-breadcrumbs',
798 ];
799
800 return in_array( $this->rtsb_base, $exceptions, true );
801 }
802 }
803