Bring up-to-date with feature branch

This commit is contained in:
claudiulodro 2017-11-10 10:43:15 -08:00
commit 2609a4cd30
55 changed files with 1626 additions and 932 deletions

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -3139,6 +3139,10 @@ img.help_tip {
box-sizing: border-box;
}
input[size] {
width: auto !important;
}
// Ignore nested inputs.
table {
select,
@ -3265,6 +3269,105 @@ img.help_tip {
.wc_emails_wrapper {
padding: 0 15px 10px 0;
}
.woocommerce-thumbnail-cropping {
margin: 0 40px 1em 0;
padding: 0;
display:inline-block;
vertical-align: top;
input[type=radio] {
vertical-align: top;
margin-top: 2px;
}
label {
display: inline-block;
span.description {
margin-top: .5em;
display:block;
color: #999;
}
span.woocommerce-thumbnail-cropping-aspect-ratio {
margin-top: .5em;
display:block;
}
}
li {
margin: 5px 0 1.5em;
padding: 0;
}
}
.woocommerce-thumbnail-preview {
display:inline-block;
width: 320px;
vertical-align: top;
h4 {
margin-top: 0;
}
.woocommerce-thumbnail-preview-block {
text-align: center;
width: 100px;
margin: 0 10px 0 0;
float: left;
.woocommerce-thumbnail-preview-block__image {
width: 90px;
height: 90px;
border: 5px solid #fff;
background: #eee;
box-shadow: 0 1px 1px #ccc;
margin: 0 0 10px;
position: relative;
overflow: hidden;
&:before,
&:after {
content: "";
display: block;
width: 30px;
height: 30px;
background: rgba(0,0,0,.1);
position: absolute;
top: 50%;
left: 50%;
margin-left: -20px;
margin-top: -20px;
}
&:before {
margin-top: -10px;
margin-left: -10px;
background: rgba(0,0,0,.1);
}
}
.woocommerce-thumbnail-preview-block__text {
width: 50%;
background: #ddd;
margin: 0 auto 10px;
height: 6px;
}
.woocommerce-thumbnail-preview-block__button {
width: 30px;
height: 5px;
border: 8px solid #fff;
background: #ededed;
box-shadow: 0 0 0 1px #ddd;
margin: 0 auto;
border-radius: 2px;
}
&:nth-child(3) {
.woocommerce-thumbnail-preview-block__text {
width: 75%;
}
}
&:nth-child(4) {
.woocommerce-thumbnail-preview-block__text {
width: 35%;
}
}
}
.woocommerce-thumbnail-preview-block:last-child {
margin: 0;
}
}
}
}

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -102,6 +102,7 @@
div.summary {
float: right;
width: 48%;
clear: none;
}
.woocommerce-tabs {
@ -144,6 +145,35 @@
}
}
ul.products {
&.columns-1 {
li.product {
width: 100%;
margin-right: 0;
}
}
&.columns-2 {
li.product {
width: 48%;
}
}
&.columns-3 {
li.product {
width: 30.75%;
}
}
&.columns-5 {
li.product {
width: 16.95%;
}
}
&.columns-6 {
li.product {
width: 13.5%;
}
}
}
&.columns-1 {
ul.products {
li.product {

View File

@ -124,4 +124,43 @@
$( this ).closest( 'td' ).find( 'select' ).trigger( 'change' );
return false;
});
// Thumbnail cropping option updates and preview.
$( '.woocommerce-thumbnail-cropping' )
.on( 'change input', 'input', function() {
var value = $( '.woocommerce-thumbnail-cropping input:checked' ).val(),
$preview_images = $( '.woocommerce-thumbnail-preview-block__image' );
if ( 'custom' === value ) {
var width_ratio = Math.max( parseInt( $( 'input[name="thumbnail_cropping_aspect_ratio_width"]' ).val(), 10 ), 1 ),
height_ratio = Math.max( parseInt( $( 'input[name="thumbnail_cropping_aspect_ratio_height"]' ).val(), 10 ), 1 ),
height = ( 90 / width_ratio ) * height_ratio;
$preview_images.animate( { height: height + 'px' }, 200 );
$( '.woocommerce-thumbnail-cropping-aspect-ratio' ).slideDown( 200 );
} else if ( 'uncropped' === value ) {
var heights = [ '120', '60', '80' ];
$preview_images.each( function( index, element ) {
var height = heights[ index ];
$( element ).animate( { height: height + 'px' }, 200 );
} );
$( '.woocommerce-thumbnail-cropping-aspect-ratio' ).hide();
} else {
$preview_images.animate( { height: '90px' }, 200 );
$( '.woocommerce-thumbnail-cropping-aspect-ratio' ).hide();
}
return false;
});
$( '.woocommerce-thumbnail-cropping' ).find( 'input' ).change();
})( jQuery );

View File

