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 +174 -33 2.1.12 → 3.2.2 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,21 @@
237 246 }
238 247
239 248 $i = 0;
240 249
241 - 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 ) {
242 261 $i++;
243 - $GLOBALS['product'] = $product;
262 + $GLOBALS['product'] = $_product;
244 263
245 264 /**
246 265 * Before product template render hook.
247 266 */
@@ -247,12 +266,12 @@
247 266 */
248 267 do_action( 'rtsb_before_product_template_render' );
249 268
250 269 // Loop arg.
251 - $arg = $this->arg_dataset( $settings, $product, $settings['lazy_load'], $i );
270 + $arg = $this->arg_dataset( $settings, $_product, $settings['lazy_load'], $i );
252 271
253 272 // Get template.
254 - $html .= Fns::load_template( $template . $settings['layout'], $arg, true );
273 + $html .= Fns::load_template( $template . $layout, $arg, true );
255 274
256 275 /**
257 276 * After product template render hook.
258 277 */
@@ -259,9 +278,11 @@
259 278 do_action( 'rtsb_after_product_template_render' );
260 279
261 280 unset( $GLOBALS['product'] );
262 281 }
263 -
282 + if ( $isGlobalProduct ) {
283 + $GLOBALS['product'] = $isGlobalProduct;
284 + }
264 285 return $html;
265 286 }
266 287
267 288 /**
@@ -279,19 +300,20 @@
279 300 if ( empty( $query ) ) {
280 301 return null;
281 302 }
282 303
283 - $i = 0;
304 + $i = 0;
305 + $layout = RenderHelpers::filter_layout( esc_html( $settings['layout'] ), $template );
284 306
285 307 while ( $query->have_posts() ) {
286 308 $query->the_post();
287 309 $i++;
288 -
310 + global $product;
289 311 // Loop arg.
290 - $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 );
291 313
292 314 // Get template.
293 - $html .= Fns::load_template( $template . $settings['layout'], $arg, true );
315 + $html .= Fns::load_template( $template . $layout, $arg, true );
294 316 }
295 317
296 318 return $html;
297 319 }
@@ -364,14 +386,20 @@
364 386 * Before Product query hook.
365 387 *
366 388 * @hooked RadiusTheme\SB\Controllers\Hooks\ActionHooks::modify_wc_query_args 10
367 389 */
390 +
368 391 do_action( 'rtsb/elements/render/before_query', $settings, $args );
369 -
370 392 // Query.
371 393 $product_query = new WC_Product_Query( $args );
372 - $products = $pagination ? $product_query->get_products()->products : $product_query->get_products();
373 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 +
374 402 if ( ! empty( $products ) ) {
375 403 // Start rendering.
376 404 $hook_html .= $this->render_start( $metas, $settings, $temp_args );
377 405
@@ -428,17 +456,17 @@
428 456 $this->get_settings = $settings;
429 457 $rand = wp_rand();
430 458 $metas = RenderHelpers::meta_dataset( $settings, $template, $widget->get_settings_for_display() );
431 459
432 - $settings['rtsb_order'] = ! empty( $wp_query->query_vars['order'] ) ? $wp_query->query_vars['order'] : 'ASC';
433 - $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';
434 463
435 464 $pagination = $metas['pagination'];
436 465
437 466 $page_type = BuilderFns::builder_type( get_the_ID() );
438 467 $is_preview = BuilderFns::is_builder_preview() && array_key_exists( $page_type, BuilderFns::builder_page_types() );
439 - $posts_per_page = wc_get_default_products_per_row() * wc_get_default_product_rows_per_page();
440 -
468 + $posts_per_page = apply_filters( 'loop_shop_per_page', wc_get_default_products_per_row() * wc_get_default_product_rows_per_page() );
441 469 if ( $is_preview ) {
442 470 $main_query = clone $wp_query;
443 471 $main_post = clone $post;
444 472
@@ -586,8 +614,11 @@
586 614
587 615 if ( rtsb()->has_pro() && ( ! empty( $metas['tag_term'] ) ) ) {
588 616 $term = $metas['tag_term'];
589 617 }
618 + if ( rtsb()->has_pro() && ( ! empty( $metas['brand_term'] ) ) ) {
619 + $term = $metas['brand_term'];
620 + }
590 621
591 622 // Query.
592 623 if ( $is_single ) {
593 624 if ( empty( $term ) ) {
@@ -688,8 +719,9 @@
688 719 *
689 720 * @return array
690 721 */
691 722 public function wp_arg_dataset( array $meta, int $post_id, bool $lazy_load = false, $i = 0 ) {
723 + // phpcs:ignore WordPress.PHP.StrictInArray.MissingTrueStrict
692 724 if ( ( empty( $meta ) && ! $post_id ) || ! in_array( get_post_type( $post_id ), [ 'product_variation', 'product' ] ) ) {
693 725 return [];
694 726 }
695 727
@@ -788,9 +820,13 @@
788 820 $arg['image_link'] = $meta['image_link'];
789 821 $arg['grid'] .= 'rtsb-col-grid ';
790 822
791 823 if ( ! $fullwidth ) {
792 - $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 + }
793 829 }
794 830
795 831 if ( ! empty( $meta['active_cat_slider'] ) ) {
796 832 $arg['class'] .= ' rtsb-slide-item swiper-slide animated rtFadeIn ';
@@ -864,8 +900,9 @@
864 900 $arg['anchor_class'] = null;
865 901 $arg['hover_img_html'] = null;
866 902 $arg['s_link'] = [];
867 903 $arg['add_to_cart'] = '';
904 + $arg['p_counter'] = absint( $i );
868 905 $arg['p_id'] = $post_id;
869 906 $arg['product'] = $product;
870 907 $arg['p_link'] = $product->get_permalink();
871 908 $arg['p_sale'] = '';
@@ -896,10 +933,15 @@
896 933 $is_list = preg_match( '/list/', $layout );
897 934 $is_carousel = preg_match( '/slider/', $layout );
898 935
899 936 if ( ! $is_carousel ) {
900 - $arg['grid'] .= 'rtsb-col-grid ';
901 - $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 + }
902 944 } else {
903 945 $arg['grid'] .= 'rtsb-col-grid rtsb-col-full rtsb-slide-item swiper-slide ';
904 946 }
905 947
@@ -930,8 +972,10 @@
930 972 }
931 973
932 974 $arg['badge_class'] = RenderHelpers::badge_class( $meta['badge_preset'] );
933 975
976 + $meta['add_to_cart_text'] = apply_filters( 'rtsb/elementor/render/add_to_cart_text', $meta['add_to_cart_text'], $product );
977 +
934 978 if ( ! $meta['show_cart_text'] ) {
935 979 $meta['add_to_cart_text'] = '';
936 980 $meta['add_to_cart_success_text'] = '';
937 981 }
@@ -957,8 +1001,9 @@
957 1001 'text' => $meta['add_to_cart_text'],
958 1002 'success' => $meta['add_to_cart_success_text'],
959 1003 'icon_html' => $cart_icon,
960 1004 'alignment' => $meta['add_to_cart_alignment'],
1005 + 'product' => $product,
961 1006 ]
962 1007 );
963 1008 }
964 1009 }
@@ -1043,9 +1088,10 @@
1043 1088 'type' => $type,
1044 1089 'text' => $text,
1045 1090 'success' => $success,
1046 1091 'icon_html' => $icon_html,
1047 - 'alignment' => $alignment
1092 + 'alignment' => $alignment,
1093 + 'product' => $product
1048 1094 ) = $args;
1049 1095
1050 1096 $content = null;
1051 1097 $rand = wp_rand();
@@ -1058,9 +1104,8 @@
1058 1104
1059 1105 $cart_attr = [
1060 1106 'class' => 'rtsb-action-btn ' . $type . '-product tipsy icon-' . $alignment . ' ' . ( empty( $text ) ? 'no-text' : 'has-text' ),
1061 1107 'href' => esc_url( $link ),
1062 - 'rel' => 'nofollow',
1063 1108 'data-quantity' => '1',
1064 1109 'data-product_id' => absint( $id ),
1065 1110 'data-id' => absint( $id ),
1066 1111 ];
@@ -1066,12 +1111,13 @@
1066 1111 ];
1067 1112
1068 1113 if ( empty( $text ) ) {
1069 1114 $tooltip_mapping = [
1070 - 'simple' => esc_attr__( 'Add to Cart', 'shopbuilder' ),
1071 - 'variable' => esc_attr__( 'Select Options', 'shopbuilder' ),
1072 - 'grouped' => esc_attr__( 'View Products', 'shopbuilder' ),
1073 - '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' ),
1074 1120 ];
1075 1121
1076 1122 $cart_attr['title'] = $tooltip_mapping[ $type ];
1077 1123 }
@@ -1076,13 +1122,22 @@
1076 1122 $cart_attr['title'] = $tooltip_mapping[ $type ];
1077 1123 }
1078 1124
1079 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 );
1080 1131
1081 - if ( 'variable' === $type || 'grouped' === $type ) {
1082 1132 $this->add_attribute( 'rtsb_add_to_cart_button_' . $id . $rand, $cart_attr );
1083 1133
1084 - $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 + );
1085 1140
1086 1141 $content .= '<a ' . $this->get_attribute_string( 'rtsb_add_to_cart_button_' . $id . $rand ) . '>';
1087 1142 $content .= $icon_html;
1088 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>';
@@ -1102,8 +1157,9 @@
1102 1157 } else {
1103 1158 $cart_attr['href'] = $cart_attr['href'] . '?add-to-cart=' . absint( $id );
1104 1159 $cart_attr['class'] .= ' rtsb-add-to-cart-btn';
1105 1160 $cart_attr['data-type'] = $type;
1161 + $cart_attr = apply_filters( 'rtsb/elementor/render/cart_attributes', $cart_attr, $product );
1106 1162
1107 1163 $this->add_attribute( 'rtsb_add_to_cart_button_' . $id . $rand, $cart_attr );
1108 1164
1109 1165 $content .= '<a ' . $this->get_attribute_string( 'rtsb_add_to_cart_button_' . $id . $rand ) . '>';
@@ -1371,8 +1427,46 @@
1371 1427 return $this;
1372 1428 }
1373 1429
1374 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 + /**
1375 1469 * Get render attribute string.
1376 1470 *
1377 1471 * @param string $element The element.
1378 1472 *
@@ -1382,7 +1476,54 @@
1382 1476 if ( empty( $this->attributes[ $element ] ) ) {
1383 1477 return '';
1384 1478 }
1385 1479
1386 - 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 );
1387 1528 }
1388 1529 }