PluginProbe
ShopBuilder – WooCommerce Builder For Elementor / 2.3.0
ShopBuilder – WooCommerce Builder For Elementor v2.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 +67 -135 3.4.22.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;
13 12 use RadiusTheme\SB\Traits\SingletonTrait;
14 13 use RadiusTheme\SB\Controllers\Builder\BuilderCpt;
15 14 use RadiusTheme\SB\Controllers\Hooks\BuilderHooks;
16 15 use RadiusTheme\SB\Elementor\Controls\ImageSelectorControl;
17 16 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,18 +54,22 @@
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 +
58 59 if ( ! is_admin() ) {
59 60 BuilderHooks::instance();
60 61 }
61 62
62 63 BuilderCpt::instance();
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 - }
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 +
68 72 // RT Select2 Ajax.
69 73 add_action( 'wp_ajax_rtsb_select2_object_search', [ $this, 'select2_ajax_posts_filter_autocomplete' ] );
70 74 add_action( 'wp_ajax_nopriv_rtsb_select2_object_search', [ $this, 'select2_ajax_posts_filter_autocomplete' ] );
71 75 // Select2 ajax save data.
@@ -88,20 +92,13 @@
88 92 *
89 93 * @return void
90 94 */
91 95 public function elementor_init() {
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 - );
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' ] );
104 101 }
105 102
106 103 /**
107 104 * Register Category
@@ -115,9 +112,9 @@
115 112 $builder_id = get_queried_object_id();
116 113 $id = Fns::wpml_object_id( $builder_id, BuilderFns::$post_type_tb, 'default' );
117 114 $type = BuilderFns::builder_type( $id );
118 115
119 - if ( $type && 'popup-builder' !== $type ) {
116 + if ( $type ) {
120 117 $builder_type = ! empty( BuilderFns::builder_page_types()[ $type ] ) ? BuilderFns::builder_page_types()[ $type ] : '';
121 118 $builder_type = str_replace( [ 'My Account - ', 'Endpoint: ' ], '', $builder_type );
122 119 $categories['rtsb-shopbuilder'] = [
123 120 'title' => esc_html__( 'ShopBuilder', 'shopbuilder' ) . ' - ' . ucfirst( $builder_type ),
@@ -162,14 +159,10 @@
162 159
163 160 /**
164 161 * Init Widgets
165 162 *
166 - * Include widget files and register them
163 + * Include widgets files and register them
167 164 *
168 - * @param object $widgets_manager Widgets Manager.
169 - *
170 - * @return void
171 - *
172 165 * @since 1.0.0
173 166 */
174 167 public function init_widgets( $widgets_manager ) {
175 168
@@ -187,24 +180,45 @@
187 180 continue;
188 181 }
189 182
190 183 if ( ! empty( $element['category'] ) ) {
191 - try {
192 - $widget = false;
193 - $import = apply_filters( 'rtsb_import_status', false );
194 -
195 - if ( $this->should_register_widget( $element['category'], $import ) ) {
184 + $widget = false;
185 + $import = apply_filters( 'rtsb_import_status', false );
186 + switch ( $element['category'] ) {
187 + case 'product':
188 + if ( BuilderFns::is_product() || $import ) {
189 + $widget = new $element['base_class']();
190 + }
191 + break;
192 + case 'shop':
193 + if ( BuilderFns::is_archive() || BuilderFns::is_shop() || $import ) {
194 + $widget = new $element['base_class']();
195 + }
196 + break;
197 + case 'archive':
198 + if ( BuilderFns::is_archive() || $import ) {
199 + $widget = new $element['base_class']();
200 + }
201 + break;
202 + case 'cart':
203 + if ( BuilderFns::is_cart() || $import ) {
204 + $widget = new $element['base_class']();
205 + }
206 + break;
207 + case 'checkout':
208 + if ( BuilderFns::is_checkout() || $import ) {
209 + $widget = new $element['base_class']();
210 + }
211 + break;
212 + case 'general':
196 213 $widget = new $element['base_class']();
197 - }
214 + break;
215 + default:
216 + }
217 + $widget = apply_filters( 'rtsb/element/list/init/widgets', $widget, $element );
198 218
199 - $widget = apply_filters( 'rtsb/element/list/init/widgets', $widget, $element );
200 -
201 - if ( $widget && is_object( $widget ) ) {
202 - $widgets_manager->register( $widget );
203 - }
204 - } catch ( \Throwable $e ) {
205 - error_log( 'ShopBuilder widget error (' . $element['base_class'] . '): ' . $e->getMessage() ); // phpcs:ignore WordPress.PHP.DevelopmentFunctions.error_log_error_log
206 - continue;
219 + if ( $widget && is_object( $widget ) ) {
220 + $widgets_manager->register( $widget );
207 221 }
208 222 }
209 223 }
210 224 }
@@ -209,48 +223,8 @@
209 223 }
210 224 }
211 225
212 226 /**
213 - * Determine whether a widget for the given category should be registered
214 - * in the current request context.
215 - *
216 - * @param string $category Element category.
217 - * @param bool $import Whether an import is in progress.
218 - *
219 - * @return bool
220 - */
221 - protected function should_register_widget( $category, $import ) {
222 - // On the frontend the Elementor Widgets Manager can initialise at an
223 - // unpredictable time — e.g. Elementor Pro's Theme Builder boots it on
224 - // template_redirect — when WooCommerce query conditionals such as
225 - // is_shop()/is_archive() are not yet reliable. Widget registration is
226 - // cached for the whole request, so gating it by those conditionals can
227 - // permanently skip ShopBuilder widgets, leaving the builder template to
228 - // render empty container shells. Register unconditionally on the
229 - // frontend; keep the per-category gate only for the editor widget panel.
230 - if ( ! is_admin() ) {
231 - return true;
232 - }
233 -
234 - switch ( $category ) {
235 - case 'product':
236 - return BuilderFns::is_product() || $import;
237 - case 'shop':
238 - return BuilderFns::is_archive() || BuilderFns::is_shop() || $import;
239 - case 'archive':
240 - return BuilderFns::is_archive() || $import;
241 - case 'cart':
242 - return BuilderFns::is_cart() || $import;
243 - case 'checkout':
244 - return BuilderFns::is_checkout() || $import;
245 - case 'general':
246 - return true;
247 - default:
248 - return false;
249 - }
250 - }
251 -
252 - /**
253 227 * Adding custom icons in Elementor
254 228 *
255 229 * @param array $tabs Tabs.
256 230 *
@@ -315,26 +289,18 @@
315 289 *
316 290 * @since 2.0.0
317 291 */
318 292 if ( did_action( 'elementor/loaded' ) && 'elementor' === $this->page_edit_with ) {
319 - do_action( 'elementor/page_templates/header-footer/before_content' ); // phpcs:ignore WordPress.NamingConventions.ValidHookName.UseUnderscores
293 + do_action( 'elementor/page_templates/header-footer/before_content' );
320 294 }
321 295
322 296 $parent_class = apply_filters( 'rtsb/builder/content/parent_class', [] );
323 297
324 298 if ( BuilderFns::is_product() ) {
325 - $product_id = Fns::get_prepared_product_id();
326 -
327 - // Ensure the WordPress global $product is a valid WC_Product before
328 - // wc_get_product_class() fires the `woocommerce_post_class` filter.
329 - // Some themes (e.g. Blocksy) read the global $product directly inside
330 - // that filter and call methods like get_type() on it, which throws a
331 - // fatal error when the global is still an unresolved string.
332 - $_product = Fns::get_product();
333 -
299 + $product_id = Fns::get_prepared_product_id();
334 300 $parent_class = wc_get_product_class( $parent_class, $product_id );
335 -
336 - if ( function_exists( 'rtwpvs' ) && $_product instanceof \WC_Product ) {
301 + if ( function_exists( 'rtwpvs' ) ) {
302 + $_product = Fns::get_product();
337 303 if ( $_product->is_type( 'variable' ) ) {
338 304 $parent_class[] = 'rtwpvs-product';
339 305 $beside_label = function_exists( 'rtwpvsp' ) && rtwpvs()->get_option( 'attribute_on_click_behavior' );
340 306 if ( $beside_label ) {
@@ -363,34 +329,10 @@
363 329 if ( BuilderFns::is_checkout() ) {
364 330 if ( ! apply_filters( 'rtsb/multi/step/checkout/widget', true ) ) {
365 331 return;
366 332 }
367 -
368 - $checkout = WC()->checkout();
369 -
370 - // Temporarily remove callbacks that Elementor checkout
371 - // handles via separate widgets to prevent duplicates.
372 - remove_action( 'woocommerce_before_checkout_form', [ Hooks\ActionHooks::class, 'woocommerce_checkout_login_form' ], 10 );
373 - remove_action( 'woocommerce_before_checkout_form', [ Hooks\ActionHooks::class, 'woocommerce_checkout_coupon_form' ], 10 );
374 - remove_action( 'woocommerce_before_checkout_form', [ Fns::class, 'woocommerce_output_all_notices' ], 10 );
375 -
376 - do_action( 'woocommerce_before_checkout_form', $checkout );
377 -
378 - // Restore callbacks for non-Elementor contexts.
379 - add_action( 'woocommerce_before_checkout_form', [ Hooks\ActionHooks::class, 'woocommerce_checkout_login_form' ], 10 );
380 - add_action( 'woocommerce_before_checkout_form', [ Hooks\ActionHooks::class, 'woocommerce_checkout_coupon_form' ], 10 );
381 - add_action( 'woocommerce_before_checkout_form', [ Fns::class, 'woocommerce_output_all_notices' ], 10 );
382 -
383 - // If checkout registration is disabled and not logged in, the user cannot checkout.
384 - if ( ! $checkout->is_registration_enabled() && $checkout->is_registration_required() && ! is_user_logged_in() ) {
385 - echo esc_html( apply_filters( 'woocommerce_checkout_must_be_logged_in_message', __( 'You must be logged in to checkout.', 'shopbuilder' ) ) );
386 - return;
387 - }
388 333 ?>
389 - <!--
390 - woocommerce-checkout added for fix issue with payment method ( Revolut Pay )
391 - -->
392 - <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">
334 + <form name="checkout" method="post" class="rtsb-woocommerce-checkout checkout" action="<?php echo esc_url( wc_get_checkout_url() ); ?>" enctype="multipart/form-data">
393 335 <?php
394 336 }
395 337 }
396 338
@@ -407,9 +349,9 @@
407 349 *
408 350 * @since 2.0.0
409 351 */
410 352 if ( did_action( 'elementor/loaded' ) && 'elementor' === $this->page_edit_with ) {
411 - do_action( 'elementor/page_templates/header-footer/after_content' ); // phpcs:ignore WordPress.NamingConventions.ValidHookName.UseUnderscores
353 + do_action( 'elementor/page_templates/header-footer/after_content' );
412 354 }
413 355
414 356 if ( BuilderFns::is_checkout() ) {
415 357 if ( ! apply_filters( 'rtsb/multi/step/checkout/widget', true ) ) {
@@ -417,9 +359,8 @@
417 359 }
418 360 ?>
419 361 </form>
420 362 <?php
421 - do_action( 'woocommerce_after_checkout_form', WC()->checkout() );
422 363 }
423 364 ?>
424 365 </div>
425 366 <!-- After Content end -->
@@ -450,9 +391,9 @@
450 391 }
451 392
452 393 // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.MissingUnslash
453 394 $search = ! empty( $_POST['search'] ) ? sanitize_text_field( $_POST['search'] ) : '';
454 - $results = $post_list = []; // phpcs:ignore Squiz.PHP.DisallowMultipleAssignments.Found
395 + $results = $post_list = [];
455 396 switch ( $source_name ) {
456 397 case 'taxonomy':
457 398 $args = [
458 399 'hide_empty' => false,
@@ -457,13 +398,13 @@
457 398 $args = [
458 399 'hide_empty' => false,
459 400 'orderby' => 'name',
460 401 'order' => 'ASC',
461 - 'name__like' => $search,
402 + 'search' => $search,
462 403 'number' => '5',
463 404 ];
464 405
465 - if ( 'all' !== $post_type ) {
406 + if ( $post_type !== 'all' ) {
466 407 $args['taxonomy'] = $post_type;
467 408 }
468 409
469 410 $post_list = wp_list_pluck( get_terms( $args ), 'name', 'term_id' );
@@ -535,10 +476,10 @@
535 476 'include' => implode( ',', $ids ),
536 477 ];
537 478
538 479 // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotValidated
539 - if ( 'all' !== $_POST['post_type'] ) {
540 - // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotValidated, WordPress.Security.ValidatedSanitizedInput.MissingUnslash
480 + if ( $_POST['post_type'] !== 'all' ) {
481 + // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotValidated, WordPress.Security.ValidatedSanitizedInput.MissingUnslash
541 482 $args['taxonomy'] = sanitize_text_field( $_POST['post_type'] );
542 483 }
543 484
544 485 $response = wp_list_pluck( get_terms( $args ), 'name', 'term_id' );
@@ -574,12 +515,12 @@
574 515
575 516 /**
576 517 * Ajax callback for rt-select2
577 518 *
578 - * @param string $post_type Post type.
579 - * @param int $limit Limit.
580 - * @param string $search Search.
581 - * @param int $paged Paged.
519 + * @param $post_type
520 + * @param $limit
521 + * @param $search
522 + * @param $paged
582 523 *
583 524 * @return array
584 525 */
585 526 public function get_query_data( $post_type = 'any', $limit = 10, $search = '', $paged = 1 ) {
@@ -614,17 +555,8 @@
614 555 }
615 556
616 557 if ( ! empty( $search ) ) {
617 558 $where .= $wpdb->prepare( " AND {$wpdb->posts}.post_title LIKE %s", '%' . esc_sql( $search ) . '%' );
618 - }
619 -
620 - // Add a query for shop_coupon post-type to check 'show on frontend' meta.
621 - if ( 'shop_coupon' === $post_type ) {
622 - $where .= " AND {$wpdb->posts}.ID IN (
623 - SELECT post_id FROM {$wpdb->postmeta}
624 - WHERE meta_key = 'rtsb_show_on_frontend'
625 - AND meta_value = 'on'
626 - )";
627 559 }
628 560
629 561 $query = "select post_title,ID from $wpdb->posts where post_status = 'publish' {$where} {$limit}";
630 562 $results = $wpdb->get_results( $query ); // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.PreparedSQL.NotPrepared, WordPress.DB.DirectDatabaseQuery.NoCaching