File Diff

Our website is made possible by displaying online advertisements to our visitors.
Please consider supporting us by disabling your ad blocker.
Compare file "includes/wc-template-functions.php"
Compare: vs
Old VersionNew Version
16function wc_template_redirect() { 16function wc_template_redirect() { 
17   global $wp_query, $wp; 17   global $wp_query, $wp; 
18 18 
  19   // When default permalinks are enabled, redirect shop page to post type archive url. 
19   if ( ! empty( $_GET['page_id'] ) && '' === get_option( 'permalink_structure' ) && wc_get_page_id( 'shop' ) === absint( $_GET['page_id'] ) && get_post_type_archive_link( 'product' ) ) { // WPCS: input var ok, CSRF ok. 20   if ( ! empty( $_GET['page_id'] ) && '' === get_option( 'permalink_structure' ) && wc_get_page_id( 'shop' ) === absint( $_GET['page_id'] ) && get_post_type_archive_link( 'product' ) ) { // WPCS: input var ok, CSRF ok. 
20   
21       // When default permalinks are enabled, redirect shop page to post type archive url.   
22       wp_safe_redirect( get_post_type_archive_link( 'product' ) ); 21       wp_safe_redirect( get_post_type_archive_link( 'product' ) ); 
23       exit; 22       exit; 
24 24   }
25   } elseif ( is_page( wc_get_page_id( 'checkout' ) ) && wc_get_page_id( 'checkout' ) !== wc_get_page_id( 'cart' ) && WC()->cart->is_empty() && empty( $wp->query_vars['order-pay'] ) && ! isset( $wp->query_vars['order-received'] ) && ! is_customize_preview() && apply_filters( 'woocommerce_checkout_redirect_empty_cart', true ) ) { 25
26 26   // When on the checkout with an empty cart, redirect to cart page.
27      // When on the checkout with an empty cart, redirect to cart page. 27   if ( is_page( wc_get_page_id( 'checkout' ) ) && wc_get_page_id( 'checkout' ) !== wc_get_page_id( 'cart' ) && WC()->cart->is_empty() && empty( $wp->query_vars['order-pay'] ) && ! isset( $wp->query_vars['order-received'] ) && ! is_customize_preview() && apply_filters( 'woocommerce_checkout_redirect_empty_cart', true ) ) {
28       wc_add_notice( __( 'Checkout is not available whilst your cart is empty.', 'woocommerce' ), 'notice' ); 27       wc_add_notice( __( 'Checkout is not available whilst your cart is empty.', 'woocommerce' ), 'notice' ); 
29       wp_safe_redirect( wc_get_page_permalink( 'cart' ) ); 28       wp_safe_redirect( wc_get_page_permalink( 'cart' ) ); 
30       exit; 29       exit; 
31 30 
32   } elseif ( isset( $wp->query_vars['customer-logout'] ) && ! empty( $_REQUEST['_wpnonce'] ) && wp_verify_nonce( sanitize_key( $_REQUEST['_wpnonce'] ), 'customer-logout' ) ) { // WPCS: input var ok, CSRF ok. 31   }
33 32
34       // Logout. 33   // Logout.
   34   if ( isset( $wp->query_vars['customer-logout'] ) && ! empty( $_REQUEST['_wpnonce'] ) && wp_verify_nonce( sanitize_key( $_REQUEST['_wpnonce'] ), 'customer-logout' ) ) { // WPCS: input var ok, CSRF ok.
35       wp_safe_redirect( str_replace( '&', '&', wp_logout_url( wc_get_page_permalink( 'myaccount' ) ) ) ); 35       wp_safe_redirect( str_replace( '&', '&', wp_logout_url( wc_get_page_permalink( 'myaccount' ) ) ) ); 
36       exit; 36       exit; 
37 37   }
38   } elseif ( isset( $wp->query_vars['customer-logout'] ) && 'true' === $wp->query_vars['customer-logout'] ) { 38
39       // Redirect to the correct logout endpoint. 39   // Redirect to the correct logout endpoint.
   40   if ( isset( $wp->query_vars['customer-logout'] ) && 'true' === $wp->query_vars['customer-logout'] ) {
40       wp_safe_redirect( esc_url_raw( wc_get_account_endpoint_url( 'customer-logout' ) ) ); 41       wp_safe_redirect( esc_url_raw( wc_get_account_endpoint_url( 'customer-logout' ) ) ); 
41       exit; 42       exit; 
42 43   }
43   } elseif ( is_search() && is_post_type_archive( 'product' ) && apply_filters( 'woocommerce_redirect_single_search_result', true ) && 1 === absint( $wp_query->found_posts ) ) { 44
44 45   // Trigger 404 if trying to access an endpoint on wrong page.
45       // Redirect to the product page if we have a single product. 46   if ( is_wc_endpoint_url() && ! is_account_page() && ! is_checkout() ) {
   47       $wp_query->set_404();
   48       status_header( 404 );
   49       include( get_query_template( '404' ) );
   50       exit;
   51   }
   52
   53   // Redirect to the product page if we have a single product.
   54   if ( is_search() && is_post_type_archive( 'product' ) && apply_filters( 'woocommerce_redirect_single_search_result', true ) && 1 === absint( $wp_query->found_posts ) ) {
46       $product = wc_get_product( $wp_query->post ); 55       $product = wc_get_product( $wp_query->post ); 
47 56 
48       if ( $product && $product->is_visible() ) { 57       if ( $product && $product->is_visible() ) { 
49           wp_safe_redirect( get_permalink( $product->get_id() ), 302 ); 58           wp_safe_redirect( get_permalink( $product->get_id() ), 302 ); 
50           exit; 59           exit; 
51       } 60       } 
52   } elseif ( is_add_payment_method_page() ) { 52   }
53 53
54       // Ensure payment gateways are loaded early. 54   // Ensure gateways and shipping methods are loaded early.
55       WC()->payment_gateways(); 55   if ( is_add_payment_method_page() || is_checkout() ) {
56   
57   } elseif ( is_checkout() ) {   
58   
59       // Checkout pages handling   
60       // Buffer the checkout page. 65       // Buffer the checkout page. 
61       ob_start(); 66       ob_start(); 
62 67 
63       // Ensure gateways and shipping methods are loaded early. 68       // Ensure gateways and shipping methods are loaded early. 
64       WC()->payment_gateways(); 69       WC()->payment_gateways(); 
65       WC()->shipping(); 70       WC()->shipping(); 
66   
67   } 71   } 
68} 72} 
69add_action( 'template_redirect', 'wc_template_redirect' ); 73add_action( 'template_redirect', 'wc_template_redirect' ); 
  
165 169 
166   // If this is a main WC query, use global args as defaults. 170   // If this is a main WC query, use global args as defaults. 
167   if ( $GLOBALS['wp_query']->get( 'wc_query' ) ) { 171   if ( $GLOBALS['wp_query']->get( 'wc_query' ) ) { 
168       $default_args = array_merge( $default_args, array( 172       $default_args = array_merge(
169           'is_search'   => $GLOBALS['wp_query']->is_search(), 173           $default_args,
170           'is_filtered' => is_filtered(), 174           array(
171           'total'       => $GLOBALS['wp_query']->found_posts, 175               'is_search'   => $GLOBALS['wp_query']->is_search(),
172           'total_pages' => $GLOBALS['wp_query']->max_num_pages, 176               'is_filtered' => is_filtered(),
173           'per_page'    => $GLOBALS['wp_query']->get( 'posts_per_page' ), 177               'total'       => $GLOBALS['wp_query']->found_posts,
174           'current_page' => max( 1, $GLOBALS['wp_query']->get( 'paged', 1 ) ), 178               'total_pages' => $GLOBALS['wp_query']->max_num_pages,
175       ) ); 179               'per_page'    => $GLOBALS['wp_query']->get( 'posts_per_page' ),
   180               'current_page' => max( 1, $GLOBALS['wp_query']->get( 'paged', 1 ) ),
   181           )
   182       );
176   } 183   } 
177 184 
178   // Merge any existing values. 185   // Merge any existing values. 
  
395   if ( ! empty( $product_grid['default_columns'] ) ) { 402   if ( ! empty( $product_grid['default_columns'] ) ) { 
396       update_option( 'woocommerce_catalog_columns', absint( $product_grid['default_columns'] ) ); 403       update_option( 'woocommerce_catalog_columns', absint( $product_grid['default_columns'] ) ); 
397   } 404   } 
  405 
  406   wp_cache_flush(); // Flush any caches which could impact settings or templates. 
398} 407} 
399add_action( 'after_switch_theme', 'wc_reset_product_grid_settings' ); 408add_action( 'after_switch_theme', 'wc_reset_product_grid_settings' ); 
400 409 
  
