PluginProbe
ShopBuilder – WooCommerce Builder For Elementor / 2.6.0
ShopBuilder – WooCommerce Builder For Elementor v2.6.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/Elementor/Render/Render.php +51 -191 3.4.2 → 2.6.0 View file →
@@ -8,9 +8,8 @@
8 8 */
9 9
10 10 namespace RadiusTheme\SB\Elementor\Render;
11 11
12 -use RadiusTheme\SBPRO\Modules\CatalogMode\CatalogModeFns;
13 12 use WC_Query;
14 13 use WP_Query;
15 14 use WC_Product;
16 15 use Elementor\Utils;
@@ -125,14 +124,8 @@
125 124 if ( ! empty( $pagination_attributes ) ) {
126 125 $container_attributes['data-rtsb-ajax'] = $pagination_attributes;
127 126 }
128 127
129 - // Opt-out of the scroll-to-top behaviour on Ajax filter/pagination when
130 - // the "Enable Scroll To Top?" switch is turned off.
131 - if ( isset( $settings['enable_ajax_scroll'] ) && empty( $settings['enable_ajax_scroll'] ) ) {
132 - $container_attributes['data-rtsb-disable-scroll'] = '1';
133 - }
134 -
135 128 // Adding render attributes.
136 129 $this->add_attribute( 'rtsb_container_attr_' . $rand, $container_attributes );
137 130
138 131 // Start rendering.
@@ -254,20 +247,18 @@
254 247
255 248 $i = 0;
256 249
257 250 global $product;
258 -
259 251 $isGlobalProduct = false;
260 -
261 252 if ( $product instanceof WC_Product ) {
262 253 $isGlobalProduct = $product;
263 254 }
264 255
265 - $layout = RenderHelpers::filter_layout( esc_html( $settings['layout'] ), $template );
266 -
267 256 foreach ( $products as $_product ) {
268 257 $i++;
269 - $GLOBALS['product'] = $_product; // phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedVariableFound -- Global variable is intentionally used to share the current product context with hooks and templates during rendering.
258 + $GLOBALS['product'] = $_product;
259 + $layout = RenderHelpers::filter_layout( esc_html( $settings['layout'] ), $template );
260 +
270 261 /**
271 262 * Before product template render hook.
272 263 */
273 264 do_action( 'rtsb_before_product_template_render' );
@@ -285,9 +276,9 @@
285 276
286 277 unset( $GLOBALS['product'] );
287 278 }
288 279 if ( $isGlobalProduct ) {
289 - $GLOBALS['product'] = $isGlobalProduct; // phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedVariableFound -- Global variable is intentionally used to share the current product context with hooks and templates during rendering.
280 + $GLOBALS['product'] = $isGlobalProduct;
290 281 }
291 282 return $html;
292 283 }
293 284
@@ -306,20 +297,19 @@
306 297 if ( empty( $query ) ) {
307 298 return null;
308 299 }
309 300
310 - $i = 0;
311 - $layout = RenderHelpers::filter_layout( esc_html( $settings['layout'] ), $template );
301 + $i = 0;
312 302
313 303 while ( $query->have_posts() ) {
314 304 $query->the_post();
315 305 $i++;
316 - global $product;
306 +
317 307 // Loop arg.
318 - $arg = $this->arg_dataset( $settings, $product, $settings['lazy_load'], $i );
308 + $arg = $this->arg_dataset( $settings, wc_get_product( get_the_ID() ), $settings['lazy_load'], $i );
319 309
320 310 // Get template.
321 - $html .= Fns::load_template( $template . $layout, $arg, true );
311 + $html .= Fns::load_template( $template . $settings['layout'], $arg, true );
322 312 }
323 313
324 314 return $html;
325 315 }
@@ -392,10 +382,10 @@
392 382 * Before Product query hook.
393 383 *
394 384 * @hooked RadiusTheme\SB\Controllers\Hooks\ActionHooks::modify_wc_query_args 10
395 385 */
386 + do_action( 'rtsb/elements/render/before_query', $settings, $args );
396 387
397 - do_action( 'rtsb/elements/render/before_query', $settings, $args );
398 388 // Query.
399 389 $product_query = new WC_Product_Query( $args );
400 390
401 391 /**
@@ -462,21 +452,17 @@
462 452 $this->get_settings = $settings;
463 453 $rand = wp_rand();
464 454 $metas = RenderHelpers::meta_dataset( $settings, $template, $widget->get_settings_for_display() );
465 455
466 - $order = strtoupper( $wp_query->query_vars['order'] ?? 'ASC' );
467 - $settings['rtsb_orderby'] = RenderHelpers::escaping_product_orderby( $wp_query->query_vars['orderby'] ?? 'menu_order' );
468 - $settings['rtsb_order'] = in_array( $order, [ 'ASC','DESC' ], true ) ? $order : 'ASC';
456 + $settings['rtsb_order'] = ! empty( $wp_query->query_vars['order'] ) ? $wp_query->query_vars['order'] : 'ASC';
457 + $settings['rtsb_orderby'] = ! empty( $wp_query->query_vars['orderby'] ) ? $wp_query->query_vars['orderby'] : 'menu_order';
469 458
470 459 $pagination = $metas['pagination'];
471 460
472 - $page_type = BuilderFns::builder_type( get_the_ID() );
473 - $is_preview = BuilderFns::is_builder_preview() && array_key_exists( $page_type, BuilderFns::builder_page_types() );
474 - $raw_settings = $widget->get_settings_for_display();
475 - $widget_per_page = ! empty( $raw_settings['posts_per_page'] ) ? absint( $raw_settings['posts_per_page'] ) : 0;
476 - $wc_per_page = wc_get_default_products_per_row() * wc_get_default_product_rows_per_page();
477 - $posts_per_page = $widget_per_page ? $widget_per_page : apply_filters( 'loop_shop_per_page', $wc_per_page ); // phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedHooknameFound -- woocommerce default hooks used.
478 - $restore_query = false;
461 + $page_type = BuilderFns::builder_type( get_the_ID() );
462 + $is_preview = BuilderFns::is_builder_preview() && array_key_exists( $page_type, BuilderFns::builder_page_types() );
463 + $posts_per_page = wc_get_default_products_per_row() * wc_get_default_product_rows_per_page();
464 +
479 465 if ( $is_preview ) {
480 466 $main_query = clone $wp_query;
481 467 $main_post = clone $post;
482 468
@@ -497,30 +483,12 @@
497 483 $wp_query = new WP_Query( $wp_query_args ); // phpcs:ignore WordPress.WP.GlobalVariablesOverride.Prohibited
498 484
499 485 wc_set_loop_prop( 'total', $wp_query->found_posts );
500 486 wc_set_loop_prop( 'total_pages', $wp_query->max_num_pages );
501 - } elseif ( ! is_admin() && ( is_shop() || is_product_taxonomy() ) && absint( $wp_query->get( 'posts_per_page' ) ) !== $posts_per_page ) {
502 - // Apply widget's posts_per_page to the main query on the live frontend.
503 - $main_query = clone $wp_query;
504 - $main_post = clone $post;
505 -
506 - $query_vars = $wp_query->query_vars;
507 - $query_vars['posts_per_page'] = $posts_per_page;
508 -
509 - $wp_query = new WP_Query( $query_vars ); // phpcs:ignore WordPress.WP.GlobalVariablesOverride.Prohibited
510 -
511 - wc_set_loop_prop( 'total', $wp_query->found_posts );
512 - wc_set_loop_prop( 'total_pages', $wp_query->max_num_pages );
513 -
514 - $restore_query = true;
515 487 }
516 488
517 - if ( rtsb()->has_pro() && ( Fns::product_has_applied_filters( 'shop' ) || Fns::product_has_applied_filters( 'archive' ) || 'rtsb_builder' === get_post_type( get_the_ID() ) ) ) {
518 - $rtsb_active_filters_html = Fns::get_active_filters_html();
519 - $rtsb_wrapper_style = '' !== $rtsb_active_filters_html ? ' style="' . esc_attr( 'display:block;' ) . '"' : '';
520 - echo '<div class="rtsb-active-filters-wrapper"' . $rtsb_wrapper_style . '>'; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- Style value is escaped above.
521 - Fns::print_html( $rtsb_active_filters_html, true );
522 - echo '</div>';
489 + if ( Fns::product_has_applied_filters( 'shop' ) || Fns::product_has_applied_filters( 'archive' ) || 'rtsb_builder' === get_post_type( get_the_ID() ) ) {
490 + echo '<div class="rtsb-active-filters-wrapper"></div>';
523 491 }
524 492
525 493 // column_per_row.
526 494 if ( woocommerce_product_loop() ) {
@@ -530,44 +498,28 @@
530 498 $this->row( $this->wc_product_loop( $wp_query, $metas, $template ), $metas, '', $settings );
531 499 }
532 500
533 501 // Pagination.
534 - $this->html .= '<div class="rtsb-archive-pagination-wrap" data-per-page="' . absint( $posts_per_page ) . '">';
502 + $this->html .= '<div class="rtsb-archive-pagination-wrap">';
535 503
536 504 if ( $pagination ) {
537 505 if ( Fns::product_filters_has_ajax( apply_filters( 'rtsb/builder/set/current/page/type', '' ) ) ) {
538 506 if ( $wp_query->max_num_pages > 1 ) {
539 - $posts_loading_type = ! empty( $metas['posts_loading_type'] ) ? $metas['posts_loading_type'] : 'pagination';
507 + $this->add_attribute(
508 + 'rtsb_load_more_btn_attr_' . $rand,
509 + [
510 + 'data-paged' => '2',
511 + 'data-max-page' => $wp_query->max_num_pages,
512 + ]
513 + );
540 514
541 - if ( 'pagination_ajax' === $posts_loading_type ) {
542 - $this->html .= Fns::custom_pagination( $wp_query->max_num_pages, $posts_per_page, true, $metas['visible_range'] ?? null );
543 - } elseif ( 'pagination' === $posts_loading_type ) {
544 - $this->html .= Fns::custom_pagination( $wp_query->max_num_pages, $posts_per_page, false, $metas['visible_range'] ?? null );
545 - } elseif ( 'load_on_scroll' === $posts_loading_type ) {
546 - $this->html .= "<div class='rtsb-infinite-scroll' data-trigger='1' data-paged='2' data-max-page='{$wp_query->max_num_pages}'>
547 - <div class='rtsb-infinite-action'>
548 - <div class='rtsb-loadmore-loading rtsb-ball-clip-rotate'><div></div></div>
549 - </div>
550 - </div>";
551 - } else {
552 - $load_more_text = ! empty( $metas['load_more_text'] ) ? $metas['load_more_text'] : esc_html__( 'Load More', 'shopbuilder' );
553 -
554 - $this->add_attribute(
555 - 'rtsb_load_more_btn_attr_' . $rand,
556 - [
557 - 'data-paged' => '2',
558 - 'data-max-page' => $wp_query->max_num_pages,
559 - ]
560 - );
561 -
562 - $this->html .=
563 - "<div class='rtsb-load-more rtsb-pos-r'>
564 - <button {$this->get_attribute_string( 'rtsb_load_more_btn_attr_' . $rand )}>
565 - <span>" . esc_html( $load_more_text ) . "</span>
566 - </button>
567 - <div class='rtsb-loadmore-loading rtsb-ball-clip-rotate'><div></div></div>
568 - </div>";
569 - }
515 + $this->html .=
516 + "<div class='rtsb-load-more rtsb-pos-r'>
517 + <button {$this->get_attribute_string( 'rtsb_load_more_btn_attr_' . $rand )}>
518 + <span>" . esc_html__( 'Load More', 'shopbuilder' ) . "</span>
519 + </button>
520 + <div class='rtsb-loadmore-loading rtsb-ball-clip-rotate'><div></div></div>
521 + </div>";
570 522 }
571 523 } else {
572 524 $pagination_args = [
573 525 'query' => $wp_query,
@@ -584,9 +536,9 @@
584 536 } else {
585 537 $this->no_products_msg( $metas );
586 538 }
587 539
588 - if ( $is_preview || ! empty( $restore_query ) ) {
540 + if ( $is_preview ) {
589 541 // phpcs:disable
590 542 $wp_query = $main_query;
591 543 $post = $main_post;
592 544
@@ -594,11 +546,8 @@
594 546 wp_reset_postdata();
595 547 // phpcs:enable
596 548 }
597 549
598 - // Ensure the container's data-rtsb-ajax uses the same posts_per_page as the initial render.
599 - $settings['pagination_per_page'] = $posts_per_page;
600 -
601 550 // Container.
602 551 $this->container( $this->html, $settings, 'rtsb-products-container', $template );
603 552
604 553 return $this->html;
@@ -652,13 +601,8 @@
652 601 *
653 602 * @return string
654 603 */
655 604 public function category_view( $template, $settings, $is_single = false ) {
656 - // Reset the shared singleton's html buffer so leftover markup from a
657 - // previously rendered widget (e.g. a products grid that ran earlier
658 - // in the same request) doesn't get folded into the categories
659 - // container by container() below.
660 - $this->html = '';
661 605 $this->get_settings = $settings;
662 606
663 607 $metas = RenderHelpers::meta_dataset( $settings, $template, $this->get_settings_for_display() );
664 608 $taxonomy = $metas['category_source'];
@@ -666,11 +610,8 @@
666 610
667 611 if ( rtsb()->has_pro() && ( ! empty( $metas['tag_term'] ) ) ) {
668 612 $term = $metas['tag_term'];
669 613 }
670 - if ( rtsb()->has_pro() && ( ! empty( $metas['brand_term'] ) ) ) {
671 - $term = $metas['brand_term'];
672 - }
673 614
674 615 // Query.
675 616 if ( $is_single ) {
676 617 if ( empty( $term ) ) {
@@ -688,9 +629,9 @@
688 629 if ( ! is_wp_error( $taxonomy_query ) && ! empty( $taxonomy_query ) ) {
689 630 // Row.
690 631 $this->row( $this->category_loop( $taxonomy_query, $metas, $template, $is_single ), $metas );
691 632 } else {
692 - $this->html = '<p>' . esc_html__( 'No categories found', 'shopbuilder' ) . '</p>';
633 + $this->html .= '<p>' . esc_html__( 'No categories found', 'shopbuilder' ) . '</p>';
693 634 }
694 635
695 636 // Container.
696 637 $this->container( $this->html, $settings, 'rtsb-categories-container', $is_single );
@@ -771,9 +712,8 @@
771 712 *
772 713 * @return array
773 714 */
774 715 public function wp_arg_dataset( array $meta, int $post_id, bool $lazy_load = false, $i = 0 ) {
775 - // phpcs:ignore WordPress.PHP.StrictInArray.MissingTrueStrict
776 716 if ( ( empty( $meta ) && ! $post_id ) || ! in_array( get_post_type( $post_id ), [ 'product_variation', 'product' ] ) ) {
777 717 return [];
778 718 }
779 719
@@ -779,9 +719,9 @@
779 719
780 720 global $product;
781 721
782 722 if ( ! $product instanceof WC_Product && $post_id ) {
783 - $product = wc_get_product( $post_id ); // phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedVariableFound -- Global variable is intentionally used to share the current product context with hooks and templates during rendering.
723 + $product = wc_get_product( $post_id );
784 724 }
785 725
786 726 $post_id = $product->get_id();
787 727 $arg = $this->build_product_arg(
@@ -1058,23 +998,8 @@
1058 998 ]
1059 999 );
1060 1000 }
1061 1001 }
1062 - if ( Fns::is_catalog_mode() && empty( $arg['add_to_cart'] ) ) {
1063 - if ( ! empty( $meta['add_to_cart_icon'] ) ) {
1064 - $cart_icon_html = Fns::icons_manager( $meta['add_to_cart_icon'], 'cart-icon' );
1065 - }
1066 - $cart_icon = ! empty( $cart_icon_html ) ? '<span class="icon">' . $cart_icon_html . '</span>' : '';
1067 - $arg['add_to_cart'] = CatalogModeFns::render_elementor_widget_catalog_mode_button(
1068 - [
1069 - 'id' => $post_id,
1070 - 'type' => $p_type,
1071 - 'text' => $meta['add_to_cart_text'],
1072 - 'icon_html' => $cart_icon,
1073 - 'alignment' => $meta['add_to_cart_alignment'],
1074 - ]
1075 - );
1076 - }
1077 1002 }
1078 1003
1079 1004 if ( in_array( 'quick_view', $meta['visibility'], true ) ) {
1080 1005 add_filter( 'rtsb/module/quick_view/button_params', [ $this, 'button_classes' ] );
@@ -1090,26 +1015,8 @@
1090 1015 add_filter( 'rtsb/module/wishlist/button_params', [ $this, 'button_classes' ] );
1091 1016 add_filter( 'rtsb/module/wishlist/icon_html', [ $this, 'wishlist_icon' ] );
1092 1017 }
1093 1018
1094 - // Eager-load the above-the-fold product images so the LCP candidate is
1095 - // fetched immediately instead of being lazy-loaded after render-blocking
1096 - // CSS and layout. Defaults to the mobile viewport row count (Lighthouse
1097 - // scores mobile); eagering below-the-fold images would only steal
1098 - // bandwidth from the visible ones. Filterable per layout.
1099 - $eager_count = (int) apply_filters( 'rtsb/loop/eager_image_count', 6, $meta );
1100 -
1101 - // The mobile LCP is often NOT the first card but the top-right one in a
1102 - // 2-column grid, so the first *row* of images gets fetchpriority=high to
1103 - // promote the real LCP candidate ahead of render-blocking CSS. Kept small
1104 - // (default 2 = one mobile row) to avoid competing high-priority requests.
1105 - $high_count = (int) apply_filters( 'rtsb/loop/fetchpriority_high_count', 2, $meta );
1106 - $img_priority = false;
1107 -
1108 - if ( $i <= $eager_count ) {
1109 - $img_priority = $i <= $high_count ? 'high' : 'eager';
1110 - }
1111 -
1112 1019 $arg['img_html'] = $meta['f_img'] ? Fns::get_product_image_html(
1113 1020 'product',
1114 1021 $post_id,
1115 1022 $meta['f_img_size'],
@@ -1114,13 +1021,9 @@
1114 1021 $post_id,
1115 1022 $meta['f_img_size'],
1116 1023 $meta['default_img_id'],
1117 1024 $meta['custom_img_size'],
1118 - $lazy_load,
1119 - false,
1120 - false,
1121 - 0,
1122 - $img_priority
1025 + $lazy_load
1123 1026 ) : null;
1124 1027
1125 1028 if ( ! ( function_exists( 'rtwpvsp' ) && $product->is_type( 'variable' ) && $product->get_attributes() ) ) {
1126 1029 $gallery_ids = $product->get_gallery_image_ids();
@@ -1161,8 +1064,9 @@
1161 1064 ];
1162 1065
1163 1066 return $arg;
1164 1067 }
1068 +
1165 1069 /**
1166 1070 * Renders add to cart button.
1167 1071 *
1168 1072 * @param array $args Cart args.
@@ -1192,8 +1096,9 @@
1192 1096
1193 1097 $cart_attr = [
1194 1098 'class' => 'rtsb-action-btn ' . $type . '-product tipsy icon-' . $alignment . ' ' . ( empty( $text ) ? 'no-text' : 'has-text' ),
1195 1099 'href' => esc_url( $link ),
1100 + 'rel' => 'nofollow',
1196 1101 'data-quantity' => '1',
1197 1102 'data-product_id' => absint( $id ),
1198 1103 'data-id' => absint( $id ),
1199 1104 ];
@@ -1199,13 +1104,12 @@
1199 1104 ];
1200 1105
1201 1106 if ( empty( $text ) ) {
1202 1107 $tooltip_mapping = [
1203 - 'simple' => esc_attr__( 'Add to Cart', 'shopbuilder' ),
1204 - 'variable' => esc_attr__( 'Select Options', 'shopbuilder' ),
1205 - 'grouped' => esc_attr__( 'View Products', 'shopbuilder' ),
1206 - 'external' => ! empty( $btn_txt ) ? esc_html( $btn_txt ) : esc_html__( 'Buy Product', 'shopbuilder' ),
1207 - 'rtsb-gift-card' => esc_attr__( 'Select Gift Card', 'shopbuilder' ),
1108 + 'simple' => esc_attr__( 'Add to Cart', 'shopbuilder' ),
1109 + 'variable' => esc_attr__( 'Select Options', 'shopbuilder' ),
1110 + 'grouped' => esc_attr__( 'View Products', 'shopbuilder' ),
1111 + 'external' => ! empty( $btn_txt ) ? esc_html( $btn_txt ) : esc_html__( 'Buy Product', 'shopbuilder' ),
1208 1112 ];
1209 1113
1210 1114 $cart_attr['title'] = $tooltip_mapping[ $type ];
1211 1115 }
@@ -1210,26 +1114,20 @@
1210 1114 $cart_attr['title'] = $tooltip_mapping[ $type ];
1211 1115 }
1212 1116
1213 1117 $content .= '<div class="rtsb-wc-add-to-cart-wrap">';
1214 - if ( 'variable' === $type ) {
1215 - $cart_attr['class'] = $cart_attr['class'] . ' rtsb_vs_add_to_cart ';
1216 - }
1118 +
1217 1119 if ( 'variable' === $type || 'grouped' === $type ) {
1218 1120 $cart_attr = apply_filters( 'rtsb/elementor/render/cart_attributes', $cart_attr, $product );
1219 1121
1220 1122 $this->add_attribute( 'rtsb_add_to_cart_button_' . $id . $rand, $cart_attr );
1221 1123
1222 - $text_btn = apply_filters(
1223 - 'rtsb/elementor/render/add_to_cart_text',
1224 - 'grouped' === $type ? __( 'View Products', 'shopbuilder' ) : __( 'Select Options', 'shopbuilder' ),
1225 - $product,
1226 - $type
1227 - );
1124 + $text_btn = 'grouped' === $type ? __( 'View Products', 'shopbuilder' ) : __( 'Select Options', 'shopbuilder' );
1228 1125
1229 1126 $content .= '<a ' . $this->get_attribute_string( 'rtsb_add_to_cart_button_' . $id . $rand ) . '>';
1230 1127 $content .= $icon_html;
1231 - $content .= '<span class="button-text text ' . ( ! empty( $success ) ? 'has-success-text' : 'no-success-text' ) . '" data-success="' . esc_html( $success ) . '" data-cart-text="' . ( ! empty( $text ) ? esc_attr( $text ) : $tooltip_mapping['simple'] ) . '" data-variable-text="' . esc_attr( $text_btn ) . '">' . esc_html( $text_btn ) . '</span>';
1128 + $content .= '<span class="text ' . ( ! empty( $success ) ? 'has-success-text' : 'no-success-text' ) . '" data-success="' . esc_html( $success ) . '" data-cart-text="' . ( ! empty( $text ) ? esc_attr( $text ) : $tooltip_mapping['simple'] ) . '" data-variable-text="' . esc_attr( $text_btn ) . '">' . esc_html( $text_btn ) . '</span>';
1129 + $content .= '<span></span>';
1232 1130 } elseif ( 'external' === $type ) {
1233 1131 if ( ! empty( $ext_link ) ) {
1234 1132 $cart_attr['target'] = '_blank';
1235 1133 }
@@ -1239,9 +1137,9 @@
1239 1137 $this->add_attribute( 'rtsb_add_to_cart_button_' . $id . $rand, $cart_attr );
1240 1138
1241 1139 $content .= '<a ' . $this->get_attribute_string( 'rtsb_add_to_cart_button_' . $id . $rand ) . '>';
1242 1140 $content .= $icon_html;
1243 - $content .= '<span class="button-text text">' . ( ! empty( $btn_txt ) ? esc_html( $btn_txt ) : esc_html__( 'Buy Product', 'shopbuilder' ) ) . '</span>';
1141 + $content .= '<span class="text">' . ( ! empty( $btn_txt ) ? esc_html( $btn_txt ) : esc_html__( 'Buy Product', 'shopbuilder' ) ) . '</span>';
1244 1142 } else {
1245 1143 $cart_attr['href'] = $cart_attr['href'] . '?add-to-cart=' . absint( $id );
1246 1144 $cart_attr['class'] .= ' rtsb-add-to-cart-btn';
1247 1145 $cart_attr['data-type'] = $type;
@@ -1250,9 +1148,10 @@
1250 1148 $this->add_attribute( 'rtsb_add_to_cart_button_' . $id . $rand, $cart_attr );
1251 1149
1252 1150 $content .= '<a ' . $this->get_attribute_string( 'rtsb_add_to_cart_button_' . $id . $rand ) . '>';
1253 1151 $content .= $icon_html;
1254 - $content .= '<span class="button-text text ' . ( ! empty( $success ) ? 'has-success-text' : 'no-success-text' ) . '" data-success="' . esc_html( $success ) . '">' . esc_html( $text ) . '</span>';
1152 + $content .= '<span class="text ' . ( ! empty( $success ) ? 'has-success-text' : 'no-success-text' ) . '" data-success="' . esc_html( $success ) . '">' . esc_html( $text ) . '</span>';
1153 + $content .= '<span></span>';
1255 1154 }
1256 1155
1257 1156 $content .= '</a>';
1258 1157 $content .= '</div>';
@@ -1353,24 +1252,11 @@
1353 1252 if ( 'pagination' === $meta['posts_loading_type'] ) {
1354 1253 if ( $is_grid ) {
1355 1254 $html_utility .= Fns::custom_pagination(
1356 1255 $total_page,
1357 - 'wc' === $query_type ? $per_page : $posts_per_page,
1358 - false,
1359 - $meta['visible_range'] ?? null
1256 + 'wc' === $query_type ? $per_page : $posts_per_page
1360 1257 );
1361 1258 }
1362 - } elseif ( 'pagination_ajax' === $meta['posts_loading_type'] && ! rtsb()->has_pro() ) {
1363 - // Free version fallback: render non-AJAX number pagination so filter
1364 - // params in the URL are preserved via get_pagenum_link().
1365 - if ( $is_grid ) {
1366 - $html_utility .= Fns::custom_pagination(
1367 - $total_page,
1368 - 'wc' === $query_type ? $per_page : $posts_per_page,
1369 - false,
1370 - $meta['visible_range'] ?? null
1371 - );
1372 - }
1373 1259 } else {
1374 1260 ob_start();
1375 1261 do_action( 'rtsb/elementor/render/pagination', $meta, $query, $args );
1376 1262 $html_utility .= ob_get_clean();
@@ -1575,14 +1461,9 @@
1575 1461 if ( empty( $this->attributes[ $element ] ) ) {
1576 1462 return '';
1577 1463 }
1578 1464
1579 - if ( class_exists( '\Elementor\Utils' ) ) {
1580 - return Utils::render_html_attributes( $this->attributes[ $element ] );
1581 - }
1582 -
1583 - // Fallback.
1584 - return $this->render_fallback_attributes( $this->attributes[ $element ] );
1465 + return Utils::render_html_attributes( $this->attributes[ $element ] );
1585 1466 }
1586 1467
1587 1468 /**
1588 1469 * Function to render link attributes.
@@ -1602,27 +1483,6 @@
1602 1483 $this->add_attribute( $id, 'role', 'button' );
1603 1484 }
1604 1485
1605 1486 return $this->get_attribute_string( $id );
1606 - }
1607 -
1608 - /**
1609 - * Render fallback attributes.
1610 - *
1611 - * @param array $attributes The attributes.
1612 - *
1613 - * @return string
1614 - */
1615 - private function render_fallback_attributes( $attributes ) {
1616 - $rendered_attributes = [];
1617 -
1618 - foreach ( $attributes as $attribute_key => $attribute_values ) {
1619 - if ( is_array( $attribute_values ) ) {
1620 - $attribute_values = implode( ' ', $attribute_values );
1621 - }
1622 -
1623 - $rendered_attributes[] = sprintf( '%1$s="%2$s"', $attribute_key, esc_attr( $attribute_values ) );
1624 - }
1625 -
1626 - return implode( ' ', $rendered_attributes );
1627 1487 }
1628 1488 }