PluginProbe
ShopBuilder – WooCommerce Builder For Elementor / 3.1.3
ShopBuilder – WooCommerce Builder For Elementor v3.1.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 +162 -26 2.1.133.1.3 View file →
@@ -93,8 +93,9 @@
93 93 $view_mode = isset( $_GET['displayview'] ) ? sanitize_text_field( wp_unslash( $_GET['displayview'] ) ) : $view_mode; // phpcs:ignore WordPress.Security.NonceVerification.Recommended
94 94 $tooltip_attr = 'list' == $view_mode && ! empty( $metas['tooltip_position_list'] ) ? esc_attr( $metas['tooltip_position_list'] ) : $metas['tooltip_position'];
95 95 $has_pro = rtsb()->has_pro();
96 96 $has_filters = $has_pro && ! empty( $settings['tax_filter'] );
97 + $grid_style = $settings['grid_style'] ?? 'even';
97 98
98 99 // Set default layout.
99 100 if ( ! $has_pro && ! in_array( $layout, array_keys( Fns::free_layouts() ), true ) ) {
100 101 $layout = RenderHelpers::set_default_layout( $layout );
@@ -99,8 +100,13 @@
99 100 if ( ! $has_pro && ! in_array( $layout, array_keys( Fns::free_layouts() ), true ) ) {
100 101 $layout = RenderHelpers::set_default_layout( $layout );
101 102 }
102 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 +
103 109 // Container classes.
104 110 $container_classes = RenderHelpers::prepare_container_classes( $metas, $settings, $class );
105 111
106 112 // Pagination attributes.
@@ -109,9 +115,9 @@
109 115 // Attributes for the container.
110 116 $container_attributes = [
111 117 'id' => $layout_id,
112 118 'class' => $container_classes,
113 - 'style' => $style_attr,
119 + 'style' => apply_filters( 'rtsb/product/container/attr', $style_attr, $settings ),
114 120 'data-layout' => $layout,
115 121 'data-tooltip-position' => $tooltip_attr,
116 122 ];
117 123
@@ -141,8 +147,9 @@
141 147 $script_generator = [];
142 148 $script_generator['layout'] = $layout_id;
143 149 $script_generator['rand'] = absint( $rand );
144 150 $script_generator['isCarousel'] = preg_match( '/slider/', $layout );
151 + $script_generator['isMasonry'] = $has_pro && 'masonry' === $grid_style;
145 152
146 153 // Register scripts in the wp_footer action.
147 154 add_action(
148 155 'wp_footer',
@@ -188,9 +195,8 @@
188 195 $this->html = ! empty( $settings['show_filter'] ) ? $hook_html . $start_wrapper : $start_wrapper;
189 196
190 197 if ( $is_carousel ) {
191 198 $slider_data = RenderHelpers::slider_data( $settings, $raw_settings );
192 -
193 199 // Adding slider render attributes.
194 200 $this->add_attribute(
195 201 'rtsb_slider_attr_' . $rand,
196 202 [
@@ -240,12 +246,21 @@
240 246 }
241 247
242 248 $i = 0;
243 249
244 - foreach ( $products as $product ) {
250 + global $product;
251 +
252 + $isGlobalProduct = false;
253 +
254 + if ( $product instanceof WC_Product ) {
255 + $isGlobalProduct = $product;
256 + }
257 +
258 + $layout = RenderHelpers::filter_layout( esc_html( $settings['layout'] ), $template );
259 +
260 + foreach ( $products as $_product ) {
245 261 $i++;
246 - $GLOBALS['product'] = $product;
247 - $layout = RenderHelpers::filter_layout( esc_html( $settings['layout'] ), $template );
262 + $GLOBALS['product'] = $_product;
248 263
249 264 /**
250 265 * Before product template render hook.
251 266 */
@@ -251,9 +266,9 @@
251 266 */
252 267 do_action( 'rtsb_before_product_template_render' );
253 268
254 269 // Loop arg.
255 - $arg = $this->arg_dataset( $settings, $product, $settings['lazy_load'], $i );
270 + $arg = $this->arg_dataset( $settings, $_product, $settings['lazy_load'], $i );
256 271
257 272 // Get template.
258 273 $html .= Fns::load_template( $template . $layout, $arg, true );
259 274
@@ -263,9 +278,11 @@
263 278 do_action( 'rtsb_after_product_template_render' );
264 279
265 280 unset( $GLOBALS['product'] );
266 281 }
267 -
282 + if ( $isGlobalProduct ) {
283 + $GLOBALS['product'] = $isGlobalProduct;
284 + }
268 285 return $html;
269 286 }
270 287
271 288 /**
@@ -283,19 +300,20 @@
283 300 if ( empty( $query ) ) {
284 301 return null;
285 302 }
286 303
287 - $i = 0;
304 + $i = 0;
305 + $layout = RenderHelpers::filter_layout( esc_html( $settings['layout'] ), $template );
288 306
289 307 while ( $query->have_posts() ) {
290 308 $query->the_post();
291 309 $i++;
292 -
310 + global $product;
293 311 // Loop arg.
294 - $arg = $this->arg_dataset( $settings, wc_get_product( get_the_ID() ), $settings['lazy_load'], $i );
312 + $arg = $this->arg_dataset( $settings, $product, $settings['lazy_load'], $i );
295 313
296 314 // Get template.
297 - $html .= Fns::load_template( $template . $settings['layout'], $arg, true );
315 + $html .= Fns::load_template( $template . $layout, $arg, true );
298 316 }
299 317
300 318 return $html;
301 319 }
@@ -372,10 +390,16 @@
372 390 do_action( 'rtsb/elements/render/before_query', $settings, $args );
373 391
374 392 // Query.
375 393 $product_query = new WC_Product_Query( $args );
376 - $products = $pagination ? $product_query->get_products()->products : $product_query->get_products();
377 394
395 + /**
396 + * Product query hook.
397 + */
398 + do_action( 'rtsb/elements/render/product_query', $product_query, $this );
399 +
400 + $products = $pagination ? $product_query->get_products()->products : $product_query->get_products();
401 +
378 402 if ( ! empty( $products ) ) {
379 403 // Start rendering.
380 404 $hook_html .= $this->render_start( $metas, $settings, $temp_args );
381 405
@@ -439,10 +463,9 @@
439 463 $pagination = $metas['pagination'];
440 464
441 465 $page_type = BuilderFns::builder_type( get_the_ID() );
442 466 $is_preview = BuilderFns::is_builder_preview() && array_key_exists( $page_type, BuilderFns::builder_page_types() );
443 - $posts_per_page = wc_get_default_products_per_row() * wc_get_default_product_rows_per_page();
444 -
467 + $posts_per_page = apply_filters( 'loop_shop_per_page', wc_get_default_products_per_row() * wc_get_default_product_rows_per_page() );
445 468 if ( $is_preview ) {
446 469 $main_query = clone $wp_query;
447 470 $main_post = clone $post;
448 471
@@ -590,8 +613,11 @@
590 613
591 614 if ( rtsb()->has_pro() && ( ! empty( $metas['tag_term'] ) ) ) {
592 615 $term = $metas['tag_term'];
593 616 }
617 + if ( rtsb()->has_pro() && ( ! empty( $metas['brand_term'] ) ) ) {
618 + $term = $metas['brand_term'];
619 + }
594 620
595 621 // Query.
596 622 if ( $is_single ) {
597 623 if ( empty( $term ) ) {
@@ -692,8 +718,9 @@
692 718 *
693 719 * @return array
694 720 */
695 721 public function wp_arg_dataset( array $meta, int $post_id, bool $lazy_load = false, $i = 0 ) {
722 + // phpcs:ignore WordPress.PHP.StrictInArray.MissingTrueStrict
696 723 if ( ( empty( $meta ) && ! $post_id ) || ! in_array( get_post_type( $post_id ), [ 'product_variation', 'product' ] ) ) {
697 724 return [];
698 725 }
699 726
@@ -792,9 +819,13 @@
792 819 $arg['image_link'] = $meta['image_link'];
793 820 $arg['grid'] .= 'rtsb-col-grid ';
794 821
795 822 if ( ! $fullwidth ) {
796 - $arg['class'] .= ' even-grid-item ';
823 + if ( 'masonry' === $meta['grid_type'] ) {
824 + $arg['class'] .= 'masonry-grid-item ';
825 + } else {
826 + $arg['class'] .= 'even-grid-item ';
827 + }
797 828 }
798 829
799 830 if ( ! empty( $meta['active_cat_slider'] ) ) {
800 831 $arg['class'] .= ' rtsb-slide-item swiper-slide animated rtFadeIn ';
@@ -868,8 +899,9 @@
868 899 $arg['anchor_class'] = null;
869 900 $arg['hover_img_html'] = null;
870 901 $arg['s_link'] = [];
871 902 $arg['add_to_cart'] = '';
903 + $arg['p_counter'] = absint( $i );
872 904 $arg['p_id'] = $post_id;
873 905 $arg['product'] = $product;
874 906 $arg['p_link'] = $product->get_permalink();
875 907 $arg['p_sale'] = '';
@@ -900,10 +932,15 @@
900 932 $is_list = preg_match( '/list/', $layout );
901 933 $is_carousel = preg_match( '/slider/', $layout );
902 934
903 935 if ( ! $is_carousel ) {
904 - $arg['grid'] .= 'rtsb-col-grid ';
905 - $arg['class'] .= ' even-grid-item ';
936 + $arg['grid'] .= 'rtsb-col-grid ';
937 +
938 + if ( 'masonry' === $meta['grid_type'] ) {
939 + $arg['class'] .= 'masonry-grid-item ';
940 + } else {
941 + $arg['class'] .= 'even-grid-item ';
942 + }
906 943 } else {
907 944 $arg['grid'] .= 'rtsb-col-grid rtsb-col-full rtsb-slide-item swiper-slide ';
908 945 }
909 946
@@ -934,8 +971,10 @@
934 971 }
935 972
936 973 $arg['badge_class'] = RenderHelpers::badge_class( $meta['badge_preset'] );
937 974
975 + $meta['add_to_cart_text'] = apply_filters( 'rtsb/elementor/render/add_to_cart_text', $meta['add_to_cart_text'], $product );
976 +
938 977 if ( ! $meta['show_cart_text'] ) {
939 978 $meta['add_to_cart_text'] = '';
940 979 $meta['add_to_cart_success_text'] = '';
941 980 }
@@ -961,8 +1000,9 @@
961 1000 'text' => $meta['add_to_cart_text'],
962 1001 'success' => $meta['add_to_cart_success_text'],
963 1002 'icon_html' => $cart_icon,
964 1003 'alignment' => $meta['add_to_cart_alignment'],
1004 + 'product' => $product,
965 1005 ]
966 1006 );
967 1007 }
968 1008 }
@@ -1047,9 +1087,10 @@
1047 1087 'type' => $type,
1048 1088 'text' => $text,
1049 1089 'success' => $success,
1050 1090 'icon_html' => $icon_html,
1051 - 'alignment' => $alignment
1091 + 'alignment' => $alignment,
1092 + 'product' => $product
1052 1093 ) = $args;
1053 1094
1054 1095 $content = null;
1055 1096 $rand = wp_rand();
@@ -1062,9 +1103,8 @@
1062 1103
1063 1104 $cart_attr = [
1064 1105 'class' => 'rtsb-action-btn ' . $type . '-product tipsy icon-' . $alignment . ' ' . ( empty( $text ) ? 'no-text' : 'has-text' ),
1065 1106 'href' => esc_url( $link ),
1066 - 'rel' => 'nofollow',
1067 1107 'data-quantity' => '1',
1068 1108 'data-product_id' => absint( $id ),
1069 1109 'data-id' => absint( $id ),
1070 1110 ];
@@ -1070,12 +1110,13 @@
1070 1110 ];
1071 1111
1072 1112 if ( empty( $text ) ) {
1073 1113 $tooltip_mapping = [
1074 - 'simple' => esc_attr__( 'Add to Cart', 'shopbuilder' ),
1075 - 'variable' => esc_attr__( 'Select Options', 'shopbuilder' ),
1076 - 'grouped' => esc_attr__( 'View Products', 'shopbuilder' ),
1077 - 'external' => ! empty( $btn_txt ) ? esc_html( $btn_txt ) : esc_html__( 'Buy Product', 'shopbuilder' ),
1114 + 'simple' => esc_attr__( 'Add to Cart', 'shopbuilder' ),
1115 + 'variable' => esc_attr__( 'Select Options', 'shopbuilder' ),
1116 + 'grouped' => esc_attr__( 'View Products', 'shopbuilder' ),
1117 + 'external' => ! empty( $btn_txt ) ? esc_html( $btn_txt ) : esc_html__( 'Buy Product', 'shopbuilder' ),
1118 + 'rtsb-gift-card' => esc_attr__( 'Select Gift Card', 'shopbuilder' ),
1078 1119 ];
1079 1120
1080 1121 $cart_attr['title'] = $tooltip_mapping[ $type ];
1081 1122 }
@@ -1080,13 +1121,22 @@
1080 1121 $cart_attr['title'] = $tooltip_mapping[ $type ];
1081 1122 }
1082 1123
1083 1124 $content .= '<div class="rtsb-wc-add-to-cart-wrap">';
1125 + if ( 'variable' === $type ) {
1126 + $cart_attr['class'] = $cart_attr['class'] . ' rtsb_vs_add_to_cart ';
1127 + }
1128 + if ( 'variable' === $type || 'grouped' === $type ) {
1129 + $cart_attr = apply_filters( 'rtsb/elementor/render/cart_attributes', $cart_attr, $product );
1084 1130
1085 - if ( 'variable' === $type || 'grouped' === $type ) {
1086 1131 $this->add_attribute( 'rtsb_add_to_cart_button_' . $id . $rand, $cart_attr );
1087 1132
1088 - $text_btn = 'grouped' === $type ? __( 'View Products', 'shopbuilder' ) : __( 'Select Options', 'shopbuilder' );
1133 + $text_btn = apply_filters(
1134 + 'rtsb/elementor/render/add_to_cart_text',
1135 + 'grouped' === $type ? __( 'View Products', 'shopbuilder' ) : __( 'Select Options', 'shopbuilder' ),
1136 + $product,
1137 + $type
1138 + );
1089 1139
1090 1140 $content .= '<a ' . $this->get_attribute_string( 'rtsb_add_to_cart_button_' . $id . $rand ) . '>';
1091 1141 $content .= $icon_html;
1092 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>';
@@ -1106,8 +1156,9 @@
1106 1156 } else {
1107 1157 $cart_attr['href'] = $cart_attr['href'] . '?add-to-cart=' . absint( $id );
1108 1158 $cart_attr['class'] .= ' rtsb-add-to-cart-btn';
1109 1159 $cart_attr['data-type'] = $type;
1160 + $cart_attr = apply_filters( 'rtsb/elementor/render/cart_attributes', $cart_attr, $product );
1110 1161
1111 1162 $this->add_attribute( 'rtsb_add_to_cart_button_' . $id . $rand, $cart_attr );
1112 1163
1113 1164 $content .= '<a ' . $this->get_attribute_string( 'rtsb_add_to_cart_button_' . $id . $rand ) . '>';
@@ -1375,8 +1426,46 @@
1375 1426 return $this;
1376 1427 }
1377 1428
1378 1429 /**
1430 + * Add link render attributes.
1431 + *
1432 + * @param array|string $element The HTML element.
1433 + * @param array $url_control Array of link settings.
1434 + * @param bool $overwrite Optional. Whether to overwrite existing
1435 + * attribute. Default is false, not to overwrite.
1436 + *
1437 + * @return Render
1438 + */
1439 + public function add_link_attributes( $element, array $url_control, $overwrite = false ) {
1440 + $attributes = [];
1441 +
1442 + if ( ! empty( $url_control['url'] ) ) {
1443 + $allowed_protocols = array_merge( wp_allowed_protocols(), [ 'skype', 'viber' ] );
1444 +
1445 + $attributes['href'] = esc_url( $url_control['url'], $allowed_protocols );
1446 + }
1447 +
1448 + if ( ! empty( $url_control['is_external'] ) ) {
1449 + $attributes['target'] = '_blank';
1450 + }
1451 +
1452 + if ( ! empty( $url_control['nofollow'] ) ) {
1453 + $attributes['rel'] = 'nofollow';
1454 + }
1455 +
1456 + if ( ! empty( $url_control['custom_attributes'] ) ) {
1457 + $attributes = array_merge( $attributes, Utils::parse_custom_attributes( $url_control['custom_attributes'] ) );
1458 + }
1459 +
1460 + if ( $attributes ) {
1461 + $this->add_attribute( $element, $attributes, null, $overwrite );
1462 + }
1463 +
1464 + return $this;
1465 + }
1466 +
1467 + /**
1379 1468 * Get render attribute string.
1380 1469 *
1381 1470 * @param string $element The element.
1382 1471 *
@@ -1386,7 +1475,54 @@
1386 1475 if ( empty( $this->attributes[ $element ] ) ) {
1387 1476 return '';
1388 1477 }
1389 1478
1390 - return Utils::render_html_attributes( $this->attributes[ $element ] );
1479 + if ( class_exists( '\Elementor\Utils' ) ) {
1480 + return Utils::render_html_attributes( $this->attributes[ $element ] );
1481 + }
1482 +
1483 + // Fallback.
1484 + return $this->render_fallback_attributes( $this->attributes[ $element ] );
1485 + }
1486 +
1487 + /**
1488 + * Function to render link attributes.
1489 + *
1490 + * @param string $id Element ID.
1491 + * @param array $control_name Control name.
1492 + * @param string $class_name Class name.
1493 + *
1494 + * @return string
1495 + */
1496 + public function render_link_attributes( $id, $control_name, $class_name = 'logo-img-link' ) {
1497 + $this->add_attribute( $id, 'class', $class_name );
1498 +
1499 + if ( ! empty( $control_name['url'] ) ) {
1500 + $this->add_link_attributes( $id, $control_name );
1501 + } else {
1502 + $this->add_attribute( $id, 'role', 'button' );
1503 + }
1504 +
1505 + return $this->get_attribute_string( $id );
1506 + }
1507 +
1508 + /**
1509 + * Render fallback attributes.
1510 + *
1511 + * @param array $attributes The attributes.
1512 + *
1513 + * @return string
1514 + */
1515 + private function render_fallback_attributes( $attributes ) {
1516 + $rendered_attributes = [];
1517 +
1518 + foreach ( $attributes as $attribute_key => $attribute_values ) {
1519 + if ( is_array( $attribute_values ) ) {
1520 + $attribute_values = implode( ' ', $attribute_values );
1521 + }
1522 +
1523 + $rendered_attributes[] = sprintf( '%1$s="%2$s"', $attribute_key, esc_attr( $attribute_values ) );
1524 + }
1525 +
1526 + return implode( ' ', $rendered_attributes );
1391 1527 }
1392 1528 }