444} 453} 
445 454 
446/** 455/** 
447* Adds extra post classes for products. 456* Adds extra post classes for products via the WordPress post_class hook, if used.
   457*
   458* Note: For performance reasons we instead recommend using wc_product_class/wc_get_product_class instead.
448* 459* 
449* @since 2.1.0 460* @since 2.1.0 
450* @param array       $classes Current classes. 461* @param array       $classes Current classes. 
  
459 470 
460   $product = wc_get_product( $post_id ); 471   $product = wc_get_product( $post_id ); 
461 472 
462   if ( $product ) { 462   if ( ! $product ) {
463       $classes[] = 'product'; 463       return $classes;
464      $classes[] = wc_get_loop_class(); 464   }
465       $classes[] = $product->get_stock_status(); 465
466 466   $classes[] = 'product';
467      if ( $product->is_on_sale() ) { 467   $classes[] = wc_get_loop_class();
468          $classes[] = 'sale'; 468   $classes[] = $product->get_stock_status();
469       } 469
470      if ( $product->is_featured() ) { 470   if ( $product->is_on_sale() ) {
471          $classes[] = 'featured'; 471       $classes[] = 'sale';
472      } 472   }
473      if ( $product->is_downloadable() ) { 473   if ( $product->is_featured() ) {
474          $classes[] = 'downloadable'; 474       $classes[] = 'featured';
475      } 475   }
476      if ( $product->is_virtual() ) { 476   if ( $product->is_downloadable() ) {
477          $classes[] = 'virtual'; 477       $classes[] = 'downloadable';
478      } 478   }
479      if ( $product->is_sold_individually() ) { 479   if ( $product->is_virtual() ) {
480          $classes[] = 'sold-individually'; 480       $classes[] = 'virtual';
481      } 481   }
482      if ( $product->is_taxable() ) { 482   if ( $product->is_sold_individually() ) {
483          $classes[] = 'taxable'; 483       $classes[] = 'sold-individually';
484      } 484   }
485      if ( $product->is_shipping_taxable() ) { 485   if ( $product->is_taxable() ) {
486          $classes[] = 'shipping-taxable'; 486       $classes[] = 'taxable';
487      } 487   }
488      if ( $product->is_purchasable() ) { 488   if ( $product->is_shipping_taxable() ) {
489          $classes[] = 'purchasable'; 489       $classes[] = 'shipping-taxable';
490      } 490   }
491      if ( $product->get_type() ) { 491   if ( $product->is_purchasable() ) {
492          $classes[] = 'product-type-' . $product->get_type(); 492       $classes[] = 'purchasable';
493      } 493   }
494      if ( $product->is_type( 'variable' ) ) { 494   if ( $product->get_type() ) {
495          if ( ! $product->get_default_attributes() ) { 495       $classes[] = 'product-type-' . $product->get_type();
496              $classes[] = 'has-default-attributes'; 496   }
497          } 497   if ( $product->is_type( 'variable' ) && $product->get_default_attributes() ) {
498       } 498       $classes[] = 'has-default-attributes';
499   } 510   } 
500 511 
501   $key = array_search( 'hentry', $classes, true ); 512   $key = array_search( 'hentry', $classes, true ); 
  
543/** 554/** 
544* Retrieves the classes for the post div as an array. 555* Retrieves the classes for the post div as an array. 
545* 556* 
546* This method is clone from WordPress's get_post_class(), allowing removing taxonomies. 557* This method was modified from WordPress's get_post_class() to allow the removal of taxonomies
   558* (for performance reasons). Previously wc_product_post_class was hooked into post_class. @since 3.6.0
   559*
   560* @since 3.4.0
   561* @param string|array          $class     One or more classes to add to the class list.
   562* @param int|WP_Post|WC_Product $product Product ID or product object.
   563* @return array
   564*/
   565function wc_get_product_class( $class = '', $product = null ) {
   566   if ( is_null( $product ) && ! empty( $GLOBALS['product'] ) ) {
   567       // Product was null so pull from global.
   568       $product = $GLOBALS['product'];
   569   }
   570
   571   if ( $product && ! is_a( $product, 'WC_Product' ) ) {
   572       // Make sure we have a valid product, or set to false.
   573       $product = wc_get_product( $product );
   574   }
   575
   576   if ( $class ) {
   577       if ( ! is_array( $class ) ) {
   578           $class = preg_split( '#\s+#', $class );
   579       }
   580   } else {
   581       $class = array();
   582   }
   583
   584   $post_classes = array_map( 'esc_attr', $class );
   585
   586   if ( ! $product ) {
   587       return $post_classes;
   588   }
   589
   590   // Run through the post_class hook so 3rd parties using this previously can still append classes.
   591   // Note, to change classes you will need to use the newer woocommerce_post_class filter.
   592   // @internal This removes the wc_product_post_class filter so classes are not duplicated.
   593   $filtered = has_filter( 'post_class', 'wc_product_post_class' );
   594
   595   if ( $filtered ) {
   596       remove_filter( 'post_class', 'wc_product_post_class', 20 );
   597   }
   598
   599   $post_classes = apply_filters( 'post_class', $post_classes, $class, $product->get_id() );
   600
   601   if ( $filtered ) {
   602       add_filter( 'post_class', 'wc_product_post_class', 20, 3 );
   603   }
   604
   605   $classes = array_merge(
   606       $post_classes,
   607       array(
   608           'product',
   609           'type-product',
   610           'post-' . $product->get_id(),
   611           'status-' . $product->get_status(),
   612           wc_get_loop_class(),
   613           $product->get_stock_status(),
   614       ),
   615       wc_get_product_taxonomy_class( $product->get_category_ids(), 'product_cat' ),
   616       wc_get_product_taxonomy_class( $product->get_tag_ids(), 'product_tag' )
   617   );
   618
   619   if ( $product->get_image_id() ) {
   620       $classes[] = 'has-post-thumbnail';
   621   }
   622   if ( $product->get_post_password() ) {
   623       $classes[] = post_password_required( $product->get_id() ) ? 'post-password-required' : 'post-password-protected';
   624   }
   625   if ( $product->is_on_sale() ) {
   626       $classes[] = 'sale';
   627   }
   628   if ( $product->is_featured() ) {
   629       $classes[] = 'featured';
   630   }
   631   if ( $product->is_downloadable() ) {
   632       $classes[] = 'downloadable';
   633   }
   634   if ( $product->is_virtual() ) {
   635       $classes[] = 'virtual';
   636   }
   637   if ( $product->is_sold_individually() ) {
   638       $classes[] = 'sold-individually';
   639   }
   640   if ( $product->is_taxable() ) {
   641       $classes[] = 'taxable';
   642   }
   643   if ( $product->is_shipping_taxable() ) {
   644       $classes[] = 'shipping-taxable';
   645   }
   646   if ( $product->is_purchasable() ) {
   647       $classes[] = 'purchasable';
   648   }
   649   if ( $product->get_type() ) {
   650       $classes[] = 'product-type-' . $product->get_type();
   651   }
   652   if ( $product->is_type( 'variable' ) && $product->get_default_attributes() ) {
   653       $classes[] = 'has-default-attributes';
   654   }
   655
   656   // Include attributes and any extra taxonomies only if enabled via the hook - this is a performance issue.
   657   if ( apply_filters( 'woocommerce_get_product_class_include_taxonomies', false ) ) {
   658       $taxonomies = get_taxonomies( array( 'public' => true ) );
   659       $type      = 'variation' === $product->get_type() ? 'product_variation' : 'product';
   660       foreach ( (array) $taxonomies as $taxonomy ) {
   661           if ( is_object_in_taxonomy( $type, $taxonomy ) && ! in_array( $taxonomy, array( 'product_cat', 'product_tag' ), true ) ) {
   662               $classes = array_merge( $classes, wc_get_product_taxonomy_class( (array) get_the_terms( $product->get_id(), $taxonomy ), $taxonomy ) );
   663           }
   664       }
   665   }
   666
   667   /**
   668    * WooCommerce Post Class filter.
   669    *
   670    * @since 3.6.2
   671    * @param array     $class Array of CSS classes.
   672    * @param WC_Product $product Product object.
   673    */
   674   $classes = apply_filters( 'woocommerce_post_class', $classes, $product );
   675
   676   return array_map( 'esc_attr', array_unique( array_filter( $classes ) ) );
   677}
   678
   679/**
   680* Display the classes for the product div.
547* 681* 
548* @since 3.4.0 682* @since 3.4.0 
549* @param string|array          $class     One or more classes to add to the class list. 683* @param string|array          $class     One or more classes to add to the class list. 
550* @param int|WP_Post|WC_Product $product_id Product ID or product object. 684* @param int|WP_Post|WC_Product $product_id Product ID or product object. 
551* @return array   
552*/   
553function wc_get_product_class( $class = '', $product_id = null ) {   
554   if ( is_a( $product_id, 'WC_Product' ) ) {   
555       $product   = $product_id;   
556       $product_id = $product_id->get_id();   
557       $post      = get_post( $product_id );   
558   } else {   
559       $post   = get_post( $product_id );   
560       $product = wc_get_product( $post->ID );   
561   }   
562   
563   $classes = array();   
564   
565   if ( $class ) {   
566       if ( ! is_array( $class ) ) {   
567           $class = preg_split( '#\s+#', $class );   
568       }   
569       $classes = array_map( 'esc_attr', $class );   
570   } else {   
571       // Ensure that we always coerce class to being an array.   
572       $class = array();   
573   }   
574   
575   if ( ! $post || ! $product ) {   
576       return $classes;   
577   }   
578   
579   $classes[] = 'post-' . $post->ID;   
580   if ( ! is_admin() ) {   
581       $classes[] = $post->post_type;   
582   }   
583   $classes[] = 'type-' . $post->post_type;   
584   $classes[] = 'status-' . $post->post_status;   
585   
586   // Post format.   
587   if ( post_type_supports( $post->post_type, 'post-formats' ) ) {   
588       $post_format = get_post_format( $post->ID );   
589   
590       if ( $post_format && ! is_wp_error( $post_format ) ) {   
591           $classes[] = 'format-' . sanitize_html_class( $post_format );   
592       } else {   
593           $classes[] = 'format-standard';   
594       }   
595   }   
596   
597   // Post requires password.   
598   $post_password_required = post_password_required( $post->ID );   
599   if ( $post_password_required ) {   
600       $classes[] = 'post-password-required';   
601   } elseif ( ! empty( $post->post_password ) ) {   
602       $classes[] = 'post-password-protected';   
603   }   
604   
605   // Post thumbnails.   
606   if ( current_theme_supports( 'post-thumbnails' ) && $product->get_image_id() && ! is_attachment( $post ) && ! $post_password_required ) {   
607       $classes[] = 'has-post-thumbnail';   
608   }   
609   
610   // Sticky for Sticky Posts.   
611   if ( is_sticky( $post->ID ) ) {   
612       if ( is_home() && ! is_paged() ) {   
613           $classes[] = 'sticky';   
614       } elseif ( is_admin() ) {   
615           $classes[] = 'status-sticky';   
616       }   
617   }   
618   
619   // Hentry for hAtom compliance.   
620   $classes[] = 'hentry';   
621   
622   // Include attributes and any extra taxonomy.   
623   if ( apply_filters( 'woocommerce_get_product_class_include_taxonomies', false ) ) {   
624       $taxonomies = get_taxonomies( array( 'public' => true ) );   
625       foreach ( (array) $taxonomies as $taxonomy ) {   
626           if ( is_object_in_taxonomy( $post->post_type, $taxonomy ) && ! in_array( $taxonomy, array( 'product_cat', 'product_tag' ), true ) ) {   
627               $classes = array_merge( $classes, wc_get_product_taxonomy_class( (array) get_the_terms( $post->ID, $taxonomy ), $taxonomy ) );   
628           }   
629       }   
630   }   
631   // Categories.   
632   $classes = array_merge( $classes, wc_get_product_taxonomy_class( $product->get_category_ids(), 'product_cat' ) );   
633   
634   // Tags.   
635   $classes = array_merge( $classes, wc_get_product_taxonomy_class( $product->get_tag_ids(), 'product_tag' ) );   
636   
637   return array_filter( array_unique( apply_filters( 'post_class', $classes, $class, $post->ID ) ) );   
638}   
639   
640/**   
641* Display the classes for the product div.   
642*   
643* @since 3.4.0   
644* @param string|array          $class     One or more classes to add to the class list.   
645* @param int|WP_Post|WC_Product $product_id Product ID or product object.   
646*/ 685*/ 
647function wc_product_class( $class = '', $product_id = null ) { 686function wc_product_class( $class = '', $product_id = null ) { 
648   echo 'class="' . esc_attr( join( ' ', wc_get_product_class( $class, $product_id ) ) ) . '"'; 648   echo 'class="' . esc_attr( implode( ' ', wc_get_product_class( $class, $product_id ) ) ) . '"';
649} 688} 
650 689 
651/** 690/** 
  
666       $values   = array(); 705       $values   = array(); 
667 706 
668       if ( ! empty( $url_parts['query'] ) ) { 707       if ( ! empty( $url_parts['query'] ) ) { 
669           parse_str( $url_parts['query'], $values ); 708           // This is to preserve full-stops, pluses and spaces in the query string when ran through parse_str.
   709           $replace_chars = array(
   710               '.'  => '{dot}',
   711               '+'  => '{plus}',
   712               '%20' => '{space}',
   713           );
   714
   715           $query_string = str_replace( array_keys( $replace_chars ), array_values( $replace_chars ), $url_parts['query'] );
   716
   717           // Parse the string.
   718           parse_str( $query_string, $parsed_query_string );
   719
   720           // Convert the full-stops, pluses and spaces back and add to values array.
   721           foreach ( $parsed_query_string as $key => $value ) {
   722               $new_key           = str_replace( array_values( $replace_chars ), array_keys( $replace_chars ), $key );
   723               $new_value         = str_replace( array_values( $replace_chars ), array_keys( $replace_chars ), $value );
   724               $values[ $new_key ] = $new_value;
   725           }
670       } 726       } 
671   } 727   } 
672   $html = ''; 728   $html = ''; 
  
903 959 
904               <?php do_action( 'woocommerce_after_shop_loop' ); ?> 960               <?php do_action( 'woocommerce_after_shop_loop' ); ?> 
905 961 
906           <?php else : ?> 906               <?php
907 907           else :
908               <?php do_action( 'woocommerce_no_products_found' ); ?> 908               do_action( 'woocommerce_no_products_found' );
909   
910           <?php   
911           endif; 965           endif; 
912   
913       } 966       } 
914   } 967   } 
915} 968} 
  
963           $notice = __( 'This is a demo store for testing purposes &mdash; no orders shall be fulfilled.', 'woocommerce' ); 1016           $notice = __( 'This is a demo store for testing purposes &mdash; no orders shall be fulfilled.', 'woocommerce' ); 
964       } 1017       } 
965 1018 
966       echo apply_filters( 'woocommerce_demo_store', '<p class="woocommerce-store-notice demo_store">' . wp_kses_post( $notice ) . ' <a href="#" class="woocommerce-store-notice__dismiss-link">' . esc_html__( 'Dismiss', 'woocommerce' ) . '</a></p>', $notice ); // WPCS: XSS ok. 1019       $notice_id = md5( $notice );
   1020
   1021       echo apply_filters( 'woocommerce_demo_store', '<p class="woocommerce-store-notice demo_store" data-notice-id="' . esc_attr( $notice_id ) . '" style="display:none;">' . wp_kses_post( $notice ) . ' <a href="#" class="woocommerce-store-notice__dismiss-link">' . esc_html__( 'Dismiss', 'woocommerce' ) . '</a></p>', $notice ); // WPCS: XSS ok.
967   } 1022   } 
968} 1023} 
969 1024 
  
1063    * Show the product title in the product loop. By default this is an H2. 1118    * Show the product title in the product loop. By default this is an H2. 
1064    */ 1119    */ 
1065   function woocommerce_template_loop_product_title() { 1120   function woocommerce_template_loop_product_title() { 
1066       echo '<h2 class="woocommerce-loop-product__title">' . get_the_title() . '</h2>'; 1066       echo '<h2 class="' . esc_attr( apply_filters( 'woocommerce_product_loop_title_classes', 'woocommerce-loop-product__title' ) ) . '">' . get_the_title() . '</h2>'; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
1067   } 1122   } 
1068} 1123} 
1069if ( ! function_exists( 'woocommerce_template_loop_category_title' ) ) { 1124if ( ! function_exists( 'woocommerce_template_loop_category_title' ) ) { 
  
1181       if ( $product ) { 1236       if ( $product ) { 
1182           $defaults = array( 1237           $defaults = array( 
1183               'quantity'  => 1, 1238               'quantity'  => 1, 
1184               'class'     => implode( ' ', array_filter( array( 1239               'class'     => implode(
1185                   'button', 1240                   ' ',
1186                   'product_type_' . $product->get_type(), 1241                   array_filter(
1187                   $product->is_purchasable() && $product->is_in_stock() ? 'add_to_cart_button' : '', 1242                       array(
1188                   $product->supports( 'ajax_add_to_cart' ) && $product->is_purchasable() && $product->is_in_stock() ? 'ajax_add_to_cart' : '', 1243                           'button',
1189               ) ) ), 1244                           'product_type_' . $product->get_type(),
   1245                           $product->is_purchasable() && $product->is_in_stock() ? 'add_to_cart_button' : '',
   1246                           $product->supports( 'ajax_add_to_cart' ) && $product->is_purchasable() && $product->is_in_stock() ? 'ajax_add_to_cart' : '',
   1247                       )
   1248                   )
   1249               ),
1190               'attributes' => array( 1250               'attributes' => array( 
1191                   'data-product_id' => $product->get_id(), 1251                   'data-product_id' => $product->get_id(), 
1192                   'data-product_sku' => $product->get_sku(), 1252                   'data-product_sku' => $product->get_sku(), 
  
1198           $args = apply_filters( 'woocommerce_loop_add_to_cart_args', wp_parse_args( $args, $defaults ), $product ); 1258           $args = apply_filters( 'woocommerce_loop_add_to_cart_args', wp_parse_args( $args, $defaults ), $product ); 
1199 1259 
1200           if ( isset( $args['attributes']['aria-label'] ) ) { 1260           if ( isset( $args['attributes']['aria-label'] ) ) { 
1201               $args['attributes']['aria-label'] = strip_tags( $args['attributes']['aria-label'] ); 1201               $args['attributes']['aria-label'] = wp_strip_all_tags( $args['attributes']['aria-label'] );
1202           } 1262           } 
1203 1263 
1204           wc_get_template( 'loop/add-to-cart.php', $args ); 1264           wc_get_template( 'loop/add-to-cart.php', $args ); 
  
1291           return; 1351           return; 
1292       } 1352       } 
1293       $show_default_orderby   = 'menu_order' === apply_filters( 'woocommerce_default_catalog_orderby', get_option( 'woocommerce_default_catalog_orderby', 'menu_order' ) ); 1353       $show_default_orderby   = 'menu_order' === apply_filters( 'woocommerce_default_catalog_orderby', get_option( 'woocommerce_default_catalog_orderby', 'menu_order' ) ); 
1294       $catalog_orderby_options = apply_filters( 'woocommerce_catalog_orderby', array( 1354       $catalog_orderby_options = apply_filters(
1295           'menu_order' => __( 'Default sorting', 'woocommerce' ), 1355           'woocommerce_catalog_orderby',
1296           'popularity' => __( 'Sort by popularity', 'woocommerce' ), 1356           array(
1297           'rating'    => __( 'Sort by average rating', 'woocommerce' ), 1357               'menu_order' => __( 'Default sorting', 'woocommerce' ),
1298           'date'      => __( 'Sort by latest', 'woocommerce' ), 1358               'popularity' => __( 'Sort by popularity', 'woocommerce' ),
1299           'price'     => __( 'Sort by price: low to high', 'woocommerce' ), 1359               'rating'    => __( 'Sort by average rating', 'woocommerce' ),
1300           'price-desc' => __( 'Sort by price: high to low', 'woocommerce' ), 1360               'date'      => __( 'Sort by latest', 'woocommerce' ),
1301       ) ); 1361               'price'     => __( 'Sort by price: low to high', 'woocommerce' ),
   1362               'price-desc' => __( 'Sort by price: high to low', 'woocommerce' ),
   1363           )
   1364       );
1302 1365 
1303       $default_orderby = wc_get_loop_prop( 'is_search' ) ? 'relevance' : apply_filters( 'woocommerce_default_catalog_orderby', get_option( 'woocommerce_default_catalog_orderby', '' ) ); 1366       $default_orderby = wc_get_loop_prop( 'is_search' ) ? 'relevance' : apply_filters( 'woocommerce_default_catalog_orderby', get_option( 'woocommerce_default_catalog_orderby', '' ) ); 
1304       $orderby        = isset( $_GET['orderby'] ) ? wc_clean( wp_unslash( $_GET['orderby'] ) ) : $default_orderby; // WPCS: sanitization ok, input var ok, CSRF ok. 1367       $orderby        = isset( $_GET['orderby'] ) ? wc_clean( wp_unslash( $_GET['orderby'] ) ) : $default_orderby; // WPCS: sanitization ok, input var ok, CSRF ok. 
  
1313           unset( $catalog_orderby_options['menu_order'] ); 1376           unset( $catalog_orderby_options['menu_order'] ); 
1314       } 1377       } 
1315 1378 
1316       if ( 'no' === get_option( 'woocommerce_enable_review_rating' ) ) { 1316       if ( ! wc_review_ratings_enabled() ) {
1317           unset( $catalog_orderby_options['rating'] ); 1380           unset( $catalog_orderby_options['rating'] ); 
1318       } 1381       } 
1319 1382 
  
1321           $orderby = current( array_keys( $catalog_orderby_options ) ); 1384           $orderby = current( array_keys( $catalog_orderby_options ) ); 
1322       } 1385       } 
1323 1386 
1324       wc_get_template( 'loop/orderby.php', array( 1387       wc_get_template(
1325           'catalog_orderby_options' => $catalog_orderby_options, 1388           'loop/orderby.php',
1326           'orderby'                => $orderby, 1389           array(
1327           'show_default_orderby'   => $show_default_orderby, 1390               'catalog_orderby_options' => $catalog_orderby_options,
1328       ) ); 1391               'orderby'                => $orderby,
   1392               'show_default_orderby'   => $show_default_orderby,
   1393           )
   1394       );
1329   } 1395   } 
1330} 1396} 
1331 1397 
  
