PluginProbe
ShopBuilder – WooCommerce Builder For Elementor / 3.3.0
ShopBuilder – WooCommerce Builder For Elementor v3.3.0
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
← All changes | app/Controllers/BuilderController.php +133 -77 2.1.93.3.0 View file →
@@ -8,14 +8,14 @@
8 8 namespace RadiusTheme\SB\Controllers;
9 9
10 10 use RadiusTheme\SB\Helpers\Fns;
11 11 use RadiusTheme\SB\Helpers\BuilderFns;
12 +use RadiusTheme\SB\Models\ElementList;
12 13 use RadiusTheme\SB\Traits\SingletonTrait;
13 14 use RadiusTheme\SB\Controllers\Builder\BuilderCpt;
14 15 use RadiusTheme\SB\Controllers\Hooks\BuilderHooks;
15 16 use RadiusTheme\SB\Elementor\Controls\ImageSelectorControl;
16 17 use RadiusTheme\SB\Elementor\Controls\Select2AjaxControl;
17 -use RadiusTheme\SB\Models\ElementList;
18 18
19 19 // Do not allow directly accessing this file.
20 20 if ( ! defined( 'ABSPATH' ) ) {
21 21 exit( 'This script cannot be accessed directly.' );
@@ -54,28 +54,24 @@
54 54 */
55 55 private function __construct() {
56 56 $this->builder_page_id = BuilderFns::builder_page_id_by_page();
57 57 $this->page_edit_with = Fns::page_edit_with( $this->builder_page_id );
58 -
59 58 if ( ! is_admin() ) {
60 59 BuilderHooks::instance();
61 60 }
62 61
63 62 BuilderCpt::instance();
64 -
65 - $this->elementor_init();
66 - $this->both_builder_frontend();
67 -
68 - // add_action( 'elementor/init', [ $this, 'elementor_init' ] );
69 - add_action( 'elementor/editor/before_enqueue_scripts', [ $this, 'editor_scripts' ] );
70 - // add_action( 'template_redirect', [ $this, 'both_builder_frontend' ], 99 );
71 -
63 + if ( defined( 'ELEMENTOR_VERSION' ) ) {
64 + $this->elementor_init();
65 + $this->both_builder_frontend();
66 + add_action( 'elementor/editor/before_enqueue_scripts', [ $this, 'editor_scripts' ] );
67 + }
72 68 // RT Select2 Ajax.
73 - add_action( 'wp_ajax_rt_select2_object_search', [ $this, 'select2_ajax_posts_filter_autocomplete' ] );
74 - add_action( 'wp_ajax_nopriv_rt_select2_object_search', [ $this, 'select2_ajax_posts_filter_autocomplete' ] );
69 + add_action( 'wp_ajax_rtsb_select2_object_search', [ $this, 'select2_ajax_posts_filter_autocomplete' ] );
70 + add_action( 'wp_ajax_nopriv_rtsb_select2_object_search', [ $this, 'select2_ajax_posts_filter_autocomplete' ] );
75 71 // Select2 ajax save data.
76 - add_action( 'wp_ajax_rt_select2_get_title', [ $this, 'select2_ajax_get_posts_value_titles' ] );
77 - add_action( 'wp_ajax_nopriv_rt_select2_get_title', [ $this, 'select2_ajax_get_posts_value_titles' ] );
72 + add_action( 'wp_ajax_rtsb_select2_get_title', [ $this, 'select2_ajax_get_posts_value_titles' ] );
73 + add_action( 'wp_ajax_nopriv_rtsb_select2_get_title', [ $this, 'select2_ajax_get_posts_value_titles' ] );
78 74 }
79 75
80 76 /**
81 77 * Apply for frontend.
@@ -92,13 +88,20 @@
92 88 *
93 89 * @return void
94 90 */
95 91 public function elementor_init() {
96 - add_action( 'elementor/elements/categories_registered', [ $this, 'add_elementor_widget_categories' ] );
97 - add_action( 'elementor/widgets/register', [ $this, 'init_widgets' ] );
98 - add_action( 'elementor/controls/register', [ $this, 'init_controls' ] );
99 - add_filter( 'elementor/editor/localize_settings', [ $this, 'promotePremiumWidgets' ] );
100 - add_action( 'elementor/icons_manager/additional_tabs', [ $this, 'rtsb_icons' ] );
92 + add_action(
93 + 'init',
94 + function () {
95 + if ( Fns::should_load_elementor_scripts() ) {
96 + add_action( 'elementor/elements/categories_registered', [ $this, 'add_elementor_widget_categories' ] );
97 + add_action( 'elementor/widgets/register', [ $this, 'init_widgets' ] );
98 + add_action( 'elementor/controls/register', [ $this, 'init_controls' ] );
99 + add_filter( 'elementor/editor/localize_settings', [ $this, 'promotePremiumWidgets' ] );
100 + add_action( 'elementor/icons_manager/additional_tabs', [ $this, 'rtsb_icons' ] );
101 + }
102 + }
103 + );
101 104 }
102 105
103 106 /**
104 107 * Register Category
@@ -108,12 +111,15 @@
108 111 * @return void
109 112 */
110 113 public function add_elementor_widget_categories( $elements_manager ) {
111 114 $categories = [];
112 - $type = BuilderFns::builder_type( get_the_ID() );
113 - if ( $type ) {
115 + $builder_id = get_queried_object_id();
116 + $id = Fns::wpml_object_id( $builder_id, BuilderFns::$post_type_tb, 'default' );
117 + $type = BuilderFns::builder_type( $id );
118 +
119 + if ( $type && 'popup-builder' !== $type ) {
114 120 $builder_type = ! empty( BuilderFns::builder_page_types()[ $type ] ) ? BuilderFns::builder_page_types()[ $type ] : '';
115 - $builder_type = str_replace( 'My Account - ', '', $builder_type );
121 + $builder_type = str_replace( [ 'My Account - ', 'Endpoint: ' ], '', $builder_type );
116 122 $categories['rtsb-shopbuilder'] = [
117 123 'title' => esc_html__( 'ShopBuilder', 'shopbuilder' ) . ' - ' . ucfirst( $builder_type ),
118 124 'icon' => 'fa fa-plug',
119 125 ];
@@ -123,9 +129,10 @@
123 129 'title' => esc_html__( 'Shopbuilder - General', 'shopbuilder' ),
124 130 'icon' => 'fa fa-plug',
125 131 ];
126 132 }
127 - $categories = apply_filters( 'rtsb_elementor_widgets_category_lists', $categories );
133 + $categories = apply_filters( 'rtsb_elementor_widgets_category_lists', $categories );
134 +
128 135 $other_categories = $elements_manager->get_categories();
129 136 $categories = array_merge(
130 137 array_slice( $other_categories, 0, 1 ),
131 138 $categories,
@@ -131,10 +138,10 @@
131 138 $categories,
132 139 array_slice( $other_categories, 1 )
133 140 );
134 141
135 - $set_categories = function ( $categories ) {
136 - $this->categories = $categories;
142 + $set_categories = function ( $categories ) use ( $elements_manager ) {
143 + $elements_manager->categories = $categories;
137 144 };
138 145
139 146 $set_categories->call( $elements_manager, $categories );
140 147 }
@@ -155,10 +162,14 @@
155 162
156 163 /**
157 164 * Init Widgets
158 165 *
159 - * Include widgets files and register them
166 + * Include widget files and register them
160 167 *
168 + * @param object $widgets_manager Widgets Manager.
169 + *
170 + * @return void
171 + *
161 172 * @since 1.0.0
162 173 */
163 174 public function init_widgets( $widgets_manager ) {
164 175
@@ -176,45 +187,50 @@
176 187 continue;
177 188 }
178 189
179 190 if ( ! empty( $element['category'] ) ) {
180 - $widget = false;
181 - $import = apply_filters( 'rtsb_import_status', false );
182 - switch ( $element['category'] ) {
183 - case 'product':
184 - if ( BuilderFns::is_product() || $import ) {
191 + try {
192 + $widget = false;
193 + $import = apply_filters( 'rtsb_import_status', false );
194 + switch ( $element['category'] ) {
195 + case 'product':
196 + if ( BuilderFns::is_product() || $import ) {
197 + $widget = new $element['base_class']();
198 + }
199 + break;
200 + case 'shop':
201 + if ( BuilderFns::is_archive() || BuilderFns::is_shop() || $import ) {
202 + $widget = new $element['base_class']();
203 + }
204 + break;
205 + case 'archive':
206 + if ( BuilderFns::is_archive() || $import ) {
207 + $widget = new $element['base_class']();
208 + }
209 + break;
210 + case 'cart':
211 + if ( BuilderFns::is_cart() || $import ) {
212 + $widget = new $element['base_class']();
213 + }
214 + break;
215 + case 'checkout':
216 + if ( BuilderFns::is_checkout() || $import ) {
217 + $widget = new $element['base_class']();
218 + }
219 + break;
220 + case 'general':
185 221 $widget = new $element['base_class']();
186 - }
187 - break;
188 - case 'shop':
189 - if ( BuilderFns::is_archive() || BuilderFns::is_shop() || $import ) {
190 - $widget = new $element['base_class']();
191 - }
192 - break;
193 - case 'archive':
194 - if ( BuilderFns::is_archive() || $import ) {
195 - $widget = new $element['base_class']();
196 - }
197 - break;
198 - case 'cart':
199 - if ( BuilderFns::is_cart() || $import ) {
200 - $widget = new $element['base_class']();
201 - }
202 - break;
203 - case 'checkout':
204 - if ( BuilderFns::is_checkout() || $import ) {
205 - $widget = new $element['base_class']();
206 - }
207 - break;
208 - case 'general':
209 - $widget = new $element['base_class']();
210 - break;
211 - default:
212 - }
213 - $widget = apply_filters( 'rtsb/element/list/init/widgets', $widget, $element );
222 + break;
223 + default:
224 + }
225 + $widget = apply_filters( 'rtsb/element/list/init/widgets', $widget, $element );
214 226
215 - if ( $widget && is_object( $widget ) ) {
216 - $widgets_manager->register( $widget );
227 + if ( $widget && is_object( $widget ) ) {
228 + $widgets_manager->register( $widget );
229 + }
230 + } catch ( \Throwable $e ) {
231 + error_log( 'ShopBuilder widget error (' . $element['base_class'] . '): ' . $e->getMessage() ); // phpcs:ignore WordPress.PHP.DevelopmentFunctions.error_log_error_log
232 + continue;
217 233 }
218 234 }
219 235 }
220 236 }
@@ -226,9 +242,9 @@
226 242 *
227 243 * @return array
228 244 */
229 245 public function rtsb_icons( $tabs = [] ) {
230 - $custom_icons = $this->get_icons();
246 + $custom_icons = Fns::get_custom_icon_names();
231 247
232 248 $tabs['shopbuilder-icons'] = [
233 249 'name' => 'rtsb-fonts',
234 250 'label' => esc_html__( 'ShopBuilder Icons', 'shopbuilder' ),
@@ -285,9 +301,9 @@
285 301 *
286 302 * @since 2.0.0
287 303 */
288 304 if ( did_action( 'elementor/loaded' ) && 'elementor' === $this->page_edit_with ) {
289 - do_action( 'elementor/page_templates/header-footer/before_content' );
305 + do_action( 'elementor/page_templates/header-footer/before_content' ); // phpcs:ignore WordPress.NamingConventions.ValidHookName.UseUnderscores
290 306 }
291 307
292 308 $parent_class = apply_filters( 'rtsb/builder/content/parent_class', [] );
293 309
@@ -325,10 +341,34 @@
325 341 if ( BuilderFns::is_checkout() ) {
326 342 if ( ! apply_filters( 'rtsb/multi/step/checkout/widget', true ) ) {
327 343 return;
328 344 }
345 +
346 + $checkout = WC()->checkout();
347 +
348 + // Temporarily remove callbacks that Elementor checkout
349 + // handles via separate widgets to prevent duplicates.
350 + remove_action( 'woocommerce_before_checkout_form', [ Hooks\ActionHooks::class, 'woocommerce_checkout_login_form' ], 10 );
351 + remove_action( 'woocommerce_before_checkout_form', [ Hooks\ActionHooks::class, 'woocommerce_checkout_coupon_form' ], 10 );
352 + remove_action( 'woocommerce_before_checkout_form', [ Fns::class, 'woocommerce_output_all_notices' ], 10 );
353 +
354 + do_action( 'woocommerce_before_checkout_form', $checkout );
355 +
356 + // Restore callbacks for non-Elementor contexts.
357 + add_action( 'woocommerce_before_checkout_form', [ Hooks\ActionHooks::class, 'woocommerce_checkout_login_form' ], 10 );
358 + add_action( 'woocommerce_before_checkout_form', [ Hooks\ActionHooks::class, 'woocommerce_checkout_coupon_form' ], 10 );
359 + add_action( 'woocommerce_before_checkout_form', [ Fns::class, 'woocommerce_output_all_notices' ], 10 );
360 +
361 + // If checkout registration is disabled and not logged in, the user cannot checkout.
362 + if ( ! $checkout->is_registration_enabled() && $checkout->is_registration_required() && ! is_user_logged_in() ) {
363 + echo esc_html( apply_filters( 'woocommerce_checkout_must_be_logged_in_message', __( 'You must be logged in to checkout.', 'shopbuilder' ) ) );
364 + return;
365 + }
329 366 ?>
330 - <form name="checkout" method="post" class="rtsb-woocommerce-checkout checkout" action="<?php echo esc_url( wc_get_checkout_url() ); ?>" enctype="multipart/form-data">
367 + <!--
368 + woocommerce-checkout added for fix issue with payment method ( Revolut Pay )
369 + -->
370 + <form name="checkout" method="post" class="rtsb-woocommerce-checkout woocommerce-checkout checkout" action="<?php echo esc_url( wc_get_checkout_url() ); ?>" enctype="multipart/form-data">
331 371 <?php
332 372 }
333 373 }
334 374
@@ -345,9 +385,9 @@
345 385 *
346 386 * @since 2.0.0
347 387 */
348 388 if ( did_action( 'elementor/loaded' ) && 'elementor' === $this->page_edit_with ) {
349 - do_action( 'elementor/page_templates/header-footer/after_content' );
389 + do_action( 'elementor/page_templates/header-footer/after_content' ); // phpcs:ignore WordPress.NamingConventions.ValidHookName.UseUnderscores
350 390 }
351 391
352 392 if ( BuilderFns::is_checkout() ) {
353 393 if ( ! apply_filters( 'rtsb/multi/step/checkout/widget', true ) ) {
@@ -355,8 +395,9 @@
355 395 }
356 396 ?>
357 397 </form>
358 398 <?php
399 + do_action( 'woocommerce_after_checkout_form', WC()->checkout() );
359 400 }
360 401 ?>
361 402 </div>
362 403 <!-- After Content end -->
@@ -376,17 +417,20 @@
376 417 $post_type = 'post';
377 418 $source_name = 'post_type';
378 419 $paged = absint( $_POST['page'] ?? 1 );
379 420 if ( ! empty( $_POST['post_type'] ) ) {
421 + // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.MissingUnslash
380 422 $post_type = sanitize_text_field( $_POST['post_type'] );
381 423 }
382 424
383 425 if ( ! empty( $_POST['source_name'] ) ) {
426 + // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.MissingUnslash
384 427 $source_name = sanitize_text_field( $_POST['source_name'] );
385 428 }
386 429
430 + // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.MissingUnslash
387 431 $search = ! empty( $_POST['search'] ) ? sanitize_text_field( $_POST['search'] ) : '';
388 - $results = $post_list = [];
432 + $results = $post_list = []; // phpcs:ignore Squiz.PHP.DisallowMultipleAssignments.Found
389 433 switch ( $source_name ) {
390 434 case 'taxonomy':
391 435 $args = [
392 436 'hide_empty' => false,
@@ -391,13 +435,13 @@
391 435 $args = [
392 436 'hide_empty' => false,
393 437 'orderby' => 'name',
394 438 'order' => 'ASC',
395 - 'search' => $search,
439 + 'name__like' => $search,
396 440 'number' => '5',
397 441 ];
398 442
399 - if ( $post_type !== 'all' ) {
443 + if ( 'all' !== $post_type ) {
400 444 $args['taxonomy'] = $post_type;
401 445 }
402 446
403 447 $post_list = wp_list_pluck( get_terms( $args ), 'name', 'term_id' );
@@ -452,13 +496,14 @@
452 496 if ( empty( $_POST['id'] ) ) {
453 497 wp_send_json_error( [] );
454 498 }
455 499
500 + // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.MissingUnslash, WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
456 501 if ( empty( array_filter( $_POST['id'] ) ) ) {
457 502 wp_send_json_error( [] );
458 503 }
459 504 $ids = array_map( 'intval', $_POST['id'] );
460 - $source_name = ! empty( $_POST['source_name'] ) ? sanitize_text_field( $_POST['source_name'] ) : '';
505 + $source_name = ! empty( $_POST['source_name'] ) ? sanitize_text_field( $_POST['source_name'] ) : ''; // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.MissingUnslash
461 506
462 507 switch ( $source_name ) {
463 508 case 'taxonomy':
464 509 $args = [
@@ -467,9 +512,11 @@
467 512 'order' => 'ASC',
468 513 'include' => implode( ',', $ids ),
469 514 ];
470 515
471 - if ( $_POST['post_type'] !== 'all' ) {
516 + // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotValidated
517 + if ( 'all' !== $_POST['post_type'] ) {
518 + // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotValidated, WordPress.Security.ValidatedSanitizedInput.MissingUnslash
472 519 $args['taxonomy'] = sanitize_text_field( $_POST['post_type'] );
473 520 }
474 521
475 522 $response = wp_list_pluck( get_terms( $args ), 'name', 'term_id' );
@@ -487,9 +534,9 @@
487 534 break;
488 535 default:
489 536 $post_info = get_posts(
490 537 [
491 - 'post_type' => sanitize_text_field( $_POST['post_type'] ),
538 + 'post_type' => sanitize_text_field( $_POST['post_type'] ), // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.MissingUnslash, WordPress.Security.ValidatedSanitizedInput.InputNotValidated
492 539 'include' => implode( ',', $ids ),
493 540 ]
494 541 );
495 542 $response = wp_list_pluck( $post_info, 'post_title', 'ID' );
@@ -505,12 +552,12 @@
505 552
506 553 /**
507 554 * Ajax callback for rt-select2
508 555 *
509 - * @param $post_type
510 - * @param $limit
511 - * @param $search
512 - * @param $paged
556 + * @param string $post_type Post type.
557 + * @param int $limit Limit.
558 + * @param string $search Search.
559 + * @param int $paged Paged.
513 560 *
514 561 * @return array
515 562 */
516 563 public function get_query_data( $post_type = 'any', $limit = 10, $search = '', $paged = 1 ) {
@@ -547,8 +594,17 @@
547 594 if ( ! empty( $search ) ) {
548 595 $where .= $wpdb->prepare( " AND {$wpdb->posts}.post_title LIKE %s", '%' . esc_sql( $search ) . '%' );
549 596 }
550 597
598 + // Add a query for shop_coupon post-type to check 'show on frontend' meta.
599 + if ( 'shop_coupon' === $post_type ) {
600 + $where .= " AND {$wpdb->posts}.ID IN (
601 + SELECT post_id FROM {$wpdb->postmeta}
602 + WHERE meta_key = 'rtsb_show_on_frontend'
603 + AND meta_value = 'on'
604 + )";
605 + }
606 +
551 607 $query = "select post_title,ID from $wpdb->posts where post_status = 'publish' {$where} {$limit}";
552 608 $results = $wpdb->get_results( $query ); // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.PreparedSQL.NotPrepared, WordPress.DB.DirectDatabaseQuery.NoCaching
553 609
554 610 if ( ! empty( $results ) ) {
@@ -581,10 +637,10 @@
581 637
582 638 $pro_widgets = [
583 639 [
584 640 'name' => 'rtsb-ajax-product-filters',
585 - 'title' => esc_html__( 'Ajax Product Filters', 'testimonial-slider-showcase' ),
586 - 'description' => esc_html__( 'Ajax Product Filters', 'testimonial-slider-showcase' ),
641 + 'title' => esc_html__( 'Ajax Product Filters', 'shopbuilder' ),
642 + 'description' => esc_html__( 'Ajax Product Filters', 'shopbuilder' ),
587 643 'icon' => 'rtsb-el-custom rtsb-element icon-rtsb-ajax-product-filters rtsb-promotional-element',
588 644 'categories' => '[ "rtsb-shopbuilder" ]',
589 645 ],
590 646 ];