1 <?php
2 3 4 5 6 7 8 9 10
11 class WC_Shortcodes {
12
13 14 15
16 public static function init() {
17
18 $shortcodes = array(
19 'product' => __CLASS__ . '::product',
20 'product_page' => __CLASS__ . '::product_page',
21 'product_category' => __CLASS__ . '::product_category',
22 'product_categories' => __CLASS__ . '::product_categories',
23 'add_to_cart' => __CLASS__ . '::product_add_to_cart',
24 'add_to_cart_url' => __CLASS__ . '::product_add_to_cart_url',
25 'products' => __CLASS__ . '::products',
26 'recent_products' => __CLASS__ . '::recent_products',
27 'sale_products' => __CLASS__ . '::sale_products',
28 'best_selling_products' => __CLASS__ . '::best_selling_products',
29 'top_rated_products' => __CLASS__ . '::top_rated_products',
30 'featured_products' => __CLASS__ . '::featured_products',
31 'product_attribute' => __CLASS__ . '::product_attribute',
32 'related_products' => __CLASS__ . '::related_products',
33 'shop_messages' => __CLASS__ . '::shop_messages',
34 'woocommerce_order_tracking' => __CLASS__ . '::order_tracking',
35 'woocommerce_cart' => __CLASS__ . '::cart',
36 'woocommerce_checkout' => __CLASS__ . '::checkout',
37 'woocommerce_my_account' => __CLASS__ . '::my_account',
38 );
39
40 foreach ( $shortcodes as $shortcode => $function ) {
41 add_shortcode( apply_filters( "{$shortcode}_shortcode_tag", $shortcode ), $function );
42 }
43
44
45 add_shortcode( 'woocommerce_messages', __CLASS__ . '::shop_messages' );
46 }
47
48 49 50 51 52 53 54
55 public static function shortcode_wrapper(
56 $function,
57 $atts = array(),
58 $wrapper = array(
59 'class' => 'woocommerce',
60 'before' => null,
61 'after' => null
62 )
63 ) {
64 ob_start();
65
66 $before = empty( $wrapper['before'] ) ? '<div class="' . esc_attr( $wrapper['class'] ) . '">' : $wrapper['before'];
67 $after = empty( $wrapper['after'] ) ? '</div>' : $wrapper['after'];
68
69 echo $before;
70 call_user_func( $function, $atts );
71 echo $after;
72
73 return ob_get_clean();
74 }
75
76 77 78 79 80 81 82
83 public static function cart( $atts ) {
84 return self::shortcode_wrapper( array( 'WC_Shortcode_Cart', 'output' ), $atts );
85 }
86
87 88 89 90 91 92 93
94 public static function checkout( $atts ) {
95 return self::shortcode_wrapper( array( 'WC_Shortcode_Checkout', 'output' ), $atts );
96 }
97
98 99 100 101 102 103 104
105 public static function order_tracking( $atts ) {
106 return self::shortcode_wrapper( array( 'WC_Shortcode_Order_Tracking', 'output' ), $atts );
107 }
108
109 110 111 112 113 114 115
116 public static function my_account( $atts ) {
117 return self::shortcode_wrapper( array( 'WC_Shortcode_My_Account', 'output' ), $atts );
118 }
119
120 121 122 123 124 125 126
127 public static function product_category( $atts ) {
128 global $woocommerce_loop;
129
130 if ( empty( $atts ) ) return '';
131
132 extract( shortcode_atts( array(
133 'per_page' => '12',
134 'columns' => '4',
135 'orderby' => 'title',
136 'order' => 'desc',
137 'category' => '',
138 'operator' => 'IN'
139 ), $atts ) );
140
141 if ( ! $category ) return '';
142
143
144 $ordering_args = WC()->query->get_catalog_ordering_args( $orderby, $order );
145
146 $args = array(
147 'post_type' => 'product',
148 'post_status' => 'publish',
149 'ignore_sticky_posts' => 1,
150 'orderby' => $ordering_args['orderby'],
151 'order' => $ordering_args['order'],
152 'posts_per_page' => $per_page,
153 'meta_query' => array(
154 array(
155 'key' => '_visibility',
156 'value' => array('catalog', 'visible'),
157 'compare' => 'IN'
158 )
159 ),
160 'tax_query' => array(
161 array(
162 'taxonomy' => 'product_cat',
163 'terms' => array( esc_attr( $category ) ),
164 'field' => 'slug',
165 'operator' => $operator
166 )
167 )
168 );
169
170 if ( isset( $ordering_args['meta_key'] ) ) {
171 $args['meta_key'] = $ordering_args['meta_key'];
172 }
173
174 ob_start();
175
176 $products = new WP_Query( apply_filters( 'woocommerce_shortcode_products_query', $args, $atts ) );
177
178 $woocommerce_loop['columns'] = $columns;
179
180 if ( $products->have_posts() ) : ?>
181
182 <?php woocommerce_product_loop_start(); ?>
183
184 <?php while ( $products->have_posts() ) : $products->the_post(); ?>
185
186 <?php wc_get_template_part( 'content', 'product' ); ?>
187
188 <?php endwhile;
189
190 <?php woocommerce_product_loop_end(); ?>
191
192 <?php endif;
193
194 woocommerce_reset_loop();
195 wp_reset_postdata();
196
197 return '<div class="woocommerce columns-' . $columns . '">' . ob_get_clean() . '</div>';
198 }
199
200
201 202 203 204 205 206 207
208 public static function product_categories( $atts ) {
209 global $woocommerce_loop;
210
211 extract( shortcode_atts( array(
212 'number' => null,
213 'orderby' => 'name',
214 'order' => 'ASC',
215 'columns' => '4',
216 'hide_empty' => 1,
217 'parent' => ''
218 ), $atts ) );
219
220 if ( isset( $atts[ 'ids' ] ) ) {
221 $ids = explode( ',', $atts[ 'ids' ] );
222 $ids = array_map( 'trim', $ids );
223 } else {
224 $ids = array();
225 }
226
227 $hide_empty = ( $hide_empty == true || $hide_empty == 1 ) ? 1 : 0;
228
229
230 $args = array(
231 'orderby' => $orderby,
232 'order' => $order,
233 'hide_empty' => $hide_empty,
234 'include' => $ids,
235 'pad_counts' => true,
236 'child_of' => $parent
237 );
238
239 $product_categories = get_terms( 'product_cat', $args );
240
241 if ( $parent !== "" ) {
242 $product_categories = wp_list_filter( $product_categories, array( 'parent' => $parent ) );
243 }
244
245 if ( $hide_empty ) {
246 foreach ( $product_categories as $key => $category ) {
247 if ( $category->count == 0 ) {
248 unset( $product_categories[ $key ] );
249 }
250 }
251 }
252
253 if ( $number ) {
254 $product_categories = array_slice( $product_categories, 0, $number );
255 }
256
257 $woocommerce_loop['columns'] = $columns;
258
259 ob_start();
260
261
262 $woocommerce_loop['loop'] = $woocommerce_loop['column'] = '';
263
264 if ( $product_categories ) {
265
266 woocommerce_product_loop_start();
267
268 foreach ( $product_categories as $category ) {
269
270 wc_get_template( 'content-product_cat.php', array(
271 'category' => $category
272 ) );
273
274 }
275
276 woocommerce_product_loop_end();
277
278 }
279
280 woocommerce_reset_loop();
281
282 return '<div class="woocommerce columns-' . $columns . '">' . ob_get_clean() . '</div>';
283 }
284
285 286 287 288 289 290 291
292 public static function recent_products( $atts ) {
293 global $woocommerce_loop;
294
295 extract( shortcode_atts( array(
296 'per_page' => '12',
297 'columns' => '4',
298 'orderby' => 'date',
299 'order' => 'desc'
300 ), $atts ) );
301
302 $meta_query = WC()->query->get_meta_query();
303
304 $args = array(
305 'post_type' => 'product',
306 'post_status' => 'publish',
307 'ignore_sticky_posts' => 1,
308 'posts_per_page' => $per_page,
309 'orderby' => $orderby,
310 'order' => $order,
311 'meta_query' => $meta_query
312 );
313
314 ob_start();
315
316 $products = new WP_Query( apply_filters( 'woocommerce_shortcode_products_query', $args, $atts ) );
317
318 $woocommerce_loop['columns'] = $columns;
319
320 if ( $products->have_posts() ) : ?>
321
322 <?php woocommerce_product_loop_start(); ?>
323
324 <?php while ( $products->have_posts() ) : $products->the_post(); ?>
325
326 <?php wc_get_template_part( 'content', 'product' ); ?>
327
328 <?php endwhile;
329
330 <?php woocommerce_product_loop_end(); ?>
331
332 <?php endif;
333
334 wp_reset_postdata();
335
336 return '<div class="woocommerce columns-' . $columns . '">' . ob_get_clean() . '</div>';
337 }
338
339
340 341 342 343 344 345 346
347 public static function products( $atts ) {
348 global $woocommerce_loop;
349
350 if ( empty( $atts ) ) return '';
351
352 extract( shortcode_atts( array(
353 'columns' => '4',
354 'orderby' => 'title',
355 'order' => 'asc'
356 ), $atts ) );
357
358 $args = array(
359 'post_type' => 'product',
360 'post_status' => 'publish',
361 'ignore_sticky_posts' => 1,
362 'orderby' => $orderby,
363 'order' => $order,
364 'posts_per_page' => -1,
365 'meta_query' => array(
366 array(
367 'key' => '_visibility',
368 'value' => array('catalog', 'visible'),
369 'compare' => 'IN'
370 )
371 )
372 );
373
374 if ( isset( $atts['skus'] ) ) {
375 $skus = explode( ',', $atts['skus'] );
376 $skus = array_map( 'trim', $skus );
377 $args['meta_query'][] = array(
378 'key' => '_sku',
379 'value' => $skus,
380 'compare' => 'IN'
381 );
382 }
383
384 if ( isset( $atts['ids'] ) ) {
385 $ids = explode( ',', $atts['ids'] );
386 $ids = array_map( 'trim', $ids );
387 $args['post__in'] = $ids;
388 }
389
390 ob_start();
391
392 $products = new WP_Query( apply_filters( 'woocommerce_shortcode_products_query', $args, $atts ) );
393
394 $woocommerce_loop['columns'] = $columns;
395
396 if ( $products->have_posts() ) : ?>
397
398 <?php woocommerce_product_loop_start(); ?>
399
400 <?php while ( $products->have_posts() ) : $products->the_post(); ?>
401
402 <?php wc_get_template_part( 'content', 'product' ); ?>
403
404 <?php endwhile;
405
406 <?php woocommerce_product_loop_end(); ?>
407
408 <?php endif;
409
410 wp_reset_postdata();
411
412 return '<div class="woocommerce columns-' . $columns . '">' . ob_get_clean() . '</div>';
413 }
414
415
416 417 418 419 420 421 422
423 public static function product( $atts ) {
424 if ( empty( $atts ) ) return '';
425
426 $args = array(
427 'post_type' => 'product',
428 'posts_per_page' => 1,
429 'no_found_rows' => 1,
430 'post_status' => 'publish',
431 'meta_query' => array(
432 array(
433 'key' => '_visibility',
434 'value' => array('catalog', 'visible'),
435 'compare' => 'IN'
436 )
437 )
438 );
439
440 if ( isset( $atts['sku'] ) ) {
441 $args['meta_query'][] = array(
442 'key' => '_sku',
443 'value' => $atts['sku'],
444 'compare' => '='
445 );
446 }
447
448 if ( isset( $atts['id'] ) ) {
449 $args['p'] = $atts['id'];
450 }
451
452 ob_start();
453
454 $products = new WP_Query( apply_filters( 'woocommerce_shortcode_products_query', $args, $atts ) );
455
456 if ( $products->have_posts() ) : ?>
457
458 <?php woocommerce_product_loop_start(); ?>
459
460 <?php while ( $products->have_posts() ) : $products->the_post(); ?>
461
462 <?php wc_get_template_part( 'content', 'product' ); ?>
463
464 <?php endwhile;
465
466 <?php woocommerce_product_loop_end(); ?>
467
468 <?php endif;
469
470 wp_reset_postdata();
471
472 return '<div class="woocommerce">' . ob_get_clean() . '</div>';
473 }
474
475 476 477 478 479 480 481
482 public static function product_add_to_cart( $atts ) {
483 global $wpdb, $post;
484
485 if ( empty( $atts ) ) return '';
486
487 extract( shortcode_atts( array(
488 'id' => '',
489 'sku' => '',
490 'style' => 'border:4px solid #ccc; padding: 12px;',
491 'show_price' => 'true'
492 ), $atts ) );
493
494 if ( ! empty( $id ) ) {
495 $product_data = get_post( $id );
496 } elseif ( ! empty( $sku ) ) {
497 $product_id = $wpdb->get_var( $wpdb->prepare( "SELECT post_id FROM $wpdb->postmeta WHERE meta_key='_sku' AND meta_value='%s' LIMIT 1", $sku ) );
498 $product_data = get_post( $product_id );
499 } else {
500 return '';
501 }
502
503 $product = wc_setup_product_data( $product_data );
504
505 if ( ! $product ) {
506 return '';
507 }
508
509 ob_start();
510 ?>
511 <p class="product woocommerce" style="<?php echo $style; ?>">
512
513 <?php if ( $show_price == 'true' ) : ?>
514 <?php echo $product->get_price_html(); ?>
515 <?php endif; ?>
516
517 <?php woocommerce_template_loop_add_to_cart(); ?>
518
519 </p><?php
520
521
522 wc_setup_product_data( $post );
523
524 return ob_get_clean();
525 }
526
527 528 529 530 531 532 533
534 public static function product_add_to_cart_url( $atts ) {
535 global $wpdb;
536
537 if ( empty( $atts ) ) return '';
538
539 if ( isset( $atts['id'] ) ) {
540 $product_data = get_post( $atts['id'] );
541 } elseif ( isset( $atts['sku'] ) ) {
542 $product_id = $wpdb->get_var( $wpdb->prepare( "SELECT post_id FROM $wpdb->postmeta WHERE meta_key='_sku' AND meta_value='%s' LIMIT 1", $atts['sku'] ) );
543 $product_data = get_post( $product_id );
544 } else {
545 return '';
546 }
547
548 if ( 'product' !== $product_data->post_type ) {
549 return '';
550 }
551
552 $_product = get_product( $product_data );
553
554 return esc_url( $_product->add_to_cart_url() );
555 }
556
557 558 559 560 561 562 563
564 public static function sale_products( $atts ) {
565 global $woocommerce_loop;
566
567 extract( shortcode_atts( array(
568 'per_page' => '12',
569 'columns' => '4',
570 'orderby' => 'title',
571 'order' => 'asc'
572 ), $atts ) );
573
574
575 $product_ids_on_sale = wc_get_product_ids_on_sale();
576
577 $meta_query = array();
578 $meta_query[] = WC()->query->visibility_meta_query();
579 $meta_query[] = WC()->query->stock_status_meta_query();
580 $meta_query = array_filter( $meta_query );
581
582 $args = array(
583 'posts_per_page' => $per_page,
584 'orderby' => $orderby,
585 'order' => $order,
586 'no_found_rows' => 1,
587 'post_status' => 'publish',
588 'post_type' => 'product',
589 'meta_query' => $meta_query,
590 'post__in' => array_merge( array( 0 ), $product_ids_on_sale )
591 );
592
593 ob_start();
594
595 $products = new WP_Query( apply_filters( 'woocommerce_shortcode_products_query', $args, $atts ) );
596
597 $woocommerce_loop['columns'] = $columns;
598
599 if ( $products->have_posts() ) : ?>
600
601 <?php woocommerce_product_loop_start(); ?>
602
603 <?php while ( $products->have_posts() ) : $products->the_post(); ?>
604
605 <?php wc_get_template_part( 'content', 'product' ); ?>
606
607 <?php endwhile;
608
609 <?php woocommerce_product_loop_end(); ?>
610
611 <?php endif;
612
613 wp_reset_postdata();
614
615 return '<div class="woocommerce columns-' . $columns . '">' . ob_get_clean() . '</div>';
616 }
617
618 619 620 621 622 623 624
625 public static function best_selling_products( $atts ) {
626 global $woocommerce_loop;
627
628 extract( shortcode_atts( array(
629 'per_page' => '12',
630 'columns' => '4'
631 ), $atts ) );
632
633 $args = array(
634 'post_type' => 'product',
635 'post_status' => 'publish',
636 'ignore_sticky_posts' => 1,
637 'posts_per_page' => $per_page,
638 'meta_key' => 'total_sales',
639 'orderby' => 'meta_value_num',
640 'meta_query' => array(
641 array(
642 'key' => '_visibility',
643 'value' => array( 'catalog', 'visible' ),
644 'compare' => 'IN'
645 )
646 )
647 );
648
649 ob_start();
650
651 $products = new WP_Query( apply_filters( 'woocommerce_shortcode_products_query', $args, $atts ) );
652
653 $woocommerce_loop['columns'] = $columns;
654
655 if ( $products->have_posts() ) : ?>
656
657 <?php woocommerce_product_loop_start(); ?>
658
659 <?php while ( $products->have_posts() ) : $products->the_post(); ?>
660
661 <?php wc_get_template_part( 'content', 'product' ); ?>
662
663 <?php endwhile;
664
665 <?php woocommerce_product_loop_end(); ?>
666
667 <?php endif;
668
669 wp_reset_postdata();
670
671 return '<div class="woocommerce columns-' . $columns . '">' . ob_get_clean() . '</div>';
672 }
673
674 675 676 677 678 679 680
681 public static function top_rated_products( $atts ) {
682 global $woocommerce_loop;
683
684 extract( shortcode_atts( array(
685 'per_page' => '12',
686 'columns' => '4',
687 'orderby' => 'title',
688 'order' => 'asc'
689 ), $atts ) );
690
691 $args = array(
692 'post_type' => 'product',
693 'post_status' => 'publish',
694 'ignore_sticky_posts' => 1,
695 'orderby' => $orderby,
696 'order' => $order,
697 'posts_per_page' => $per_page,
698 'meta_query' => array(
699 array(
700 'key' => '_visibility',
701 'value' => array('catalog', 'visible'),
702 'compare' => 'IN'
703 )
704 )
705 );
706
707 ob_start();
708
709 add_filter( 'posts_clauses', array( __CLASS__, 'order_by_rating_post_clauses' ) );
710
711 $products = new WP_Query( apply_filters( 'woocommerce_shortcode_products_query', $args, $atts ) );
712
713 remove_filter( 'posts_clauses', array( __CLASS__, 'order_by_rating_post_clauses' ) );
714
715 $woocommerce_loop['columns'] = $columns;
716
717 if ( $products->have_posts() ) : ?>
718
719 <?php woocommerce_product_loop_start(); ?>
720
721 <?php while ( $products->have_posts() ) : $products->the_post(); ?>
722
723 <?php wc_get_template_part( 'content', 'product' ); ?>
724
725 <?php endwhile;
726
727 <?php woocommerce_product_loop_end(); ?>
728
729 <?php endif;
730
731 wp_reset_postdata();
732
733 return '<div class="woocommerce columns-' . $columns . '">' . ob_get_clean() . '</div>';
734 }
735
736 737 738 739 740 741 742
743 public static function featured_products( $atts ) {
744 global $woocommerce_loop;
745
746 extract( shortcode_atts( array(
747 'per_page' => '12',
748 'columns' => '4',
749 'orderby' => 'date',
750 'order' => 'desc'
751 ), $atts ) );
752
753 $args = array(
754 'post_type' => 'product',
755 'post_status' => 'publish',
756 'ignore_sticky_posts' => 1,
757 'posts_per_page' => $per_page,
758 'orderby' => $orderby,
759 'order' => $order,
760 'meta_query' => array(
761 array(
762 'key' => '_visibility',
763 'value' => array('catalog', 'visible'),
764 'compare' => 'IN'
765 ),
766 array(
767 'key' => '_featured',
768 'value' => 'yes'
769 )
770 )
771 );
772
773 ob_start();
774
775 $products = new WP_Query( apply_filters( 'woocommerce_shortcode_products_query', $args, $atts ) );
776
777 $woocommerce_loop['columns'] = $columns;
778
779 if ( $products->have_posts() ) : ?>
780
781 <?php woocommerce_product_loop_start(); ?>
782
783 <?php while ( $products->have_posts() ) : $products->the_post(); ?>
784
785 <?php wc_get_template_part( 'content', 'product' ); ?>
786
787 <?php endwhile;
788
789 <?php woocommerce_product_loop_end(); ?>
790
791 <?php endif;
792
793 wp_reset_postdata();
794
795 return '<div class="woocommerce columns-' . $columns . '">' . ob_get_clean() . '</div>';
796 }
797
798
799 800 801 802 803 804 805
806 public static function product_page( $atts ) {
807 if ( empty( $atts ) ) return '';
808
809 if ( ! isset( $atts['id'] ) && ! isset( $atts['sku'] ) ) return '';
810
811 $args = array(
812 'posts_per_page' => 1,
813 'post_type' => 'product',
814 'post_status' => 'publish',
815 'ignore_sticky_posts' => 1,
816 'no_found_rows' => 1
817 );
818
819 if ( isset( $atts['sku'] ) ) {
820 $args['meta_query'][] = array(
821 'key' => '_sku',
822 'value' => $atts['sku'],
823 'compare' => '='
824 );
825 }
826
827 if ( isset( $atts['id'] ) ) {
828 $args['p'] = $atts['id'];
829 }
830
831 $single_product = new WP_Query( $args );
832
833 ob_start();
834
835 while ( $single_product->have_posts() ) : $single_product->the_post(); wp_enqueue_script( 'wc-single-product' ); ?>
836
837 <div class="single-product">
838
839 <?php wc_get_template_part( 'content', 'single-product' ); ?>
840
841 </div>
842
843 <?php endwhile;
844
845 wp_reset_postdata();
846
847 return '<div class="woocommerce">' . ob_get_clean() . '</div>';
848 }
849
850
851 852 853 854 855 856
857 public static function shop_messages() {
858 ob_start();
859
860 wc_print_notices();
861
862 return '<div class="woocommerce">' . ob_get_clean() . '</div>';
863 }
864
865 866 867 868 869 870 871
872 public static function order_by_rating_post_clauses( $args ) {
873 global $wpdb;
874
875 $args['where'] .= " AND $wpdb->commentmeta.meta_key = 'rating' ";
876
877 $args['join'] .= "
878 LEFT JOIN $wpdb->comments ON($wpdb->posts.ID = $wpdb->comments.comment_post_ID)
879 LEFT JOIN $wpdb->commentmeta ON($wpdb->comments.comment_ID = $wpdb->commentmeta.comment_id)
880 ";
881
882 $args['orderby'] = "$wpdb->commentmeta.meta_value DESC";
883
884 $args['groupby'] = "$wpdb->posts.ID";
885
886 return $args;
887 }
888
889
890 891 892 893 894 895 896 897
898 public static function product_attribute( $atts ) {
899 global $woocommerce_loop;
900
901 extract( shortcode_atts( array(
902 'per_page' => '12',
903 'columns' => '4',
904 'orderby' => 'title',
905 'order' => 'asc',
906 'attribute' => '',
907 'filter' => ''
908 ), $atts ) );
909
910 $attribute = strstr( $attribute, 'pa_' ) ? sanitize_title( $attribute ) : 'pa_' . sanitize_title( $attribute );
911
912 $args = array(
913 'post_type' => 'product',
914 'post_status' => 'publish',
915 'ignore_sticky_posts' => 1,
916 'posts_per_page' => $per_page,
917 'orderby' => $orderby,
918 'order' => $order,
919 'meta_query' => array(
920 array(
921 'key' => '_visibility',
922 'value' => array('catalog', 'visible'),
923 'compare' => 'IN'
924 )
925 ),
926 'tax_query' => array(
927 array(
928 'taxonomy' => $attribute,
929 'terms' => array_map( 'sanitize_title', explode( ",", $filter ) ),
930 'field' => 'slug'
931 )
932 )
933 );
934
935 ob_start();
936
937 $products = new WP_Query( apply_filters( 'woocommerce_shortcode_products_query', $args, $atts ) );
938
939 $woocommerce_loop['columns'] = $columns;
940
941 if ( $products->have_posts() ) : ?>
942
943 <?php woocommerce_product_loop_start(); ?>
944
945 <?php while ( $products->have_posts() ) : $products->the_post(); ?>
946
947 <?php wc_get_template_part( 'content', 'product' ); ?>
948
949 <?php endwhile;
950
951 <?php woocommerce_product_loop_end(); ?>
952
953 <?php endif;
954
955 wp_reset_postdata();
956
957 return '<div class="woocommerce">' . ob_get_clean() . '</div>';
958 }
959
960 961 962 963
964 public static function related_products( $atts ) {
965
966 $atts = shortcode_atts( array(
967 'posts_per_page' => '2',
968 'columns' => '2',
969 'orderby' => 'rand',
970 ), $atts );
971
972 if ( isset( $atts['per_page'] ) ) {
973 _deprecated_argument( __CLASS__ . '->' . __FUNCTION__, '2.1', __( 'Use $args["posts_per_page"] instead. Deprecated argument will be removed in WC 2.2.', 'woocommerce' ) );
974 $atts['posts_per_page'] = $atts['per_page'];
975 unset( $atts['per_page'] );
976 }
977
978 ob_start();
979
980 woocommerce_related_products( $atts );
981
982 return ob_get_clean();
983 }
984 }
985