1396   $full_size        = apply_filters( 'woocommerce_gallery_full_size', apply_filters( 'woocommerce_product_thumbnails_large_size', 'full' ) ); 1462   $full_size        = apply_filters( 'woocommerce_gallery_full_size', apply_filters( 'woocommerce_product_thumbnails_large_size', 'full' ) ); 
1397   $thumbnail_src    = wp_get_attachment_image_src( $attachment_id, $thumbnail_size ); 1463   $thumbnail_src    = wp_get_attachment_image_src( $attachment_id, $thumbnail_size ); 
1398   $full_src         = wp_get_attachment_image_src( $attachment_id, $full_size ); 1464   $full_src         = wp_get_attachment_image_src( $attachment_id, $full_size ); 
  1465   $alt_text         = trim( wp_strip_all_tags( get_post_meta( $attachment_id, '_wp_attachment_image_alt', true ) ) ); 
1399   $image            = wp_get_attachment_image( 1466   $image            = wp_get_attachment_image( 
1400       $attachment_id, 1467       $attachment_id, 
1401       $image_size, 1468       $image_size, 
  
1417       ) 1484       ) 
1418   ); 1485   ); 
1419 1486 
1420   return '<div data-thumb="' . esc_url( $thumbnail_src[0] ) . '" class="woocommerce-product-gallery__image"><a href="' . esc_url( $full_src[0] ) . '">' . $image . '</a></div>'; 1420   return '<div data-thumb="' . esc_url( $thumbnail_src[0] ) . '" data-thumb-alt="' . esc_attr( $alt_text ) . '" class="woocommerce-product-gallery__image"><a href="' . esc_url( $full_src[0] ) . '">' . $image . '</a></div>';
1421} 1488} 
1422 1489 
1423if ( ! function_exists( 'woocommerce_output_product_data_tabs' ) ) { 1490if ( ! function_exists( 'woocommerce_output_product_data_tabs' ) ) { 
  
1525       $products = array_filter( array_map( 'wc_get_product', $product->get_children() ), 'wc_products_array_filter_visible_grouped' ); 1592       $products = array_filter( array_map( 'wc_get_product', $product->get_children() ), 'wc_products_array_filter_visible_grouped' ); 
1526 1593 
1527       if ( $products ) { 1594       if ( $products ) { 
1528           wc_get_template( 'single-product/add-to-cart/grouped.php', array( 1595           wc_get_template(
1529               'grouped_product'   => $product, 1596               'single-product/add-to-cart/grouped.php',
1530               'grouped_products'  => $products, 1597               array(
1531               'quantites_required' => false, 1598                   'grouped_product'   => $product,
1532           ) ); 1599                   'grouped_products'  => $products,
   1600                   'quantites_required' => false,
   1601               )
   1602           );
1533       } 1603       } 
1534   } 1604   } 
1535} 1605} 
  
