PluginProbe
ShopBuilder – WooCommerce Builder For Elementor / 2.6.4
ShopBuilder – WooCommerce Builder For Elementor v2.6.4
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 +132 -27 2.1.32.6.4 View file →
@@ -85,9 +85,10 @@
85 85 public function container( $content, $settings, $class = '', $template = '', $fullwidth = false, $ajax = true ) {
86 86 $rand = wp_rand();
87 87 $layout_id = 'rtsb-container-' . $rand;
88 88 $metas = RenderHelpers::meta_dataset( $settings, $template );
89 - $layout = $metas['layout'];
89 + $raw_layout = esc_html( $metas['layout'] );
90 + $layout = RenderHelpers::filter_layout( $raw_layout, $template );
90 91 $style_attr = '--rtsb-default-columns: ' . esc_attr( RenderHelpers::default_columns( $layout ) );
91 92 $view_mode = $settings['view_mode'] ?? 'grid';
92 93 $view_mode = isset( $_GET['displayview'] ) ? sanitize_text_field( wp_unslash( $_GET['displayview'] ) ) : $view_mode; // phpcs:ignore WordPress.Security.NonceVerification.Recommended
93 94 $tooltip_attr = 'list' == $view_mode && ! empty( $metas['tooltip_position_list'] ) ? esc_attr( $metas['tooltip_position_list'] ) : $metas['tooltip_position'];
@@ -92,8 +93,9 @@
92 93 $view_mode = isset( $_GET['displayview'] ) ? sanitize_text_field( wp_unslash( $_GET['displayview'] ) ) : $view_mode; // phpcs:ignore WordPress.Security.NonceVerification.Recommended
93 94 $tooltip_attr = 'list' == $view_mode && ! empty( $metas['tooltip_position_list'] ) ? esc_attr( $metas['tooltip_position_list'] ) : $metas['tooltip_position'];
94 95 $has_pro = rtsb()->has_pro();
95 96 $has_filters = $has_pro && ! empty( $settings['tax_filter'] );
97 + $grid_style = $settings['grid_style'] ?? 'even';
96 98
97 99 // Set default layout.
98 100 if ( ! $has_pro && ! in_array( $layout, array_keys( Fns::free_layouts() ), true ) ) {
99 101 $layout = RenderHelpers::set_default_layout( $layout );
@@ -98,8 +100,13 @@
98 100 if ( ! $has_pro && ! in_array( $layout, array_keys( Fns::free_layouts() ), true ) ) {
99 101 $layout = RenderHelpers::set_default_layout( $layout );
100 102 }
101 103
104 + if ( $has_pro && 'masonry' === $grid_style ) {
105 + $style_attr .= '; --rtsb-masonry-columns: ' . esc_attr( RenderHelpers::default_columns( $layout ) );
106 + $style_attr .= '; --rtsb-masonry-list-columns: ' . esc_attr( RenderHelpers::default_columns( $layout ) );
107 + }
108 +
102 109 // Container classes.
103 110 $container_classes = RenderHelpers::prepare_container_classes( $metas, $settings, $class );
104 111
105 112 // Pagination attributes.
@@ -108,9 +115,9 @@
108 115 // Attributes for the container.
109 116 $container_attributes = [
110 117 'id' => $layout_id,
111 118 'class' => $container_classes,
112 - 'style' => $style_attr,
119 + 'style' => apply_filters( 'rtsb/product/container/attr', $style_attr, $settings ),
113 120 'data-layout' => $layout,
114 121 'data-tooltip-position' => $tooltip_attr,
115 122 ];
116 123
@@ -140,8 +147,9 @@
140 147 $script_generator = [];
141 148 $script_generator['layout'] = $layout_id;
142 149 $script_generator['rand'] = absint( $rand );
143 150 $script_generator['isCarousel'] = preg_match( '/slider/', $layout );
151 + $script_generator['isMasonry'] = $has_pro && 'masonry' === $grid_style;
144 152
145 153 // Register scripts in the wp_footer action.
146 154 add_action(
147 155 'wp_footer',
@@ -163,13 +171,15 @@
163 171 *
164 172 * @return string
165 173 */
166 174 public function row( $content, $settings, $hook_html = '', $raw_settings = [] ) {
167 - $layout = $settings['layout'];
175 + $raw_layout = esc_html( $settings['layout'] );
176 + $layout = RenderHelpers::filter_layout( $raw_layout );
177 +
168 178 $rand = wp_rand();
169 - $is_carousel = preg_match( '/slider/', $layout );
179 + $is_carousel = preg_match( '/slider/', $raw_layout );
170 180
171 - if ( preg_match( '/category/', $layout ) && ( ! empty( $settings['active_cat_slider'] ) ) ) {
181 + if ( preg_match( '/category/', $raw_layout ) && ( ! empty( $settings['active_cat_slider'] ) ) ) {
172 182 $is_carousel = true;
173 183 }
174 184
175 185 // Row classes.
@@ -185,9 +195,8 @@
185 195 $this->html = ! empty( $settings['show_filter'] ) ? $hook_html . $start_wrapper : $start_wrapper;
186 196
187 197 if ( $is_carousel ) {
188 198 $slider_data = RenderHelpers::slider_data( $settings, $raw_settings );
189 -
190 199 // Adding slider render attributes.
191 200 $this->add_attribute(
192 201 'rtsb_slider_attr_' . $rand,
193 202 [
@@ -237,11 +246,18 @@
237 246 }
238 247
239 248 $i = 0;
240 249
241 - foreach ( $products as $product ) {
250 + global $product;
251 + $isGlobalProduct = false;
252 + if ( $product instanceof WC_Product ) {
253 + $isGlobalProduct = $product;
254 + }
255 +
256 + foreach ( $products as $_product ) {
242 257 $i++;
243 - $GLOBALS['product'] = $product;
258 + $GLOBALS['product'] = $_product;
259 + $layout = RenderHelpers::filter_layout( esc_html( $settings['layout'] ), $template );
244 260
245 261 /**
246 262 * Before product template render hook.
247 263 */
@@ -247,12 +263,12 @@
247 263 */
248 264 do_action( 'rtsb_before_product_template_render' );
249 265
250 266 // Loop arg.
251 - $arg = $this->arg_dataset( $settings, $product, $settings['lazy_load'], $i );
267 + $arg = $this->arg_dataset( $settings, $_product, $settings['lazy_load'], $i );
252 268
253 269 // Get template.
254 - $html .= Fns::load_template( $template . $settings['layout'], $arg, true );
270 + $html .= Fns::load_template( $template . $layout, $arg, true );
255 271
256 272 /**
257 273 * After product template render hook.
258 274 */
@@ -259,9 +275,11 @@
259 275 do_action( 'rtsb_after_product_template_render' );
260 276
261 277 unset( $GLOBALS['product'] );
262 278 }
263 -
279 + if ( $isGlobalProduct ) {
280 + $GLOBALS['product'] = $isGlobalProduct;
281 + }
264 282 return $html;
265 283 }
266 284
267 285 /**
@@ -284,11 +302,11 @@
284 302
285 303 while ( $query->have_posts() ) {
286 304 $query->the_post();
287 305 $i++;
288 -
306 + global $product;
289 307 // Loop arg.
290 - $arg = $this->arg_dataset( $settings, wc_get_product( get_the_ID() ), $settings['lazy_load'], $i );
308 + $arg = $this->arg_dataset( $settings, $product, $settings['lazy_load'], $i );
291 309
292 310 // Get template.
293 311 $html .= Fns::load_template( $template . $settings['layout'], $arg, true );
294 312 }
@@ -368,10 +386,16 @@
368 386 do_action( 'rtsb/elements/render/before_query', $settings, $args );
369 387
370 388 // Query.
371 389 $product_query = new WC_Product_Query( $args );
372 - $products = $pagination ? $product_query->get_products()->products : $product_query->get_products();
373 390
391 + /**
392 + * Product query hook.
393 + */
394 + do_action( 'rtsb/elements/render/product_query', $product_query, $this );
395 +
396 + $products = $pagination ? $product_query->get_products()->products : $product_query->get_products();
397 +
374 398 if ( ! empty( $products ) ) {
375 399 // Start rendering.
376 400 $hook_html .= $this->render_start( $metas, $settings, $temp_args );
377 401
@@ -477,9 +501,9 @@
477 501 // Pagination.
478 502 $this->html .= '<div class="rtsb-archive-pagination-wrap">';
479 503
480 504 if ( $pagination ) {
481 - if ( Fns::product_filters_has_ajax( 'shop' ) || Fns::product_filters_has_ajax( 'archive' ) ) {
505 + if ( Fns::product_filters_has_ajax( apply_filters( 'rtsb/builder/set/current/page/type', '' ) ) ) {
482 506 if ( $wp_query->max_num_pages > 1 ) {
483 507 $this->add_attribute(
484 508 'rtsb_load_more_btn_attr_' . $rand,
485 509 [
@@ -489,9 +513,9 @@
489 513 );
490 514
491 515 $this->html .=
492 516 "<div class='rtsb-load-more rtsb-pos-r'>
493 - <button '{$this->get_attribute_string( 'rtsb_load_more_btn_attr_' . $rand )}'>
517 + <button {$this->get_attribute_string( 'rtsb_load_more_btn_attr_' . $rand )}>
494 518 <span>" . esc_html__( 'Load More', 'shopbuilder' ) . "</span>
495 519 </button>
496 520 <div class='rtsb-loadmore-loading rtsb-ball-clip-rotate'><div></div></div>
497 521 </div>";
@@ -586,8 +610,11 @@
586 610
587 611 if ( rtsb()->has_pro() && ( ! empty( $metas['tag_term'] ) ) ) {
588 612 $term = $metas['tag_term'];
589 613 }
614 + if ( rtsb()->has_pro() && ( ! empty( $metas['brand_term'] ) ) ) {
615 + $term = $metas['brand_term'];
616 + }
590 617
591 618 // Query.
592 619 if ( $is_single ) {
593 620 if ( empty( $term ) ) {
@@ -788,9 +815,13 @@
788 815 $arg['image_link'] = $meta['image_link'];
789 816 $arg['grid'] .= 'rtsb-col-grid ';
790 817
791 818 if ( ! $fullwidth ) {
792 - $arg['class'] .= ' even-grid-item ';
819 + if ( 'masonry' === $meta['grid_type'] ) {
820 + $arg['class'] .= 'masonry-grid-item ';
821 + } else {
822 + $arg['class'] .= 'even-grid-item ';
823 + }
793 824 }
794 825
795 826 if ( ! empty( $meta['active_cat_slider'] ) ) {
796 827 $arg['class'] .= ' rtsb-slide-item swiper-slide animated rtFadeIn ';
@@ -864,8 +895,9 @@
864 895 $arg['anchor_class'] = null;
865 896 $arg['hover_img_html'] = null;
866 897 $arg['s_link'] = [];
867 898 $arg['add_to_cart'] = '';
899 + $arg['p_counter'] = absint( $i );
868 900 $arg['p_id'] = $post_id;
869 901 $arg['product'] = $product;
870 902 $arg['p_link'] = $product->get_permalink();
871 903 $arg['p_sale'] = '';
@@ -896,10 +928,15 @@
896 928 $is_list = preg_match( '/list/', $layout );
897 929 $is_carousel = preg_match( '/slider/', $layout );
898 930
899 931 if ( ! $is_carousel ) {
900 - $arg['grid'] .= 'rtsb-col-grid ';
901 - $arg['class'] .= ' even-grid-item ';
932 + $arg['grid'] .= 'rtsb-col-grid ';
933 +
934 + if ( 'masonry' === $meta['grid_type'] ) {
935 + $arg['class'] .= 'masonry-grid-item ';
936 + } else {
937 + $arg['class'] .= 'even-grid-item ';
938 + }
902 939 } else {
903 940 $arg['grid'] .= 'rtsb-col-grid rtsb-col-full rtsb-slide-item swiper-slide ';
904 941 }
905 942
@@ -919,18 +956,21 @@
919 956
920 957 $arg['class'] .= ' animated rtFadeIn';
921 958
922 959 if ( in_array( 'badges', $meta['visibility'], true ) ) {
923 - $arg['p_sale'] = Fns::get_promo_badge(
960 + $badge_module = ! empty( $meta['enable_badges_module'] );
961 + $arg['p_sale'] = Fns::is_module_active( 'product_badges' ) && $badge_module ? 'rtsb_yes' : Fns::get_promo_badge(
924 962 $product,
925 963 $meta['sale_badge_type'],
926 964 $meta['sale_badge_text'],
927 - $meta['out_of_stock_badge_text']
965 + apply_filters( 'rtsb/elementor/render/out_of_stock_badge_text', $meta['out_of_stock_badge_text'] )
928 966 );
929 967 }
930 968
931 969 $arg['badge_class'] = RenderHelpers::badge_class( $meta['badge_preset'] );
932 970
971 + $meta['add_to_cart_text'] = apply_filters( 'rtsb/elementor/render/add_to_cart_text', $meta['add_to_cart_text'], $product );
972 +
933 973 if ( ! $meta['show_cart_text'] ) {
934 974 $meta['add_to_cart_text'] = '';
935 975 $meta['add_to_cart_success_text'] = '';
936 976 }
@@ -956,8 +996,9 @@
956 996 'text' => $meta['add_to_cart_text'],
957 997 'success' => $meta['add_to_cart_success_text'],
958 998 'icon_html' => $cart_icon,
959 999 'alignment' => $meta['add_to_cart_alignment'],
1000 + 'product' => $product,
960 1001 ]
961 1002 );
962 1003 }
963 1004 }
@@ -1042,9 +1083,10 @@
1042 1083 'type' => $type,
1043 1084 'text' => $text,
1044 1085 'success' => $success,
1045 1086 'icon_html' => $icon_html,
1046 - 'alignment' => $alignment
1087 + 'alignment' => $alignment,
1088 + 'product' => $product
1047 1089 ) = $args;
1048 1090
1049 1091 $content = null;
1050 1092 $rand = wp_rand();
@@ -1065,12 +1107,13 @@
1065 1107 ];
1066 1108
1067 1109 if ( empty( $text ) ) {
1068 1110 $tooltip_mapping = [
1069 - 'simple' => esc_attr__( 'Add to Cart', 'shopbuilder' ),
1070 - 'variable' => esc_attr__( 'Select Options', 'shopbuilder' ),
1071 - 'grouped' => esc_attr__( 'View Products', 'shopbuilder' ),
1072 - 'external' => ! empty( $btn_txt ) ? esc_html( $btn_txt ) : esc_html__( 'Buy Product', 'shopbuilder' ),
1111 + 'simple' => esc_attr__( 'Add to Cart', 'shopbuilder' ),
1112 + 'variable' => esc_attr__( 'Select Options', 'shopbuilder' ),
1113 + 'grouped' => esc_attr__( 'View Products', 'shopbuilder' ),
1114 + 'external' => ! empty( $btn_txt ) ? esc_html( $btn_txt ) : esc_html__( 'Buy Product', 'shopbuilder' ),
1115 + 'rtsb-gift-card' => esc_attr__( 'Select Gift Card', 'shopbuilder' ),
1073 1116 ];
1074 1117
1075 1118 $cart_attr['title'] = $tooltip_mapping[ $type ];
1076 1119 }
@@ -1077,8 +1120,10 @@
1077 1120
1078 1121 $content .= '<div class="rtsb-wc-add-to-cart-wrap">';
1079 1122
1080 1123 if ( 'variable' === $type || 'grouped' === $type ) {
1124 + $cart_attr = apply_filters( 'rtsb/elementor/render/cart_attributes', $cart_attr, $product );
1125 +
1081 1126 $this->add_attribute( 'rtsb_add_to_cart_button_' . $id . $rand, $cart_attr );
1082 1127
1083 1128 $text_btn = 'grouped' === $type ? __( 'View Products', 'shopbuilder' ) : __( 'Select Options', 'shopbuilder' );
1084 1129
@@ -1101,8 +1146,9 @@
1101 1146 } else {
1102 1147 $cart_attr['href'] = $cart_attr['href'] . '?add-to-cart=' . absint( $id );
1103 1148 $cart_attr['class'] .= ' rtsb-add-to-cart-btn';
1104 1149 $cart_attr['data-type'] = $type;
1150 + $cart_attr = apply_filters( 'rtsb/elementor/render/cart_attributes', $cart_attr, $product );
1105 1151
1106 1152 $this->add_attribute( 'rtsb_add_to_cart_button_' . $id . $rand, $cart_attr );
1107 1153
1108 1154 $content .= '<a ' . $this->get_attribute_string( 'rtsb_add_to_cart_button_' . $id . $rand ) . '>';
@@ -1280,9 +1326,9 @@
1280 1326 * @return void
1281 1327 */
1282 1328 public function no_products_msg( $metas ) {
1283 1329 $content =
1284 - '<div class="woocommerce-no-products-found">
1330 + '<div class="rtsb-notice woocommerce-no-products-found">
1285 1331 <div class="woocommerce-info">' . esc_html__( 'No products were found matching your selection.', 'shopbuilder' ) . '</div>
1286 1332 </div>';
1287 1333
1288 1334 $this->row( $content, $metas );
@@ -1370,8 +1416,46 @@
1370 1416 return $this;
1371 1417 }
1372 1418
1373 1419 /**
1420 + * Add link render attributes.
1421 + *
1422 + * @param array|string $element The HTML element.
1423 + * @param array $url_control Array of link settings.
1424 + * @param bool $overwrite Optional. Whether to overwrite existing
1425 + * attribute. Default is false, not to overwrite.
1426 + *
1427 + * @return Render
1428 + */
1429 + public function add_link_attributes( $element, array $url_control, $overwrite = false ) {
1430 + $attributes = [];
1431 +
1432 + if ( ! empty( $url_control['url'] ) ) {
1433 + $allowed_protocols = array_merge( wp_allowed_protocols(), [ 'skype', 'viber' ] );
1434 +
1435 + $attributes['href'] = esc_url( $url_control['url'], $allowed_protocols );
1436 + }
1437 +
1438 + if ( ! empty( $url_control['is_external'] ) ) {
1439 + $attributes['target'] = '_blank';
1440 + }
1441 +
1442 + if ( ! empty( $url_control['nofollow'] ) ) {
1443 + $attributes['rel'] = 'nofollow';
1444 + }
1445 +
1446 + if ( ! empty( $url_control['custom_attributes'] ) ) {
1447 + $attributes = array_merge( $attributes, Utils::parse_custom_attributes( $url_control['custom_attributes'] ) );
1448 + }
1449 +
1450 + if ( $attributes ) {
1451 + $this->add_attribute( $element, $attributes, null, $overwrite );
1452 + }
1453 +
1454 + return $this;
1455 + }
1456 +
1457 + /**
1374 1458 * Get render attribute string.
1375 1459 *
1376 1460 * @param string $element The element.
1377 1461 *
@@ -1382,6 +1466,27 @@
1382 1466 return '';
1383 1467 }
1384 1468
1385 1469 return Utils::render_html_attributes( $this->attributes[ $element ] );
1470 + }
1471 +
1472 + /**
1473 + * Function to render link attributes.
1474 + *
1475 + * @param string $id Element ID.
1476 + * @param array $control_name Control name.
1477 + * @param string $class_name Class name.
1478 + *
1479 + * @return string
1480 + */
1481 + public function render_link_attributes( $id, $control_name, $class_name = 'logo-img-link' ) {
1482 + $this->add_attribute( $id, 'class', $class_name );
1483 +
1484 + if ( ! empty( $control_name['url'] ) ) {
1485 + $this->add_link_attributes( $id, $control_name );
1486 + } else {
1487 + $this->add_attribute( $id, 'role', 'button' );
1488 + }
1489 +
1490 + return $this->get_attribute_string( $id );
1386 1491 }
1387 1492 }