PluginProbe
ShopBuilder – WooCommerce Builder For Elementor / 3.2.6
ShopBuilder – WooCommerce Builder For Elementor v3.2.6
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 +18 -78 3.4.23.2.6 View file →
@@ -125,14 +125,8 @@
125 125 if ( ! empty( $pagination_attributes ) ) {
126 126 $container_attributes['data-rtsb-ajax'] = $pagination_attributes;
127 127 }
128 128
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 129 // Adding render attributes.
136 130 $this->add_attribute( 'rtsb_container_attr_' . $rand, $container_attributes );
137 131
138 132 // Start rendering.
@@ -468,15 +462,11 @@
468 462 $settings['rtsb_order'] = in_array( $order, [ 'ASC','DESC' ], true ) ? $order : 'ASC';
469 463
470 464 $pagination = $metas['pagination'];
471 465
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;
466 + $page_type = BuilderFns::builder_type( get_the_ID() );
467 + $is_preview = BuilderFns::is_builder_preview() && array_key_exists( $page_type, BuilderFns::builder_page_types() );
468 + $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 469 if ( $is_preview ) {
480 470 $main_query = clone $wp_query;
481 471 $main_post = clone $post;
482 472
@@ -497,30 +487,12 @@
497 487 $wp_query = new WP_Query( $wp_query_args ); // phpcs:ignore WordPress.WP.GlobalVariablesOverride.Prohibited
498 488
499 489 wc_set_loop_prop( 'total', $wp_query->found_posts );
500 490 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 491 }
516 492
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>';
493 + if ( Fns::product_has_applied_filters( 'shop' ) || Fns::product_has_applied_filters( 'archive' ) || 'rtsb_builder' === get_post_type( get_the_ID() ) ) {
494 + echo '<div class="rtsb-active-filters-wrapper"></div>';
523 495 }
524 496
525 497 // column_per_row.
526 498 if ( woocommerce_product_loop() ) {
@@ -530,9 +502,9 @@
530 502 $this->row( $this->wc_product_loop( $wp_query, $metas, $template ), $metas, '', $settings );
531 503 }
532 504
533 505 // Pagination.
534 - $this->html .= '<div class="rtsb-archive-pagination-wrap" data-per-page="' . absint( $posts_per_page ) . '">';
506 + $this->html .= '<div class="rtsb-archive-pagination-wrap">';
535 507
536 508 if ( $pagination ) {
537 509 if ( Fns::product_filters_has_ajax( apply_filters( 'rtsb/builder/set/current/page/type', '' ) ) ) {
538 510 if ( $wp_query->max_num_pages > 1 ) {
@@ -538,11 +510,11 @@
538 510 if ( $wp_query->max_num_pages > 1 ) {
539 511 $posts_loading_type = ! empty( $metas['posts_loading_type'] ) ? $metas['posts_loading_type'] : 'pagination';
540 512
541 513 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 );
514 + $this->html .= Fns::custom_pagination( $wp_query->max_num_pages, $posts_per_page, true );
543 515 } elseif ( 'pagination' === $posts_loading_type ) {
544 - $this->html .= Fns::custom_pagination( $wp_query->max_num_pages, $posts_per_page, false, $metas['visible_range'] ?? null );
516 + $this->html .= Fns::custom_pagination( $wp_query->max_num_pages, $posts_per_page, false );
545 517 } elseif ( 'load_on_scroll' === $posts_loading_type ) {
546 518 $this->html .= "<div class='rtsb-infinite-scroll' data-trigger='1' data-paged='2' data-max-page='{$wp_query->max_num_pages}'>
547 519 <div class='rtsb-infinite-action'>
548 520 <div class='rtsb-loadmore-loading rtsb-ball-clip-rotate'><div></div></div>
@@ -584,9 +556,9 @@
584 556 } else {
585 557 $this->no_products_msg( $metas );
586 558 }
587 559
588 - if ( $is_preview || ! empty( $restore_query ) ) {
560 + if ( $is_preview ) {
589 561 // phpcs:disable
590 562 $wp_query = $main_query;
591 563 $post = $main_post;
592 564
@@ -594,11 +566,8 @@
594 566 wp_reset_postdata();
595 567 // phpcs:enable
596 568 }
597 569
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 570 // Container.
602 571 $this->container( $this->html, $settings, 'rtsb-products-container', $template );
603 572
604 573 return $this->html;
@@ -652,13 +621,8 @@
652 621 *
653 622 * @return string
654 623 */
655 624 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 625 $this->get_settings = $settings;
662 626
663 627 $metas = RenderHelpers::meta_dataset( $settings, $template, $this->get_settings_for_display() );
664 628 $taxonomy = $metas['category_source'];
@@ -688,9 +652,9 @@
688 652 if ( ! is_wp_error( $taxonomy_query ) && ! empty( $taxonomy_query ) ) {
689 653 // Row.
690 654 $this->row( $this->category_loop( $taxonomy_query, $metas, $template, $is_single ), $metas );
691 655 } else {
692 - $this->html = '<p>' . esc_html__( 'No categories found', 'shopbuilder' ) . '</p>';
656 + $this->html .= '<p>' . esc_html__( 'No categories found', 'shopbuilder' ) . '</p>';
693 657 }
694 658
695 659 // Container.
696 660 $this->container( $this->html, $settings, 'rtsb-categories-container', $is_single );
@@ -1090,26 +1054,8 @@
1090 1054 add_filter( 'rtsb/module/wishlist/button_params', [ $this, 'button_classes' ] );
1091 1055 add_filter( 'rtsb/module/wishlist/icon_html', [ $this, 'wishlist_icon' ] );
1092 1056 }
1093 1057
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 1058 $arg['img_html'] = $meta['f_img'] ? Fns::get_product_image_html(
1113 1059 'product',
1114 1060 $post_id,
1115 1061 $meta['f_img_size'],
@@ -1114,13 +1060,9 @@
1114 1060 $post_id,
1115 1061 $meta['f_img_size'],
1116 1062 $meta['default_img_id'],
1117 1063 $meta['custom_img_size'],
1118 - $lazy_load,
1119 - false,
1120 - false,
1121 - 0,
1122 - $img_priority
1064 + $lazy_load
1123 1065 ) : null;
1124 1066
1125 1067 if ( ! ( function_exists( 'rtwpvsp' ) && $product->is_type( 'variable' ) && $product->get_attributes() ) ) {
1126 1068 $gallery_ids = $product->get_gallery_image_ids();
@@ -1227,9 +1169,10 @@
1227 1169 );
1228 1170
1229 1171 $content .= '<a ' . $this->get_attribute_string( 'rtsb_add_to_cart_button_' . $id . $rand ) . '>';
1230 1172 $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>';
1173 + $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>';
1174 + $content .= '<span></span>';
1232 1175 } elseif ( 'external' === $type ) {
1233 1176 if ( ! empty( $ext_link ) ) {
1234 1177 $cart_attr['target'] = '_blank';
1235 1178 }
@@ -1239,9 +1182,9 @@
1239 1182 $this->add_attribute( 'rtsb_add_to_cart_button_' . $id . $rand, $cart_attr );
1240 1183
1241 1184 $content .= '<a ' . $this->get_attribute_string( 'rtsb_add_to_cart_button_' . $id . $rand ) . '>';
1242 1185 $content .= $icon_html;
1243 - $content .= '<span class="button-text text">' . ( ! empty( $btn_txt ) ? esc_html( $btn_txt ) : esc_html__( 'Buy Product', 'shopbuilder' ) ) . '</span>';
1186 + $content .= '<span class="text">' . ( ! empty( $btn_txt ) ? esc_html( $btn_txt ) : esc_html__( 'Buy Product', 'shopbuilder' ) ) . '</span>';
1244 1187 } else {
1245 1188 $cart_attr['href'] = $cart_attr['href'] . '?add-to-cart=' . absint( $id );
1246 1189 $cart_attr['class'] .= ' rtsb-add-to-cart-btn';
1247 1190 $cart_attr['data-type'] = $type;
@@ -1250,9 +1193,10 @@
1250 1193 $this->add_attribute( 'rtsb_add_to_cart_button_' . $id . $rand, $cart_attr );
1251 1194
1252 1195 $content .= '<a ' . $this->get_attribute_string( 'rtsb_add_to_cart_button_' . $id . $rand ) . '>';
1253 1196 $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>';
1197 + $content .= '<span class="text ' . ( ! empty( $success ) ? 'has-success-text' : 'no-success-text' ) . '" data-success="' . esc_html( $success ) . '">' . esc_html( $text ) . '</span>';
1198 + $content .= '<span></span>';
1255 1199 }
1256 1200
1257 1201 $content .= '</a>';
1258 1202 $content .= '</div>';
@@ -1353,11 +1297,9 @@
1353 1297 if ( 'pagination' === $meta['posts_loading_type'] ) {
1354 1298 if ( $is_grid ) {
1355 1299 $html_utility .= Fns::custom_pagination(
1356 1300 $total_page,
1357 - 'wc' === $query_type ? $per_page : $posts_per_page,
1358 - false,
1359 - $meta['visible_range'] ?? null
1301 + 'wc' === $query_type ? $per_page : $posts_per_page
1360 1302 );
1361 1303 }
1362 1304 } elseif ( 'pagination_ajax' === $meta['posts_loading_type'] && ! rtsb()->has_pro() ) {
1363 1305 // Free version fallback: render non-AJAX number pagination so filter
@@ -1364,11 +1306,9 @@
1364 1306 // params in the URL are preserved via get_pagenum_link().
1365 1307 if ( $is_grid ) {
1366 1308 $html_utility .= Fns::custom_pagination(
1367 1309 $total_page,
1368 - 'wc' === $query_type ? $per_page : $posts_per_page,
1369 - false,
1370 - $meta['visible_range'] ?? null
1310 + 'wc' === $query_type ? $per_page : $posts_per_page
1371 1311 );
1372 1312 }
1373 1313 } else {
1374 1314 ob_start();