1548       $get_variations = count( $product->get_children() ) <= apply_filters( 'woocommerce_ajax_variation_threshold', 30, $product ); 1618       $get_variations = count( $product->get_children() ) <= apply_filters( 'woocommerce_ajax_variation_threshold', 30, $product ); 
1549 1619 
1550       // Load the template. 1620       // Load the template. 
1551       wc_get_template( 'single-product/add-to-cart/variable.php', array( 1621       wc_get_template(
1552           'available_variations' => $get_variations ? $product->get_available_variations() : false, 1622           'single-product/add-to-cart/variable.php',
1553           'attributes'          => $product->get_variation_attributes(), 1623           array(
1554           'selected_attributes' => $product->get_default_attributes(), 1624               'available_variations' => $get_variations ? $product->get_available_variations() : false,
1555       ) ); 1625               'attributes'          => $product->get_variation_attributes(),
   1626               'selected_attributes' => $product->get_default_attributes(),
   1627           )
   1628       );
1556   } 1629   } 
1557} 1630} 
1558if ( ! function_exists( 'woocommerce_external_add_to_cart' ) ) { 1631if ( ! function_exists( 'woocommerce_external_add_to_cart' ) ) { 
  
1567           return; 1640           return; 
1568       } 1641       } 
1569 1642 
1570       wc_get_template( 'single-product/add-to-cart/external.php', array( 1643       wc_get_template(
1571           'product_url' => $product->add_to_cart_url(), 1644           'single-product/add-to-cart/external.php',
1572           'button_text' => $product->single_add_to_cart_text(), 1645           array(
1573       ) ); 1646               'product_url' => $product->add_to_cart_url(),
   1647               'button_text' => $product->single_add_to_cart_text(),
   1648           )
   1649       );
1574   } 1650   } 
1575} 1651} 
1576 1652 
  
1594           'input_id'    => uniqid( 'quantity_' ), 1670           'input_id'    => uniqid( 'quantity_' ), 
1595           'input_name'  => 'quantity', 1671           'input_name'  => 'quantity', 
1596           'input_value' => '1', 1672           'input_value' => '1', 
  1673           'classes'     => apply_filters( 'woocommerce_quantity_input_classes', array( 'input-text', 'qty', 'text' ), $product ), 
1597           'max_value'   => apply_filters( 'woocommerce_quantity_input_max', -1, $product ), 1674           'max_value'   => apply_filters( 'woocommerce_quantity_input_max', -1, $product ), 
1598           'min_value'   => apply_filters( 'woocommerce_quantity_input_min', 0, $product ), 1675           'min_value'   => apply_filters( 'woocommerce_quantity_input_min', 0, $product ), 
1599           'step'        => apply_filters( 'woocommerce_quantity_input_step', 1, $product ), 1676           'step'        => apply_filters( 'woocommerce_quantity_input_step', 1, $product ), 
  
1736    */ 1813    */ 
1737   function woocommerce_comments( $comment, $args, $depth ) { 1814   function woocommerce_comments( $comment, $args, $depth ) { 
1738       $GLOBALS['comment'] = $comment; // WPCS: override ok. 1815       $GLOBALS['comment'] = $comment; // WPCS: override ok. 
1739       wc_get_template( 'single-product/review.php', array( 1816       wc_get_template(
1740           'comment' => $comment, 1817           'single-product/review.php',
1741           'args'   => $args, 1818           array(
1742           'depth'  => $depth, 1819               'comment' => $comment,
1743       ) ); 1820               'args'   => $args,
   1821               'depth'  => $depth,
   1822           )
   1823       );
1744   } 1824   } 
1745} 1825} 
1746 1826 
  
