This project does not seem to handle request data directly as such no vulnerable execution paths were found.
include
, or for example
via PHP's auto-loading mechanism.
These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more
1 | <?php |
||
2 | |||
3 | if ( ! defined( 'ABSPATH' ) ) { |
||
4 | exit; // Exit if accessed directly |
||
5 | } |
||
6 | |||
7 | /** |
||
8 | * WC_Shortcodes class |
||
9 | * |
||
10 | * @class WC_Shortcodes |
||
11 | * @version 2.1.0 |
||
12 | * @package WooCommerce/Classes |
||
13 | * @category Class |
||
14 | * @author WooThemes |
||
15 | */ |
||
16 | class WC_Shortcodes { |
||
17 | |||
18 | /** |
||
19 | * Init shortcodes. |
||
20 | */ |
||
21 | public static function init() { |
||
22 | $shortcodes = array( |
||
23 | 'product' => __CLASS__ . '::product', |
||
24 | 'product_page' => __CLASS__ . '::product_page', |
||
25 | 'product_category' => __CLASS__ . '::product_category', |
||
26 | 'product_categories' => __CLASS__ . '::product_categories', |
||
27 | 'add_to_cart' => __CLASS__ . '::product_add_to_cart', |
||
28 | 'add_to_cart_url' => __CLASS__ . '::product_add_to_cart_url', |
||
29 | 'products' => __CLASS__ . '::products', |
||
30 | 'recent_products' => __CLASS__ . '::recent_products', |
||
31 | 'sale_products' => __CLASS__ . '::sale_products', |
||
32 | 'best_selling_products' => __CLASS__ . '::best_selling_products', |
||
33 | 'top_rated_products' => __CLASS__ . '::top_rated_products', |
||
34 | 'featured_products' => __CLASS__ . '::featured_products', |
||
35 | 'product_attribute' => __CLASS__ . '::product_attribute', |
||
36 | 'related_products' => __CLASS__ . '::related_products', |
||
37 | 'shop_messages' => __CLASS__ . '::shop_messages', |
||
38 | 'woocommerce_order_tracking' => __CLASS__ . '::order_tracking', |
||
39 | 'woocommerce_cart' => __CLASS__ . '::cart', |
||
40 | 'woocommerce_checkout' => __CLASS__ . '::checkout', |
||
41 | 'woocommerce_my_account' => __CLASS__ . '::my_account', |
||
42 | ); |
||
43 | |||
44 | foreach ( $shortcodes as $shortcode => $function ) { |
||
45 | add_shortcode( apply_filters( "{$shortcode}_shortcode_tag", $shortcode ), $function ); |
||
46 | } |
||
47 | |||
48 | // Alias for pre 2.1 compatibility |
||
49 | add_shortcode( 'woocommerce_messages', __CLASS__ . '::shop_messages' ); |
||
50 | } |
||
51 | |||
52 | /** |
||
53 | * Shortcode Wrapper. |
||
54 | * |
||
55 | * @param string[] $function |
||
56 | * @param array $atts (default: array()) |
||
57 | * @return string |
||
58 | */ |
||
59 | public static function shortcode_wrapper( |
||
60 | $function, |
||
61 | $atts = array(), |
||
62 | $wrapper = array( |
||
63 | 'class' => 'woocommerce', |
||
64 | 'before' => null, |
||
65 | 'after' => null |
||
66 | ) |
||
67 | ) { |
||
68 | ob_start(); |
||
69 | |||
70 | echo empty( $wrapper['before'] ) ? '<div class="' . esc_attr( $wrapper['class'] ) . '">' : $wrapper['before']; |
||
71 | call_user_func( $function, $atts ); |
||
72 | echo empty( $wrapper['after'] ) ? '</div>' : $wrapper['after']; |
||
73 | |||
74 | return ob_get_clean(); |
||
75 | } |
||
76 | |||
77 | /** |
||
78 | * Loop over found products. |
||
79 | * @param array $query_args |
||
80 | * @param array $atts |
||
81 | * @param string $loop_name |
||
82 | * @return string |
||
83 | */ |
||
84 | private static function product_loop( $query_args, $atts, $loop_name ) { |
||
85 | global $woocommerce_loop; |
||
86 | |||
87 | $products = new WP_Query( apply_filters( 'woocommerce_shortcode_products_query', $query_args, $atts, $loop_name ) ); |
||
88 | $columns = absint( $atts['columns'] ); |
||
89 | $woocommerce_loop['columns'] = $columns; |
||
90 | $woocommerce_loop['name'] = $loop_name; |
||
91 | |||
92 | ob_start(); |
||
93 | |||
94 | if ( $products->have_posts() ) { |
||
95 | ?> |
||
96 | |||
97 | <?php do_action( "woocommerce_shortcode_before_{$loop_name}_loop" ); ?> |
||
98 | |||
99 | <?php woocommerce_product_loop_start(); ?> |
||
100 | |||
101 | <?php while ( $products->have_posts() ) : $products->the_post(); ?> |
||
102 | |||
103 | <?php wc_get_template_part( 'content', 'product' ); ?> |
||
104 | |||
105 | <?php endwhile; // end of the loop. ?> |
||
106 | |||
107 | <?php woocommerce_product_loop_end(); ?> |
||
108 | |||
109 | <?php do_action( "woocommerce_shortcode_after_{$loop_name}_loop" ); ?> |
||
110 | |||
111 | <?php |
||
112 | } else { |
||
113 | do_action( "woocommerce_shortcode_{$loop_name}_loop_no_results" ); |
||
114 | } |
||
115 | |||
116 | woocommerce_reset_loop(); |
||
117 | wp_reset_postdata(); |
||
118 | |||
119 | return '<div class="woocommerce columns-' . $columns . '">' . ob_get_clean() . '</div>'; |
||
120 | } |
||
121 | |||
122 | /** |
||
123 | * Cart page shortcode. |
||
124 | * |
||
125 | * @return string |
||
126 | */ |
||
127 | public static function cart() { |
||
128 | return is_null( WC()->cart ) ? '' : self::shortcode_wrapper( array( 'WC_Shortcode_Cart', 'output' ) ); |
||
129 | } |
||
130 | |||
131 | /** |
||
132 | * Checkout page shortcode. |
||
133 | * |
||
134 | * @param mixed $atts |
||
135 | * @return string |
||
136 | */ |
||
137 | public static function checkout( $atts ) { |
||
138 | return self::shortcode_wrapper( array( 'WC_Shortcode_Checkout', 'output' ), $atts ); |
||
139 | } |
||
140 | |||
141 | /** |
||
142 | * Order tracking page shortcode. |
||
143 | * |
||
144 | * @param mixed $atts |
||
145 | * @return string |
||
146 | */ |
||
147 | public static function order_tracking( $atts ) { |
||
148 | return self::shortcode_wrapper( array( 'WC_Shortcode_Order_Tracking', 'output' ), $atts ); |
||
149 | } |
||
150 | |||
151 | /** |
||
152 | * Cart shortcode. |
||
153 | * |
||
154 | * @param mixed $atts |
||
155 | * @return string |
||
156 | */ |
||
157 | public static function my_account( $atts ) { |
||
158 | return self::shortcode_wrapper( array( 'WC_Shortcode_My_Account', 'output' ), $atts ); |
||
159 | } |
||
160 | |||
161 | /** |
||
162 | * List products in a category shortcode. |
||
163 | * |
||
164 | * @param array $atts |
||
165 | * @return string |
||
166 | */ |
||
167 | public static function product_category( $atts ) { |
||
168 | $atts = shortcode_atts( array( |
||
169 | 'per_page' => '12', |
||
170 | 'columns' => '4', |
||
171 | 'orderby' => 'title', |
||
172 | 'order' => 'desc', |
||
173 | 'category' => '', // Slugs |
||
174 | 'operator' => 'IN' // Possible values are 'IN', 'NOT IN', 'AND'. |
||
175 | ), $atts ); |
||
176 | |||
177 | if ( ! $atts['category'] ) { |
||
178 | return ''; |
||
179 | } |
||
180 | |||
181 | // Default ordering args |
||
182 | $ordering_args = WC()->query->get_catalog_ordering_args( $atts['orderby'], $atts['order'] ); |
||
183 | $meta_query = WC()->query->get_meta_query(); |
||
184 | $query_args = array( |
||
185 | 'post_type' => 'product', |
||
186 | 'post_status' => 'publish', |
||
187 | 'ignore_sticky_posts' => 1, |
||
188 | 'orderby' => $ordering_args['orderby'], |
||
189 | 'order' => $ordering_args['order'], |
||
190 | 'posts_per_page' => $atts['per_page'], |
||
191 | 'meta_query' => $meta_query |
||
192 | ); |
||
193 | |||
194 | $query_args = self::_maybe_add_category_args( $query_args, $atts['category'], $atts['operator'] ); |
||
195 | |||
196 | if ( isset( $ordering_args['meta_key'] ) ) { |
||
197 | $query_args['meta_key'] = $ordering_args['meta_key']; |
||
198 | } |
||
199 | |||
200 | $return = self::product_loop( $query_args, $atts, 'product_cat' ); |
||
201 | |||
202 | // Remove ordering query arguments |
||
203 | WC()->query->remove_ordering_args(); |
||
204 | |||
205 | return $return; |
||
206 | } |
||
207 | |||
208 | |||
209 | /** |
||
210 | * List all (or limited) product categories. |
||
211 | * |
||
212 | * @param array $atts |
||
213 | * @return string |
||
214 | */ |
||
215 | public static function product_categories( $atts ) { |
||
216 | global $woocommerce_loop; |
||
217 | |||
218 | $atts = shortcode_atts( array( |
||
219 | 'number' => null, |
||
220 | 'orderby' => 'name', |
||
221 | 'order' => 'ASC', |
||
222 | 'columns' => '4', |
||
223 | 'hide_empty' => 1, |
||
224 | 'parent' => '', |
||
225 | 'ids' => '' |
||
226 | ), $atts ); |
||
227 | |||
228 | if ( isset( $atts['ids'] ) ) { |
||
229 | $ids = explode( ',', $atts['ids'] ); |
||
230 | $ids = array_map( 'trim', $ids ); |
||
231 | } else { |
||
232 | $ids = array(); |
||
233 | } |
||
234 | |||
235 | $hide_empty = ( $atts['hide_empty'] == true || $atts['hide_empty'] == 1 ) ? 1 : 0; |
||
236 | |||
237 | // get terms and workaround WP bug with parents/pad counts |
||
238 | $args = array( |
||
239 | 'orderby' => $atts['orderby'], |
||
240 | 'order' => $atts['order'], |
||
241 | 'hide_empty' => $hide_empty, |
||
242 | 'include' => $ids, |
||
243 | 'pad_counts' => true, |
||
244 | 'child_of' => $atts['parent'] |
||
245 | ); |
||
246 | |||
247 | $product_categories = get_terms( 'product_cat', $args ); |
||
248 | |||
249 | if ( '' !== $atts['parent'] ) { |
||
250 | $product_categories = wp_list_filter( $product_categories, array( 'parent' => $atts['parent'] ) ); |
||
251 | } |
||
252 | |||
253 | if ( $hide_empty ) { |
||
254 | foreach ( $product_categories as $key => $category ) { |
||
255 | if ( $category->count == 0 ) { |
||
256 | unset( $product_categories[ $key ] ); |
||
257 | } |
||
258 | } |
||
259 | } |
||
260 | |||
261 | if ( $atts['number'] ) { |
||
262 | $product_categories = array_slice( $product_categories, 0, $atts['number'] ); |
||
263 | } |
||
264 | |||
265 | $columns = absint( $atts['columns'] ); |
||
266 | $woocommerce_loop['columns'] = $columns; |
||
267 | |||
268 | ob_start(); |
||
269 | |||
270 | // Reset loop/columns globals when starting a new loop |
||
271 | $woocommerce_loop['loop'] = $woocommerce_loop['column'] = ''; |
||
272 | |||
273 | if ( $product_categories ) { |
||
274 | woocommerce_product_loop_start(); |
||
275 | |||
276 | foreach ( $product_categories as $category ) { |
||
277 | wc_get_template( 'content-product_cat.php', array( |
||
278 | 'category' => $category |
||
279 | ) ); |
||
280 | } |
||
281 | |||
282 | woocommerce_product_loop_end(); |
||
283 | } |
||
284 | |||
285 | woocommerce_reset_loop(); |
||
286 | |||
287 | return '<div class="woocommerce columns-' . $columns . '">' . ob_get_clean() . '</div>'; |
||
288 | } |
||
289 | |||
290 | /** |
||
291 | * Recent Products shortcode. |
||
292 | * |
||
293 | * @param array $atts |
||
294 | * @return string |
||
295 | */ |
||
296 | public static function recent_products( $atts ) { |
||
297 | $atts = shortcode_atts( array( |
||
298 | 'per_page' => '12', |
||
299 | 'columns' => '4', |
||
300 | 'orderby' => 'date', |
||
301 | 'order' => 'desc', |
||
302 | 'category' => '', // Slugs |
||
303 | 'operator' => 'IN' // Possible values are 'IN', 'NOT IN', 'AND'. |
||
304 | ), $atts ); |
||
305 | |||
306 | $query_args = array( |
||
307 | 'post_type' => 'product', |
||
308 | 'post_status' => 'publish', |
||
309 | 'ignore_sticky_posts' => 1, |
||
310 | 'posts_per_page' => $atts['per_page'], |
||
311 | 'orderby' => $atts['orderby'], |
||
312 | 'order' => $atts['order'], |
||
313 | 'meta_query' => WC()->query->get_meta_query() |
||
314 | ); |
||
315 | |||
316 | $query_args = self::_maybe_add_category_args( $query_args, $atts['category'], $atts['operator'] ); |
||
317 | |||
318 | return self::product_loop( $query_args, $atts, 'recent_products' ); |
||
319 | } |
||
320 | |||
321 | /** |
||
322 | * List multiple products shortcode. |
||
323 | * |
||
324 | * @param array $atts |
||
325 | * @return string |
||
326 | */ |
||
327 | public static function products( $atts ) { |
||
328 | $atts = shortcode_atts( array( |
||
329 | 'columns' => '4', |
||
330 | 'orderby' => 'title', |
||
331 | 'order' => 'asc', |
||
332 | 'ids' => '', |
||
333 | 'skus' => '' |
||
334 | ), $atts ); |
||
335 | |||
336 | $query_args = array( |
||
337 | 'post_type' => 'product', |
||
338 | 'post_status' => 'publish', |
||
339 | 'ignore_sticky_posts' => 1, |
||
340 | 'orderby' => $atts['orderby'], |
||
341 | 'order' => $atts['order'], |
||
342 | 'posts_per_page' => -1, |
||
343 | 'meta_query' => WC()->query->get_meta_query() |
||
344 | ); |
||
345 | |||
346 | if ( ! empty( $atts['skus'] ) ) { |
||
347 | $query_args['meta_query'][] = array( |
||
348 | 'key' => '_sku', |
||
349 | 'value' => array_map( 'trim', explode( ',', $atts['skus'] ) ), |
||
350 | 'compare' => 'IN' |
||
351 | ); |
||
352 | |||
353 | // Ignore catalog visibility |
||
354 | $query_args['meta_query'] = WC()->query->stock_status_meta_query(); |
||
355 | } |
||
356 | |||
357 | if ( ! empty( $atts['ids'] ) ) { |
||
358 | $query_args['post__in'] = array_map( 'trim', explode( ',', $atts['ids'] ) ); |
||
359 | |||
360 | // Ignore catalog visibility |
||
361 | $query_args['meta_query'] = WC()->query->stock_status_meta_query(); |
||
362 | } |
||
363 | |||
364 | return self::product_loop( $query_args, $atts, 'products' ); |
||
365 | } |
||
366 | |||
367 | /** |
||
368 | * Display a single product. |
||
369 | * |
||
370 | * @param array $atts |
||
371 | * @return string |
||
372 | */ |
||
373 | public static function product( $atts ) { |
||
374 | if ( empty( $atts ) ) { |
||
375 | return ''; |
||
376 | } |
||
377 | |||
378 | $meta_query = WC()->query->get_meta_query(); |
||
379 | |||
380 | $args = array( |
||
381 | 'post_type' => 'product', |
||
382 | 'posts_per_page' => 1, |
||
383 | 'no_found_rows' => 1, |
||
384 | 'post_status' => 'publish', |
||
385 | 'meta_query' => $meta_query |
||
386 | ); |
||
387 | |||
388 | if ( isset( $atts['sku'] ) ) { |
||
389 | $args['meta_query'][] = array( |
||
390 | 'key' => '_sku', |
||
391 | 'value' => $atts['sku'], |
||
392 | 'compare' => '=' |
||
393 | ); |
||
394 | } |
||
395 | |||
396 | if ( isset( $atts['id'] ) ) { |
||
397 | $args['p'] = $atts['id']; |
||
398 | } |
||
399 | |||
400 | ob_start(); |
||
401 | |||
402 | $products = new WP_Query( apply_filters( 'woocommerce_shortcode_products_query', $args, $atts ) ); |
||
403 | |||
404 | View Code Duplication | if ( $products->have_posts() ) : ?> |
|
0 ignored issues
–
show
|
|||
405 | |||
406 | <?php woocommerce_product_loop_start(); ?> |
||
407 | |||
408 | <?php while ( $products->have_posts() ) : $products->the_post(); ?> |
||
409 | |||
410 | <?php wc_get_template_part( 'content', 'product' ); ?> |
||
411 | |||
412 | <?php endwhile; // end of the loop. ?> |
||
413 | |||
414 | <?php woocommerce_product_loop_end(); ?> |
||
415 | |||
416 | <?php endif; |
||
417 | |||
418 | wp_reset_postdata(); |
||
419 | |||
420 | $css_class = 'woocommerce'; |
||
421 | |||
422 | if ( isset( $atts['class'] ) ) { |
||
423 | $css_class .= ' ' . $atts['class']; |
||
424 | } |
||
425 | |||
426 | return '<div class="' . esc_attr( $css_class ) . '">' . ob_get_clean() . '</div>'; |
||
427 | } |
||
428 | |||
429 | /** |
||
430 | * Display a single product price + cart button. |
||
431 | * |
||
432 | * @param array $atts |
||
433 | * @return string |
||
434 | */ |
||
435 | public static function product_add_to_cart( $atts ) { |
||
436 | global $wpdb, $post; |
||
437 | |||
438 | if ( empty( $atts ) ) { |
||
439 | return ''; |
||
440 | } |
||
441 | |||
442 | $atts = shortcode_atts( array( |
||
443 | 'id' => '', |
||
444 | 'class' => '', |
||
445 | 'quantity' => '1', |
||
446 | 'sku' => '', |
||
447 | 'style' => 'border:4px solid #ccc; padding: 12px;', |
||
448 | 'show_price' => 'true' |
||
449 | ), $atts ); |
||
450 | |||
451 | if ( ! empty( $atts['id'] ) ) { |
||
452 | $product_data = get_post( $atts['id'] ); |
||
453 | View Code Duplication | } elseif ( ! empty( $atts['sku'] ) ) { |
|
0 ignored issues
–
show
This code seems to be duplicated across your project.
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation. You can also find more detailed suggestions in the “Code” section of your repository. ![]() |
|||
454 | $product_id = wc_get_product_id_by_sku( $atts['sku'] ); |
||
455 | $product_data = get_post( $product_id ); |
||
456 | } else { |
||
457 | return ''; |
||
458 | } |
||
459 | |||
460 | $product = is_object( $product_data ) && in_array( $product_data->post_type, array( 'product', 'product_variation' ) ) ? wc_setup_product_data( $product_data ) : false; |
||
461 | |||
462 | if ( ! $product ) { |
||
463 | return ''; |
||
464 | } |
||
465 | |||
466 | $styles = empty( $atts['style'] ) ? '' : ' style="' . esc_attr( $atts['style'] ) . '"'; |
||
467 | |||
468 | ob_start(); |
||
469 | ?> |
||
470 | <p class="product woocommerce add_to_cart_inline <?php echo esc_attr( $atts['class'] ); ?>"<?php echo $styles; ?>> |
||
471 | |||
472 | <?php if ( 'true' == $atts['show_price'] ) : ?> |
||
473 | <?php echo $product->get_price_html(); ?> |
||
474 | <?php endif; ?> |
||
475 | |||
476 | <?php woocommerce_template_loop_add_to_cart( array( 'quantity' => $atts['quantity'] ) ); ?> |
||
477 | |||
478 | </p><?php |
||
479 | |||
480 | // Restore Product global in case this is shown inside a product post |
||
481 | wc_setup_product_data( $post ); |
||
482 | |||
483 | return ob_get_clean(); |
||
484 | } |
||
485 | |||
486 | /** |
||
487 | * Get the add to cart URL for a product. |
||
488 | * |
||
489 | * @param array $atts |
||
490 | * @return string |
||
491 | */ |
||
492 | public static function product_add_to_cart_url( $atts ) { |
||
493 | global $wpdb; |
||
494 | |||
495 | if ( empty( $atts ) ) { |
||
496 | return ''; |
||
497 | } |
||
498 | |||
499 | if ( isset( $atts['id'] ) ) { |
||
500 | $product_data = get_post( $atts['id'] ); |
||
501 | View Code Duplication | } elseif ( isset( $atts['sku'] ) ) { |
|
0 ignored issues
–
show
This code seems to be duplicated across your project.
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation. You can also find more detailed suggestions in the “Code” section of your repository. ![]() |
|||
502 | $product_id = wc_get_product_id_by_sku( $atts['sku'] ); |
||
503 | $product_data = get_post( $product_id ); |
||
504 | } else { |
||
505 | return ''; |
||
506 | } |
||
507 | |||
508 | $product = is_object( $product_data ) && in_array( $product_data->post_type, array( 'product', 'product_variation' ) ) ? wc_setup_product_data( $product_data ) : false; |
||
509 | |||
510 | if ( ! $product ) { |
||
511 | return ''; |
||
512 | } |
||
513 | |||
514 | $_product = wc_get_product( $product_data ); |
||
515 | |||
516 | return esc_url( $_product->add_to_cart_url() ); |
||
517 | } |
||
518 | |||
519 | /** |
||
520 | * List all products on sale. |
||
521 | * |
||
522 | * @param array $atts |
||
523 | * @return string |
||
524 | */ |
||
525 | public static function sale_products( $atts ) { |
||
526 | $atts = shortcode_atts( array( |
||
527 | 'per_page' => '12', |
||
528 | 'columns' => '4', |
||
529 | 'orderby' => 'title', |
||
530 | 'order' => 'asc', |
||
531 | 'category' => '', // Slugs |
||
532 | 'operator' => 'IN' // Possible values are 'IN', 'NOT IN', 'AND'. |
||
533 | ), $atts ); |
||
534 | |||
535 | $query_args = array( |
||
536 | 'posts_per_page' => $atts['per_page'], |
||
537 | 'orderby' => $atts['orderby'], |
||
538 | 'order' => $atts['order'], |
||
539 | 'no_found_rows' => 1, |
||
540 | 'post_status' => 'publish', |
||
541 | 'post_type' => 'product', |
||
542 | 'meta_query' => WC()->query->get_meta_query(), |
||
543 | 'post__in' => array_merge( array( 0 ), wc_get_product_ids_on_sale() ) |
||
544 | ); |
||
545 | |||
546 | $query_args = self::_maybe_add_category_args( $query_args, $atts['category'], $atts['operator'] ); |
||
547 | |||
548 | return self::product_loop( $query_args, $atts, 'sale_products' ); |
||
549 | } |
||
550 | |||
551 | /** |
||
552 | * List best selling products on sale. |
||
553 | * |
||
554 | * @param array $atts |
||
555 | * @return string |
||
556 | */ |
||
557 | public static function best_selling_products( $atts ) { |
||
558 | $atts = shortcode_atts( array( |
||
559 | 'per_page' => '12', |
||
560 | 'columns' => '4', |
||
561 | 'category' => '', // Slugs |
||
562 | 'operator' => 'IN' // Possible values are 'IN', 'NOT IN', 'AND'. |
||
563 | ), $atts ); |
||
564 | |||
565 | $query_args = array( |
||
566 | 'post_type' => 'product', |
||
567 | 'post_status' => 'publish', |
||
568 | 'ignore_sticky_posts' => 1, |
||
569 | 'posts_per_page' => $atts['per_page'], |
||
570 | 'meta_key' => 'total_sales', |
||
571 | 'orderby' => 'meta_value_num', |
||
572 | 'meta_query' => WC()->query->get_meta_query() |
||
573 | ); |
||
574 | |||
575 | $query_args = self::_maybe_add_category_args( $query_args, $atts['category'], $atts['operator'] ); |
||
576 | |||
577 | return self::product_loop( $query_args, $atts, 'best_selling_products' ); |
||
578 | } |
||
579 | |||
580 | /** |
||
581 | * List top rated products on sale. |
||
582 | * |
||
583 | * @param array $atts |
||
584 | * @return string |
||
585 | */ |
||
586 | public static function top_rated_products( $atts ) { |
||
587 | $atts = shortcode_atts( array( |
||
588 | 'per_page' => '12', |
||
589 | 'columns' => '4', |
||
590 | 'orderby' => 'title', |
||
591 | 'order' => 'asc', |
||
592 | 'category' => '', // Slugs |
||
593 | 'operator' => 'IN' // Possible values are 'IN', 'NOT IN', 'AND'. |
||
594 | ), $atts ); |
||
595 | |||
596 | $query_args = array( |
||
597 | 'post_type' => 'product', |
||
598 | 'post_status' => 'publish', |
||
599 | 'ignore_sticky_posts' => 1, |
||
600 | 'orderby' => $atts['orderby'], |
||
601 | 'order' => $atts['order'], |
||
602 | 'posts_per_page' => $atts['per_page'], |
||
603 | 'meta_query' => WC()->query->get_meta_query() |
||
604 | ); |
||
605 | |||
606 | $query_args = self::_maybe_add_category_args( $query_args, $atts['category'], $atts['operator'] ); |
||
607 | |||
608 | add_filter( 'posts_clauses', array( __CLASS__, 'order_by_rating_post_clauses' ) ); |
||
609 | |||
610 | $return = self::product_loop( $query_args, $atts, 'top_rated_products' ); |
||
611 | |||
612 | remove_filter( 'posts_clauses', array( __CLASS__, 'order_by_rating_post_clauses' ) ); |
||
613 | |||
614 | return $return; |
||
615 | } |
||
616 | |||
617 | /** |
||
618 | * Output featured products. |
||
619 | * |
||
620 | * @param array $atts |
||
621 | * @return string |
||
622 | */ |
||
623 | public static function featured_products( $atts ) { |
||
624 | $atts = shortcode_atts( array( |
||
625 | 'per_page' => '12', |
||
626 | 'columns' => '4', |
||
627 | 'orderby' => 'date', |
||
628 | 'order' => 'desc', |
||
629 | 'category' => '', // Slugs |
||
630 | 'operator' => 'IN' // Possible values are 'IN', 'NOT IN', 'AND'. |
||
631 | ), $atts ); |
||
632 | |||
633 | $meta_query = WC()->query->get_meta_query(); |
||
634 | $meta_query[] = array( |
||
635 | 'key' => '_featured', |
||
636 | 'value' => 'yes' |
||
637 | ); |
||
638 | |||
639 | $query_args = array( |
||
640 | 'post_type' => 'product', |
||
641 | 'post_status' => 'publish', |
||
642 | 'ignore_sticky_posts' => 1, |
||
643 | 'posts_per_page' => $atts['per_page'], |
||
644 | 'orderby' => $atts['orderby'], |
||
645 | 'order' => $atts['order'], |
||
646 | 'meta_query' => $meta_query |
||
647 | ); |
||
648 | |||
649 | $query_args = self::_maybe_add_category_args( $query_args, $atts['category'], $atts['operator'] ); |
||
650 | |||
651 | return self::product_loop( $query_args, $atts, 'featured_products' ); |
||
652 | } |
||
653 | |||
654 | /** |
||
655 | * Show a single product page. |
||
656 | * |
||
657 | * @param array $atts |
||
658 | * @return string |
||
659 | */ |
||
660 | public static function product_page( $atts ) { |
||
661 | if ( empty( $atts ) ) { |
||
662 | return ''; |
||
663 | } |
||
664 | |||
665 | if ( ! isset( $atts['id'] ) && ! isset( $atts['sku'] ) ) { |
||
666 | return ''; |
||
667 | } |
||
668 | |||
669 | $args = array( |
||
670 | 'posts_per_page' => 1, |
||
671 | 'post_type' => 'product', |
||
672 | 'post_status' => 'publish', |
||
673 | 'ignore_sticky_posts' => 1, |
||
674 | 'no_found_rows' => 1 |
||
675 | ); |
||
676 | |||
677 | View Code Duplication | if ( isset( $atts['sku'] ) ) { |
|
0 ignored issues
–
show
This code seems to be duplicated across your project.
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation. You can also find more detailed suggestions in the “Code” section of your repository. ![]() |
|||
678 | $args['meta_query'][] = array( |
||
679 | 'key' => '_sku', |
||
680 | 'value' => sanitize_text_field( $atts['sku'] ), |
||
681 | 'compare' => '=' |
||
682 | ); |
||
683 | |||
684 | $args['post_type'] = array( 'product', 'product_variation' ); |
||
685 | } |
||
686 | |||
687 | if ( isset( $atts['id'] ) ) { |
||
688 | $args['p'] = absint( $atts['id'] ); |
||
689 | } |
||
690 | |||
691 | $single_product = new WP_Query( $args ); |
||
692 | |||
693 | $preselected_id = '0'; |
||
694 | |||
695 | // check if sku is a variation |
||
696 | if ( isset( $atts['sku'] ) && $single_product->have_posts() && $single_product->post->post_type === 'product_variation' ) { |
||
697 | |||
698 | $variation = new WC_Product_Variation( $single_product->post->ID ); |
||
699 | $attributes = $variation->get_variation_attributes(); |
||
700 | |||
701 | // set preselected id to be used by JS to provide context |
||
702 | $preselected_id = $single_product->post->ID; |
||
703 | |||
704 | // get the parent product object |
||
705 | $args = array( |
||
706 | 'posts_per_page' => 1, |
||
707 | 'post_type' => 'product', |
||
708 | 'post_status' => 'publish', |
||
709 | 'ignore_sticky_posts' => 1, |
||
710 | 'no_found_rows' => 1, |
||
711 | 'p' => $single_product->post->post_parent |
||
712 | ); |
||
713 | |||
714 | $single_product = new WP_Query( $args ); |
||
715 | ?> |
||
716 | <script type="text/javascript"> |
||
717 | jQuery( document ).ready( function( $ ) { |
||
718 | var $variations_form = $( '[data-product-page-preselected-id="<?php echo esc_attr( $preselected_id ); ?>"]' ).find( 'form.variations_form' ); |
||
719 | |||
720 | <?php foreach( $attributes as $attr => $value ) { ?> |
||
721 | $variations_form.find( 'select[name="<?php echo esc_attr( $attr ); ?>"]' ).val( '<?php echo $value; ?>' ); |
||
722 | <?php } ?> |
||
723 | }); |
||
724 | </script> |
||
725 | <?php |
||
726 | } |
||
727 | |||
728 | ob_start(); |
||
729 | |||
730 | while ( $single_product->have_posts() ) : $single_product->the_post(); wp_enqueue_script( 'wc-single-product' ); ?> |
||
731 | |||
732 | <div class="single-product" data-product-page-preselected-id="<?php echo esc_attr( $preselected_id ); ?>"> |
||
733 | |||
734 | <?php wc_get_template_part( 'content', 'single-product' ); ?> |
||
735 | |||
736 | </div> |
||
737 | |||
738 | <?php endwhile; // end of the loop. |
||
739 | |||
740 | wp_reset_postdata(); |
||
741 | |||
742 | return '<div class="woocommerce">' . ob_get_clean() . '</div>'; |
||
743 | } |
||
744 | |||
745 | /** |
||
746 | * Show messages. |
||
747 | * |
||
748 | * @return string |
||
749 | */ |
||
750 | public static function shop_messages() { |
||
751 | ob_start(); |
||
752 | wc_print_notices(); |
||
753 | return '<div class="woocommerce">' . ob_get_clean() . '</div>'; |
||
754 | } |
||
755 | |||
756 | /** |
||
757 | * woocommerce_order_by_rating_post_clauses function. |
||
758 | * |
||
759 | * @param array $args |
||
760 | * @return array |
||
761 | */ |
||
762 | public static function order_by_rating_post_clauses( $args ) { |
||
763 | global $wpdb; |
||
764 | |||
765 | $args['where'] .= " AND $wpdb->commentmeta.meta_key = 'rating' "; |
||
766 | $args['join'] .= "LEFT JOIN $wpdb->comments ON($wpdb->posts.ID = $wpdb->comments.comment_post_ID) LEFT JOIN $wpdb->commentmeta ON($wpdb->comments.comment_ID = $wpdb->commentmeta.comment_id)"; |
||
767 | $args['orderby'] = "$wpdb->commentmeta.meta_value DESC"; |
||
768 | $args['groupby'] = "$wpdb->posts.ID"; |
||
769 | |||
770 | return $args; |
||
771 | } |
||
772 | |||
773 | /** |
||
774 | * List products with an attribute shortcode. |
||
775 | * Example [product_attribute attribute='color' filter='black']. |
||
776 | * |
||
777 | * @param array $atts |
||
778 | * @return string |
||
779 | */ |
||
780 | public static function product_attribute( $atts ) { |
||
781 | $atts = shortcode_atts( array( |
||
782 | 'per_page' => '12', |
||
783 | 'columns' => '4', |
||
784 | 'orderby' => 'title', |
||
785 | 'order' => 'asc', |
||
786 | 'attribute' => '', |
||
787 | 'filter' => '' |
||
788 | ), $atts ); |
||
789 | |||
790 | $query_args = array( |
||
791 | 'post_type' => 'product', |
||
792 | 'post_status' => 'publish', |
||
793 | 'ignore_sticky_posts' => 1, |
||
794 | 'posts_per_page' => $atts['per_page'], |
||
795 | 'orderby' => $atts['orderby'], |
||
796 | 'order' => $atts['order'], |
||
797 | 'meta_query' => WC()->query->get_meta_query(), |
||
798 | 'tax_query' => array( |
||
799 | array( |
||
800 | 'taxonomy' => strstr( $atts['attribute'], 'pa_' ) ? sanitize_title( $atts['attribute'] ) : 'pa_' . sanitize_title( $atts['attribute'] ), |
||
801 | 'terms' => array_map( 'sanitize_title', explode( ',', $atts['filter'] ) ), |
||
802 | 'field' => 'slug' |
||
803 | ) |
||
804 | ) |
||
805 | ); |
||
806 | |||
807 | return self::product_loop( $query_args, $atts, 'product_attribute' ); |
||
808 | } |
||
809 | |||
810 | /** |
||
811 | * List related products. |
||
812 | * @param array $atts |
||
813 | * @return string |
||
814 | */ |
||
815 | public static function related_products( $atts ) { |
||
816 | $atts = shortcode_atts( array( |
||
817 | 'per_page' => '4', |
||
818 | 'columns' => '4', |
||
819 | 'orderby' => 'rand' |
||
820 | ), $atts ); |
||
821 | |||
822 | ob_start(); |
||
823 | |||
824 | woocommerce_related_products( $atts ); |
||
825 | |||
826 | return ob_get_clean(); |
||
827 | } |
||
828 | |||
829 | /** |
||
830 | * Adds a tax_query index to the query to filter by category. |
||
831 | * |
||
832 | * @param array $args |
||
833 | * @param string $category |
||
834 | * @param string $operator |
||
835 | * @return array; |
||
0 ignored issues
–
show
The doc-type
array; could not be parsed: Expected "|" or "end of type", but got ";" at position 5. (view supported doc-types)
This check marks PHPDoc comments that could not be parsed by our parser. To see which comment annotations we can parse, please refer to our documentation on supported doc-types. ![]() |
|||
836 | * @access private |
||
837 | */ |
||
838 | private static function _maybe_add_category_args( $args, $category, $operator ) { |
||
839 | View Code Duplication | if ( ! empty( $category ) ) { |
|
0 ignored issues
–
show
This code seems to be duplicated across your project.
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation. You can also find more detailed suggestions in the “Code” section of your repository. ![]() |
|||
840 | $args['tax_query'] = array( |
||
841 | array( |
||
842 | 'taxonomy' => 'product_cat', |
||
843 | 'terms' => array_map( 'sanitize_title', explode( ',', $category ) ), |
||
844 | 'field' => 'slug', |
||
845 | 'operator' => $operator |
||
846 | ) |
||
847 | ); |
||
848 | } |
||
849 | |||
850 | return $args; |
||
851 | } |
||
852 | } |
||
853 |
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.
You can also find more detailed suggestions in the “Code” section of your repository.