@ -1 +1 @@
!function(t){t("select#woocommerce_allowed_countries").change(function(){"specific"===t(this).val()?(t(this).closest("tr").next("tr").hide(),t(this).closest("tr").next().next("tr").show()):"all_except"===t(this).val()?(t(this).closest("tr").next("tr").show(),t(this).closest("tr").next().next("tr").hide()):(t(this).closest("tr").next("tr").hide(),t(this).closest("tr").next().next("tr").hide())}).change(),t("select#woocommerce_ship_to_countries").change(function(){"specific"===t(this).val()?t(this).closest("tr").next("tr").show():t(this).closest("tr").next("tr").hide()}).change(),t("input#woocommerce_manage_stock").change(function(){t(this).is(":checked")?t(this).closest("tbody").find(".manage_stock_field").closest("tr").show():t(this).closest("tbody").find(".manage_stock_field").closest("tr").hide()}).change(),t(".colorpick").iris({change:function(e,i){t(this).parent().find(".colorpickpreview").css({backgroundColor:i.color.toString()})},hide:!0,border:!0}).on("click focus",function(e){e.stopPropagation(),t(".iris-picker").hide(),t(this).closest("td").find(".iris-picker").show(),t(this).data("original-value",t(this).val())}).on("change",function(){t(this).is(".iris-error")&&(t(this).data("original-value").match(/^\#([a-fA-F0-9]{6}|[a-fA-F0-9]{3})$/)?t(this).val(t(this).data("original-value")).change():t(this).val("").change())}),t("body").on("click",function(){t(".iris-picker").hide()}),t(function(){var e=!1;t("input, textarea, select, checkbox").change(function(){e=!0}),t(".woo-nav-tab-wrapper a").click(function(){window.onbeforeunload=e?function(){return woocommerce_settings_params.i18n_nav_warning}:""}),t(".submit input").click(function(){window.onbeforeunload=""})}),t("table.wc_gateways tbody, table.wc_shipping tbody").sortable({items:"tr",cursor:"move",axis:"y",handle:"td.sort",scrollSensitivity:40,helper:function(e,i){return i.children().each(function(){t(this).width(t(this).width())}),i.css("left","0"),i},start:function(t,e){e.item.css("background-color","#f6f6f6")},stop:function(t,e){e.item.removeAttr("style")}}),t(".woocommerce").on("click",".select_all",function(){return t(this).closest("td").find("select option").attr("selected","selected"),t(this).closest("td").find("select").trigger("change"),!1}),t(".woocommerce").on("click",".select_none",function(){return t(this).closest("td").find("select option").removeAttr("selected"),t(this).closest("td").find("select").trigger("change"),!1})}(jQuery);
!function(t){t("select#woocommerce_allowed_countries").change(function(){"specific"===t(this).val()?(t(this).closest("tr").next("tr").hide(),t(this).closest("tr").next().next("tr").show()):"all_except"===t(this).val()?(t(this).closest("tr").next("tr").show(),t(this).closest("tr").next().next("tr").hide()):(t(this).closest("tr").next("tr").hide(),t(this).closest("tr").next().next("tr").hide())}).change(),t("select#woocommerce_ship_to_countries").change(function(){"specific"===t(this).val()?t(this).closest("tr").next("tr").show():t(this).closest("tr").next("tr").hide()}).change(),t("input#woocommerce_manage_stock").change(function(){t(this).is(":checked")?t(this).closest("tbody").find(".manage_stock_field").closest("tr").show():t(this).closest("tbody").find(".manage_stock_field").closest("tr").hide()}).change(),t(".colorpick").iris({change:function(e,i){t(this).parent().find(".colorpickpreview").css({backgroundColor:i.color.toString()})},hide:!0,border:!0}).on("click focus",function(e){e.stopPropagation(),t(".iris-picker").hide(),t(this).closest("td").find(".iris-picker").show(),t(this).data("original-value",t(this).val())}).on("change",function(){t(this).is(".iris-error")&&(t(this).data("original-value").match(/^\#([a-fA-F0-9]{6}|[a-fA-F0-9]{3})$/)?t(this).val(t(this).data("original-value")).change():t(this).val("").change())}),t("body").on("click",function(){t(".iris-picker").hide()}),t(function(){var e=!1;t("input, textarea, select, checkbox").change(function(){e=!0}),t(".woo-nav-tab-wrapper a").click(function(){window.onbeforeunload=e?function(){return woocommerce_settings_params.i18n_nav_warning}:""}),t(".submit input").click(function(){window.onbeforeunload=""})}),t("table.wc_gateways tbody, table.wc_shipping tbody").sortable({items:"tr",cursor:"move",axis:"y",handle:"td.sort",scrollSensitivity:40,helper:function(e,i){return i.children().each(function(){t(this).width(t(this).width())}),i.css("left","0"),i},start:function(t,e){e.item.css("background-color","#f6f6f6")},stop:function(t,e){e.item.removeAttr("style")}}),t(".woocommerce").on("click",".select_all",function(){return t(this).closest("td").find("select option").attr("selected","selected"),t(this).closest("td").find("select").trigger("change"),!1}),t(".woocommerce").on("click",".select_none",function(){return t(this).closest("td").find("select option").removeAttr("selected"),t(this).closest("td").find("select").trigger("change"),!1}),t(".woocommerce-thumbnail-cropping").on("change","input",function(){var e=t(".woocommerce-thumbnail-cropping input:checked").val(),i=t(".woocommerce-thumbnail-preview-block__image");if("custom"===e){var o=90/Math.max(parseInt(t('input[name="thumbnail_cropping_aspect_ratio_width"]').val(),10),1)*Math.max(parseInt(t('input[name="thumbnail_cropping_aspect_ratio_height"]').val(),10),1);i.animate({height:o+"px"},200),t(".woocommerce-thumbnail-cropping-aspect-ratio").slideDown(200)}else if("uncropped"===e){var c=["120","60","80"];i.each(function(e,i){var o=c[e];t(i).animate({height:o+"px"},200)}),t(".woocommerce-thumbnail-cropping-aspect-ratio").hide()}else i.animate({height:"90px"},200),t(".woocommerce-thumbnail-cropping-aspect-ratio").hide();return!1}),t(".woocommerce-thumbnail-cropping").find("input").change()}(jQuery);

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -1763,12 +1763,12 @@ class WC_Product extends WC_Abstract_Legacy_Product {
/**
* Returns the main product image.
*
* @param string $size (default: 'shop_thumbnail').
* @param string $size (default: 'woocommerce_thumbnail').
* @param array $attr Image attributes.
* @param bool $placeholder True to return $placeholder if no image is found, or false to return an empty string.
* @return string
*/
public function get_image( $size = 'shop_thumbnail', $attr = array(), $placeholder = true ) {
public function get_image( $size = 'woocommerce_thumbnail', $attr = array(), $placeholder = true ) {
if ( has_post_thumbnail( $this->get_id() ) ) {
$image = get_the_post_thumbnail( $this->get_id(), $size, $attr );
} elseif ( ( $parent_id = wp_get_post_parent_id( $this->get_id() ) ) && has_post_thumbnail( $parent_id ) ) {

View File

@ -274,4 +274,71 @@ abstract class WC_Widget extends WP_Widget {
}
}
}
/**
* Get current page URL with various filtering props supported by WC.
*
* @return string
*/
protected function get_page_base_url() {
if ( defined( 'SHOP_IS_ON_FRONT' ) ) {
$link = home_url();
} elseif ( is_shop() ) {
$link = get_permalink( wc_get_page_id( 'shop' ) );
} elseif ( is_product_category() ) {
$link = get_term_link( get_query_var( 'product_cat' ), 'product_cat' );
} elseif ( is_product_tag() ) {
$link = get_term_link( get_query_var( 'product_tag' ), 'product_tag' );
} else {
$queried_object = get_queried_object();
$link = get_term_link( $queried_object->slug, $queried_object->taxonomy );
}
// Min/Max.
if ( isset( $_GET['min_price'] ) ) {
$link = add_query_arg( 'min_price', wc_clean( wp_unslash( $_GET['min_price'] ) ), $link );
}
if ( isset( $_GET['max_price'] ) ) {
$link = add_query_arg( 'max_price', wc_clean( wp_unslash( $_GET['max_price'] ) ), $link );
}
// Order by.
if ( isset( $_GET['orderby'] ) ) {
$link = add_query_arg( 'orderby', wc_clean( wp_unslash( $_GET['orderby'] ) ), $link );
}
/**
* Search Arg.
* To support quote characters, first they are decoded from " entities, then URL encoded.
*/
if ( get_search_query() ) {
$link = add_query_arg( 's', rawurlencode( htmlspecialchars_decode( get_search_query() ) ), $link );
}
// Post Type Arg.
if ( isset( $_GET['post_type'] ) ) {
$link = add_query_arg( 'post_type', wc_clean( wp_unslash( $_GET['post_type'] ) ), $link );
}
// Min Rating Arg.
if ( isset( $_GET['rating_filter'] ) ) {
$link = add_query_arg( 'rating_filter', wc_clean( wp_unslash( $_GET['rating_filter'] ) ), $link );
}
// All current filters.
if ( $_chosen_attributes = WC_Query::get_layered_nav_chosen_attributes() ) {
foreach ( $_chosen_attributes as $name => $data ) {
$filter_name = sanitize_title( str_replace( 'pa_', '', $name ) );
if ( ! empty( $data['terms'] ) ) {
$link = add_query_arg( 'filter_' . $filter_name, implode( ',', $data['terms'] ), $link );
}
if ( 'or' == $data['query_type'] ) {
$link = add_query_arg( 'query_type_' . $filter_name, 'or', $link );
}
}
}
return $link;
}
}

View File

@ -79,7 +79,7 @@ class WC_Admin_Notices {
* Reset notices for themes when switched or a new version of WC is installed.
*/
public static function reset_admin_notices() {
if ( ! current_theme_supports( 'woocommerce' ) && ! in_array( get_option( 'template' ), wc_get_core_supported_themes() ) ) {
if ( ! current_theme_supports( 'woocommerce' ) ) {
self::add_notice( 'theme_support' );
}
@ -216,7 +216,7 @@ class WC_Admin_Notices {
* Show the Theme Check notice.
*/
public static function theme_check_notice() {
if ( ! current_theme_supports( 'woocommerce' ) && ! in_array( get_option( 'template' ), wc_get_core_supported_themes() ) ) {
if ( ! current_theme_supports( 'woocommerce' ) ) {
include( 'views/html-notice-theme-support.php' );
} else {
self::remove_notice( 'theme_support' );

View File

@ -225,6 +225,9 @@ class WC_Admin_Settings {
if ( ! isset( $value['placeholder'] ) ) {
$value['placeholder'] = '';
}
if ( ! isset( $value['suffix'] ) ) {
$value['suffix'] = '';
}
// Custom attribute handling
$custom_attributes = array();
@ -289,7 +292,7 @@ class WC_Admin_Settings {
class="<?php echo esc_attr( $value['class'] ); ?>"
placeholder="<?php echo esc_attr( $value['placeholder'] ); ?>"
<?php echo implode( ' ', $custom_attributes ); ?>
/> <?php echo $description; ?>
/><?php echo esc_html( $value['suffix'] ); ?> <?php echo $description; ?>
</td>
</tr><?php
break;
@ -491,7 +494,7 @@ class WC_Admin_Settings {
}
break;
// Image width settings
// Image width settings. @todo deprecate and remove in 4.0. No longer needed by core.
case 'image_width' :
$image_size = str_replace( '_image_size', '', $value['id'] );
@ -519,6 +522,62 @@ class WC_Admin_Settings {
</tr><?php
break;
// Thumbnail cropping setting. DEVELOPERS: This is private. Re-use at your own risk.
case 'thumbnail_cropping' :
$option_value = self::get_option( $value['id'], $value['default'] );
if ( strstr( $option_value, ':' ) ) {
$cropping_split = explode( ':', $option_value );
$width = max( 1, current( $cropping_split ) );
$height = max( 1, end( $cropping_split ) );
} else {
$width = 4;
$height = 3;
}
?><tr valign="top">
<th scope="row" class="titledesc"><?php echo esc_html( $value['title'] ) ?> <?php echo $tooltip_html; ?></th>
<td class="forminp">
<ul class="woocommerce-thumbnail-cropping">
<li>
<input type="radio" name="woocommerce_thumbnail_cropping" id="thumbnail_cropping_1_1" value="1:1" <?php checked( $option_value, '1:1' ); ?> />
<label for="thumbnail_cropping_1_1">1:1<br/><span class="description"><?php esc_html_e( 'Images will be cropped into a square', 'woocommerce' ); ?></span></label>
</li>
<li>
<input type="radio" name="woocommerce_thumbnail_cropping" id="thumbnail_cropping_custom" value="custom" <?php checked( ! in_array( $option_value, array( '1:1', 'uncropped' ), true ), true ); ?> />
<label for="thumbnail_cropping_custom">
<?php esc_html_e( 'Custom', 'woocommerce' ); ?><br/><span class="description"><?php esc_html_e( 'Images will be cropped to a custom aspect ratio', 'woocommerce' ); ?></span>
<span class="woocommerce-thumbnail-cropping-aspect-ratio">
<input name="thumbnail_cropping_aspect_ratio_width" type="text" pattern="\d*" size="3" value="<?php echo $width; ?>" /> : <input name="thumbnail_cropping_aspect_ratio_height" type="text" pattern="\d*" size="3" value="<?php echo $height; ?>" />
</span>
</label>
</li>
<li>
<input type="radio" name="woocommerce_thumbnail_cropping" id="thumbnail_cropping_uncropped" value="uncropped" <?php checked( $option_value, 'uncropped' ); ?> />
<label for="thumbnail_cropping_uncropped"><?php esc_html_e( 'Uncropped', 'woocommerce' ); ?><br/><span class="description"><?php esc_html_e( 'Images will display using the aspect ratio in which they were uploaded', 'woocommerce' ); ?></span></label>
</li>
</ul>
<div class="woocommerce-thumbnail-preview hide-if-no-js">
<h4><?php esc_html_e( 'Preview', 'woocommerce' ); ?></h4>
<div class="woocommerce-thumbnail-preview-block">
<div class="woocommerce-thumbnail-preview-block__image"></div>
<div class="woocommerce-thumbnail-preview-block__text"></div>
<div class="woocommerce-thumbnail-preview-block__button"></div>
</div>
<div class="woocommerce-thumbnail-preview-block">
<div class="woocommerce-thumbnail-preview-block__image"></div>
<div class="woocommerce-thumbnail-preview-block__text"></div>
<div class="woocommerce-thumbnail-preview-block__button"></div>
</div>
<div class="woocommerce-thumbnail-preview-block">
<div class="woocommerce-thumbnail-preview-block__image"></div>
<div class="woocommerce-thumbnail-preview-block__text"></div>
<div class="woocommerce-thumbnail-preview-block__button"></div>
</div>
</div>
</td>
</tr><?php
break;
// Single page selects
case 'single_select_page' :
@ -711,6 +770,15 @@ class WC_Admin_Settings {
$value['crop'] = $option['default']['crop'];
}
break;
case 'thumbnail_cropping' :
$value = wc_clean( $raw_value );
if ( 'custom' === $value ) {
$width_ratio = wc_clean( wp_unslash( $_POST['thumbnail_cropping_aspect_ratio_width'] ) );
$height_ratio = wc_clean( wp_unslash( $_POST['thumbnail_cropping_aspect_ratio_height'] ) );
$value = $width_ratio . ':' . $height_ratio;
}
break;
case 'select':
$allowed_values = empty( $option['options'] ) ? array() : array_keys( $option['options'] );
if ( empty( $option['default'] ) && empty( $allowed_values ) ) {

View File

@ -9,10 +9,12 @@
*/
if ( ! defined( 'ABSPATH' ) ) {
exit; // Exit if accessed directly
exit;
}
if ( ! class_exists( 'WC_Settings_Products', false ) ) :
if ( class_exists( 'WC_Settings_Products', false ) ) {
return new WC_Settings_Products();
}
/**
* WC_Settings_Products.
@ -35,7 +37,6 @@ class WC_Settings_Products extends WC_Settings_Page {
* @return array
*/
public function get_sections() {
$sections = array(
'' => __( 'General', 'woocommerce' ),
'display' => __( 'Display', 'woocommerce' ),
@ -70,22 +71,20 @@ class WC_Settings_Products extends WC_Settings_Page {
/**
* Get settings array.
*
* @param string $current_section
*
* @param string $current_section Current section name.
* @return array
*/
public function get_settings( $current_section = '' ) {
if ( 'display' == $current_section ) {
$settings = apply_filters( 'woocommerce_product_settings', array(
if ( 'display' === $current_section ) {
$theme_support = get_theme_support( 'woocommerce' );
$theme_support = is_array( $theme_support ) ? $theme_support[0]: false;
$settings = array(
array(
'title' => __( 'Shop &amp; product pages', 'woocommerce' ),
'type' => 'title',
'desc' => '',
'id' => 'catalog_options',
),
array(
'title' => __( 'Shop page', 'woocommerce' ),
'desc' => '<br/>' . sprintf( __( 'The base page can also be used in your <a href="%s">product permalinks</a>.', 'woocommerce' ), admin_url( 'options-permalink.php' ) ),
@ -96,7 +95,6 @@ class WC_Settings_Products extends WC_Settings_Page {
'css' => 'min-width:300px;',
'desc_tip' => __( 'This sets the base page of your shop - this is where your product archive will be.', 'woocommerce' ),
),
array(
'title' => __( 'Shop page display', 'woocommerce' ),
'desc' => __( 'This controls what is shown on the product archive.', 'woocommerce' ),
@ -112,7 +110,6 @@ class WC_Settings_Products extends WC_Settings_Page {
),
'desc_tip' => true,
),
array(
'title' => __( 'Default category display', 'woocommerce' ),
'desc' => __( 'This controls what is shown on category archives.', 'woocommerce' ),
@ -128,7 +125,6 @@ class WC_Settings_Products extends WC_Settings_Page {
),
'desc_tip' => true,
),
array(
'title' => __( 'Default product sorting', 'woocommerce' ),
'desc' => __( 'This controls the default sort order of the catalog.', 'woocommerce' ),
@ -147,7 +143,34 @@ class WC_Settings_Products extends WC_Settings_Page {
) ),
'desc_tip' => true,
),
'columns' => array(
'title' => __( 'Products per row', 'woocommerce' ),
'desc' => __( 'How many products should be shown per row?', 'woocommerce' ),
'id' => 'woocommerce_catalog_columns',
'default' => '3',
'type' => 'number',
'css' => 'width: 50px;',
'custom_attributes' => array(
'min' => isset( $theme_support['product_grid']['min_columns'] ) ? absint( $theme_support['product_grid']['min_columns'] ) : 1,
'max' => isset( $theme_support['product_grid']['max_columns'] ) ? absint( $theme_support['product_grid']['max_columns'] ) : '',
'step' => 1,
),
'desc_tip' => true,
),
'rows' => array(
'title' => __( 'Rows per page', 'woocommerce' ),
'desc' => __( 'How many rows of products should be shown per page?', 'woocommerce' ),
'id' => 'woocommerce_catalog_rows',
'default' => '4',
'type' => 'number',
'css' => 'width: 50px;',
'custom_attributes' => array(
'min' => isset( $theme_support['product_grid']['min_rows'] ) ? absint( $theme_support['product_grid']['min_rows'] ): 1,
'max' => isset( $theme_support['product_grid']['max_rows'] ) ? absint( $theme_support['product_grid']['max_rows'] ): '',
'step' => 1,
),
'desc_tip' => true,
),
array(
'title' => __( 'Add to cart behaviour', 'woocommerce' ),
'desc' => __( 'Redirect to the cart page after successful addition', 'woocommerce' ),
@ -156,7 +179,6 @@ class WC_Settings_Products extends WC_Settings_Page {
'type' => 'checkbox',
'checkboxgroup' => 'start',
),
array(
'desc' => __( 'Enable AJAX add to cart buttons on archives', 'woocommerce' ),
'id' => 'woocommerce_enable_ajax_add_to_cart',
@ -164,68 +186,75 @@ class WC_Settings_Products extends WC_Settings_Page {
'type' => 'checkbox',
'checkboxgroup' => 'end',
),
array(
'type' => 'sectionend',
'id' => 'catalog_options',
),
);
if ( has_filter( 'loop_shop_columns' ) ) {
unset( $settings['columns'], $settings['rows'] );
}
$image_settings = array(
array(
'title' => __( 'Product images', 'woocommerce' ),
'type' => 'title',
'desc' => sprintf( __( 'These settings affect the display and dimensions of images in your catalog - the display on the front-end will still be affected by CSS styles. After changing these settings you may need to <a target="_blank" href="%s">regenerate your thumbnails</a>.', 'woocommerce' ), 'https://wordpress.org/plugins/regenerate-thumbnails/' ),
'desc' => __( 'These settings change how product images are displayed in your catalog.', 'woocommerce' ),
'id' => 'image_options',
),
array(
'title' => __( 'Catalog images', 'woocommerce' ),
'desc' => __( 'This size is usually used in product listings. (W x H)', 'woocommerce' ),
'id' => 'shop_catalog_image_size',
'single_image_width' => array(
'title' => __( 'Main image width', 'woocommerce' ),
'desc' => __( 'This is the width used by the main image on single product pages. These images will be uncropped.', 'woocommerce' ),
'id' => 'woocommerce_single_image_width',
'css' => '',
'type' => 'image_width',
'default' => array(
'width' => '300',
'height' => '300',
'crop' => 1,
'type' => 'text',
'custom_attributes' => array(
'size' => 3,
),
'suffix' => 'px',
'default' => 600,
'desc_tip' => true,
),
array(
'title' => __( 'Single product image', 'woocommerce' ),
'desc' => __( 'This is the size used by the main image on the product page. (W x H)', 'woocommerce' ),
'id' => 'shop_single_image_size',
'thumbnail_image_width' => array(
'title' => __( 'Thumbnail width', 'woocommerce' ),
'desc' => __( 'This size is used for product archives and product listings.', 'woocommerce' ),
'id' => 'woocommerce_thumbnail_image_width',
'css' => '',
'type' => 'image_width',
'default' => array(
'width' => '600',
'height' => '600',
'crop' => 1,
'type' => 'text',
'custom_attributes' => array(
'size' => 3,
),
'suffix' => 'px',
'default' => 300,
'desc_tip' => true,
),
array(
'title' => __( 'Product thumbnails', 'woocommerce' ),
'desc' => __( 'This size is usually used for the gallery of images on the product page. (W x H)', 'woocommerce' ),
'id' => 'shop_thumbnail_image_size',
'title' => __( 'Thumbnail cropping', 'woocommerce' ),
'desc' => __( 'This determines how thumbnails appear. Widths will be fixed, whilst heights may vary.', 'woocommerce' ),
'id' => 'woocommerce_thumbnail_cropping',
'css' => '',
'type' => 'image_width',
'default' => array(
'width' => '180',
'height' => '180',
'crop' => 1,
),
'desc_tip' => true,
'type' => 'thumbnail_cropping',
'default' => '1:1',
'desc_tip' => false,
),
array(
'type' => 'sectionend',
'id' => 'image_options',
),
);
));
} elseif ( 'inventory' == $current_section ) {
if ( isset( $theme_support['single_image_width'] ) ) {
unset( $image_settings['single_image_width'] );
}
if ( isset( $theme_support['thumbnail_image_width'] ) ) {
unset( $image_settings['thumbnail_image_width'] );
}
$settings = apply_filters( 'woocommerce_product_settings', array_merge( $settings, $image_settings ) );
} elseif ( 'inventory' === $current_section ) {
$settings = apply_filters( 'woocommerce_inventory_settings', array(
@ -354,7 +383,7 @@ class WC_Settings_Products extends WC_Settings_Page {
));
} elseif ( 'downloadable' == $current_section ) {
} elseif ( 'downloadable' === $current_section ) {
$settings = apply_filters( 'woocommerce_downloadable_products_settings', array(
array(
'title' => __( 'Downloadable products', 'woocommerce' ),
@ -530,6 +559,4 @@ class WC_Settings_Products extends WC_Settings_Page {
}
}
endif;
return new WC_Settings_Products();

View File

@ -418,6 +418,7 @@ class WC_REST_Setting_Options_Controller extends WC_REST_Controller {
* For image_width, Crop can return "0" instead of false -- so we want
* to make sure we return these consistently the same we accept them.
*
* @todo remove in 4.0
* @since 3.0.0
* @param array $setting
* @return array
@ -475,6 +476,7 @@ class WC_REST_Setting_Options_Controller extends WC_REST_Controller {
'radio', // Validates with validate_setting_radio_field (-> validate_setting_select_field).
'checkbox', // Validates with validate_setting_checkbox_field.
'image_width', // Validates with validate_setting_image_width_field.
'thumbnail_cropping', // Validates with validate_setting_text_field.
) );
}
@ -553,7 +555,7 @@ class WC_REST_Setting_Options_Controller extends WC_REST_Controller {
'sanitize_callback' => 'sanitize_text_field',
),
'context' => array( 'view', 'edit' ),
'enum' => array( 'text', 'email', 'number', 'color', 'password', 'textarea', 'select', 'multiselect', 'radio', 'image_width', 'checkbox' ),
'enum' => array( 'text', 'email', 'number', 'color', 'password', 'textarea', 'select', 'multiselect', 'radio', 'image_width', 'checkbox', 'thumbnail_cropping' ),
'readonly' => true,
),
'options' => array(

View File

@ -874,7 +874,7 @@ class WC_REST_System_Status_Controller extends WC_REST_Controller {
'version_latest' => WC_Admin_Status::get_latest_theme_version( $active_theme ),
'author_url' => esc_url_raw( $active_theme->{'Author URI'} ),
'is_child_theme' => is_child_theme(),
'has_woocommerce_support' => ( current_theme_supports( 'woocommerce' ) || in_array( $active_theme->template, wc_get_core_supported_themes() ) ),
'has_woocommerce_support' => current_theme_supports( 'woocommerce' ),
'has_woocommerce_file' => ( file_exists( get_stylesheet_directory() . '/woocommerce.php' ) || file_exists( get_template_directory() . '/woocommerce.php' ) ),
'has_outdated_templates' => $outdated_templates,
'overrides' => $override_files,

View File

@ -1764,7 +1764,7 @@ class WC_Cart extends WC_Legacy_Cart {
* @return string formatted price
*/
public function get_total_ex_tax() {
return apply_filters( 'woocommerce_cart_total_ex_tax', wc_price( max( 0, $this->get_total( 'edit' ) - $this->get_cart_contents_tax() - $this->get_shipping_tax() ) ) );
return apply_filters( 'woocommerce_cart_total_ex_tax', wc_price( max( 0, $this->get_total( 'edit' ) - $this->get_total_tax() ) ) );
}
/**

View File

@ -43,20 +43,6 @@ class WC_Frontend_Scripts {
add_action( 'wp_enqueue_scripts', array( __CLASS__, 'load_scripts' ) );
add_action( 'wp_print_scripts', array( __CLASS__, 'localize_printed_scripts' ), 5 );
add_action( 'wp_print_footer_scripts', array( __CLASS__, 'localize_printed_scripts' ), 5 );
add_action( 'setup_theme', array( __CLASS__, 'add_default_theme_support' ) );
}
/**
* Add theme support for default WP themes.
*
* @since 3.0.0
*/
public static function add_default_theme_support() {
if ( in_array( get_option( 'template' ), wc_get_core_supported_themes() ) ) {
add_theme_support( 'wc-product-gallery-zoom' );
add_theme_support( 'wc-product-gallery-lightbox' );
add_theme_support( 'wc-product-gallery-slider' );
}
}
/**

View File

@ -96,6 +96,10 @@ class WC_Install {
'wc_update_320_mexican_states',
'wc_update_320_db_version',
),
'3.3.0' => array(
'wc_update_330_image_options',
'wc_update_330_db_version',
),
);
/**

View File

@ -255,6 +255,14 @@ class WC_Post_types {
$supports[] = 'comments';
}
$shop_page_id = wc_get_page_id( 'shop' );
if ( current_theme_supports( 'woocommerce' ) ) {
$has_archive = $shop_page_id && get_post( $shop_page_id ) ? urldecode( get_page_uri( $shop_page_id ) ) : 'shop';
} else {
$has_archive = false;
}
register_post_type( 'product',
apply_filters( 'woocommerce_register_post_type_product',
array(
@ -295,7 +303,7 @@ class WC_Post_types {
'rewrite' => $permalinks['product_rewrite_slug'] ? array( 'slug' => $permalinks['product_rewrite_slug'], 'with_front' => false, 'feeds' => true ) : false,
'query_var' => true,
'supports' => $supports,
'has_archive' => ( $shop_page_id = wc_get_page_id( 'shop' ) ) && get_post( $shop_page_id ) ? urldecode( get_page_uri( $shop_page_id ) ) : 'shop',
'has_archive' => $has_archive,
'show_in_nav_menus' => true,
'show_in_rest' => true,
)

View File

@ -23,6 +23,13 @@ class WC_Query {
*/
public $query_vars = array();
/**
* Reference to the main product query on the page.
*
* @var array
*/
private static $product_query;
/**
* Stores chosen attributes.
*
@ -50,7 +57,7 @@ class WC_Query {
* Get any errors from querystring.
*/
public function get_errors() {
if ( ! empty( $_GET['wc_error'] ) && ( $error = sanitize_text_field( $_GET['wc_error'] ) ) && ! wc_has_notice( $error, 'error' ) ) {
if ( ! empty( $_GET['wc_error'] ) && ( $error = sanitize_text_field( wp_unslash( $_GET['wc_error'] ) ) ) && ! wc_has_notice( $error, 'error' ) ) { // WPCS: sanitization ok, input var ok.
wc_add_notice( $error, 'error' );
}
}
@ -81,7 +88,8 @@ class WC_Query {
/**
* Get page title for an endpoint.
* @param string
*
* @param string $endpoint Endpoint to get.
* @return string
*/
public function get_endpoint_title( $endpoint ) {
@ -145,7 +153,7 @@ class WC_Query {
$myaccount_page_id = get_option( 'woocommerce_myaccount_page_id' );
$checkout_page_id = get_option( 'woocommerce_checkout_page_id' );
if ( in_array( $page_on_front, array( $myaccount_page_id, $checkout_page_id ) ) ) {
if ( in_array( $page_on_front, array( $myaccount_page_id, $checkout_page_id ), true ) ) {
return EP_ROOT | EP_PAGES;
}
}
@ -169,8 +177,7 @@ class WC_Query {
/**
* Add query vars.
*
* @access public
* @param array $vars
* @param array $vars Vars to append.
* @return array
*/
public function add_query_vars( $vars ) {
@ -196,6 +203,7 @@ class WC_Query {
*/
public function get_current_endpoint() {
global $wp;
foreach ( $this->get_query_vars() as $key => $value ) {
if ( isset( $wp->query_vars[ $key ] ) ) {
return $key;
@ -210,10 +218,9 @@ class WC_Query {
public function parse_request() {
global $wp;
// Map query vars to their keys, or get them if endpoints are not supported
foreach ( $this->get_query_vars() as $key => $var ) {
if ( isset( $_GET[ $var ] ) ) {
$wp->query_vars[ $key ] = $_GET[ $var ];
if ( isset( $_GET[ $var ] ) ) { // WPCS: input var ok.
$wp->query_vars[ $key ] = wc_clean( wp_unslash( $_GET[ $var ] ) ); // WPCS: sanitization ok, input var ok.
} elseif ( isset( $wp->query_vars[ $var ] ) ) {
$wp->query_vars[ $key ] = $wp->query_vars[ $var ];
}
@ -223,8 +230,7 @@ class WC_Query {
/**
* Are we currently on the front page?
*
* @param object $q
*
* @param object $q Query object.
* @return bool
*/
private function is_showing_page_on_front( $q ) {
@ -234,8 +240,7 @@ class WC_Query {
/**
* Is the front page a page we define?
*
* @param int $page_id
*
* @param int $page_id Page ID to check.
* @return bool
*/
private function page_on_front_is( $page_id ) {
@ -245,15 +250,15 @@ class WC_Query {
/**
* Hook into pre_get_posts to do the main product query.
*
* @param object $q query object
* @param object $q query object.
*/
public function pre_get_posts( $q ) {
// We only want to affect the main query
// We only want to affect the main query.
if ( ! $q->is_main_query() ) {
return;
}
// Fix for endpoints on the homepage
// Fix for endpoints on the homepage.
if ( $this->is_showing_page_on_front( $q ) && ! $this->page_on_front_is( $q->get( 'page_id' ) ) ) {
$_query = wp_parse_args( $q->query );
if ( ! empty( $_query ) && array_intersect( array_keys( $_query ), array_keys( $this->query_vars ) ) ) {
@ -276,14 +281,14 @@ class WC_Query {
}
}
// Fix product feeds
// Fix product feeds.
if ( $q->is_feed() && $q->is_post_type_archive( 'product' ) ) {
$q->is_comment_feed = false;
}
// Special check for shops with the product archive on front
// Special check for shops with the product archive on front.
if ( $q->is_page() && 'page' === get_option( 'show_on_front' ) && absint( $q->get( 'page_id' ) ) === wc_get_page_id( 'shop' ) ) {
// This is a front-page shop
// This is a front-page shop.
$q->set( 'post_type', 'product' );
$q->set( 'page_id', '' );
@ -291,11 +296,10 @@ class WC_Query {
$q->set( 'paged', $q->query['paged'] );
}
// Define a variable so we know this is the front page shop later on
// Define a variable so we know this is the front page shop later on.
wc_maybe_define_constant( 'SHOP_IS_ON_FRONT', true );
// Get the actual WP page to avoid errors and let us use is_front_page()
// This is hacky but works. Awaiting https://core.trac.wordpress.org/ticket/21096
// Get the actual WP page to avoid errors and let us use is_front_page(). This is hacky but works. Awaiting https://core.trac.wordpress.org/ticket/21096.
global $wp_post_types;
$shop_page = get_post( wc_get_page_id( 'shop' ) );
@ -306,41 +310,28 @@ class WC_Query {
$wp_post_types['product']->post_type = $shop_page->post_type;
$wp_post_types['product']->ancestors = get_ancestors( $shop_page->ID, $shop_page->post_type );
// Fix conditional Functions like is_front_page
// Fix conditional Functions like is_front_page.
$q->is_singular = false;
$q->is_post_type_archive = true;
$q->is_archive = true;
$q->is_page = true;
// Remove post type archive name from front page title tag
// Remove post type archive name from front page title tag.
add_filter( 'post_type_archive_title', '__return_empty_string', 5 );
// Fix WP SEO
// Fix WP SEO.
if ( class_exists( 'WPSEO_Meta' ) ) {
add_filter( 'wpseo_metadesc', array( $this, 'wpseo_metadesc' ) );
add_filter( 'wpseo_metakey', array( $this, 'wpseo_metakey' ) );
}
// Only apply to product categories, the product post archive, the shop page, product tags, and product attribute taxonomies
} elseif ( ! $q->is_post_type_archive( 'product' ) && ! $q->is_tax( get_object_taxonomies( 'product' ) ) ) {
return;
}
$this->product_query( $q );
// And remove the pre_get_posts hook
$this->remove_product_query();
}
/**
* Search post excerpt.
* @deprecated 3.2.0 - Not needed anymore since WordPress 4.5.
*/
public function search_post_excerpt( $where = '' ) {
wc_deprecated_function( 'WC_Query::search_post_excerpt', '3.2.0', 'Excerpt added to search query by default since WordPress 4.5.' );
return $where;
}
/**
* WP SEO meta description.
*
@ -368,7 +359,7 @@ class WC_Query {
/**
* Query the products, applying sorting/ordering etc. This applies to the main wordpress loop.
*
* @param mixed $q
* @param mixed $q Query object.
*/
public function product_query( $q ) {
if ( ! is_feed() ) {
@ -381,13 +372,18 @@ class WC_Query {
}
}
// Query vars that affect posts shown
// Query vars that affect posts shown.
$q->set( 'meta_query', $this->get_meta_query( $q->get( 'meta_query' ), true ) );
$q->set( 'tax_query', $this->get_tax_query( $q->get( 'tax_query' ), true ) );
$q->set( 'posts_per_page', $q->get( 'posts_per_page' ) ? $q->get( 'posts_per_page' ) : apply_filters( 'loop_shop_per_page', get_option( 'posts_per_page' ) ) );
$q->set( 'wc_query', 'product_query' );
$q->set( 'post__in', array_unique( (array) apply_filters( 'loop_shop_post_in', array() ) ) );
// Work out how many products to query.
$q->set( 'posts_per_page', $q->get( 'posts_per_page' ) ? $q->get( 'posts_per_page' ) : apply_filters( 'loop_shop_per_page', wc_get_default_products_per_row() * wc_get_default_product_rows_per_page() ) );
// Store reference to this query.
self::$product_query = $q;
do_action( 'woocommerce_product_query', $q, $this );
}
@ -409,30 +405,27 @@ class WC_Query {
remove_filter( 'posts_clauses', array( $this, 'order_by_rating_post_clauses' ) );
}
/**
* Remove the posts_where filter.
* @deprecated 3.2.0 - Nothing to remove anymore because search_post_excerpt() is deprecated.
*/
public function remove_posts_where() {
wc_deprecated_function( 'WC_Query::remove_posts_where', '3.2.0', 'Nothing to remove anymore because search_post_excerpt() is deprecated.' );
}
/**
* Returns an array of arguments for ordering products based on the selected values.
*
* @access public
*
* @param string $orderby
* @param string $order
*
* @param string $orderby Order by param.
* @param string $order Order param.
* @return array
*/
public function get_catalog_ordering_args( $orderby = '', $order = '' ) {
// Get ordering from query string unless defined
// Get ordering from query string unless defined.
if ( ! $orderby ) {
$orderby_value = isset( $_GET['orderby'] ) ? wc_clean( (string) $_GET['orderby'] ) : apply_filters( 'woocommerce_default_catalog_orderby', get_option( 'woocommerce_default_catalog_orderby' ) );
$orderby_value = isset( $_GET['orderby'] ) ? wc_clean( (string) wp_unslash( $_GET['orderby'] ) ) : ''; // WPCS: sanitization ok, input var ok.
// Get order + orderby args from string
if ( ! $orderby_value ) {
if ( is_search() ) {
$orderby_value = 'relevance';
} else {
$orderby_value = apply_filters( 'woocommerce_default_catalog_orderby', get_option( 'woocommerce_default_catalog_orderby' ) );
}
}
// Get order + orderby args from string.
$orderby_value = explode( '-', $orderby_value );
$orderby = esc_attr( $orderby_value[0] );
$order = ! empty( $orderby_value[1] ) ? $orderby_value[1] : $order;
@ -441,21 +434,21 @@ class WC_Query {
$orderby = strtolower( $orderby );
$order = strtoupper( $order );
$args = array(
'orderby' => 'relevance',
'order' => 'DESC',
'meta_key' => '',
'orderby' => $orderby,
'order' => ( 'DESC' === $order ) ? 'DESC' : 'ASC',
'meta_key' => '', // @codingStandardsIgnoreLine
);
// Set to default. Menu order for non-searches, relevance for searches.
if ( ! is_search() ) {
$args['orderby'] = 'menu_order title';
$args['order'] = ( 'DESC' === $order ) ? 'DESC' : 'ASC';
$args['meta_key'] = '';
}
switch ( $orderby ) {
case 'menu_order' :
$args['orderby'] = 'menu_order title';
break;
case 'relevance' :
$args['orderby']= 'relevance';
$args['order'] = 'DESC';
break;
case 'rand' :
$args['orderby'] = 'rand';
$args['orderby'] = 'rand'; // @codingStandardsIgnoreLine
break;
case 'date' :
$args['orderby'] = 'date ID';
@ -469,13 +462,13 @@ class WC_Query {
}
break;
case 'popularity' :
$args['meta_key'] = 'total_sales';
$args['meta_key'] = 'total_sales'; // @codingStandardsIgnoreLine
// Sorting handled later though a hook
// Sorting handled later though a hook.
add_filter( 'posts_clauses', array( $this, 'order_by_popularity_post_clauses' ) );
break;
case 'rating' :
$args['meta_key'] = '_wc_average_rating';
$args['meta_key'] = '_wc_average_rating'; // @codingStandardsIgnoreLine
$args['orderby'] = array(
'meta_value_num' => 'DESC',
'ID' => 'ASC',
@ -497,22 +490,20 @@ class WC_Query {
/**
* Handle numeric price sorting.
*
* @access public
* @param array $args
* @param array $args Array of args to append to.
* @return array
*/
public function order_by_price_asc_post_clauses( $args ) {
global $wpdb;
$args['join'] .= " INNER JOIN ( SELECT post_id, min( meta_value+0 ) price FROM $wpdb->postmeta WHERE meta_key='_price' GROUP BY post_id ) as price_query ON $wpdb->posts.ID = price_query.post_id ";
$args['orderby'] = " price_query.price ASC ";
$args['orderby'] = ' price_query.price ASC ';
return $args;
}
/**
* Handle numeric price sorting.
*
* @access public
* @param array $args
* @param array $args Array of args to append to.
* @return array
*/
public function order_by_price_desc_post_clauses( $args ) {
@ -535,7 +526,7 @@ class WC_Query {
$args['join'] .= " INNER JOIN ( SELECT post_id, max( meta_value+0 ) price FROM $wpdb->postmeta WHERE meta_key='_price' GROUP BY post_id ) as price_query ON $wpdb->posts.ID = price_query.post_id ";
}
$args['orderby'] = " price_query.price DESC ";
$args['orderby'] = ' price_query.price DESC ';
return $args;
}
@ -545,8 +536,7 @@ class WC_Query {
*
* This lets us sort by meta value desc, and have a second orderby param.
*
* @access public
* @param array $args
* @param array $args Array of args to append to.
* @return array
*/
public function order_by_popularity_post_clauses( $args ) {
@ -555,35 +545,11 @@ class WC_Query {
return $args;
}
/**
* Order by rating post clauses.
*
* @deprecated 3.0.0
* @param array $args
* @return array
*/
public function order_by_rating_post_clauses( $args ) {
global $wpdb;
wc_deprecated_function( 'order_by_rating_post_clauses', '3.0' );
$args['fields'] .= ", AVG( $wpdb->commentmeta.meta_value ) as average_rating ";
$args['where'] .= " AND ( $wpdb->commentmeta.meta_key = 'rating' OR $wpdb->commentmeta.meta_key IS null ) ";
$args['join'] .= "
LEFT OUTER JOIN $wpdb->comments ON($wpdb->posts.ID = $wpdb->comments.comment_post_ID)
LEFT JOIN $wpdb->commentmeta ON($wpdb->comments.comment_ID = $wpdb->commentmeta.comment_id)
";
$args['orderby'] = "average_rating DESC, $wpdb->posts.post_date DESC";
$args['groupby'] = "$wpdb->posts.ID";
return $args;
}
/**
* Appends meta queries to an array.
*
* @param array $meta_query
* @param bool $main_query
* @param array $meta_query Existing meta query.
* @param bool $main_query Is this the main query.
* @return array
*/
public function get_meta_query( $meta_query = array(), $main_query = false ) {
@ -596,8 +562,9 @@ class WC_Query {
/**
* Appends tax queries to an array.
* @param array $tax_query
* @param bool $main_query
*
* @param array $tax_query Existing tax query.
* @param bool $main_query Is this the main query.
* @return array
*/
public function get_tax_query( $tax_query = array(), $main_query = false ) {
@ -627,11 +594,11 @@ class WC_Query {
}
// Filter by rating.
if ( isset( $_GET['rating_filter'] ) ) {
$rating_filter = array_filter( array_map( 'absint', explode( ',', $_GET['rating_filter'] ) ) );
if ( isset( $_GET['rating_filter'] ) ) { // WPCS: input var ok.
$rating_filter = array_filter( array_map( 'absint', explode( ',', wp_unslash( $_GET['rating_filter'] ) ) ) ); // WPCS: sanitization ok, input var ok.
$rating_terms = array();
for ( $i = 1; $i <= 5; $i ++ ) {
if ( in_array( $i, $rating_filter ) && isset( $product_visibility_terms[ 'rated-' . $i ] ) ) {
if ( in_array( $i, $rating_filter, true ) && isset( $product_visibility_terms[ 'rated-' . $i ] ) ) {
$rating_terms[] = $product_visibility_terms[ 'rated-' . $i ];
}
}
@ -660,11 +627,12 @@ class WC_Query {
/**
* Return a meta query for filtering by price.
*
* @return array
*/
private function price_filter_meta_query() {
if ( isset( $_GET['max_price'] ) || isset( $_GET['min_price'] ) ) {
$meta_query = wc_get_min_max_price_meta_query( $_GET );
if ( isset( $_GET['max_price'] ) || isset( $_GET['min_price'] ) ) { // WPCS: input var ok.
$meta_query = wc_get_min_max_price_meta_query( $_GET ); // WPCS: input var ok.
$meta_query['price_filter'] = true;
return $meta_query;
@ -673,6 +641,123 @@ class WC_Query {
return array();
}
/**
* Get the main query which product queries ran against.
*
* @return array
*/
public static function get_main_query() {
return self::$product_query;
}
/**
* Get the tax query which was used by the main query.
*
* @return array
*/
public static function get_main_tax_query() {
$tax_query = isset( self::$product_query->tax_query, self::$product_query->tax_query->queries ) ? self::$product_query->tax_query->queries : array();
return $tax_query;
}
/**
* Get the meta query which was used by the main query.
*
* @return array
*/
public static function get_main_meta_query() {
$args = self::$product_query->query_vars;
$meta_query = isset( $args['meta_query'] ) ? $args['meta_query'] : array();
return $meta_query;
}
/**
* Based on WP_Query::parse_search
*/
public static function get_main_search_query_sql() {
global $wpdb;
$args = self::$product_query->query_vars;
$search_terms = isset( $args['search_terms'] ) ? $args['search_terms'] : array();
$sql = array();
foreach ( $search_terms as $term ) {
// Terms prefixed with '-' should be excluded.
$include = '-' !== substr( $term, 0, 1 );
if ( $include ) {
$like_op = 'LIKE';
$andor_op = 'OR';
} else {
$like_op = 'NOT LIKE';
$andor_op = 'AND';
$term = substr( $term, 1 );
}
$like = '%' . $wpdb->esc_like( $term ) . '%';
$sql[] = $wpdb->prepare( "(($wpdb->posts.post_title $like_op %s) $andor_op ($wpdb->posts.post_excerpt $like_op %s) $andor_op ($wpdb->posts.post_content $like_op %s))", $like, $like, $like ); // unprepared SQL ok.
}
if ( ! empty( $sql ) && ! is_user_logged_in() ) {
$sql[] = "($wpdb->posts.post_password = '')";
}
return implode( ' AND ', $sql );
}
/**
* Layered Nav Init.
*/
public static function get_layered_nav_chosen_attributes() {
if ( ! is_array( self::$_chosen_attributes ) ) {
self::$_chosen_attributes = array();
if ( $attribute_taxonomies = wc_get_attribute_taxonomies() ) {
foreach ( $attribute_taxonomies as $tax ) {
$attribute = wc_sanitize_taxonomy_name( $tax->attribute_name );
$taxonomy = wc_attribute_taxonomy_name( $attribute );
$filter_terms = ! empty( $_GET[ 'filter_' . $attribute ] ) ? explode( ',', wc_clean( wp_unslash( $_GET[ 'filter_' . $attribute ] ) ) ) : array(); // WPCS: sanitization ok, input var ok.
if ( empty( $filter_terms ) || ! taxonomy_exists( $taxonomy ) ) {
continue;
}
$query_type = ! empty( $_GET[ 'query_type_' . $attribute ] ) && in_array( $_GET[ 'query_type_' . $attribute ], array( 'and', 'or' ), true ) ? wc_clean( wp_unslash( $_GET[ 'query_type_' . $attribute ] ) ) : ''; // WPCS: sanitization ok, input var ok.
self::$_chosen_attributes[ $taxonomy ]['terms'] = array_map( 'sanitize_title', $filter_terms ); // Ensures correct encoding.
self::$_chosen_attributes[ $taxonomy ]['query_type'] = $query_type ? $query_type : apply_filters( 'woocommerce_layered_nav_default_query_type', 'and' );
}
}
}
return self::$_chosen_attributes;
}
// @codingStandardsIgnoreStart
/**
* Order by rating post clauses.
*
* @deprecated 3.0.0
* @param array $args
* @return array
*/
public function order_by_rating_post_clauses( $args ) {
global $wpdb;
wc_deprecated_function( 'order_by_rating_post_clauses', '3.0' );
$args['fields'] .= ", AVG( $wpdb->commentmeta.meta_value ) as average_rating ";
$args['where'] .= " AND ( $wpdb->commentmeta.meta_key = 'rating' OR $wpdb->commentmeta.meta_key IS null ) ";
$args['join'] .= "
LEFT OUTER JOIN $wpdb->comments ON($wpdb->posts.ID = $wpdb->comments.comment_post_ID)
LEFT JOIN $wpdb->commentmeta ON($wpdb->comments.comment_ID = $wpdb->commentmeta.comment_id)
";
$args['orderby'] = "average_rating DESC, $wpdb->posts.post_date DESC";
$args['groupby'] = "$wpdb->posts.ID";
return $args;
}
/**
* Return a meta query for filtering by rating.
*
@ -705,91 +790,6 @@ class WC_Query {
return array();
}
/**
* Get the tax query which was used by the main query.
* @return array
*/
public static function get_main_tax_query() {
global $wp_the_query;
$tax_query = isset( $wp_the_query->tax_query, $wp_the_query->tax_query->queries ) ? $wp_the_query->tax_query->queries : array();
return $tax_query;
}
/**
* Get the meta query which was used by the main query.
* @return array
*/
public static function get_main_meta_query() {
global $wp_the_query;
$args = $wp_the_query->query_vars;
$meta_query = isset( $args['meta_query'] ) ? $args['meta_query'] : array();
return $meta_query;
}
/**
* Based on WP_Query::parse_search
*/
public static function get_main_search_query_sql() {
global $wp_the_query, $wpdb;
$args = $wp_the_query->query_vars;
$search_terms = isset( $args['search_terms'] ) ? $args['search_terms'] : array();
$sql = array();
foreach ( $search_terms as $term ) {
// Terms prefixed with '-' should be excluded.
$include = '-' !== substr( $term, 0, 1 );
if ( $include ) {
$like_op = 'LIKE';
$andor_op = 'OR';
} else {
$like_op = 'NOT LIKE';
$andor_op = 'AND';
$term = substr( $term, 1 );
}
$like = '%' . $wpdb->esc_like( $term ) . '%';
$sql[] = $wpdb->prepare( "(($wpdb->posts.post_title $like_op %s) $andor_op ($wpdb->posts.post_excerpt $like_op %s) $andor_op ($wpdb->posts.post_content $like_op %s))", $like, $like, $like );
}
if ( ! empty( $sql ) && ! is_user_logged_in() ) {
$sql[] = "($wpdb->posts.post_password = '')";
}
return implode( ' AND ', $sql );
}
/**
* Layered Nav Init.
*/
public static function get_layered_nav_chosen_attributes() {
if ( ! is_array( self::$_chosen_attributes ) ) {
self::$_chosen_attributes = array();
if ( $attribute_taxonomies = wc_get_attribute_taxonomies() ) {
foreach ( $attribute_taxonomies as $tax ) {
$attribute = wc_sanitize_taxonomy_name( $tax->attribute_name );
$taxonomy = wc_attribute_taxonomy_name( $attribute );
$filter_terms = ! empty( $_GET[ 'filter_' . $attribute ] ) ? explode( ',', wc_clean( $_GET[ 'filter_' . $attribute ] ) ) : array();
if ( empty( $filter_terms ) || ! taxonomy_exists( $taxonomy ) ) {
continue;
}
$query_type = ! empty( $_GET[ 'query_type_' . $attribute ] ) && in_array( $_GET[ 'query_type_' . $attribute ], array( 'and', 'or' ) ) ? wc_clean( $_GET[ 'query_type_' . $attribute ] ) : '';
self::$_chosen_attributes[ $taxonomy ]['terms'] = array_map( 'sanitize_title', $filter_terms ); // Ensures correct encoding
self::$_chosen_attributes[ $taxonomy ]['query_type'] = $query_type ? $query_type : apply_filters( 'woocommerce_layered_nav_default_query_type', 'and' );
}
}
}
return self::$_chosen_attributes;
}
/**
* @deprecated 2.6.0
*/
@ -814,4 +814,23 @@ class WC_Query {
public function layered_nav_query( $filtered_posts ) {
wc_deprecated_function( 'layered_nav_query', '2.6' );
}
/**
* Search post excerpt.
*
* @deprecated 3.2.0 - Not needed anymore since WordPress 4.5.
*/
public function search_post_excerpt( $where = '' ) {
wc_deprecated_function( 'WC_Query::search_post_excerpt', '3.2.0', 'Excerpt added to search query by default since WordPress 4.5.' );
return $where;
}
/**
* Remove the posts_where filter.
* @deprecated 3.2.0 - Nothing to remove anymore because search_post_excerpt() is deprecated.
*/
public function remove_posts_where() {
wc_deprecated_function( 'WC_Query::remove_posts_where', '3.2.0', 'Nothing to remove anymore because search_post_excerpt() is deprecated.' );
}
// @codingStandardsIgnoreEnd
}

View File

@ -1,26 +1,124 @@
<?php
if ( ! defined( 'ABSPATH' ) ) {
exit; // Exit if accessed directly
}
/**
* Template Loader
*
* @class WC_Template
* @version 2.2.0
* @package WooCommerce/Classes
* @category Class
* @author WooThemes
* @author Automattic
*/
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
/**
* WC_Template_Loader.
*/
class WC_Template_Loader {
/**
* Store the shop page ID.
*
* @var integer
*/
private static $shop_page_id = 0;
/**
* Hook in methods.
*/
public static function init() {
add_filter( 'template_include', array( __CLASS__, 'template_loader' ) );
add_filter( 'comments_template', array( __CLASS__, 'comments_template_loader' ) );
self::$shop_page_id = wc_get_page_id( 'shop' );
if ( ! current_theme_supports( 'woocommerce' ) && self::$shop_page_id ) {
add_filter( 'the_content', array( __CLASS__, 'the_content_filter' ), 10 );
add_filter( 'the_title', array( __CLASS__, 'the_title_filter' ), 10, 2 );
add_filter( 'comments_number', '__return_empty_string' );
}
}
/**
* Get information about the current shop page view.
*
* @since 3.3.0
* @return array
*/
private static function get_current_shop_view_args() {
return (object) array(
'page' => absint( max( 1, absint( get_query_var( 'paged' ) ) ) ),
'columns' => wc_get_default_products_per_row(),
'rows' => wc_get_default_product_rows_per_page(),
);
}
/**
* Filter the title and insert WooCommerce content on the shop page.
*
* For non-WC themes, this will setup the main shop page to be shortcode based to improve default appearance.
*
* @since 3.3.0
* @param string $title Existing title.
* @param int $id ID of the post being filtered.
* @return string
*/
public static function the_title_filter( $title, $id ) {
if ( ! current_theme_supports( 'woocommerce' ) && is_page( self::$shop_page_id ) && $id === self::$shop_page_id ) {
$args = self::get_current_shop_view_args();
$title_suffix = array();
if ( $args->page > 1 ) {
$title_suffix[] = sprintf( esc_html__( 'Page %d', 'woocommerce' ), $args->page );
}
if ( $title_suffix ) {
$title = $title . ' &ndash; ' . implode( ', ', $title_suffix );
}
}
return $title;
}
/**
* Filter the content and insert WooCommerce content on the shop page.
*
* For non-WC themes, this will setup the main shop page to be shortcode based to improve default appearance.
*
* @since 3.3.0
* @param string $content Existing post content.
* @return string
*/
public static function the_content_filter( $content ) {
global $wp_query;
if ( ! current_theme_supports( 'woocommerce' ) && is_page( self::$shop_page_id ) && is_main_query() ) {
$args = self::get_current_shop_view_args();
$shortcode = new WC_Shortcode_Products(
array_merge(
wc()->query->get_catalog_ordering_args(),
array(
'page' => $args->page,
'columns' => $args->columns,
'rows' => $args->rows,
'orderby' => '',
'order' => '',
'paginate' => true,
'cache' => false,
)
),
'products' );
// Allow queries to run e.g. layered nav.
add_action( 'pre_get_posts', array( wc()->query, 'product_query' ) );
$content = $content . $shortcode->get_content();
// Remove actions and self to avoid nested calls.
remove_action( 'pre_get_posts', array( wc()->query, 'product_query' ) );
remove_filter( 'the_content', array( __CLASS__, 'the_content_filter' ) );
}
return $content;
}
/**
@ -35,7 +133,7 @@ class WC_Template_Loader {
* this to the theme (containing a woocommerce() inside) this will be used for all.
* woocommerce templates.
*
* @param mixed $template
* @param string $template Template to load.
* @return string
*/
public static function template_loader( $template ) {
@ -79,7 +177,7 @@ class WC_Template_Loader {
$default_file = 'archive-product.php';
}
} elseif ( is_post_type_archive( 'product' ) || is_page( wc_get_page_id( 'shop' ) ) ) {
$default_file = 'archive-product.php';
$default_file = current_theme_supports( 'woocommerce' ) ? 'archive-product.php' : '';
} else {
$default_file = '';
}
@ -118,7 +216,7 @@ class WC_Template_Loader {
/**
* Load comments template.
*
* @param mixed $template
* @param string $template template to load.
* @return string
*/
public static function comments_template_loader( $template ) {
@ -146,4 +244,4 @@ class WC_Template_Loader {
}
}
WC_Template_Loader::init();
add_action( 'after_setup_theme', array( 'WC_Template_Loader', 'init' ) );

View File

@ -141,7 +141,7 @@ class WC_Tracker {
public static function get_theme_info() {
$theme_data = wp_get_theme();
$theme_child_theme = is_child_theme() ? 'Yes' : 'No';
$theme_wc_support = ( ! current_theme_supports( 'woocommerce' ) && ! in_array( $theme_data->template, wc_get_core_supported_themes() ) ) ? 'No' : 'Yes';
$theme_wc_support = ! current_theme_supports( 'woocommerce' ) ? 'No' : 'Yes';
return array( 'name' => $theme_data->Name, 'version' => $theme_data->Version, 'child_theme' => $theme_child_theme, 'wc_support' => $theme_wc_support );
}

View File

@ -256,7 +256,7 @@ final class WooCommerce {
* @return bool
*/
private function is_active_theme( $theme ) {
return get_template() === $theme;
return is_array( $theme ) ? in_array( get_template(), $theme, true ) : get_template() === $theme;
}
/**
@ -392,10 +392,49 @@ final class WooCommerce {
include_once( WC_ABSPATH . 'includes/class-wc-tracker.php' );
}
$this->theme_support_includes();
$this->query = new WC_Query();
$this->api = new WC_API();
}
/**
* Include classes sfor theme support.
*
* @since 3.3.0
*/
private function theme_support_includes() {
$theme_support = array( 'twentyseventeen', 'twentysixteen', 'twentyfifteen', 'twentyfourteen', 'twentythirteen', 'twentyeleven', 'twentytwelve', 'twentyten' );
if ( $this->is_active_theme( array( 'twentyseventeen', 'twentysixteen', 'twentyfifteen', 'twentyfourteen', 'twentythirteen', 'twentyeleven', 'twentytwelve', 'twentyten' ) ) ) {
switch ( get_template() ) {
case 'twentyten' :
include_once( WC_ABSPATH . 'includes/theme-support/class-wc-twenty-ten.php' );
break;
case 'twentyeleven' :
include_once( WC_ABSPATH . 'includes/theme-support/class-wc-twenty-eleven.php' );
break;
case 'twentytwelve' :
include_once( WC_ABSPATH . 'includes/theme-support/class-wc-twenty-twelve.php' );
break;
case 'twentythirteen' :
include_once( WC_ABSPATH . 'includes/theme-support/class-wc-twenty-thirteen.php' );
break;
case 'twentyfourteen' :
include_once( WC_ABSPATH . 'includes/theme-support/class-wc-twenty-fourteen.php' );
break;
case 'twentyfifteen' :
include_once( WC_ABSPATH . 'includes/theme-support/class-wc-twenty-fifteen.php' );
break;
case 'twentysixteen' :
include_once( WC_ABSPATH . 'includes/theme-support/class-wc-twenty-sixteen.php' );
break;
case 'twentyseventeen' :
include_once( WC_ABSPATH . 'includes/theme-support/class-wc-twenty-seventeen.php' );
break;
}
}
}
/**
* Include required frontend files.
*/
@ -413,10 +452,6 @@ final class WooCommerce {
include_once( WC_ABSPATH . 'includes/class-wc-shortcodes.php' ); // Shortcodes class.
include_once( WC_ABSPATH . 'includes/class-wc-embed.php' ); // Embeds.
include_once( WC_ABSPATH . 'includes/class-wc-structured-data.php' ); // Structured Data class.
if ( $this->is_active_theme( 'twentyseventeen' ) ) {
include_once( WC_ABSPATH . 'includes/theme-support/class-wc-twenty-seventeen.php' );
}
}
/**
@ -506,16 +541,28 @@ final class WooCommerce {
/**
* Add WC Image sizes to WP.
*
* As of 3.3, image sizes can be registered via themes using add_theme_support for woocommerce
* and defining an array of args. If these are not defined, we will use defaults. This is
* handled in wc_get_image_size function.
*
* 3.3 sizes:
*
* thumbnail - Used in product listings.
* single - Used on single product pages for the main image.
*
* shop_thumbnail, shop_single, shop_catalog registered for bw compat. @todo remove in 4.0.
*
* @since 2.3
*/
private function add_image_sizes() {
$shop_thumbnail = wc_get_image_size( 'shop_thumbnail' );
$shop_catalog = wc_get_image_size( 'shop_catalog' );
$shop_single = wc_get_image_size( 'shop_single' );
$thumbnail = wc_get_image_size( 'thumbnail' );
$single = wc_get_image_size( 'single' );
add_image_size( 'shop_thumbnail', $shop_thumbnail['width'], $shop_thumbnail['height'], $shop_thumbnail['crop'] );
add_image_size( 'shop_catalog', $shop_catalog['width'], $shop_catalog['height'], $shop_catalog['crop'] );
add_image_size( 'shop_single', $shop_single['width'], $shop_single['height'], $shop_single['crop'] );
add_image_size( 'woocommerce_thumbnail', $thumbnail['width'], $thumbnail['height'], $thumbnail['crop'] );
add_image_size( 'woocommerce_single', $single['width'], $single['height'], $single['crop'] );
add_image_size( 'shop_thumbnail', $thumbnail['width'], $thumbnail['height'], $thumbnail['crop'] );
add_image_size( 'shop_catalog', $thumbnail['width'], $thumbnail['height'], $thumbnail['crop'] );
add_image_size( 'shop_single', $single['width'], $single['height'], $single['crop'] );
}
/**

View File

@ -114,7 +114,8 @@ class WC_Shortcode_Products {
return shortcode_atts( array(
'limit' => '-1', // Results limit.
'columns' => '4', // Number of columns.
'columns' => '3', // Number of columns.
'rows' => '', // Number of rows. If defined, limit will be ignored.
'orderby' => 'title', // menu_order, title, date, rand, price, popularity, rating, or id.
'order' => 'ASC', // ASC or DESC.
'ids' => '', // Comma separated IDs.
@ -126,6 +127,9 @@ class WC_Shortcode_Products {
'terms_operator' => 'IN', // Operator to compare terms. Possible values are 'IN', 'NOT IN', 'AND'.
'visibility' => 'visible', // Possible values are 'visible', 'catalog', 'search', 'hidden'.
'class' => '', // HTML class.
'page' => 1, // Page for pagination.
'paginate' => false, // Should results be paginated.
'cache' => true, // Should shortcode output be cached.
), $attributes, $this->type );
}
@ -164,13 +168,30 @@ class WC_Shortcode_Products {
'post_type' => 'product',
'post_status' => 'publish',
'ignore_sticky_posts' => true,
'no_found_rows' => true,
'no_found_rows' => false === wc_string_to_bool( $this->attributes['paginate'] ),
'orderby' => $this->attributes['orderby'],
'order' => strtoupper( $this->attributes['order'] ),
);
if ( wc_string_to_bool( $this->attributes['paginate'] ) ) {
$this->attributes['page'] = get_query_var( 'paged', 1 );
}
if ( ! empty( $this->attributes['rows'] ) ) {
$this->attributes['limit'] = $this->attributes['columns'] * $this->attributes['rows'];
}
// @codingStandardsIgnoreStart
$query_args['posts_per_page'] = (int) $this->attributes['limit'];
$ordering_args = WC()->query->get_catalog_ordering_args( $query_args['orderby'], $query_args['order'] );
$query_args['orderby'] = $ordering_args['orderby'];
$query_args['order'] = $ordering_args['order'];
if ( $ordering_args['meta_key'] ) {
$query_args['meta_key'] = $ordering_args['meta_key'];
}
$query_args['posts_per_page'] = intval( $this->attributes['limit'] );
if ( 1 < $this->attributes['page'] ) {
$query_args['paged'] = absint( $this->attributes['page'] );
}
$query_args['meta_query'] = WC()->query->get_meta_query();
$query_args['tax_query'] = array();
// @codingStandardsIgnoreEnd
@ -258,13 +279,6 @@ class WC_Shortcode_Products {
*/
protected function set_categories_query_args( &$query_args ) {
if ( ! empty( $this->attributes['category'] ) ) {
$ordering_args = WC()->query->get_catalog_ordering_args( $query_args['orderby'], $query_args['order'] );
$query_args['orderby'] = $ordering_args['orderby'];
$query_args['order'] = $ordering_args['order'];
// @codingStandardsIgnoreStart
$query_args['meta_key'] = $ordering_args['meta_key'];
// @codingStandardsIgnoreEnd
$query_args['tax_query'][] = array(
'taxonomy' => 'product_cat',
'terms' => array_map( 'sanitize_title', explode( ',', $this->attributes['category'] ) ),
@ -457,7 +471,8 @@ class WC_Shortcode_Products {
*/
protected function get_products() {
$transient_name = $this->get_transient_name();
$products = get_transient( $transient_name );
$cache = true === wc_string_to_bool( $this->attributes['cache'] );
$products = $cache ? get_transient( $transient_name ) : false;
if ( false === $products || ! is_a( $products, 'WP_Query' ) ) {
if ( 'top_rated_products' === $this->type ) {
@ -468,7 +483,9 @@ class WC_Shortcode_Products {
$products = new WP_Query( $this->query_args );
}
set_transient( $transient_name, $products, DAY_IN_SECONDS * 30 );
if ( $cache ) {
set_transient( $transient_name, $products, DAY_IN_SECONDS * 30 );
}
}
// Remove ordering query arguments.
@ -502,6 +519,11 @@ class WC_Shortcode_Products {
do_action( "woocommerce_shortcode_before_{$this->type}_loop", $this->attributes );
if ( true === wc_string_to_bool( $this->attributes['paginate'] ) ) {
woocommerce_result_count( $products );
woocommerce_catalog_ordering( $products );
}
woocommerce_product_loop_start();
while ( $products->have_posts() ) {
@ -519,6 +541,10 @@ class WC_Shortcode_Products {
woocommerce_product_loop_end();
if ( true === wc_string_to_bool( $this->attributes['paginate'] ) ) {
woocommerce_pagination( $products, '?product-page=%#%' );
}
do_action( "woocommerce_shortcode_after_{$this->type}_loop", $this->attributes );
} else {
do_action( "woocommerce_shortcode_{$this->type}_loop_no_results", $this->attributes );

View File

@ -0,0 +1,52 @@
<?php
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
/**
* Twenty Eleven support.
*
* @class WC_Twenty_Eleven
* @since 3.3.0
* @package WooCommerce/Classes
*/
class WC_Twenty_Eleven {
/**
* Theme init.
*/
public static function init() {
// Remove default wrappers.
remove_action( 'woocommerce_before_main_content', 'woocommerce_output_content_wrapper' );
remove_action( 'woocommerce_after_main_content', 'woocommerce_output_content_wrapper_end' );
// Add custom wrappers.
add_action( 'woocommerce_before_main_content', array( __CLASS__, 'output_content_wrapper' ) );
add_action( 'woocommerce_after_main_content', array( __CLASS__, 'output_content_wrapper_end' ) );
// Declare theme support for features.
add_theme_support( 'wc-product-gallery-zoom' );
add_theme_support( 'wc-product-gallery-lightbox' );
add_theme_support( 'wc-product-gallery-slider' );
add_theme_support( 'woocommerce', array(
'thumbnail_image_width' => 130,
'single_image_width' => 280,
) );
}
/**
* Open wrappers.
*/
public static function output_content_wrapper() {
echo '<div id="primary"><div id="content" role="main" class="twentyeleven">';
}
/**
* Close wrappers.
*/
public static function output_content_wrapper_end() {
echo '</div></div>';
}
}
WC_Twenty_Eleven::init();

View File

@ -0,0 +1,52 @@
<?php
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
/**
* Twenty Fifteen support.
*
* @class WC_Twenty_Fifteen
* @since 3.3.0
* @package WooCommerce/Classes
*/
class WC_Twenty_Fifteen {
/**
* Theme init.
*/
public static function init() {
// Remove default wrappers.
remove_action( 'woocommerce_before_main_content', 'woocommerce_output_content_wrapper' );
remove_action( 'woocommerce_after_main_content', 'woocommerce_output_content_wrapper_end' );
// Add custom wrappers.
add_action( 'woocommerce_before_main_content', array( __CLASS__, 'output_content_wrapper' ) );
add_action( 'woocommerce_after_main_content', array( __CLASS__, 'output_content_wrapper_end' ) );
// Declare theme support for features.
add_theme_support( 'wc-product-gallery-zoom' );
add_theme_support( 'wc-product-gallery-lightbox' );
add_theme_support( 'wc-product-gallery-slider' );
add_theme_support( 'woocommerce', array(
'thumbnail_image_width' => 140,
'single_image_width' => 302,
) );
}
/**
* Open wrappers.
*/
public static function output_content_wrapper() {
echo '<div id="primary" role="main" class="content-area twentyfifteen"><div id="main" class="site-main t15wc">';
}
/**
* Close wrappers.
*/
public static function output_content_wrapper_end() {
echo '</div></div>';
}
}
WC_Twenty_Fifteen::init();

View File

@ -0,0 +1,53 @@
<?php
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
/**
* Twenty Fourteen support.
*
* @class WC_Twenty_Fourteen
* @since 3.3.0
* @package WooCommerce/Classes
*/
class WC_Twenty_Fourteen {
/**
* Theme init.
*/
public static function init() {
// Remove default wrappers.
remove_action( 'woocommerce_before_main_content', 'woocommerce_output_content_wrapper' );
remove_action( 'woocommerce_after_main_content', 'woocommerce_output_content_wrapper_end' );
// Add custom wrappers.
add_action( 'woocommerce_before_main_content', array( __CLASS__, 'output_content_wrapper' ) );
add_action( 'woocommerce_after_main_content', array( __CLASS__, 'output_content_wrapper_end' ) );
// Declare theme support for features.
add_theme_support( 'wc-product-gallery-zoom' );
add_theme_support( 'wc-product-gallery-lightbox' );
add_theme_support( 'wc-product-gallery-slider' );
add_theme_support( 'woocommerce', array(
'thumbnail_image_width' => 105,
'single_image_width' => 228,
) );
}
/**
* Open wrappers.
*/
public static function output_content_wrapper() {
echo '<div id="primary" class="content-area"><div id="content" role="main" class="site-content twentyfourteen"><div class="tfwc">';
}
/**
* Close wrappers.
*/
public static function output_content_wrapper_end() {
echo '</div></div></div>';
get_sidebar( 'content' );
}
}
WC_Twenty_Fourteen::init();

View File

@ -8,7 +8,6 @@ if ( ! defined( 'ABSPATH' ) ) {
*
* @class WC_Twenty_Seventeen
* @since 2.6.9
* @version 2.6.9
* @package WooCommerce/Classes
*/
class WC_Twenty_Seventeen {
@ -24,12 +23,20 @@ class WC_Twenty_Seventeen {
add_action( 'woocommerce_after_main_content', array( __CLASS__, 'output_content_wrapper_end' ), 10 );
add_filter( 'woocommerce_enqueue_styles', array( __CLASS__, 'enqueue_styles' ) );
add_filter( 'twentyseventeen_custom_colors_css', array( __CLASS__, 'custom_colors_css' ), 10, 3 );
add_theme_support( 'wc-product-gallery-zoom' );
add_theme_support( 'wc-product-gallery-lightbox' );
add_theme_support( 'wc-product-gallery-slider' );
add_theme_support( 'woocommerce', array(
'thumbnail_image_width' => 150,
'single_image_width' => 322,
) );
}
/**
* Enqueue CSS for this theme.
*
* @param array $styles
* @param array $styles Array of registered styles.
* @return array
*/
public static function enqueue_styles( $styles ) {
@ -48,30 +55,28 @@ class WC_Twenty_Seventeen {
/**
* Open the Twenty Seventeen wrapper.
*/
public static function output_content_wrapper() { ?>
<div class="wrap">
<div id="primary" class="content-area twentyseventeen">
<main id="main" class="site-main" role="main">
<?php
public static function output_content_wrapper() {
echo '<div class="wrap">';
echo '<div id="primary" class="content-area twentyseventeen">';
echo '<main id="main" class="site-main" role="main">';
}
/**
* Close the Twenty Seventeen wrapper.
*/
public static function output_content_wrapper_end() { ?>
</main>
</div>
<?php get_sidebar(); ?>
</div>
<?php
public static function output_content_wrapper_end() {
echo '</main>';
echo '</div>';
get_sidebar();
echo '</div>';
}
/**
* Custom colors.
*
* @param string $css
* @param string $hue
* @param string $saturation
* @param string $css Styles.
* @param string $hue Color.
* @param string $saturation Saturation.
* @return string
*/
public static function custom_colors_css( $css, $hue, $saturation ) {

View File

@ -0,0 +1,52 @@
<?php
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
/**
* Twenty Sixteen support.
*
* @class WC_Twenty_Sixteen
* @since 3.3.0
* @package WooCommerce/Classes
*/
class WC_Twenty_Sixteen {
/**
* Theme init.
*/
public static function init() {
// Remove default wrappers.
remove_action( 'woocommerce_before_main_content', 'woocommerce_output_content_wrapper' );
remove_action( 'woocommerce_after_main_content', 'woocommerce_output_content_wrapper_end' );
// Add custom wrappers.
add_action( 'woocommerce_before_main_content', array( __CLASS__, 'output_content_wrapper' ) );
add_action( 'woocommerce_after_main_content', array( __CLASS__, 'output_content_wrapper_end' ) );
// Declare theme support for features.
add_theme_support( 'wc-product-gallery-zoom' );
add_theme_support( 'wc-product-gallery-lightbox' );
add_theme_support( 'wc-product-gallery-slider' );
add_theme_support( 'woocommerce', array(
'thumbnail_image_width' => 186,
'single_image_width' => 390,
) );
}
/**
* Open wrappers.
*/
public static function output_content_wrapper() {
echo '<div id="primary" class="content-area twentysixteen"><main id="main" class="site-main" role="main">';
}
/**
* Close wrappers.
*/
public static function output_content_wrapper_end() {
echo '</main></div>';
}
}
WC_Twenty_Sixteen::init();

View File

@ -0,0 +1,52 @@
<?php
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
/**
* Twenty Ten support.
*
* @class WC_Twenty_Ten
* @since 3.3.0
* @package WooCommerce/Classes
*/
class WC_Twenty_Ten {
/**
* Theme init.
*/
public static function init() {
// Remove default wrappers.
remove_action( 'woocommerce_before_main_content', 'woocommerce_output_content_wrapper' );
remove_action( 'woocommerce_after_main_content', 'woocommerce_output_content_wrapper_end' );
// Add custom wrappers.
add_action( 'woocommerce_before_main_content', array( __CLASS__, 'output_content_wrapper' ) );
add_action( 'woocommerce_after_main_content', array( __CLASS__, 'output_content_wrapper_end' ) );
// Declare theme support for features.
add_theme_support( 'wc-product-gallery-zoom' );
add_theme_support( 'wc-product-gallery-lightbox' );
add_theme_support( 'wc-product-gallery-slider' );
add_theme_support( 'woocommerce', array(
'thumbnail_image_width' => 140,
'single_image_width' => 300,
) );
}
/**
* Open wrappers.
*/
public static function output_content_wrapper() {
echo '<div id="container"><div id="content" role="main">';
}
/**
* Close wrappers.
*/
public static function output_content_wrapper_end() {
echo '</div></div>';
}
}
WC_Twenty_Ten::init();

View File

@ -0,0 +1,52 @@
<?php
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
/**
* Twenty Thirteen support.
*
* @class WC_Twenty_Thirteen
* @since 3.3.0
* @package WooCommerce/Classes
*/
class WC_Twenty_Thirteen {
/**
* Theme init.
*/
public static function init() {
// Remove default wrappers.
remove_action( 'woocommerce_before_main_content', 'woocommerce_output_content_wrapper' );
remove_action( 'woocommerce_after_main_content', 'woocommerce_output_content_wrapper_end' );
// Add custom wrappers.
add_action( 'woocommerce_before_main_content', array( __CLASS__, 'output_content_wrapper' ) );
add_action( 'woocommerce_after_main_content', array( __CLASS__, 'output_content_wrapper_end' ) );
// Declare theme support for features.
add_theme_support( 'wc-product-gallery-zoom' );
add_theme_support( 'wc-product-gallery-lightbox' );
add_theme_support( 'wc-product-gallery-slider' );
add_theme_support( 'woocommerce', array(
'thumbnail_image_width' => 140,
'single_image_width' => 290,
) );
}
/**
* Open wrappers.
*/
public static function output_content_wrapper() {
echo '<div id="primary" class="site-content"><div id="content" role="main" class="entry-content twentythirteen">';
}
/**
* Close wrappers.
*/
public static function output_content_wrapper_end() {
echo '</div></div>';
}
}
WC_Twenty_Thirteen::init();

View File

@ -0,0 +1,52 @@
<?php
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
/**
* Twenty Twelve support.
*
* @class WC_Twenty_Twelve
* @since 3.3.0
* @package WooCommerce/Classes
*/
class WC_Twenty_Twelve {
/**
* Theme init.
*/
public static function init() {
// Remove default wrappers.
remove_action( 'woocommerce_before_main_content', 'woocommerce_output_content_wrapper' );
remove_action( 'woocommerce_after_main_content', 'woocommerce_output_content_wrapper_end' );
// Add custom wrappers.
add_action( 'woocommerce_before_main_content', array( __CLASS__, 'output_content_wrapper' ) );
add_action( 'woocommerce_after_main_content', array( __CLASS__, 'output_content_wrapper_end' ) );
// Declare theme support for features.
add_theme_support( 'wc-product-gallery-zoom' );
add_theme_support( 'wc-product-gallery-lightbox' );
add_theme_support( 'wc-product-gallery-slider' );
add_theme_support( 'woocommerce', array(
'thumbnail_image_width' => 140,
'single_image_width' => 300,
) );
}
/**
* Open wrappers.
*/
public static function output_content_wrapper() {
echo '<div id="primary" class="site-content"><div id="content" role="main" class="twentytwelve">';
}
/**
* Close wrappers.
*/
public static function output_content_wrapper_end() {
echo '</div></div>';
}
}
WC_Twenty_Twelve::init();

View File

@ -659,39 +659,64 @@ function wc_mail( $to, $subject, $message, $headers = "Content-Type: text/html\r
}
/**
* Get an image size.
* Get an image size by name or defined dimensions.
*
* Variable is filtered by woocommerce_get_image_size_{image_size}.
* The returned variable is filtered by woocommerce_get_image_size_{image_size} filter to
* allow 3rd party customisation.
*
* @param array|string $image_size
* @return array
* Sizes defined by the theme take priority over settings. Settings are hidden when a theme
* defines sizes.
*
* @param array|string $image_size Name of the image size to get, or an array of dimensions.
* @return array Array of dimensions including width, height, and cropping mode. Cropping mode is 0 for no crop, and 1 for hard crop.
*/
function wc_get_image_size( $image_size ) {
$theme_support = get_theme_support( 'woocommerce' );
$theme_support = is_array( $theme_support ) ? $theme_support[0]: false;
$size = array(
'width' => 600,
'height' => 600,
'crop' => 1,
);
if ( is_array( $image_size ) ) {
$width = isset( $image_size[0] ) ? $image_size[0] : '300';
$height = isset( $image_size[1] ) ? $image_size[1] : '300';
$crop = isset( $image_size[2] ) ? $image_size[2] : 1;
$size = array(
'width' => $width,
'height' => $height,
'crop' => $crop,
'width' => isset( $image_size[0] ) ? $image_size[0] : 600,
'height' => isset( $image_size[1] ) ? $image_size[1] : 600,
'crop' => isset( $image_size[2] ) ? $image_size[2] : 1,
);
$image_size = $size['width'] . '_' . $size['height'];
} elseif ( in_array( $image_size, array( 'single', 'shop_single' ), true ) ) {
// If the theme supports woocommerce, take image sizes from that definition.
if ( isset( $theme_support['single_image_width'] ) ) {
$size['width'] = $theme_support['single_image_width'];
} else {
$size['width'] = get_option( 'woocommerce_single_image_width', 600 );
}
$size['height'] = 9999999999;
$size['crop'] = 0;
$image_size = 'single';
} elseif ( in_array( $image_size, array( 'thumbnail', 'shop_thumbnail', 'shop_catalog' ), true ) ) {
// If the theme supports woocommerce, take image sizes from that definition.
if ( isset( $theme_support['thumbnail_image_width'] ) ) {
$size['width'] = $theme_support['thumbnail_image_width'];
} else {
$size['width'] = get_option( 'woocommerce_thumbnail_image_width', 300 );
}
$image_size = $width . '_' . $height;
$cropping = get_option( 'woocommerce_thumbnail_cropping', '1:1' );
} elseif ( in_array( $image_size, array( 'shop_thumbnail', 'shop_catalog', 'shop_single' ) ) ) {
$size = get_option( $image_size . '_image_size', array() );
$size['width'] = isset( $size['width'] ) ? $size['width'] : '300';
$size['height'] = isset( $size['height'] ) ? $size['height'] : '300';
$size['crop'] = isset( $size['crop'] ) ? $size['crop'] : 0;
} else {
$size = array(
'width' => '300',
'height' => '300',
'crop' => 1,
);
if ( 'uncropped' === $cropping ) {
$size['height'] = 9999999999;
$size['crop'] = 0;
} else {
$cropping_split = explode( ':', $cropping );
$width_ratio = max( 1, current( $cropping_split ) );
$height_ratio = max( 1, end( $cropping_split ) );
$size['height'] = round( ( $size['width'] / $width_ratio ) * $height_ratio );
$size['crop'] = 1;
}
$image_size = 'thumbnail';
}
return apply_filters( 'woocommerce_get_image_size_' . $image_size, $size );
@ -899,11 +924,11 @@ add_filter( 'attachment_link', 'wc_fix_product_attachment_link', 10, 2 );
/**
* Protect downloads from ms-files.php in multisite.
*
* @param mixed $rewrite
* @param string $rewrite rewrite rules.
* @return string
*/
function wc_ms_protect_download_rewite_rules( $rewrite ) {
if ( ! is_multisite() || 'redirect' == get_option( 'woocommerce_file_download_method' ) ) {
if ( ! is_multisite() || 'redirect' === get_option( 'woocommerce_file_download_method' ) ) {
return $rewrite;
}
@ -918,16 +943,6 @@ function wc_ms_protect_download_rewite_rules( $rewrite ) {
}
add_filter( 'mod_rewrite_rules', 'wc_ms_protect_download_rewite_rules' );
/**
* WooCommerce Core Supported Themes.
*
* @since 2.2
* @return string[]
*/
function wc_get_core_supported_themes() {
return array( 'twentyseventeen', 'twentysixteen', 'twentyfifteen', 'twentyfourteen', 'twentythirteen', 'twentyeleven', 'twentytwelve', 'twentyten' );
}
/**
* Wrapper function to execute the `woocommerce_deliver_webhook_async` cron.
* hook, see WC_Webhook::process().

View File

@ -809,7 +809,7 @@ function woocommerce_placeholder_img_src() {
/**
* @deprecated 3.0
*/
function woocommerce_placeholder_img( $size = 'shop_thumbnail' ) {
function woocommerce_placeholder_img( $size = 'woocommerce_thumbnail' ) {
wc_deprecated_function( __FUNCTION__, '3.0', 'wc_placeholder_img' );
return wc_placeholder_img( $size );
}
@ -972,3 +972,15 @@ function wc_get_customer_avatar_url( $email ) {
return get_avatar_url( $email );
}
/**
* WooCommerce Core Supported Themes.
*
* @deprecated 3.3.0
* @since 2.2
* @return string[]
*/
function wc_get_core_supported_themes() {
wc_deprecated_function( 'wc_get_core_supported_themes()', '3.3' );
return array( 'twentyseventeen', 'twentysixteen', 'twentyfifteen', 'twentyfourteen', 'twentythirteen', 'twentyeleven', 'twentytwelve', 'twentyten' );
}

View File

@ -294,7 +294,7 @@ function wc_placeholder_img_src() {
*
* @return string
*/
function wc_placeholder_img( $size = 'shop_thumbnail' ) {
function wc_placeholder_img( $size = 'woocommerce_thumbnail' ) {
$dimensions = wc_get_image_size( $size );
return apply_filters( 'woocommerce_placeholder_img', '<img src="' . wc_placeholder_img_src() . '" alt="' . esc_attr__( 'Placeholder', 'woocommerce' ) . '" width="' . esc_attr( $dimensions['width'] ) . '" class="woocommerce-placeholder wp-post-image" height="' . esc_attr( $dimensions['height'] ) . '" />', $size, $dimensions );
@ -693,18 +693,18 @@ function wc_get_product_attachment_props( $attachment_id = null, $product = fals
$props['full_src_h'] = $src[2];
// Thumbnail version.
$src = wp_get_attachment_image_src( $attachment_id, 'shop_thumbnail' );
$src = wp_get_attachment_image_src( $attachment_id, 'woocommerce_thumbnail' );
$props['thumb_src'] = $src[0];
$props['thumb_src_w'] = $src[1];
$props['thumb_src_h'] = $src[2];
// Image source.
$src = wp_get_attachment_image_src( $attachment_id, 'shop_single' );
$src = wp_get_attachment_image_src( $attachment_id, 'woocommerce_single' );
$props['src'] = $src[0];
$props['src_w'] = $src[1];
$props['src_h'] = $src[2];
$props['srcset'] = function_exists( 'wp_get_attachment_image_srcset' ) ? wp_get_attachment_image_srcset( $attachment_id, 'shop_single' ) : false;
$props['sizes'] = function_exists( 'wp_get_attachment_image_sizes' ) ? wp_get_attachment_image_sizes( $attachment_id, 'shop_single' ) : false;
$props['srcset'] = function_exists( 'wp_get_attachment_image_srcset' ) ? wp_get_attachment_image_srcset( $attachment_id, 'woocommerce_single' ) : false;
$props['sizes'] = function_exists( 'wp_get_attachment_image_sizes' ) ? wp_get_attachment_image_sizes( $attachment_id, 'woocommerce_single' ) : false;
// Alt text fallbacks.
$props['alt'] = empty( $props['alt'] ) ? $props['caption'] : $props['alt'];

View File

@ -280,6 +280,59 @@ function wc_product_cat_class( $class = '', $category = null ) {
echo 'class="' . esc_attr( join( ' ', wc_get_product_cat_class( $class, $category ) ) ) . '"';
}
/**
* Get the default columns setting - this is how many products will be shown per row in loops.
*
* @since 3.3.0
* @return int
*/
function wc_get_default_products_per_row() {
$columns = get_option( 'woocommerce_catalog_columns', 3 );
// Theme support.
$theme_support = get_theme_support( 'woocommerce' );
$theme_support = is_array( $theme_support ) ? $theme_support[0]: false;
if ( isset( $theme_support['product_grid']['min_columns'] ) && $columns < $theme_support['product_grid']['min_columns'] ) {
$columns = $theme_support['product_grid']['min_columns'];
update_option( 'woocommerce_catalog_columns', $columns );
} elseif ( ! empty( $theme_support['product_grid']['max_columns'] ) && $columns > $theme_support['product_grid']['max_columns'] ) {
$columns = $theme_support['product_grid']['max_columns'];
update_option( 'woocommerce_catalog_columns', $columns );
}
// Legacy filter.
if ( has_filter( 'loop_shop_columns' ) ) {
$columns = apply_filters( 'loop_shop_columns', $columns );
}
return absint( $columns );
}
/**
* Get the default rows setting - this is how many product rows will be shown in loops.
*
* @since 3.3.0
* @return int
*/
function wc_get_default_product_rows_per_page() {
$rows = absint( get_option( 'woocommerce_catalog_rows', 4 ) );
// Theme support.
$theme_support = get_theme_support( 'woocommerce' );
$theme_support = is_array( $theme_support ) ? $theme_support[0]: false;
if ( isset( $theme_support['product_grid']['min_rows'] ) && $rows < $theme_support['product_grid']['min_rows'] ) {
$rows = $theme_support['product_grid']['min_rows'];
update_option( 'woocommerce_catalog_rows', $rows );
} elseif ( ! empty( $theme_support['product_grid']['max_rows'] ) && $rows > $theme_support['product_grid']['max_rows'] ) {
$rows = $theme_support['product_grid']['max_rows'];
update_option( 'woocommerce_catalog_rows', $rows );
}
return $rows;
}
/**
* Get classname for loops based on $woocommerce_loop global.
*
@ -290,7 +343,7 @@ function wc_get_loop_class() {
global $woocommerce_loop;
$woocommerce_loop['loop'] = ! empty( $woocommerce_loop['loop'] ) ? $woocommerce_loop['loop'] + 1 : 1;
$woocommerce_loop['columns'] = max( 1, ! empty( $woocommerce_loop['columns'] ) ? $woocommerce_loop['columns'] : apply_filters( 'loop_shop_columns', 4 ) );
$woocommerce_loop['columns'] = ! empty( $woocommerce_loop['columns'] ) ? $woocommerce_loop['columns'] : wc_get_default_products_per_row();
if ( 0 === ( $woocommerce_loop['loop'] - 1 ) % $woocommerce_loop['columns'] || 1 === $woocommerce_loop['columns'] ) {
return 'first';
@ -474,7 +527,7 @@ if ( ! function_exists( 'woocommerce_content' ) ) {
<?php do_action( 'woocommerce_after_shop_loop' ); ?>
<?php elseif ( ! woocommerce_product_subcategories( array( 'before' => woocommerce_product_loop_start( false ), 'after' => woocommerce_product_loop_end( false ) ) ) ) : ?>
<?php else : ?>
<?php do_action( 'woocommerce_no_products_found' ); ?>
@ -588,8 +641,11 @@ if ( ! function_exists( 'woocommerce_product_loop_start' ) ) {
*/
function woocommerce_product_loop_start( $echo = true ) {
ob_start();
$GLOBALS['woocommerce_loop']['loop'] = 0;
wc_get_template( 'loop/loop-start.php' );
if ( $echo ) {
echo ob_get_clean(); // WPCS: XSS ok.
} else {
@ -794,12 +850,12 @@ if ( ! function_exists( 'woocommerce_get_product_thumbnail' ) ) {
* Get the product thumbnail, or the placeholder if not set.
*
* @subpackage Loop
* @param string $size (default: 'shop_catalog').
* @param string $size (default: 'woocommerce_thumbnail').
* @param int $deprecated1 Deprecated since WooCommerce 2.0 (default: 0).
* @param int $deprecated2 Deprecated since WooCommerce 2.0 (default: 0).
* @return string
*/
function woocommerce_get_product_thumbnail( $size = 'shop_catalog', $deprecated1 = 0, $deprecated2 = 0 ) {
function woocommerce_get_product_thumbnail( $size = 'woocommerce_thumbnail', $deprecated1 = 0, $deprecated2 = 0 ) {
global $product;
$image_size = apply_filters( 'single_product_archive_thumbnail_size', $size );
@ -813,10 +869,24 @@ if ( ! function_exists( 'woocommerce_result_count' ) ) {
/**
* Output the result count text (Showing x - x of x results).
*
* @subpackage Loop
* @param WP_Query $query Pass a query object or use global to pull pagination info.
*/
function woocommerce_result_count() {
wc_get_template( 'loop/result-count.php' );
function woocommerce_result_count( $query = null ) {
if ( ! is_a( $query, 'WP_Query' ) ) {
$query = $GLOBALS['wp_query'];
}
if ( ! woocommerce_products_will_display() ) {
return;
}
$args = array(
'total' => $query->found_posts,
'per_page' => $query->get( 'posts_per_page' ),
'current' => max( 1, $query->get( 'paged', 1 ) ),
);
wc_get_template( 'loop/result-count.php', $args );
}
}
@ -825,12 +895,14 @@ if ( ! function_exists( 'woocommerce_catalog_ordering' ) ) {
/**
* Output the product sorting options.
*
* @subpackage Loop
* @param WP_Query $query Pass a query object or use global.
*/
function woocommerce_catalog_ordering() {
global $wp_query;
function woocommerce_catalog_ordering( $query = null ) {
if ( ! is_a( $query, 'WP_Query' ) ) {
$query = $GLOBALS['wp_query'];
}
if ( 1 === (int) $wp_query->found_posts || ! woocommerce_products_will_display() ) {
if ( ! woocommerce_products_will_display() ) {
return;
}
@ -845,7 +917,7 @@ if ( ! function_exists( 'woocommerce_catalog_ordering' ) ) {
'price-desc' => __( 'Sort by price: high to low', 'woocommerce' ),
) );
if ( $wp_query->is_search() ) {
if ( $query->is_search() ) {
$catalog_orderby_options = array_merge( array( 'relevance' => __( 'Relevance', 'woocommerce' ) ), $catalog_orderby_options );
unset( $catalog_orderby_options['menu_order'] );
if ( 'menu_order' === $orderby ) {
@ -870,10 +942,19 @@ if ( ! function_exists( 'woocommerce_pagination' ) ) {
/**
* Output the pagination.
*
* @subpackage Loop
* @param WP_Query $query Pass a query object or use global to pull pagination info.
*/
function woocommerce_pagination() {
wc_get_template( 'loop/pagination.php' );
function woocommerce_pagination( $query = null ) {
if ( ! is_a( $query, 'WP_Query' ) ) {
$query = $GLOBALS['wp_query'];
}
$args = array(
'total' => $query->max_num_pages,
'current' => max( 1, $query->get( 'paged', 1 ) ),
);
wc_get_template( 'loop/pagination.php', $args );
}
}
@ -1664,77 +1745,34 @@ if ( ! function_exists( 'woocommerce_products_will_display' ) ) {
/**
* Check if we will be showing products or not (and not sub-categories only).
*
* @subpackage Loop
* @return bool
*/
function woocommerce_products_will_display() {
global $wpdb;
if ( is_shop() ) {
return 'subcategories' !== get_option( 'woocommerce_shop_page_display' ) || is_search();
}
if ( ! is_product_taxonomy() ) {
return false;
}
if ( is_search() || is_filtered() || is_paged() ) {
return true;
}
$term = get_queried_object();
$display_type = '';
if ( is_product_category() ) {
switch ( get_woocommerce_term_meta( $term->term_id, 'display_type', true ) ) {
case 'subcategories' :
// Nothing - we want to continue to see if there are products/subcats.
break;
case 'products' :
case 'both' :
if ( is_shop() ) {
$display_type = get_option( 'woocommerce_shop_page_display', '' );
} elseif ( is_product_category() ) {
$parent_id = get_queried_object_id();
$display_type = get_woocommerce_term_meta( $parent_id, 'display_type', true );
$display_type = '' === $display_type ? get_option( 'woocommerce_category_archive_display', '' ) : $display_type;
}
if ( 'subcategories' === $display_type ) {
if ( is_product_category() ) {
$term = get_queried_object();
if ( $term && ! count( get_term_children( $term->term_id, $term->taxonomy ) ) ) {
return true;
break;
default :
// Default - no setting.
if ( get_option( 'woocommerce_category_archive_display' ) != 'subcategories' ) {
return true;
}
break;
}
}
// Begin subcategory logic.
if ( empty( $term->term_id ) || empty( $term->taxonomy ) ) {
return true;
}
$transient_name = 'wc_products_will_display_' . $term->term_id . '_' . WC_Cache_Helper::get_transient_version( 'product_query' );
if ( false === ( $products_will_display = get_transient( $transient_name ) ) ) {
$has_children = $wpdb->get_col( $wpdb->prepare( "SELECT term_id FROM {$wpdb->term_taxonomy} WHERE parent = %d AND taxonomy = %s", $term->term_id, $term->taxonomy ) ); // WPCS: cache ok.
if ( $has_children ) {
// Check terms have products inside - parents first. If products are found inside, subcats will be shown instead of products so we can return false.
if ( count( get_objects_in_term( $has_children, $term->taxonomy ) ) > 0 ) {
$products_will_display = false;
} else {
// If we get here, the parents were empty so we're forced to check children.
foreach ( $has_children as $term_id ) {
$children = get_term_children( $term_id, $term->taxonomy );
if ( count( get_objects_in_term( $children, $term->taxonomy ) ) > 0 ) {
$products_will_display = false;
break;
}
}
}
} else {
$products_will_display = true;
}
return false;
}
set_transient( $transient_name, $products_will_display, DAY_IN_SECONDS * 30 );
return $products_will_display;
return true;
}
}
@ -1743,55 +1781,36 @@ if ( ! function_exists( 'woocommerce_product_subcategories' ) ) {
/**
* Display product sub categories as thumbnails.
*
* @subpackage Loop
* @param array $args Arguments.
* @return null|boolean
* @return boolean
*/
function woocommerce_product_subcategories( $args = array() ) {
global $wp_query;
$args = wp_parse_args( $args, array(
'before' => '',
'after' => '',
'parent_id' => 0,
'display_type' => '',
) );
$defaults = array(
'before' => '',
'after' => '',
'force_display' => false,
);
$args = wp_parse_args( $args, $defaults );
extract( $args ); // @codingStandardsIgnoreLine
// Main query only.
if ( ! is_main_query() && ! $force_display ) {
// Don't show when filtering, searching or when on page > 1.
if ( is_search() || is_filtered() || is_paged() ) {
return;
}
// Don't show when filtering, searching or when on page > 1 and ensure we're on a product archive.
if ( is_search() || is_filtered() || is_paged() || ( ! is_product_category() && ! is_shop() ) ) {
return;
$parent_id = $args['parent_id'];
$display_type = $args['display_type'];
// Check categories are enabled and see what level to query.
if ( is_shop() ) {
$display_type = get_option( 'woocommerce_shop_page_display', '' );
} elseif ( is_product_category() ) {
$parent_id = get_queried_object_id();
$display_type = get_woocommerce_term_meta( $parent_id, 'display_type', true );
$display_type = '' === $display_type ? get_option( 'woocommerce_category_archive_display', '' ) : $display_type;
}
// Check categories are enabled.
if ( is_shop() && '' === get_option( 'woocommerce_shop_page_display' ) ) {
return;
}
// Find the category + category parent, if applicable.
$term = get_queried_object();
$parent_id = empty( $term->term_id ) ? 0 : $term->term_id;
if ( is_product_category() ) {
$display_type = get_woocommerce_term_meta( $term->term_id, 'display_type', true );
switch ( $display_type ) {
case 'products' :
return;
break;
case '' :
if ( '' === get_option( 'woocommerce_category_archive_display' ) ) {
return;
}
break;
}
if ( '' === $display_type ) {
return false;
}
// 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.
@ -1809,7 +1828,7 @@ if ( ! function_exists( 'woocommerce_product_subcategories' ) ) {
}
if ( $product_categories ) {
echo wp_kses_post( $before );
echo wp_kses_post( $args['before'] );
foreach ( $product_categories as $category ) {
wc_get_template( 'content-product_cat.php', array(
@ -1817,33 +1836,20 @@ if ( ! function_exists( 'woocommerce_product_subcategories' ) ) {
) );
}
echo wp_kses_post( $args['after'] );
// If we are hiding products disable the loop and pagination.
if ( is_product_category() ) {
$display_type = get_woocommerce_term_meta( $term->term_id, 'display_type', true );
if ( 'subcategories' === $display_type ) {
global $wp_query;
switch ( $display_type ) {
case 'subcategories' :
$wp_query->post_count = 0;
$wp_query->max_num_pages = 0;
break;
case '' :
if ( 'subcategories' === get_option( 'woocommerce_category_archive_display' ) ) {
$wp_query->post_count = 0;
$wp_query->max_num_pages = 0;
}
break;
}
}
if ( is_shop() && 'subcategories' === get_option( 'woocommerce_shop_page_display' ) ) {
$wp_query->post_count = 0;
$wp_query->max_num_pages = 0;
}
echo wp_kses_post( $after );
return true;
}
return false;
}
}
@ -1856,7 +1862,7 @@ if ( ! function_exists( 'woocommerce_subcategory_thumbnail' ) ) {
* @subpackage Loop
*/
function woocommerce_subcategory_thumbnail( $category ) {
$small_thumbnail_size = apply_filters( 'subcategory_archive_thumbnail_size', 'shop_catalog' );
$small_thumbnail_size = apply_filters( 'subcategory_archive_thumbnail_size', 'woocommerce_thumbnail' );
$dimensions = wc_get_image_size( $small_thumbnail_size );
$thumbnail_id = get_woocommerce_term_meta( $category->term_id, 'thumbnail_id', true );

View File

@ -1409,3 +1409,32 @@ function wc_update_320_mexican_states() {
function wc_update_320_db_version() {
WC_Install::update_db_version( '3.2.0' );
}
/**
* Update image settings to use new aspect ratios and widths.
*/
function wc_update_330_image_options() {
$old_thumbnail_size = get_option( 'shop_catalog_image_size', array() );
$old_single_size = get_option( 'shop_single_image_size', array() );
if ( ! empty( $old_thumbnail_size['width'] ) ) {
update_option( 'woocommerce_thumbnail_image_width', absint( $old_thumbnail_size['width'] ) );
}
if ( ! empty( $old_thumbnail_size['crop'] ) ) {
update_option( 'woocommerce_thumbnail_cropping', '1:1' );
} elseif ( isset( $old_thumbnail_size['crop'] ) ) {
update_option( 'woocommerce_thumbnail_cropping', 'uncropped' );
}
if ( ! empty( $old_single_size['width'] ) ) {
update_option( 'woocommerce_single_image_width', absint( $old_single_size['width'] ) );
}
}
/**
* Update DB Version.
*/
function wc_update_330_db_version() {
WC_Install::update_db_version( '3.3.0' );
}

View File

@ -34,73 +34,6 @@ class WC_Widget_Layered_Nav_Filters extends WC_Widget {
parent::__construct();
}
/**
* Get current page URL for layered nav items.
*
* @return string
*/
protected function get_page_base_url() {
if ( defined( 'SHOP_IS_ON_FRONT' ) ) {
$link = home_url();
} elseif ( is_post_type_archive( 'product' ) || is_page( wc_get_page_id( 'shop' ) ) ) {
$link = get_post_type_archive_link( 'product' );
} elseif ( is_product_category() ) {
$link = get_term_link( get_query_var( 'product_cat' ), 'product_cat' );
} elseif ( is_product_tag() ) {
$link = get_term_link( get_query_var( 'product_tag' ), 'product_tag' );
} else {
$queried_object = get_queried_object();
$link = get_term_link( $queried_object->slug, $queried_object->taxonomy );
}
// Min/Max
if ( isset( $_GET['min_price'] ) ) {
$link = add_query_arg( 'min_price', wc_clean( $_GET['min_price'] ), $link );
}
if ( isset( $_GET['max_price'] ) ) {
$link = add_query_arg( 'max_price', wc_clean( $_GET['max_price'] ), $link );
}
// Order by
if ( isset( $_GET['orderby'] ) ) {
$link = add_query_arg( 'orderby', wc_clean( $_GET['orderby'] ), $link );
}
/**
* Search Arg.
* To support quote characters, first they are decoded from &quot; entities, then URL encoded.
*/
if ( get_search_query() ) {
$link = add_query_arg( 's', rawurlencode( htmlspecialchars_decode( get_search_query() ) ), $link );
}
// Post Type Arg
if ( isset( $_GET['post_type'] ) ) {
$link = add_query_arg( 'post_type', wc_clean( $_GET['post_type'] ), $link );
}
// Min Rating Arg
if ( isset( $_GET['rating_filter'] ) ) {
$link = add_query_arg( 'rating_filter', wc_clean( $_GET['rating_filter'] ), $link );
}
// All current filters
if ( $_chosen_attributes = WC_Query::get_layered_nav_chosen_attributes() ) {
foreach ( $_chosen_attributes as $name => $data ) {
$filter_name = sanitize_title( str_replace( 'pa_', '', $name ) );
if ( ! empty( $data['terms'] ) ) {
$link = add_query_arg( 'filter_' . $filter_name, implode( ',', $data['terms'] ), $link );
}
if ( 'or' == $data['query_type'] ) {
$link = add_query_arg( 'query_type_' . $filter_name, 'or', $link );
}
}
}
return $link;
}
/**
* Output widget.
*
@ -109,7 +42,7 @@ class WC_Widget_Layered_Nav_Filters extends WC_Widget {
* @param array $instance
*/
public function widget( $args, $instance ) {
if ( ! is_post_type_archive( 'product' ) && ! is_tax( get_object_taxonomies( 'product' ) ) ) {
if ( ! is_shop() && ! is_product_taxonomy() ) {
return;
}

View File

@ -115,7 +115,7 @@ class WC_Widget_Layered_Nav extends WC_Widget {
* @param array $instance Instance.
*/
public function widget( $args, $instance ) {
if ( ! is_post_type_archive( 'product' ) && ! is_tax( get_object_taxonomies( 'product' ) ) ) {
if ( ! is_shop() && ! is_product_taxonomy() ) {
return;
}
@ -316,78 +316,6 @@ class WC_Widget_Layered_Nav extends WC_Widget {
return $found;
}
/**
* Get current page URL for layered nav items.
*
* @param string $taxonomy Taxonomy.
*
* @return string
*/
protected function get_page_base_url( $taxonomy ) {
if ( defined( 'SHOP_IS_ON_FRONT' ) ) {
$link = home_url();
} elseif ( is_post_type_archive( 'product' ) || is_page( wc_get_page_id( 'shop' ) ) ) {
$link = get_post_type_archive_link( 'product' );
} elseif ( is_product_category() ) {
$link = get_term_link( get_query_var( 'product_cat' ), 'product_cat' );
} elseif ( is_product_tag() ) {
$link = get_term_link( get_query_var( 'product_tag' ), 'product_tag' );
} else {
$queried_object = get_queried_object();
$link = get_term_link( $queried_object->slug, $queried_object->taxonomy );
}
// Min/Max.
if ( isset( $_GET['min_price'] ) ) {
$link = add_query_arg( 'min_price', wc_clean( wp_unslash( $_GET['min_price'] ) ), $link );
}
if ( isset( $_GET['max_price'] ) ) {
$link = add_query_arg( 'max_price', wc_clean( wp_unslash( $_GET['max_price'] ) ), $link );
}
// Order by.
if ( isset( $_GET['orderby'] ) ) {
$link = add_query_arg( 'orderby', wc_clean( wp_unslash( $_GET['orderby'] ) ), $link );
}
/**
* Search Arg.
* To support quote characters, first they are decoded from &quot; entities, then URL encoded.
*/
if ( get_search_query() ) {
$link = add_query_arg( 's', rawurlencode( htmlspecialchars_decode( get_search_query() ) ), $link );
}
// Post Type Arg.
if ( isset( $_GET['post_type'] ) ) {
$link = add_query_arg( 'post_type', wc_clean( wp_unslash( $_GET['post_type'] ) ), $link );
}
// Min Rating Arg.
if ( isset( $_GET['rating_filter'] ) ) {
$link = add_query_arg( 'rating_filter', wc_clean( wp_unslash( $_GET['rating_filter'] ) ), $link );
}
// All current filters.
if ( $_chosen_attributes = WC_Query::get_layered_nav_chosen_attributes() ) {
foreach ( $_chosen_attributes as $name => $data ) {
if ( $name === $taxonomy ) {
continue;
}
$filter_name = sanitize_title( str_replace( 'pa_', '', $name ) );
if ( ! empty( $data['terms'] ) ) {
$link = add_query_arg( 'filter_' . $filter_name, implode( ',', $data['terms'] ), $link );
}
if ( 'or' == $data['query_type'] ) {
$link = add_query_arg( 'query_type_' . $filter_name, 'or', $link );
}
}
}
return $link;
}
/**
* Count products within certain terms, taking the main WP query into consideration.
*
@ -496,7 +424,7 @@ class WC_Widget_Layered_Nav extends WC_Widget {
$current_filter[] = $term->slug;
}
$link = $this->get_page_base_url( $taxonomy );
$link = remove_query_arg( $filter_name, $this->get_page_base_url() );
// Add current filters to URL.
foreach ( $current_filter as $key => $value ) {

View File

@ -60,13 +60,13 @@ class WC_Widget_Price_Filter extends WC_Widget {
* @param array $instance
*/
public function widget( $args, $instance ) {
global $wp, $wp_the_query;
global $wp;
if ( ! is_post_type_archive( 'product' ) && ! is_tax( get_object_taxonomies( 'product' ) ) ) {
if ( ! is_shop() && ! is_product_taxonomy() ) {
return;
}
if ( ! $wp_the_query->post_count ) {
if ( ! wc()->query->get_main_query()->post_count ) {
return;
}
@ -134,9 +134,9 @@ class WC_Widget_Price_Filter extends WC_Widget {
* @return int
*/
protected function get_filtered_price() {
global $wpdb, $wp_the_query;
global $wpdb;
$args = $wp_the_query->query_vars;
$args = wc()->query->get_main_query()->query_vars;
$tax_query = isset( $args['tax_query'] ) ? $args['tax_query'] : array();
$meta_query = isset( $args['meta_query'] ) ? $args['meta_query'] : array();

View File

@ -34,62 +34,6 @@ class WC_Widget_Rating_Filter extends WC_Widget {
parent::__construct();
}
/**
* Get current page URL for layered nav items.
* @return string
*/
protected function get_page_base_url() {
if ( defined( 'SHOP_IS_ON_FRONT' ) ) {
$link = home_url();
} elseif ( is_post_type_archive( 'product' ) || is_page( wc_get_page_id( 'shop' ) ) ) {
$link = get_post_type_archive_link( 'product' );
} else {
$link = get_term_link( get_query_var( 'term' ), get_query_var( 'taxonomy' ) );
}
// Min/Max
if ( isset( $_GET['min_price'] ) ) {
$link = add_query_arg( 'min_price', wc_clean( $_GET['min_price'] ), $link );
}
if ( isset( $_GET['max_price'] ) ) {
$link = add_query_arg( 'max_price', wc_clean( $_GET['max_price'] ), $link );
}
// Order by
if ( isset( $_GET['orderby'] ) ) {
$link = add_query_arg( 'orderby', wc_clean( $_GET['orderby'] ), $link );
}
/**
* Search Arg.
* To support quote characters, first they are decoded from &quot; entities, then URL encoded.
*/
if ( get_search_query() ) {
$link = add_query_arg( 's', rawurlencode( htmlspecialchars_decode( get_search_query() ) ), $link );
}
// Post Type Arg
if ( isset( $_GET['post_type'] ) ) {
$link = add_query_arg( 'post_type', wc_clean( $_GET['post_type'] ), $link );
}
// All current filters
if ( $_chosen_attributes = WC_Query::get_layered_nav_chosen_attributes() ) {
foreach ( $_chosen_attributes as $name => $data ) {
$filter_name = sanitize_title( str_replace( 'pa_', '', $name ) );
if ( ! empty( $data['terms'] ) ) {
$link = add_query_arg( 'filter_' . $filter_name, implode( ',', $data['terms'] ), $link );
}
if ( 'or' == $data['query_type'] ) {
$link = add_query_arg( 'query_type_' . $filter_name, 'or', $link );
}
}
}
return $link;
}
/**
* Count products after other filters have occurred by adjusting the main query.
* @param int $rating
@ -145,13 +89,11 @@ class WC_Widget_Rating_Filter extends WC_Widget {
* @param array $instance
*/
public function widget( $args, $instance ) {
global $wp_the_query;
if ( ! is_post_type_archive( 'product' ) && ! is_tax( get_object_taxonomies( 'product' ) ) ) {
if ( ! is_shop() && ! is_product_taxonomy() ) {
return;
}
if ( ! $wp_the_query->post_count ) {
if ( ! wc()->query->get_main_query()->post_count ) {
return;
}

View File

@ -17,114 +17,97 @@
*/
if ( ! defined( 'ABSPATH' ) ) {
exit; // Exit if accessed directly
exit;
}
get_header( 'shop' ); ?>
get_header( 'shop' );
/**
* Hook: woocommerce_before_main_content.
*
* @hooked woocommerce_output_content_wrapper - 10 (outputs opening divs for the content)
* @hooked woocommerce_breadcrumb - 20
* @hooked WC_Structured_Data::generate_website_data() - 30
*/
do_action( 'woocommerce_before_main_content' );
?>
<header class="woocommerce-products-header">
<?php if ( apply_filters( 'woocommerce_show_page_title', true ) ) : ?>
<h1 class="woocommerce-products-header__title page-title"><?php woocommerce_page_title(); ?></h1>
<?php endif; ?>
<?php
/**
* woocommerce_before_main_content hook.
*
* @hooked woocommerce_output_content_wrapper - 10 (outputs opening divs for the content)
* @hooked woocommerce_breadcrumb - 20
* @hooked WC_Structured_Data::generate_website_data() - 30
*/
do_action( 'woocommerce_before_main_content' );
/**
* Hook: woocommerce_archive_description.
*
* @hooked woocommerce_taxonomy_archive_description - 10
* @hooked woocommerce_product_archive_description - 10
*/
do_action( 'woocommerce_archive_description' );
?>
</header>
<?php
<header class="woocommerce-products-header">
if ( have_posts() ) :
<?php if ( apply_filters( 'woocommerce_show_page_title', true ) ) : ?>
/**
* Hook: woocommerce_before_shop_loop.
*
* @hooked wc_print_notices - 10
* @hooked woocommerce_result_count - 20
* @hooked woocommerce_catalog_ordering - 30
*/
do_action( 'woocommerce_before_shop_loop' );
<h1 class="woocommerce-products-header__title page-title"><?php woocommerce_page_title(); ?></h1>
woocommerce_product_loop_start();
woocommerce_product_subcategories();
<?php endif; ?>
while ( have_posts() ) :
the_post();
<?php
/**
* woocommerce_archive_description hook.
*
* @hooked woocommerce_taxonomy_archive_description - 10
* @hooked woocommerce_product_archive_description - 10
*/
do_action( 'woocommerce_archive_description' );
?>
</header>
<?php if ( have_posts() ) : ?>
<?php
/**
* woocommerce_before_shop_loop hook.
*
* @hooked wc_print_notices - 10
* @hooked woocommerce_result_count - 20
* @hooked woocommerce_catalog_ordering - 30
*/
do_action( 'woocommerce_before_shop_loop' );
?>
<?php woocommerce_product_loop_start(); ?>
<?php woocommerce_product_subcategories(); ?>
<?php while ( have_posts() ) : the_post(); ?>
<?php
/**
* woocommerce_shop_loop hook.
*
* @hooked WC_Structured_Data::generate_product_data() - 10
*/
do_action( 'woocommerce_shop_loop' );
?>
<?php wc_get_template_part( 'content', 'product' ); ?>
<?php endwhile; // end of the loop. ?>
<?php woocommerce_product_loop_end(); ?>
<?php
/**
* woocommerce_after_shop_loop hook.
*
* @hooked woocommerce_pagination - 10
*/
do_action( 'woocommerce_after_shop_loop' );
?>
<?php elseif ( ! woocommerce_product_subcategories( array( 'before' => woocommerce_product_loop_start( false ), 'after' => woocommerce_product_loop_end( false ) ) ) ) : ?>
<?php
/**
* woocommerce_no_products_found hook.
*
* @hooked wc_no_products_found - 10
*/
do_action( 'woocommerce_no_products_found' );
?>
<?php endif; ?>
<?php
/**
* woocommerce_after_main_content hook.
* Hook: woocommerce_shop_loop.
*
* @hooked woocommerce_output_content_wrapper_end - 10 (outputs closing divs for the content)
* @hooked WC_Structured_Data::generate_product_data() - 10
*/
do_action( 'woocommerce_after_main_content' );
?>
do_action( 'woocommerce_shop_loop' );
<?php
/**
* woocommerce_sidebar hook.
*
* @hooked woocommerce_get_sidebar - 10
*/
do_action( 'woocommerce_sidebar' );
?>
wc_get_template_part( 'content', 'product' );
endwhile;
<?php get_footer( 'shop' ); ?>
woocommerce_product_loop_end();
/**
* Hook: woocommerce_after_shop_loop.
*
* @hooked woocommerce_pagination - 10
*/
do_action( 'woocommerce_after_shop_loop' );
else :
/**
* Hook: woocommerce_no_products_found.
*
* @hooked wc_no_products_found - 10
*/
do_action( 'woocommerce_no_products_found' );
endif;
/**
* Hook: woocommerce_after_main_content.
*
* @hooked woocommerce_output_content_wrapper_end - 10 (outputs closing divs for the content)
*/
do_action( 'woocommerce_after_main_content' );
/**
* Hook: woocommerce_sidebar.
*
* @hooked woocommerce_get_sidebar - 10
*/
do_action( 'woocommerce_sidebar' );
get_footer( 'shop' );

View File

@ -13,7 +13,11 @@
* @see https://docs.woocommerce.com/document/template-structure/
* @author WooThemes
* @package WooCommerce/Templates
* @version 2.0.0
* @version 3.3.0
*/
global $woocommerce_loop;
$columns = ! empty( $woocommerce_loop['columns'] ) ? $woocommerce_loop['columns'] : wc_get_default_products_per_row();
?>
<ul class="products">
<ul class="products columns-<?php echo esc_attr( $columns ); ?>">

View File

@ -13,11 +13,11 @@
* @see https://docs.woocommerce.com/document/template-structure/
* @author WooThemes
* @package WooCommerce/Templates
* @version 2.2.0
* @version 3.3.0
*/
if ( ! defined( 'ABSPATH' ) ) {
exit; // Exit if accessed directly
exit;
}
?>
@ -27,5 +27,6 @@ if ( ! defined( 'ABSPATH' ) ) {
<option value="<?php echo esc_attr( $id ); ?>" <?php selected( $orderby, $id ); ?>><?php echo esc_html( $name ); ?></option>
<?php endforeach; ?>
</select>
<?php wc_query_string_form_fields( null, array( 'orderby', 'submit' ) ); ?>
<input type="hidden" name="paged" value="1" />
<?php wc_query_string_form_fields( null, array( 'orderby', 'submit', 'paged' ) ); ?>
</form>

View File

@ -13,16 +13,14 @@
* @see https://docs.woocommerce.com/document/template-structure/
* @author WooThemes
* @package WooCommerce/Templates
* @version 2.2.2
* @version 3.3.0
*/
if ( ! defined( 'ABSPATH' ) ) {
exit; // Exit if accessed directly
exit;
}
global $wp_query;
if ( $wp_query->max_num_pages <= 1 ) {
if ( $total <= 1 ) {
return;
}
?>
@ -32,8 +30,8 @@ if ( $wp_query->max_num_pages <= 1 ) {
'base' => esc_url_raw( str_replace( 999999999, '%#%', remove_query_arg( 'add-to-cart', get_pagenum_link( 999999999, false ) ) ) ),
'format' => '',
'add_args' => false,
'current' => max( 1, get_query_var( 'paged' ) ),
'total' => $wp_query->max_num_pages,
'current' => max( 1, $current ),
'total' => $total,
'prev_text' => '&larr;',
'next_text' => '&rarr;',
'type' => 'list',

View File

@ -15,31 +15,21 @@
* @see https://docs.woocommerce.com/document/template-structure/
* @author WooThemes
* @package WooCommerce/Templates
* @version 3.0.0
* @version 3.3.0
*/
if ( ! defined( 'ABSPATH' ) ) {
exit; // Exit if accessed directly
}
global $wp_query;
if ( ! woocommerce_products_will_display() ) {
return;
exit;
}
?>
<p class="woocommerce-result-count">
<?php
$paged = max( 1, $wp_query->get( 'paged' ) );
$per_page = $wp_query->get( 'posts_per_page' );
$total = $wp_query->found_posts;
$first = ( $per_page * $paged ) - $per_page + 1;
$last = min( $total, $wp_query->get( 'posts_per_page' ) * $paged );
if ( $total <= $per_page || -1 === $per_page ) {
/* translators: %d: total results */
printf( _n( 'Showing the single result', 'Showing all %d results', $total, 'woocommerce' ), $total );
} else {
$first = ( $per_page * $current ) - $per_page + 1;
$last = min( $total, $per_page * $current );
/* translators: 1: first result 2: last result 3: total results */
printf( _nx( 'Showing the single result', 'Showing %1$d&ndash;%2$d of %3$d results', $total, 'with first and last result', 'woocommerce' ), $first, $last, $total );
}

View File

@ -46,8 +46,8 @@ $wrapper_classes = apply_filters( 'woocommerce_single_product_image_gallery_cl
);
if ( has_post_thumbnail() ) {
$html = '<div data-thumb="' . get_the_post_thumbnail_url( $post->ID, 'shop_thumbnail' ) . '" class="woocommerce-product-gallery__image"><a href="' . esc_url( $full_size_image[0] ) . '">';
$html .= get_the_post_thumbnail( $post->ID, 'shop_single', $attributes );
$html = '<div data-thumb="' . get_the_post_thumbnail_url( $post->ID, 'woocommerce_thumbnail' ) . '" class="woocommerce-product-gallery__image"><a href="' . esc_url( $full_size_image[0] ) . '">';
$html .= get_the_post_thumbnail( $post->ID, 'woocommerce_single', $attributes );
$html .= '</a></div>';
} else {
$html = '<div class="woocommerce-product-gallery__image--placeholder">';

View File

@ -27,7 +27,7 @@ $attachment_ids = $product->get_gallery_image_ids();
if ( $attachment_ids && has_post_thumbnail() ) {
foreach ( $attachment_ids as $attachment_id ) {
$full_size_image = wp_get_attachment_image_src( $attachment_id, 'full' );
$thumbnail = wp_get_attachment_image_src( $attachment_id, 'shop_thumbnail' );
$thumbnail = wp_get_attachment_image_src( $attachment_id, 'woocommerce_thumbnail' );
$attributes = array(
'title' => get_post_field( 'post_title', $attachment_id ),
'data-caption' => get_post_field( 'post_excerpt', $attachment_id ),
@ -38,7 +38,7 @@ if ( $attachment_ids && has_post_thumbnail() ) {
);
$html = '<div data-thumb="' . esc_url( $thumbnail[0] ) . '" class="woocommerce-product-gallery__image"><a href="' . esc_url( $full_size_image[0] ) . '">';
$html .= wp_get_attachment_image( $attachment_id, 'shop_single', false, $attributes );
$html .= wp_get_attachment_image( $attachment_id, 'woocommerce_single', false, $attributes );
$html .= '</a></div>';
echo apply_filters( 'woocommerce_single_product_image_thumbnail_html', $html, $attachment_id );

View File

@ -697,44 +697,6 @@ class Settings extends WC_REST_Unit_Test_Case {
$this->assertEquals( 'lbs', $setting['value'] );
}
/**
* Test validation of image_width.
*
* @since 3.0.0
*/
public function test_validation_image_width() {
wp_set_current_user( $this->user );
$response = $this->server->dispatch( new WP_REST_Request( 'GET', sprintf( '/wc/v2/settings/%s/%s', 'products', 'shop_thumbnail_image_size' ) ) );
$setting = $response->get_data();
$this->assertEquals( array( 'width' => 180, 'height' => 180, 'crop' => true ), $setting['value'] );
// test bogus
$request = new WP_REST_Request( 'PUT', sprintf( '/wc/v2/settings/%s/%s', 'products', 'shop_thumbnail_image_size' ) );
$request->set_body_params( array(
'value' => array(
'width' => 400,
'height' => 200,
'crop' => 'asdasdasd',
),
) );
$response = $this->server->dispatch( $request );
$setting = $response->get_data();
$this->assertEquals( array( 'width' => 400, 'height' => 200, 'crop' => true ), $setting['value'] );
$request = new WP_REST_Request( 'PUT', sprintf( '/wc/v2/settings/%s/%s', 'products', 'shop_thumbnail_image_size' ) );
$request->set_body_params( array(
'value' => array(
'width' => 200,
'height' => 100,
'crop' => false,
),
) );
$response = $this->server->dispatch( $request );
$setting = $response->get_data();
$this->assertEquals( array( 'width' => 200, 'height' => 100, 'crop' => false ), $setting['value'] );
}
/**
* Test to make sure the 'base location' setting is present in the response.
* That it is returned as 'select' and not 'single_select_country',

View File

@ -682,37 +682,50 @@ class WC_Tests_Cart extends WC_Unit_Test_Case {
* @since 2.3
*/
public function test_get_total_ex_tax() {
global $wpdb;
// Set calc taxes option
// Set calc taxes option.
update_option( 'woocommerce_calc_taxes', 'yes' );
$tax_rate = array(
'tax_rate_country' => '',
'tax_rate_state' => '',
'tax_rate' => '10.0000',
'tax_rate_name' => 'TAX',
'tax_rate_priority' => '1',
'tax_rate_compound' => '0',
'tax_rate_shipping' => '1',
'tax_rate_order' => '1',
'tax_rate_class' => '',
);
WC_Tax::_insert_tax_rate( $tax_rate );
// Create dummy product
// Create dummy product.
$product = WC_Helper_Product::create_simple_product();
// We need this to have the calculate_totals() method calculate totals
// We need this to have the calculate_totals() method calculate totals.
if ( ! defined( 'WOOCOMMERCE_CHECKOUT' ) ) {
define( 'WOOCOMMERCE_CHECKOUT', true );
}
// Add product to cart
// Add 10 fee.
WC_Helper_Fee::add_cart_fee( 'taxed' );
// Add product to cart (10).
WC()->cart->add_to_cart( $product->get_id(), 1 );
// Calc total
$total = WC()->cart->total - WC()->cart->tax_total - WC()->cart->shipping_tax_total;
if ( $total < 0 ) {
$total = 0;
}
// Check.
$this->assertEquals( wc_price( 22 ), WC()->cart->get_total() );
$this->assertEquals( wc_price( 20 ), WC()->cart->get_total_ex_tax() );
// Check
$this->assertEquals( apply_filters( 'woocommerce_cart_total_ex_tax', wc_price( $total ) ), WC()->cart->get_total_ex_tax() );
// Clean up the cart
// Clean up the cart.
WC()->cart->empty_cart();
// Clean up product
// Clean up product.
WC_Helper_Product::delete_product( $product->get_id() );
// Restore option
// Restore option.
$wpdb->query( "DELETE FROM {$wpdb->prefix}woocommerce_tax_rates" );
$wpdb->query( "DELETE FROM {$wpdb->prefix}woocommerce_tax_rate_locations" );
update_option( 'woocommerce_calc_taxes', 'no' );
}

View File

@ -549,19 +549,7 @@ class WC_Tests_Product_Functions extends WC_Unit_Test_Case {
* @since 2.4
*/
public function test_wc_placeholder_img() {
$sizes = array(
'shop_thumbnail' => array( 'width' => '180', 'height' => '180' ),
'shop_single' => array( 'width' => '600', 'height' => '600' ),
'shop_catalog' => array( 'width' => '300', 'height' => '300' ),
);
foreach ( $sizes as $size => $values ) {
$img = '<img src="' . wc_placeholder_img_src() . '" alt="Placeholder" width="' . $values['width'] . '" class="woocommerce-placeholder wp-post-image" height="' . $values['height'] . '" />';
$this->assertEquals( apply_filters( 'woocommerce_placeholder_img', $img ), wc_placeholder_img( $size ) );
}
$img = '<img src="' . wc_placeholder_img_src() . '" alt="Placeholder" width="180" class="woocommerce-placeholder wp-post-image" height="180" />';
$this->assertEquals( apply_filters( 'woocommerce_placeholder_img', $img ), wc_placeholder_img() );
$this->assertTrue( (bool) strstr( wc_placeholder_img(), wc_placeholder_img_src() ) );
}
/**

View File

@ -14,7 +14,7 @@ class WC_Test_Shortcode_Products extends WC_Unit_Test_Case {
$shortcode = new WC_Shortcode_Products();
$expected = array(
'limit' => '-1',
'columns' => '4',
'columns' => '3',
'orderby' => 'title',
'order' => 'ASC',
'ids' => '',
@ -26,6 +26,11 @@ class WC_Test_Shortcode_Products extends WC_Unit_Test_Case {
'terms_operator' => 'IN',
'visibility' => 'visible',
'class' => '',
'rows' => '',
'page' => 1,
'paginate' => false,
'cache' => true,
);
$this->assertEquals( $expected, $shortcode->get_attributes() );
@ -35,7 +40,7 @@ class WC_Test_Shortcode_Products extends WC_Unit_Test_Case {
) );
$expected2 = array(
'limit' => '-1',
'columns' => '4',
'columns' => '3',
'orderby' => 'id',
'order' => 'DESC',
'ids' => '',
@ -47,6 +52,10 @@ class WC_Test_Shortcode_Products extends WC_Unit_Test_Case {
'terms_operator' => 'IN',
'visibility' => 'visible',
'class' => '',
'rows' => '',
'page' => 1,
'paginate' => false,
'cache' => true,
);
$this->assertEquals( $expected2, $shortcode2->get_attributes() );
}
@ -67,7 +76,7 @@ class WC_Test_Shortcode_Products extends WC_Unit_Test_Case {
'no_found_rows' => true,
'orderby' => 'title',
'order' => 'ASC',
'posts_per_page' => -1,
'posts_per_page' => '-1',
'meta_query' => $meta_query,
'tax_query' => $tax_query,
);
@ -85,7 +94,7 @@ class WC_Test_Shortcode_Products extends WC_Unit_Test_Case {
'no_found_rows' => true,
'orderby' => 'id',
'order' => 'DESC',
'posts_per_page' => -1,
'posts_per_page' => '-1',
'meta_query' => $meta_query,
'tax_query' => $tax_query,
);
@ -102,7 +111,7 @@ class WC_Test_Shortcode_Products extends WC_Unit_Test_Case {
'no_found_rows' => true,
'orderby' => 'title',
'order' => 'ASC',
'posts_per_page' => -1,
'posts_per_page' => '-1',
'meta_query' => $meta_query,
'tax_query' => $tax_query,
'post__in' => array( '1', '2', '3' ),
@ -119,7 +128,7 @@ class WC_Test_Shortcode_Products extends WC_Unit_Test_Case {
$shortcode4 = new WC_Shortcode_Products( array(
'per_page' => '12',
'columns' => '4',
'orderby' => 'menu_order title',
'orderby' => 'title',
'order' => 'ASC',
'category' => 'clothing',
'operator' => 'IN',
@ -129,12 +138,11 @@ class WC_Test_Shortcode_Products extends WC_Unit_Test_Case {
'post_status' => 'publish',
'ignore_sticky_posts' => true,
'no_found_rows' => true,
'orderby' => 'menu_order title',
'orderby' => 'title',
'order' => 'ASC',
'posts_per_page' => 12,
'posts_per_page' => '12',
'meta_query' => $meta_query,
'tax_query' => $tax_query,
'meta_key' => '',
);
$expected4['tax_query'][] = array(
'taxonomy' => 'product_cat',
@ -159,9 +167,9 @@ class WC_Test_Shortcode_Products extends WC_Unit_Test_Case {
'post_status' => 'publish',
'ignore_sticky_posts' => true,
'no_found_rows' => true,
'orderby' => 'date',
'orderby' => 'date ID',
'order' => 'DESC',
'posts_per_page' => 12,
'posts_per_page' => '12',
'meta_query' => $meta_query,
'tax_query' => $tax_query,
);
@ -180,7 +188,7 @@ class WC_Test_Shortcode_Products extends WC_Unit_Test_Case {
'no_found_rows' => true,
'orderby' => 'title',
'order' => 'ASC',
'posts_per_page' => 1,
'posts_per_page' => '1',
'meta_query' => $meta_query,
'tax_query' => $tax_query,
'p' => '1',
@ -272,7 +280,7 @@ class WC_Test_Shortcode_Products extends WC_Unit_Test_Case {
'post_status' => 'publish',
'ignore_sticky_posts' => true,
'no_found_rows' => true,
'orderby' => 'date',
'orderby' => 'date ID',
'order' => 'DESC',
'posts_per_page' => 12,
'meta_query' => $meta_query,

View File

@ -268,18 +268,6 @@ class WC_Tests_Core_Functions extends WC_Unit_Test_Case {
return __CLASS__;
}
/**
* Test wc_get_core_supported_themes().
*
* @since 2.2
*/
public function test_wc_get_core_supported_themes() {
$expected_themes = array( 'twentyseventeen', 'twentysixteen', 'twentyfifteen', 'twentyfourteen', 'twentythirteen', 'twentyeleven', 'twentytwelve', 'twentyten' );
$this->assertEquals( $expected_themes, wc_get_core_supported_themes() );
}
/**
* Test wc_get_base_location().
*