1864       } 1944       } 
1865 1945 
1866       // Handle the legacy filter which controlled posts per page etc. 1946       // Handle the legacy filter which controlled posts per page etc. 
1867       $args = apply_filters( 'woocommerce_upsell_display_args', array( 1947       $args = apply_filters(
1868           'posts_per_page' => $limit, 1948           'woocommerce_upsell_display_args',
1869           'orderby'       => $orderby, 1949           array(
1870           'columns'       => $columns, 1950               'posts_per_page' => $limit,
1871       ) ); 1951               'orderby'       => $orderby,
   1952               'columns'       => $columns,
   1953           )
   1954       );
1872       wc_set_loop_prop( 'name', 'up-sells' ); 1955       wc_set_loop_prop( 'name', 'up-sells' ); 
1873       wc_set_loop_prop( 'columns', apply_filters( 'woocommerce_upsells_columns', isset( $args['columns'] ) ? $args['columns'] : $columns ) ); 1956       wc_set_loop_prop( 'columns', apply_filters( 'woocommerce_upsells_columns', isset( $args['columns'] ) ? $args['columns'] : $columns ) ); 
1874 1957 
  
1879       $upsells = wc_products_array_orderby( array_filter( array_map( 'wc_get_product', $product->get_upsell_ids() ), 'wc_products_array_filter_visible' ), $orderby, $order ); 1962       $upsells = wc_products_array_orderby( array_filter( array_map( 'wc_get_product', $product->get_upsell_ids() ), 'wc_products_array_filter_visible' ), $orderby, $order ); 
1880       $upsells = $limit > 0 ? array_slice( $upsells, 0, $limit ) : $upsells; 1963       $upsells = $limit > 0 ? array_slice( $upsells, 0, $limit ) : $upsells; 
1881 1964 
1882       wc_get_template( 'single-product/up-sells.php', array( 1965       wc_get_template(
1883           'upsells'       => $upsells, 1966           'single-product/up-sells.php',
1884 1967           array(
1885           // Not used now, but used in previous version of up-sells.php. 1968               'upsells'       => $upsells,
1886           'posts_per_page' => $limit, 1969
1887           'orderby'       => $orderby, 1970               // Not used now, but used in previous version of up-sells.php.
1888           'columns'       => $columns, 1971               'posts_per_page' => $limit,
1889       ) ); 1972               'orderby'       => $orderby,
   1973               'columns'       => $columns,
   1974           )
   1975       );
1890   } 1976   } 
1891} 1977} 
1892 1978 
  
1904           return; 1990           return; 
1905       } 1991       } 
1906       wp_enqueue_script( 'wc-country-select' ); 1992       wp_enqueue_script( 'wc-country-select' ); 
1907       wc_get_template( 'cart/shipping-calculator.php', array( 1993       wc_get_template(
1908           'button_text' => $button_text, 1994           'cart/shipping-calculator.php',
1909       ) ); 1995           array(
   1996               'button_text' => $button_text,
   1997           )
   1998       );
1910   } 1999   } 
1911} 2000} 
1912 2001 
  
1950       $limit      = apply_filters( 'woocommerce_cross_sells_total', $limit ); 2039       $limit      = apply_filters( 'woocommerce_cross_sells_total', $limit ); 
1951       $cross_sells = $limit > 0 ? array_slice( $cross_sells, 0, $limit ) : $cross_sells; 2040       $cross_sells = $limit > 0 ? array_slice( $cross_sells, 0, $limit ) : $cross_sells; 
1952 2041 
1953       wc_get_template( 'cart/cross-sells.php', array( 2042       wc_get_template(
1954           'cross_sells'   => $cross_sells, 2043           'cart/cross-sells.php',
1955 2044           array(
1956           // Not used now, but used in previous version of up-sells.php. 2045               'cross_sells'   => $cross_sells,
1957           'posts_per_page' => $limit, 2046
1958           'orderby'       => $orderby, 2047               // Not used now, but used in previous version of up-sells.php.
1959           'columns'       => $columns, 2048               'posts_per_page' => $limit,
1960       ) ); 2049               'orderby'       => $orderby,
   2050               'columns'       => $columns,
   2051           )
   2052       );
1961   } 2053   } 
1962} 2054} 
1963 2055 
  
2041    * Output the WooCommerce Checkout Login Form. 2133    * Output the WooCommerce Checkout Login Form. 
2042    */ 2134    */ 
2043   function woocommerce_checkout_login_form() { 2135   function woocommerce_checkout_login_form() { 
2044       wc_get_template( 'checkout/form-login.php', array( 2136       wc_get_template(
2045           'checkout' => WC()->checkout(), 2137           'checkout/form-login.php',
2046       ) ); 2138           array(
   2139               'checkout' => WC()->checkout(),
   2140           )
   2141       );
2047   } 2142   } 
2048} 2143} 
2049 2144 
  
2055    * @param array $args Arguments. 2150    * @param array $args Arguments. 
2056    */ 2151    */ 
2057   function woocommerce_breadcrumb( $args = array() ) { 2152   function woocommerce_breadcrumb( $args = array() ) { 
2058       $args = wp_parse_args( $args, apply_filters( 'woocommerce_breadcrumb_defaults', array( 2153       $args = wp_parse_args(
2059           'delimiter'  => '&nbsp;&#47;&nbsp;', 2154           $args,
2060           'wrap_before' => '<nav class="woocommerce-breadcrumb">', 2155           apply_filters(
2061           'wrap_after' => '</nav>', 2156               'woocommerce_breadcrumb_defaults',
2062           'before'     => '', 2157               array(
2063           'after'      => '', 2158                   'delimiter'  => '&nbsp;&#47;&nbsp;',
2064           'home'       => _x( 'Home', 'breadcrumb', 'woocommerce' ), 2159                   'wrap_before' => '<nav class="woocommerce-breadcrumb">',
2065       ) ) ); 2160                   'wrap_after' => '</nav>',
   2161                   'before'     => '',
   2162                   'after'      => '',
   2163                   'home'       => _x( 'Home', 'breadcrumb', 'woocommerce' ),
   2164               )
   2165           )
   2166       );
2066 2167 
2067       $breadcrumbs = new WC_Breadcrumb(); 2168       $breadcrumbs = new WC_Breadcrumb(); 
2068 2169 
  
2091    * @param bool $deprecated Deprecated param. 2192    * @param bool $deprecated Deprecated param. 
2092    */ 2193    */ 
2093   function woocommerce_order_review( $deprecated = false ) { 2194   function woocommerce_order_review( $deprecated = false ) { 
2094       wc_get_template( 'checkout/review-order.php', array( 2195       wc_get_template(
2095           'checkout' => WC()->checkout(), 2196           'checkout/review-order.php',
2096       ) ); 2197           array(
   2198               'checkout' => WC()->checkout(),
   2199           )
   2200       );
2097   } 2201   } 
2098} 2202} 
2099 2203 
  
2110           $available_gateways = array(); 2214           $available_gateways = array(); 
2111       } 2215       } 
2112 2216 
2113       wc_get_template( 'checkout/payment.php', array( 2217       wc_get_template(
2114           'checkout'          => WC()->checkout(), 2218           'checkout/payment.php',
2115           'available_gateways' => $available_gateways, 2219           array(
2116           'order_button_text' => apply_filters( 'woocommerce_order_button_text', __( 'Place order', 'woocommerce' ) ), 2220               'checkout'          => WC()->checkout(),
2117       ) ); 2221               'available_gateways' => $available_gateways,
   2222               'order_button_text' => apply_filters( 'woocommerce_order_button_text', __( 'Place order', 'woocommerce' ) ),
   2223           )
   2224       );
2118   } 2225   } 
2119} 2226} 
2120 2227 
  
2124    * Output the Coupon form for the checkout. 2231    * Output the Coupon form for the checkout. 
2125    */ 2232    */ 
2126   function woocommerce_checkout_coupon_form() { 2233   function woocommerce_checkout_coupon_form() { 
2127       wc_get_template( 'checkout/form-coupon.php', array( 2234       wc_get_template(
2128           'checkout' => WC()->checkout(), 2235           'checkout/form-coupon.php',
2129       ) ); 2236           array(
   2237               'checkout' => WC()->checkout(),
   2238           )
   2239       );
2130   } 2240   } 
2131} 2241} 
2132 2242 
  
2154    */ 2264    */ 
2155   function woocommerce_get_loop_display_mode() { 2265   function woocommerce_get_loop_display_mode() { 
2156       // Only return products when filtering things. 2266       // Only return products when filtering things. 
2157       if ( 1 < wc_get_loop_prop( 'current_page' ) || wc_get_loop_prop( 'is_search' ) || wc_get_loop_prop( 'is_filtered' ) ) { 2157       if ( wc_get_loop_prop( 'is_search' ) || wc_get_loop_prop( 'is_filtered' ) ) {
2158           return 'products'; 2268           return 'products'; 
2159       } 2269       } 
2160 2270 
  
2165           $display_type = get_option( 'woocommerce_shop_page_display', '' ); 2275           $display_type = get_option( 'woocommerce_shop_page_display', '' ); 
2166       } elseif ( is_product_category() ) { 2276       } elseif ( is_product_category() ) { 
2167           $parent_id   = get_queried_object_id(); 2277           $parent_id   = get_queried_object_id(); 
2168           $display_type = get_woocommerce_term_meta( $parent_id, 'display_type', true ); 2168           $display_type = get_term_meta( $parent_id, 'display_type', true );
2169           $display_type = '' === $display_type ? get_option( 'woocommerce_category_archive_display', '' ) : $display_type; 2279           $display_type = '' === $display_type ? get_option( 'woocommerce_category_archive_display', '' ) : $display_type; 
  2280       } 
  2281 
  2282       if ( ( ! is_shop() || 'subcategories' !== $display_type ) && 1 < wc_get_loop_prop( 'current_page' ) ) { 
  2283           return 'products'; 
2170       } 2284       } 
2171 2285 
2172       // Ensure valid value. 2286       // Ensure valid value. 
  
