PluginProbe
ShopBuilder – WooCommerce Builder For Elementor / 3.2.2
ShopBuilder – WooCommerce Builder For Elementor v3.2.2
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 +166 -29 2.1.13 → 3.2.2 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 }
@@ -368,14 +386,20 @@
368 386 * Before Product query hook.
369 387 *
370 388 * @hooked RadiusTheme\SB\Controllers\Hooks\ActionHooks::modify_wc_query_args 10
371 389 */
390 +
372 391 do_action( 'rtsb/elements/render/before_query', $settings, $args );
373 -
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
@@ -432,17 +456,17 @@
432 456 $this->get_settings = $settings;
433 457 $rand = wp_rand();
434 458 $metas = RenderHelpers::meta_dataset( $settings, $template, $widget->get_settings_for_display() );
435 459
436 - $settings['rtsb_order'] = ! empty( $wp_query->query_vars['order'] ) ? $wp_query->query_vars['order'] : 'ASC';
437 - $settings['rtsb_orderby'] = ! empty( $wp_query->query_vars['orderby'] ) ? $wp_query->query_vars['orderby'] : 'menu_order';
460 + $order = strtoupper( $wp_query->query_vars['order'] ?? 'ASC' );
461 + $settings['rtsb_orderby'] = RenderHelpers::escaping_product_orderby( $wp_query->query_vars['orderby'] ?? 'menu_order' );
462 + $settings['rtsb_order'] = in_array( $order, [ 'ASC','DESC' ], true ) ? $order : 'ASC';
438 463
439 464 $pagination = $metas['pagination'];
440 465
441 466 $page_type = BuilderFns::builder_type( get_the_ID() );
442 467 $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 -
468 + $posts_per_page = apply_filters( 'loop_shop_per_page', wc_get_default_products_per_row() * wc_get_default_product_rows_per_page() );
445 469 if ( $is_preview ) {
446 470 $main_query = clone $wp_query;
447 471 $main_post = clone $post;
448 472
@@ -590,8 +614,11 @@
590 614
591 615 if ( rtsb()->has_pro() && ( ! empty( $metas['tag_term'] ) ) ) {
592 616 $term = $metas['tag_term'];
593 617 }
618 + if ( rtsb()->has_pro() && ( ! empty( $metas['brand_term'] ) ) ) {
619 + $term = $metas['brand_term'];
620 + }
594 621
595 622 // Query.
596 623 if ( $is_single ) {
597 624 if ( empty( $term ) ) {
@@ -692,8 +719,9 @@
692 719 *
693 720 * @return array
694 721 */
695 722 public function wp_arg_dataset( array $meta, int $post_id, bool $lazy_load = false, $i = 0 ) {
723 + // phpcs:ignore WordPress.PHP.StrictInArray.MissingTrueStrict
696 724 if ( ( empty( $meta ) && ! $post_id ) || ! in_array( get_post_type( $post_id ), [ 'product_variation', 'product' ] ) ) {
697 725 return [];
698 726 }
699 727
@@ -792,9 +820,13 @@
792 820 $arg['image_link'] = $meta['image_link'];
793 821 $arg['grid'] .= 'rtsb-col-grid ';
794 822
795 823 if ( ! $fullwidth ) {
796 - $arg['class'] .= ' even-grid-item ';
824 + if ( 'masonry' === $meta['grid_type'] ) {
825 + $arg['class'] .= 'masonry-grid-item ';
826 + } else {
827 + $arg['class'] .= 'even-grid-item ';
828 + }
797 829 }
798 830
799 831 if ( ! empty( $meta['active_cat_slider'] ) ) {
800 832 $arg['class'] .= ' rtsb-slide-item swiper-slide animated rtFadeIn ';
@@ -868,8 +900,9 @@
868 900 $arg['anchor_class'] = null;
869 901 $arg['hover_img_html'] = null;
870 902 $arg['s_link'] = [];
871 903 $arg['add_to_cart'] = '';
904 + $arg['p_counter'] = absint( $i );
872 905 $arg['p_id'] = $post_id;
873 906 $arg['product'] = $product;
874 907 $arg['p_link'] = $product->get_permalink();
875 908 $arg['p_sale'] = '';
@@ -900,10 +933,15 @@
900 933 $is_list = preg_match( '/list/', $layout );
901 934 $is_carousel = preg_match( '/slider/', $layout );
902 935
903 936 if ( ! $is_carousel ) {
904 - $arg['grid'] .= 'rtsb-col-grid ';
905 - $arg['class'] .= ' even-grid-item ';
937 + $arg['grid'] .= 'rtsb-col-grid ';
938 +
939 + if ( 'masonry' === $meta['grid_type'] ) {
940 + $arg['class'] .= 'masonry-grid-item ';
941 + } else {
942 + $arg['class'] .= 'even-grid-item ';
943 + }
906 944 } else {
907 945 $arg['grid'] .= 'rtsb-col-grid rtsb-col-full rtsb-slide-item swiper-slide ';
908 946 }
909 947
@@ -934,8 +972,10 @@
934 972 }
935 973
936 974 $arg['badge_class'] = RenderHelpers::badge_class( $meta['badge_preset'] );
937 975
976 + $meta['add_to_cart_text'] = apply_filters( 'rtsb/elementor/render/add_to_cart_text', $meta['add_to_cart_text'], $product );
977 +
938 978 if ( ! $meta['show_cart_text'] ) {
939 979 $meta['add_to_cart_text'] = '';
940 980 $meta['add_to_cart_success_text'] = '';
941 981 }
@@ -961,8 +1001,9 @@
961 1001 'text' => $meta['add_to_cart_text'],
962 1002 'success' => $meta['add_to_cart_success_text'],
963 1003 'icon_html' => $cart_icon,
964 1004 'alignment' => $meta['add_to_cart_alignment'],
1005 + 'product' => $product,
965 1006 ]
966 1007 );
967 1008 }
968 1009 }
@@ -1047,9 +1088,10 @@
1047 1088 'type' => $type,
1048 1089 'text' => $text,
1049 1090 'success' => $success,
1050 1091 'icon_html' => $icon_html,
1051 - 'alignment' => $alignment
1092 + 'alignment' => $alignment,
1093 + 'product' => $product
1052 1094 ) = $args;
1053 1095
1054 1096 $content = null;
1055 1097 $rand = wp_rand();
@@ -1062,9 +1104,8 @@
1062 1104
1063 1105 $cart_attr = [
1064 1106 'class' => 'rtsb-action-btn ' . $type . '-product tipsy icon-' . $alignment . ' ' . ( empty( $text ) ? 'no-text' : 'has-text' ),
1065 1107 'href' => esc_url( $link ),
1066 - 'rel' => 'nofollow',
1067 1108 'data-quantity' => '1',
1068 1109 'data-product_id' => absint( $id ),
1069 1110 'data-id' => absint( $id ),
1070 1111 ];
@@ -1070,12 +1111,13 @@
1070 1111 ];
1071 1112
1072 1113 if ( empty( $text ) ) {
1073 1114 $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' ),
1115 + 'simple' => esc_attr__( 'Add to Cart', 'shopbuilder' ),
1116 + 'variable' => esc_attr__( 'Select Options', 'shopbuilder' ),
1117 + 'grouped' => esc_attr__( 'View Products', 'shopbuilder' ),
1118 + 'external' => ! empty( $btn_txt ) ? esc_html( $btn_txt ) : esc_html__( 'Buy Product', 'shopbuilder' ),
1119 + 'rtsb-gift-card' => esc_attr__( 'Select Gift Card', 'shopbuilder' ),
1078 1120 ];
1079 1121
1080 1122 $cart_attr['title'] = $tooltip_mapping[ $type ];
1081 1123 }
@@ -1080,13 +1122,22 @@
1080 1122 $cart_attr['title'] = $tooltip_mapping[ $type ];
1081 1123 }
1082 1124
1083 1125 $content .= '<div class="rtsb-wc-add-to-cart-wrap">';
1126 + if ( 'variable' === $type ) {
1127 + $cart_attr['class'] = $cart_attr['class'] . ' rtsb_vs_add_to_cart ';
1128 + }
1129 + if ( 'variable' === $type || 'grouped' === $type ) {
1130 + $cart_attr = apply_filters( 'rtsb/elementor/render/cart_attributes', $cart_attr, $product );
1084 1131
1085 - if ( 'variable' === $type || 'grouped' === $type ) {
1086 1132 $this->add_attribute( 'rtsb_add_to_cart_button_' . $id . $rand, $cart_attr );
1087 1133
1088 - $text_btn = 'grouped' === $type ? __( 'View Products', 'shopbuilder' ) : __( 'Select Options', 'shopbuilder' );
1134 + $text_btn = apply_filters(
1135 + 'rtsb/elementor/render/add_to_cart_text',
1136 + 'grouped' === $type ? __( 'View Products', 'shopbuilder' ) : __( 'Select Options', 'shopbuilder' ),
1137 + $product,
1138 + $type
1139 + );
1089 1140
1090 1141 $content .= '<a ' . $this->get_attribute_string( 'rtsb_add_to_cart_button_' . $id . $rand ) . '>';
1091 1142 $content .= $icon_html;
1092 1143 $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 +1157,9 @@
1106 1157 } else {
1107 1158 $cart_attr['href'] = $cart_attr['href'] . '?add-to-cart=' . absint( $id );
1108 1159 $cart_attr['class'] .= ' rtsb-add-to-cart-btn';
1109 1160 $cart_attr['data-type'] = $type;
1161 + $cart_attr = apply_filters( 'rtsb/elementor/render/cart_attributes', $cart_attr, $product );
1110 1162
1111 1163 $this->add_attribute( 'rtsb_add_to_cart_button_' . $id . $rand, $cart_attr );
1112 1164
1113 1165 $content .= '<a ' . $this->get_attribute_string( 'rtsb_add_to_cart_button_' . $id . $rand ) . '>';
@@ -1375,8 +1427,46 @@
1375 1427 return $this;
1376 1428 }
1377 1429
1378 1430 /**
1431 + * Add link render attributes.
1432 + *
1433 + * @param array|string $element The HTML element.
1434 + * @param array $url_control Array of link settings.
1435 + * @param bool $overwrite Optional. Whether to overwrite existing
1436 + * attribute. Default is false, not to overwrite.
1437 + *
1438 + * @return Render
1439 + */
1440 + public function add_link_attributes( $element, array $url_control, $overwrite = false ) {
1441 + $attributes = [];
1442 +
1443 + if ( ! empty( $url_control['url'] ) ) {
1444 + $allowed_protocols = array_merge( wp_allowed_protocols(), [ 'skype', 'viber' ] );
1445 +
1446 + $attributes['href'] = esc_url( $url_control['url'], $allowed_protocols );
1447 + }
1448 +
1449 + if ( ! empty( $url_control['is_external'] ) ) {
1450 + $attributes['target'] = '_blank';
1451 + }
1452 +
1453 + if ( ! empty( $url_control['nofollow'] ) ) {
1454 + $attributes['rel'] = 'nofollow';
1455 + }
1456 +
1457 + if ( ! empty( $url_control['custom_attributes'] ) ) {
1458 + $attributes = array_merge( $attributes, Utils::parse_custom_attributes( $url_control['custom_attributes'] ) );
1459 + }
1460 +
1461 + if ( $attributes ) {
1462 + $this->add_attribute( $element, $attributes, null, $overwrite );
1463 + }
1464 +
1465 + return $this;
1466 + }
1467 +
1468 + /**
1379 1469 * Get render attribute string.
1380 1470 *
1381 1471 * @param string $element The element.
1382 1472 *
@@ -1386,7 +1476,54 @@
1386 1476 if ( empty( $this->attributes[ $element ] ) ) {
1387 1477 return '';
1388 1478 }
1389 1479
1390 - return Utils::render_html_attributes( $this->attributes[ $element ] );
1480 + if ( class_exists( '\Elementor\Utils' ) ) {
1481 + return Utils::render_html_attributes( $this->attributes[ $element ] );
1482 + }
1483 +
1484 + // Fallback.
1485 + return $this->render_fallback_attributes( $this->attributes[ $element ] );
1486 + }
1487 +
1488 + /**
1489 + * Function to render link attributes.
1490 + *
1491 + * @param string $id Element ID.
1492 + * @param array $control_name Control name.
1493 + * @param string $class_name Class name.
1494 + *
1495 + * @return string
1496 + */
1497 + public function render_link_attributes( $id, $control_name, $class_name = 'logo-img-link' ) {
1498 + $this->add_attribute( $id, 'class', $class_name );
1499 +
1500 + if ( ! empty( $control_name['url'] ) ) {
1501 + $this->add_link_attributes( $id, $control_name );
1502 + } else {
1503 + $this->add_attribute( $id, 'role', 'button' );
1504 + }
1505 +
1506 + return $this->get_attribute_string( $id );
1507 + }
1508 +
1509 + /**
1510 + * Render fallback attributes.
1511 + *
1512 + * @param array $attributes The attributes.
1513 + *
1514 + * @return string
1515 + */
1516 + private function render_fallback_attributes( $attributes ) {
1517 + $rendered_attributes = [];
1518 +
1519 + foreach ( $attributes as $attribute_key => $attribute_values ) {
1520 + if ( is_array( $attribute_values ) ) {
1521 + $attribute_values = implode( ' ', $attribute_values );
1522 + }
1523 +
1524 + $rendered_attributes[] = sprintf( '%1$s="%2$s"', $attribute_key, esc_attr( $attribute_values ) );
1525 + }
1526 +
1527 + return implode( ' ', $rendered_attributes );
1391 1528 }
1392 1529 }