PluginProbe
ShopBuilder – WooCommerce Builder For Elementor / 3.2.3
ShopBuilder – WooCommerce Builder For Elementor v3.2.3
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 +30 -130 3.4.2 → 3.2.3 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.
@@ -468,15 +461,11 @@
468 461 $settings['rtsb_order'] = in_array( $order, [ 'ASC','DESC' ], true ) ? $order : 'ASC';
469 462
470 463 $pagination = $metas['pagination'];
471 464
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;
465 + $page_type = BuilderFns::builder_type( get_the_ID() );
466 + $is_preview = BuilderFns::is_builder_preview() && array_key_exists( $page_type, BuilderFns::builder_page_types() );
467 + $posts_per_page = apply_filters( 'loop_shop_per_page', wc_get_default_products_per_row() * wc_get_default_product_rows_per_page() ); // phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedHooknameFound -- woocommerce default hooks used.
479 468 if ( $is_preview ) {
480 469 $main_query = clone $wp_query;
481 470 $main_post = clone $post;
482 471
@@ -497,30 +486,12 @@
497 486 $wp_query = new WP_Query( $wp_query_args ); // phpcs:ignore WordPress.WP.GlobalVariablesOverride.Prohibited
498 487
499 488 wc_set_loop_prop( 'total', $wp_query->found_posts );
500 489 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 490 }
516 491
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>';
492 + if ( Fns::product_has_applied_filters( 'shop' ) || Fns::product_has_applied_filters( 'archive' ) || 'rtsb_builder' === get_post_type( get_the_ID() ) ) {
493 + echo '<div class="rtsb-active-filters-wrapper"></div>';
523 494 }
524 495
525 496 // column_per_row.
526 497 if ( woocommerce_product_loop() ) {
@@ -530,44 +501,28 @@
530 501 $this->row( $this->wc_product_loop( $wp_query, $metas, $template ), $metas, '', $settings );
531 502 }
532 503
533 504 // Pagination.
534 - $this->html .= '<div class="rtsb-archive-pagination-wrap" data-per-page="' . absint( $posts_per_page ) . '">';
505 + $this->html .= '<div class="rtsb-archive-pagination-wrap">';
535 506
536 507 if ( $pagination ) {
537 508 if ( Fns::product_filters_has_ajax( apply_filters( 'rtsb/builder/set/current/page/type', '' ) ) ) {
538 509 if ( $wp_query->max_num_pages > 1 ) {
539 - $posts_loading_type = ! empty( $metas['posts_loading_type'] ) ? $metas['posts_loading_type'] : 'pagination';
510 + $this->add_attribute(
511 + 'rtsb_load_more_btn_attr_' . $rand,
512 + [
513 + 'data-paged' => '2',
514 + 'data-max-page' => $wp_query->max_num_pages,
515 + ]
516 + );
540 517
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 - }
518 + $this->html .=
519 + "<div class='rtsb-load-more rtsb-pos-r'>
520 + <button {$this->get_attribute_string( 'rtsb_load_more_btn_attr_' . $rand )}>
521 + <span>" . esc_html__( 'Load More', 'shopbuilder' ) . "</span>
522 + </button>
523 + <div class='rtsb-loadmore-loading rtsb-ball-clip-rotate'><div></div></div>
524 + </div>";
570 525 }
571 526 } else {
572 527 $pagination_args = [
573 528 'query' => $wp_query,
@@ -584,9 +539,9 @@
584 539 } else {
585 540 $this->no_products_msg( $metas );
586 541 }
587 542
588 - if ( $is_preview || ! empty( $restore_query ) ) {
543 + if ( $is_preview ) {
589 544 // phpcs:disable
590 545 $wp_query = $main_query;
591 546 $post = $main_post;
592 547
@@ -594,11 +549,8 @@
594 549 wp_reset_postdata();
595 550 // phpcs:enable
596 551 }
597 552
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 553 // Container.
602 554 $this->container( $this->html, $settings, 'rtsb-products-container', $template );
603 555
604 556 return $this->html;
@@ -652,13 +604,8 @@
652 604 *
653 605 * @return string
654 606 */
655 607 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 608 $this->get_settings = $settings;
662 609
663 610 $metas = RenderHelpers::meta_dataset( $settings, $template, $this->get_settings_for_display() );
664 611 $taxonomy = $metas['category_source'];
@@ -688,9 +635,9 @@
688 635 if ( ! is_wp_error( $taxonomy_query ) && ! empty( $taxonomy_query ) ) {
689 636 // Row.
690 637 $this->row( $this->category_loop( $taxonomy_query, $metas, $template, $is_single ), $metas );
691 638 } else {
692 - $this->html = '<p>' . esc_html__( 'No categories found', 'shopbuilder' ) . '</p>';
639 + $this->html .= '<p>' . esc_html__( 'No categories found', 'shopbuilder' ) . '</p>';
693 640 }
694 641
695 642 // Container.
696 643 $this->container( $this->html, $settings, 'rtsb-categories-container', $is_single );
@@ -1058,23 +1005,8 @@
1058 1005 ]
1059 1006 );
1060 1007 }
1061 1008 }
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 1009 }
1078 1010
1079 1011 if ( in_array( 'quick_view', $meta['visibility'], true ) ) {
1080 1012 add_filter( 'rtsb/module/quick_view/button_params', [ $this, 'button_classes' ] );
@@ -1090,26 +1022,8 @@
1090 1022 add_filter( 'rtsb/module/wishlist/button_params', [ $this, 'button_classes' ] );
1091 1023 add_filter( 'rtsb/module/wishlist/icon_html', [ $this, 'wishlist_icon' ] );
1092 1024 }
1093 1025
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 1026 $arg['img_html'] = $meta['f_img'] ? Fns::get_product_image_html(
1113 1027 'product',
1114 1028 $post_id,
1115 1029 $meta['f_img_size'],
@@ -1114,13 +1028,9 @@
1114 1028 $post_id,
1115 1029 $meta['f_img_size'],
1116 1030 $meta['default_img_id'],
1117 1031 $meta['custom_img_size'],
1118 - $lazy_load,
1119 - false,
1120 - false,
1121 - 0,
1122 - $img_priority
1032 + $lazy_load
1123 1033 ) : null;
1124 1034
1125 1035 if ( ! ( function_exists( 'rtwpvsp' ) && $product->is_type( 'variable' ) && $product->get_attributes() ) ) {
1126 1036 $gallery_ids = $product->get_gallery_image_ids();
@@ -1161,8 +1071,9 @@
1161 1071 ];
1162 1072
1163 1073 return $arg;
1164 1074 }
1075 +
1165 1076 /**
1166 1077 * Renders add to cart button.
1167 1078 *
1168 1079 * @param array $args Cart args.
@@ -1227,9 +1138,10 @@
1227 1138 );
1228 1139
1229 1140 $content .= '<a ' . $this->get_attribute_string( 'rtsb_add_to_cart_button_' . $id . $rand ) . '>';
1230 1141 $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>';
1142 + $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>';
1143 + $content .= '<span></span>';
1232 1144 } elseif ( 'external' === $type ) {
1233 1145 if ( ! empty( $ext_link ) ) {
1234 1146 $cart_attr['target'] = '_blank';
1235 1147 }
@@ -1239,9 +1151,9 @@
1239 1151 $this->add_attribute( 'rtsb_add_to_cart_button_' . $id . $rand, $cart_attr );
1240 1152
1241 1153 $content .= '<a ' . $this->get_attribute_string( 'rtsb_add_to_cart_button_' . $id . $rand ) . '>';
1242 1154 $content .= $icon_html;
1243 - $content .= '<span class="button-text text">' . ( ! empty( $btn_txt ) ? esc_html( $btn_txt ) : esc_html__( 'Buy Product', 'shopbuilder' ) ) . '</span>';
1155 + $content .= '<span class="text">' . ( ! empty( $btn_txt ) ? esc_html( $btn_txt ) : esc_html__( 'Buy Product', 'shopbuilder' ) ) . '</span>';
1244 1156 } else {
1245 1157 $cart_attr['href'] = $cart_attr['href'] . '?add-to-cart=' . absint( $id );
1246 1158 $cart_attr['class'] .= ' rtsb-add-to-cart-btn';
1247 1159 $cart_attr['data-type'] = $type;
@@ -1250,9 +1162,10 @@
1250 1162 $this->add_attribute( 'rtsb_add_to_cart_button_' . $id . $rand, $cart_attr );
1251 1163
1252 1164 $content .= '<a ' . $this->get_attribute_string( 'rtsb_add_to_cart_button_' . $id . $rand ) . '>';
1253 1165 $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>';
1166 + $content .= '<span class="text ' . ( ! empty( $success ) ? 'has-success-text' : 'no-success-text' ) . '" data-success="' . esc_html( $success ) . '">' . esc_html( $text ) . '</span>';
1167 + $content .= '<span></span>';
1255 1168 }
1256 1169
1257 1170 $content .= '</a>';
1258 1171 $content .= '</div>';
@@ -1353,22 +1266,9 @@
1353 1266 if ( 'pagination' === $meta['posts_loading_type'] ) {
1354 1267 if ( $is_grid ) {
1355 1268 $html_utility .= Fns::custom_pagination(
1356 1269 $total_page,
1357 - 'wc' === $query_type ? $per_page : $posts_per_page,
1358 - false,
1359 - $meta['visible_range'] ?? null
1360 - );
1361 - }
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
1270 + 'wc' === $query_type ? $per_page : $posts_per_page
1371 1271 );
1372 1272 }
1373 1273 } else {
1374 1274 ob_start();