2206       // If displaying categories, append to the loop. 2320       // If displaying categories, append to the loop. 
2207       if ( 'subcategories' === $display_type || 'both' === $display_type ) { 2321       if ( 'subcategories' === $display_type || 'both' === $display_type ) { 
2208           ob_start(); 2322           ob_start(); 
2209           woocommerce_output_product_categories( array( 2323           woocommerce_output_product_categories(
2210               'parent_id' => is_product_category() ? get_queried_object_id() : 0, 2324               array(
2211           ) ); 2325                   'parent_id' => is_product_category() ? get_queried_object_id() : 0,
   2326               )
   2327           );
2212           $loop_html .= ob_get_clean(); 2328           $loop_html .= ob_get_clean(); 
2213 2329 
2214           if ( 'subcategories' === $display_type ) { 2330           if ( 'subcategories' === $display_type ) { 
  
2255 2371 
2256       if ( $args['force_display'] ) { 2372       if ( $args['force_display'] ) { 
2257           // We can still render if display is forced. 2373           // We can still render if display is forced. 
2258           woocommerce_output_product_categories( array( 2374           woocommerce_output_product_categories(
2259               'before'   => $args['before'], 2375               array(
2260               'after'    => $args['after'], 2376                   'before'   => $args['before'],
2261               'parent_id' => is_product_category() ? get_queried_object_id() : 0, 2377                   'after'    => $args['after'],
2262           ) ); 2378                   'parent_id' => is_product_category() ? get_queried_object_id() : 0,
   2379               )
   2380           );
2263           return true; 2381           return true; 
2264       } else { 2382       } else { 
2265           // Output nothing. woocommerce_maybe_show_product_subcategories will handle the output of cats. 2383           // Output nothing. woocommerce_maybe_show_product_subcategories will handle the output of cats. 
  
2292    * @return boolean 2410    * @return boolean 
2293    */ 2411    */ 
2294   function woocommerce_output_product_categories( $args = array() ) { 2412   function woocommerce_output_product_categories( $args = array() ) { 
2295       $args = wp_parse_args( $args, array( 2413       $args = wp_parse_args(
2296           'before'   => apply_filters( 'woocommerce_before_output_product_categories', '' ), 2414           $args,
2297           'after'    => apply_filters( 'woocommerce_after_output_product_categories', '' ), 2415           array(
2298           'parent_id' => 0, 2416               'before'   => apply_filters( 'woocommerce_before_output_product_categories', '' ),
2299       ) ); 2417               'after'    => apply_filters( 'woocommerce_after_output_product_categories', '' ),
   2418               'parent_id' => 0,
   2419           )
   2420       );
2300 2421 
2301       $product_categories = woocommerce_get_product_subcategories( $args['parent_id'] ); 2422       $product_categories = woocommerce_get_product_subcategories( $args['parent_id'] ); 
2302 2423 
  
2307       echo $args['before']; // WPCS: XSS ok. 2428       echo $args['before']; // WPCS: XSS ok. 
2308 2429 
2309       foreach ( $product_categories as $category ) { 2430       foreach ( $product_categories as $category ) { 
2310           wc_get_template( 'content-product_cat.php', array( 2431           wc_get_template(
2311               'category' => $category, 2432               'content-product_cat.php',
2312           ) ); 2433               array(
   2434                   'category' => $category,
   2435               )
   2436           );
2313       } 2437       } 
2314 2438 
2315       echo $args['after']; // WPCS: XSS ok. 2439       echo $args['after']; // WPCS: XSS ok. 
  
2327    */ 2451    */ 
2328   function woocommerce_get_product_subcategories( $parent_id = 0 ) { 2452   function woocommerce_get_product_subcategories( $parent_id = 0 ) { 
2329       $parent_id         = absint( $parent_id ); 2453       $parent_id         = absint( $parent_id ); 
2330       $product_categories = wp_cache_get( 'product-category-hierarchy-' . $parent_id, 'product_cat' ); 2454       $cache_key         = apply_filters( 'woocommerce_get_product_subcategories_cache_key', 'product-category-hierarchy-' . $parent_id, $parent_id );
   2455       $product_categories = $cache_key ? wp_cache_get( $cache_key, 'product_cat' ) : false;
2331 2456 
2332       if ( false === $product_categories ) { 2457       if ( false === $product_categories ) { 
2333           // NOTE: using child_of instead of parent - this is not ideal but due to a WP bug ( https://core.trac.wordpress.org/ticket/15626 ) pad_counts won't work. 2458           // NOTE: using child_of instead of parent - this is not ideal but due to a WP bug ( https://core.trac.wordpress.org/ticket/15626 ) pad_counts won't work. 
2334           $product_categories = get_categories( apply_filters( 'woocommerce_product_subcategories_args', array( 2459           $product_categories = get_categories(
2335               'parent'      => $parent_id, 2460               apply_filters(
2336               'menu_order'  => 'ASC', 2461                   'woocommerce_product_subcategories_args',
2337               'hide_empty'  => 0, 2462                   array(
2338               'hierarchical' => 1, 2463                       'parent'      => $parent_id,
2339               'taxonomy'    => 'product_cat', 2464                       'hide_empty'  => 0,
2340               'pad_counts'  => 1, 2465                       'hierarchical' => 1,
2341           ) ) ); 2466                       'taxonomy'    => 'product_cat',
2342 2467                       'pad_counts'  => 1,
2343           wp_cache_set( 'product-category-hierarchy-' . $parent_id, $product_categories, 'product_cat' ); 2468                   )
   2469               )
   2470           );
   2471
   2472           if ( $cache_key ) {
   2473               wp_cache_set( $cache_key, $product_categories, 'product_cat' );
   2474           }
2344       } 2475       } 
2345 2476 
2346       if ( apply_filters( 'woocommerce_product_subcategories_hide_empty', true ) ) { 2477       if ( apply_filters( 'woocommerce_product_subcategories_hide_empty', true ) ) { 
  
2361   function woocommerce_subcategory_thumbnail( $category ) { 2492   function woocommerce_subcategory_thumbnail( $category ) { 
2362       $small_thumbnail_size = apply_filters( 'subcategory_archive_thumbnail_size', 'woocommerce_thumbnail' ); 2493       $small_thumbnail_size = apply_filters( 'subcategory_archive_thumbnail_size', 'woocommerce_thumbnail' ); 
2363       $dimensions          = wc_get_image_size( $small_thumbnail_size ); 2494       $dimensions          = wc_get_image_size( $small_thumbnail_size ); 
2364       $thumbnail_id        = get_woocommerce_term_meta( $category->term_id, 'thumbnail_id', true ); 2364       $thumbnail_id        = get_term_meta( $category->term_id, 'thumbnail_id', true );
2365 2496 
2366       if ( $thumbnail_id ) { 2497       if ( $thumbnail_id ) { 
2367           $image       = wp_get_attachment_image_src( $thumbnail_id, $small_thumbnail_size ); 2498           $image       = wp_get_attachment_image_src( $thumbnail_id, $small_thumbnail_size ); 
  
2401           return; 2532           return; 
2402       } 2533       } 
2403 2534 
2404       wc_get_template( 'order/order-details.php', array( 2535       wc_get_template(
2405           'order_id' => $order_id, 2536           'order/order-details.php',
2406       ) ); 2537           array(
   2538               'order_id' => $order_id,
   2539           )
   2540       );
2407   } 2541   } 
2408} 2542} 
2409 2543 
  
2419       if ( ! $downloads ) { 2553       if ( ! $downloads ) { 
2420           return; 2554           return; 
2421       } 2555       } 
2422       wc_get_template( 'order/order-downloads.php', array( 2556       wc_get_template(
2423           'downloads' => $downloads, 2557           'order/order-downloads.php',
2424       ) ); 2558           array(
   2559               'downloads' => $downloads,
   2560           )
   2561       );
2425   } 2562   } 
2426} 2563} 
2427 2564 
  
2437           return; 2574           return; 
2438       } 2575       } 
2439 2576 
2440       wc_get_template( 'order/order-again.php', array( 2577       wc_get_template(
2441           'order'          => $order, 2578           'order/order-again.php',
2442           'order_again_url' => wp_nonce_url( add_query_arg( 'order_again', $order->get_id(), wc_get_cart_url() ), 'woocommerce-order_again' ), 2579           array(
2443       ) ); 2580               'order'          => $order,
   2581               'order_again_url' => wp_nonce_url( add_query_arg( 'order_again', $order->get_id(), wc_get_cart_url() ), 'woocommerce-order_again' ),
   2582           )
   2583       );
2444   } 2584   } 
2445} 2585} 
2446 2586 
  
2571 2711 
2572               } elseif ( ! is_null( $for_country ) && is_array( $states ) ) { 2712               } elseif ( ! is_null( $for_country ) && is_array( $states ) ) { 
2573 2713 
2574                   $field .= '<select name="' . esc_attr( $key ) . '" id="' . esc_attr( $args['id'] ) . '" class="state_select ' . esc_attr( implode( ' ', $args['input_class'] ) ) . '" ' . implode( ' ', $custom_attributes ) . ' data-placeholder="' . esc_attr( $args['placeholder'] ) . '"> 2574                   $field .= '<select name="' . esc_attr( $key ) . '" id="' . esc_attr( $args['id'] ) . '" class="state_select ' . esc_attr( implode( ' ', $args['input_class'] ) ) . '" ' . implode( ' ', $custom_attributes ) . ' data-placeholder="' . esc_attr( $args['placeholder'] ? $args['placeholder'] : esc_html__( 'Select an option&hellip;', 'woocommerce' ) ) . '">
2575                       <option value="">' . esc_html__( 'Select an option&hellip;', 'woocommerce' ) . '</option>'; 2715                       <option value="">' . esc_html__( 'Select an option&hellip;', 'woocommerce' ) . '</option>'; 
2576 2716 
2577                   foreach ( $states as $ckey => $cvalue ) { 2717                   foreach ( $states as $ckey => $cvalue ) { 
  
2711 2851 
2712       do_action( 'pre_get_product_search_form' ); 2852       do_action( 'pre_get_product_search_form' ); 
2713 2853 
2714       wc_get_template( 'product-searchform.php', array( 2854       wc_get_template(
2715           'index' => $product_search_form_index++, 2855           'product-searchform.php',
2716       ) ); 2856           array(
   2857               'index' => $product_search_form_index++,
   2858           )
   2859       );
2717 2860 
2718       $form = apply_filters( 'get_product_search_form', ob_get_clean() ); 2861       $form = apply_filters( 'get_product_search_form', ob_get_clean() ); 
2719 2862 
  
2774    * @since 2.4.0 2917    * @since 2.4.0 
2775    */ 2918    */ 
2776   function wc_dropdown_variation_attribute_options( $args = array() ) { 2919   function wc_dropdown_variation_attribute_options( $args = array() ) { 
2777       $args = wp_parse_args( apply_filters( 'woocommerce_dropdown_variation_attribute_options_args', $args ), array( 2920       $args = wp_parse_args(
2778           'options'         => false, 2921           apply_filters( 'woocommerce_dropdown_variation_attribute_options_args', $args ),
2779           'attribute'       => false, 2922           array(
2780           'product'         => false, 2923               'options'         => false,
2781           'selected'        => false, 2924               'attribute'       => false,
2782           'name'            => '', 2925               'product'         => false,
2783           'id'              => '', 2926               'selected'        => false,
2784           'class'           => '', 2927               'name'            => '',
2785           'show_option_none' => __( 'Choose an option', 'woocommerce' ), 2928               'id'              => '',
2786       ) ); 2929               'class'           => '',
   2930               'show_option_none' => __( 'Choose an option', 'woocommerce' ),
   2931           )
   2932       );
2787 2933 
2788       // Get selected value. 2934       // Get selected value. 
2789       if ( false === $args['selected'] && $args['attribute'] && $args['product'] instanceof WC_Product ) { 2935       if ( false === $args['selected'] && $args['attribute'] && $args['product'] instanceof WC_Product ) { 
  
2811       if ( ! empty( $options ) ) { 2957       if ( ! empty( $options ) ) { 
2812           if ( $product && taxonomy_exists( $attribute ) ) { 2958           if ( $product && taxonomy_exists( $attribute ) ) { 
2813               // Get terms if this is a taxonomy - ordered. We need the names too. 2959               // Get terms if this is a taxonomy - ordered. We need the names too. 
2814               $terms = wc_get_product_terms( $product->get_id(), $attribute, array( 2960               $terms = wc_get_product_terms(
2815                   'fields' => 'all', 2961                   $product->get_id(),
2816               ) ); 2962                   $attribute,
   2963                   array(
   2964                       'fields' => 'all',
   2965                   )
   2966               );
2817 2967 
2818               foreach ( $terms as $term ) { 2968               foreach ( $terms as $term ) { 
2819                   if ( in_array( $term->slug, $options, true ) ) { 2969                   if ( in_array( $term->slug, $options, true ) ) { 
2820                       $html .= '<option value="' . esc_attr( $term->slug ) . '" ' . selected( sanitize_title( $args['selected'] ), $term->slug, false ) . '>' . esc_html( apply_filters( 'woocommerce_variation_option_name', $term->name ) ) . '</option>'; 2820                       $html .= '<option value="' . esc_attr( $term->slug ) . '" ' . selected( sanitize_title( $args['selected'] ), $term->slug, false ) . '>' . esc_html( apply_filters( 'woocommerce_variation_option_name', $term->name, $term, $attribute, $product ) ) . '</option>';
2821                   } 2971                   } 
2822               } 2972               } 
2823           } else { 2973           } else { 
2824               foreach ( $options as $option ) { 2974               foreach ( $options as $option ) { 
2825                   // This handles < 2.4.0 bw compatibility where text attributes were not sanitized. 2975                   // This handles < 2.4.0 bw compatibility where text attributes were not sanitized. 
2826                   $selected = sanitize_title( $args['selected'] ) === $args['selected'] ? selected( $args['selected'], sanitize_title( $option ), false ) : selected( $args['selected'], $option, false ); 2976                   $selected = sanitize_title( $args['selected'] ) === $args['selected'] ? selected( $args['selected'], sanitize_title( $option ), false ) : selected( $args['selected'], $option, false ); 
2827                   $html   .= '<option value="' . esc_attr( $option ) . '" ' . $selected . '>' . esc_html( apply_filters( 'woocommerce_variation_option_name', $option ) ) . '</option>'; 2827                   $html   .= '<option value="' . esc_attr( $option ) . '" ' . $selected . '>' . esc_html( apply_filters( 'woocommerce_variation_option_name', $option, null, $attribute, $product ) ) . '</option>';
2828               } 2978               } 
2829           } 2979           } 
2830       } 2980       } 
  
2858       } 3008       } 
2859 3009 
2860       // No endpoint found? Default to dashboard. 3010       // No endpoint found? Default to dashboard. 
2861       wc_get_template( 'myaccount/dashboard.php', array( 3011       wc_get_template(
2862           'current_user' => get_user_by( 'id', get_current_user_id() ), 3012           'myaccount/dashboard.php',
2863       ) ); 3013           array(
   3014               'current_user' => get_user_by( 'id', get_current_user_id() ),
   3015           )
   3016       );
2864   } 3017   } 
2865} 3018} 
2866 3019 
  
2883    */ 3036    */ 
2884   function woocommerce_account_orders( $current_page ) { 3037   function woocommerce_account_orders( $current_page ) { 
2885       $current_page   = empty( $current_page ) ? 1 : absint( $current_page ); 3038       $current_page   = empty( $current_page ) ? 1 : absint( $current_page ); 
2886       $customer_orders = wc_get_orders( apply_filters( 'woocommerce_my_account_my_orders_query', array( 3039       $customer_orders = wc_get_orders(
2887           'customer' => get_current_user_id(), 3040           apply_filters(
2888           'page'    => $current_page, 3041               'woocommerce_my_account_my_orders_query',
2889           'paginate' => true, 3042               array(
2890       ) ) ); 3043                   'customer' => get_current_user_id(),
   3044                   'page'    => $current_page,
   3045                   'paginate' => true,
   3046               )
   3047           )
   3048       );
2891 3049 
2892       wc_get_template( 3050       wc_get_template( 
2893           'myaccount/orders.php', 3051           'myaccount/orders.php', 
  
3001       $args    = wp_parse_args( $args, $defaults ); 3159       $args    = wp_parse_args( $args, $defaults ); 
3002       $template = $args['plain_text'] ? 'emails/plain/email-order-items.php' : 'emails/email-order-items.php'; 3160       $template = $args['plain_text'] ? 'emails/plain/email-order-items.php' : 'emails/email-order-items.php'; 
3003 3161 
3004       wc_get_template( $template, apply_filters( 'woocommerce_email_order_items_args', array( 3162       wc_get_template(
3005           'order'              => $order, 3163           $template,
3006           'items'              => $order->get_items(), 3164           apply_filters(
3007           'show_download_links' => $order->is_download_permitted() && ! $args['sent_to_admin'], 3165               'woocommerce_email_order_items_args',
3008           'show_sku'           => $args['show_sku'], 3166               array(
3009           'show_purchase_note' => $order->is_paid() && ! $args['sent_to_admin'], 3167                   'order'              => $order,
3010           'show_image'         => $args['show_image'], 3168                   'items'              => $order->get_items(),
3011           'image_size'         => $args['image_size'], 3169                   'show_download_links' => $order->is_download_permitted() && ! $args['sent_to_admin'],
3012           'plain_text'         => $args['plain_text'], 3170                   'show_sku'           => $args['show_sku'],
3013           'sent_to_admin'      => $args['sent_to_admin'], 3171                   'show_purchase_note' => $order->is_paid() && ! $args['sent_to_admin'],
3014       ) ) ); 3172                   'show_image'         => $args['show_image'],
   3173                   'image_size'         => $args['image_size'],
   3174                   'plain_text'         => $args['plain_text'],
   3175                   'sent_to_admin'      => $args['sent_to_admin'],
   3176               )
   3177           )
   3178       );
3015 3179 
3016       return apply_filters( 'woocommerce_email_order_items_table', ob_get_clean(), $order ); 3180       return apply_filters( 'woocommerce_email_order_items_table', ob_get_clean(), $order ); 
3017   } 3181   } 
  
3029   function wc_display_item_meta( $item, $args = array() ) { 3193   function wc_display_item_meta( $item, $args = array() ) { 
3030       $strings = array(); 3194       $strings = array(); 
3031       $html   = ''; 3195       $html   = ''; 
3032       $args   = wp_parse_args( $args, array( 3196       $args   = wp_parse_args(
3033           'before'   => '<ul class="wc-item-meta"><li>', 3197           $args,
3034           'after'    => '</li></ul>', 3198           array(
3035           'separator' => '</li><li>', 3199               'before'      => '<ul class="wc-item-meta"><li>',
3036           'echo'     => true, 3200               'after'       => '</li></ul>',
3037           'autop'    => false, 3201               'separator'   => '</li><li>',
3038           'label_before' => '<strong class="wc-item-meta-label">', 3202               'echo'        => true,
3039           'label_after' => ':</strong> ', 3203               'autop'       => false,
3040       ) ); 3204               'label_before' => '<strong class="wc-item-meta-label">',
   3205               'label_after' => ':</strong> ',
   3206           )
   3207       );
3041 3208 
3042       foreach ( $item->get_formatted_meta_data() as $meta_id => $meta ) { 3209       foreach ( $item->get_formatted_meta_data() as $meta_id => $meta ) { 
3043           $value    = $args['autop'] ? wp_kses_post( $meta->display_value ) : wp_kses_post( make_clickable( trim( $meta->display_value ) ) ); 3210           $value    = $args['autop'] ? wp_kses_post( $meta->display_value ) : wp_kses_post( make_clickable( trim( $meta->display_value ) ) ); 
  
3070   function wc_display_item_downloads( $item, $args = array() ) { 3237   function wc_display_item_downloads( $item, $args = array() ) { 
3071       $strings = array(); 3238       $strings = array(); 
3072       $html   = ''; 3239       $html   = ''; 
3073       $args   = wp_parse_args( $args, array( 3240       $args   = wp_parse_args(
3074           'before'   => '<ul class ="wc-item-downloads"><li>', 3241           $args,
3075           'after'    => '</li></ul>', 3242           array(
3076           'separator' => '</li><li>', 3243               'before'   => '<ul class ="wc-item-downloads"><li>',
3077           'echo'     => true, 3244               'after'    => '</li></ul>',
3078           'show_url' => false, 3245               'separator' => '</li><li>',
3079       ) ); 3246               'echo'     => true,
   3247               'show_url' => false,
   3248           )
   3249       );
3080 3250 
3081       $downloads = is_object( $item ) && $item->is_type( 'line_item' ) ? $item->get_item_downloads() : array(); 3251       $downloads = is_object( $item ) && $item->is_type( 'line_item' ) ? $item->get_item_downloads() : array(); 
3082 3252 
  
3128* @param WC_Product $product Product Object. 3298* @param WC_Product $product Product Object. 
3129*/ 3299*/ 
3130function wc_display_product_attributes( $product ) { 3300function wc_display_product_attributes( $product ) { 
3131   wc_get_template( 'single-product/product-attributes.php', array( 3301   $product_attributes = array();
3132       'product'           => $product, 3302
3133       'attributes'        => array_filter( $product->get_attributes(), 'wc_attributes_array_filter_visible' ), 3303   // Display weight and dimensions before attribute list.
3134       'display_dimensions' => apply_filters( 'wc_product_enable_dimensions_display', $product->has_weight() || $product->has_dimensions() ), 3304   $display_dimensions = apply_filters( 'wc_product_enable_dimensions_display', $product->has_weight() || $product->has_dimensions() );
3135   ) ); 3305
   3306   if ( $display_dimensions && $product->has_weight() ) {
   3307       $product_attributes['weight'] = array(
   3308           'label' => __( 'Weight', 'woocommerce' ),
   3309           'value' => wc_format_weight( $product->get_weight() ),
   3310       );
   3311   }
   3312
   3313   if ( $display_dimensions && $product->has_dimensions() ) {
   3314       $product_attributes['dimensions'] = array(
   3315           'label' => __( 'Dimensions', 'woocommerce' ),
   3316           'value' => wc_format_dimensions( $product->get_dimensions( false ) ),
   3317       );
   3318   }
   3319
   3320   // Add product attributes to list.
   3321   $attributes = array_filter( $product->get_attributes(), 'wc_attributes_array_filter_visible' );
   3322
   3323   foreach ( $attributes as $attribute ) {
   3324       $values = array();
   3325
   3326       if ( $attribute->is_taxonomy() ) {
   3327           $attribute_taxonomy = $attribute->get_taxonomy_object();
   3328           $attribute_values  = wc_get_product_terms( $product->get_id(), $attribute->get_name(), array( 'fields' => 'all' ) );
   3329
   3330           foreach ( $attribute_values as $attribute_value ) {
   3331               $value_name = esc_html( $attribute_value->name );
   3332
   3333               if ( $attribute_taxonomy->attribute_public ) {
   3334                   $values[] = '<a href="' . esc_url( get_term_link( $attribute_value->term_id, $attribute->get_name() ) ) . '" rel="tag">' . $value_name . '</a>';
   3335               } else {
   3336                   $values[] = $value_name;
   3337               }
   3338           }
   3339       } else {
   3340           $values = $attribute->get_options();
   3341
   3342           foreach ( $values as &$value ) {
   3343               $value = make_clickable( esc_html( $value ) );
   3344           }
   3345       }
   3346
   3347       $product_attributes[ 'attribute_' . sanitize_title_with_dashes( $attribute->get_name() ) ] = array(
   3348           'label' => wc_attribute_label( $attribute->get_name() ),
   3349           'value' => apply_filters( 'woocommerce_attribute', wpautop( wptexturize( implode( ', ', $values ) ) ), $attribute, $values ),
   3350       );
   3351   }
   3352
   3353   /**
   3354    * Hook: woocommerce_display_product_attributes.
   3355    *
   3356    * @since 3.6.0.
   3357    * @param array $product_attributes Array of atributes to display; label, value.
   3358    * @param WC_Product $product Showing attributes for this product.
   3359    */
   3360   $product_attributes = apply_filters( 'woocommerce_display_product_attributes', $product_attributes, $product );
   3361
   3362   wc_get_template(
   3363       'single-product/product-attributes.php',
   3364       array(
   3365           'product_attributes' => $product_attributes,
   3366           // Legacy params.
   3367           'product'           => $product,
   3368           'attributes'        => $attributes,
   3369           'display_dimensions' => $display_dimensions,
   3370       )
   3371   );
3136} 3372} 
3137 3373 
3138/** 3374/** 
  
3149   if ( ! empty( $availability['availability'] ) ) { 3385   if ( ! empty( $availability['availability'] ) ) { 
3150       ob_start(); 3386       ob_start(); 
3151 3387 
3152       wc_get_template( 'single-product/stock.php', array( 3388       wc_get_template(
3153           'product'     => $product, 3389           'single-product/stock.php',
3154           'class'       => $availability['class'], 3390           array(
3155           'availability' => $availability['availability'], 3391               'product'     => $product,
3156       ) ); 3392               'class'       => $availability['class'],
   3393               'availability' => $availability['availability'],
   3394           )
   3395       );
3157 3396 
3158       $html = ob_get_clean(); 3397       $html = ob_get_clean(); 
3159   } 3398   } 
  
3175* @return string 3414* @return string 
3176*/ 3415*/ 
3177function wc_get_rating_html( $rating, $count = 0 ) { 3416function wc_get_rating_html( $rating, $count = 0 ) { 
3178   $html = 0 < $rating ? '<div class="star-rating">' . wc_get_star_rating_html( $rating, $count ) . '</div>' : ''; 3417   $html = '';
   3418
   3419   if ( 0 < $rating ) {
   3420       /* translators: %s: rating */
   3421       $label = sprintf( __( 'Rated %s out of 5', 'woocommerce' ), $rating );
   3422       $html = '<div class="star-rating" role="img" aria-label="' . esc_attr( $label ) . '">' . wc_get_star_rating_html( $rating, $count ) . '</div>';
   3423   }
   3424
3179   return apply_filters( 'woocommerce_product_get_rating_html', $html, $rating, $count ); 3425   return apply_filters( 'woocommerce_product_get_rating_html', $html, $rating, $count ); 
3180} 3426} 
3181 3427 
  
3289               $label = wc_attribute_label( $taxonomy ); 3535               $label = wc_attribute_label( $taxonomy ); 
3290           } else { 3536           } else { 
3291               // If this is a custom option slug, get the options name. 3537               // If this is a custom option slug, get the options name. 
3292               $value = apply_filters( 'woocommerce_variation_option_name', $value ); 3292               $value = apply_filters( 'woocommerce_variation_option_name', $value, null, $taxonomy, $cart_item['data'] );
3293               $label = wc_attribute_label( str_replace( 'attribute_', '', $name ), $cart_item['data'] ); 3539               $label = wc_attribute_label( str_replace( 'attribute_', '', $name ), $cart_item['data'] ); 
3294           } 3540           } 
3295 3541