Merge pull request #17683 from woocommerce/feature/unsupported-theme

Unsupported theme enhancements
This commit is contained in:
Claudiu Lodromanean 2017-12-07 08:05:29 -08:00 committed by GitHub
commit 804c771296
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
38 changed files with 1696 additions and 1196 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

@ -3467,105 +3467,6 @@ 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

@ -145,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 {

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -682,7 +682,6 @@ p.demo_store,
color: $secondarytext;
background-color: $secondary;
border: 0;
white-space: nowrap;
display: inline-block;
background-image: none;
box-shadow: none;
@ -762,7 +761,6 @@ p.demo_store,
a.added_to_cart {
padding-top: 0.5em;
white-space: nowrap;
display: inline-block;
}

View File

@ -124,43 +124,4 @@
$( 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}),t(".woocommerce-thumbnail-cropping").on("change input","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);
!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);

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

@ -522,62 +522,6 @@ 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' :
@ -770,15 +714,6 @@ 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

@ -183,24 +183,6 @@ class WC_Settings_General extends WC_Settings_Page {
'type' => 'checkbox',
),
array(
'title' => __( 'Store notice', 'woocommerce' ),
'desc' => __( 'Enable site-wide store notice text', 'woocommerce' ),
'id' => 'woocommerce_demo_store',
'default' => 'no',
'type' => 'checkbox',
),
array(
'title' => __( 'Store notice text', 'woocommerce' ),
'desc' => '',
'id' => 'woocommerce_demo_store_notice',
'default' => __( 'This is a demo store for testing purposes &mdash; no orders shall be fulfilled.', 'woocommerce' ),
'type' => 'textarea',
'css' => 'width:350px; height: 65px;',
'autoload' => false,
),
array( 'type' => 'sectionend', 'id' => 'general_options' ),
array( 'title' => __( 'Currency options', 'woocommerce' ), 'type' => 'title', 'desc' => __( 'The following options affect how prices are displayed on the frontend.', 'woocommerce' ), 'id' => 'pricing_options' ),

View File

@ -39,7 +39,6 @@ class WC_Settings_Products extends WC_Settings_Page {
public function get_sections() {
$sections = array(
'' => __( 'General', 'woocommerce' ),
'display' => __( 'Display', 'woocommerce' ),
'inventory' => __( 'Inventory', 'woocommerce' ),
'downloadable' => __( 'Downloadable products', 'woocommerce' ),
);
@ -75,155 +74,7 @@ class WC_Settings_Products extends WC_Settings_Page {
* @return array
*/
public function get_settings( $current_section = '' ) {
if ( 'display' === $current_section ) {
$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' ) ),
'id' => 'woocommerce_shop_page_id',
'type' => 'single_select_page',
'default' => '',
'class' => 'wc-enhanced-select-nostd',
'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' ),
'id' => 'woocommerce_shop_page_display',
'class' => 'wc-enhanced-select',
'css' => 'min-width:300px;',
'default' => '',
'type' => 'select',
'options' => array(
'' => __( 'Show products', 'woocommerce' ),
'subcategories' => __( 'Show categories', 'woocommerce' ),
'both' => __( 'Show categories &amp; products', 'woocommerce' ),
),
'desc_tip' => true,
),
array(
'title' => __( 'Default category display', 'woocommerce' ),
'desc' => __( 'This controls what is shown on category archives.', 'woocommerce' ),
'id' => 'woocommerce_category_archive_display',
'class' => 'wc-enhanced-select',
'css' => 'min-width:300px;',
'default' => '',
'type' => 'select',
'options' => array(
'' => __( 'Show products', 'woocommerce' ),
'subcategories' => __( 'Show subcategories', 'woocommerce' ),
'both' => __( 'Show subcategories &amp; products', 'woocommerce' ),
),
'desc_tip' => true,
),
array(
'title' => __( 'Default product sorting', 'woocommerce' ),
'desc' => __( 'This controls the default sort order of the catalog.', 'woocommerce' ),
'id' => 'woocommerce_default_catalog_orderby',
'class' => 'wc-enhanced-select',
'css' => 'min-width:300px;',
'default' => 'menu_order',
'type' => 'select',
'options' => apply_filters( 'woocommerce_default_catalog_orderby_options', array(
'menu_order' => __( 'Default sorting (custom ordering + name)', 'woocommerce' ),
'popularity' => __( 'Popularity (sales)', 'woocommerce' ),
'rating' => __( 'Average rating', 'woocommerce' ),
'date' => __( 'Sort by most recent', 'woocommerce' ),
'price' => __( 'Sort by price (asc)', 'woocommerce' ),
'price-desc' => __( 'Sort by price (desc)', 'woocommerce' ),
) ),
'desc_tip' => true,
),
array(
'title' => __( 'Add to cart behaviour', 'woocommerce' ),
'desc' => __( 'Redirect to the cart page after successful addition', 'woocommerce' ),
'id' => 'woocommerce_cart_redirect_after_add',
'default' => 'no',
'type' => 'checkbox',
'checkboxgroup' => 'start',
),
array(
'desc' => __( 'Enable AJAX add to cart buttons on archives', 'woocommerce' ),
'id' => 'woocommerce_enable_ajax_add_to_cart',
'default' => 'yes',
'type' => 'checkbox',
'checkboxgroup' => 'end',
),
array(
'type' => 'sectionend',
'id' => 'catalog_options',
),
);
$theme_support = get_theme_support( 'woocommerce' );
$theme_support = is_array( $theme_support ) ? $theme_support[0]: false;
$image_settings = array(
array(
'title' => __( 'Product images', 'woocommerce' ),
'type' => 'title',
'desc' => __( 'These settings change how product images are displayed in your catalog.', 'woocommerce' ),
'id' => 'image_options',
),
'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' => 'text',
'custom_attributes' => array(
'size' => 3,
),
'suffix' => 'px',
'default' => 600,
'desc_tip' => true,
),
'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' => 'text',
'custom_attributes' => array(
'size' => 3,
),
'suffix' => 'px',
'default' => 300,
'desc_tip' => true,
),
array(
'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' => 'thumbnail_cropping',
'default' => '1:1',
'desc_tip' => false,
),
array(
'type' => 'sectionend',
'id' => 'image_options',
),
);
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 ) {
if ( 'inventory' === $current_section ) {
$settings = apply_filters( 'woocommerce_inventory_settings', array(
array(
@ -411,7 +262,91 @@ class WC_Settings_Products extends WC_Settings_Page {
));
} else {
$settings = apply_filters( 'woocommerce_products_general_settings', array(
$settings = apply_filters( 'woocommerce_product_settings', apply_filters( 'woocommerce_products_general_settings', array(
array(
'title' => __( 'Shop 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' ) ),
'id' => 'woocommerce_shop_page_id',
'type' => 'single_select_page',
'default' => '',
'class' => 'wc-enhanced-select-nostd',
'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' ),
'id' => 'woocommerce_shop_page_display',
'class' => 'wc-enhanced-select',
'css' => 'min-width:300px;',
'default' => '',
'type' => 'select',
'options' => array(
'' => __( 'Show products', 'woocommerce' ),
'subcategories' => __( 'Show categories', 'woocommerce' ),
'both' => __( 'Show categories &amp; products', 'woocommerce' ),
),
'desc_tip' => true,
),
array(
'title' => __( 'Default category display', 'woocommerce' ),
'desc' => __( 'This controls what is shown on category archives.', 'woocommerce' ),
'id' => 'woocommerce_category_archive_display',
'class' => 'wc-enhanced-select',
'css' => 'min-width:300px;',
'default' => '',
'type' => 'select',
'options' => array(
'' => __( 'Show products', 'woocommerce' ),
'subcategories' => __( 'Show subcategories', 'woocommerce' ),
'both' => __( 'Show subcategories &amp; products', 'woocommerce' ),
),
'desc_tip' => true,
),
array(
'title' => __( 'Default product sorting', 'woocommerce' ),
'desc' => __( 'This controls the default sort order of the catalog.', 'woocommerce' ),
'id' => 'woocommerce_default_catalog_orderby',
'class' => 'wc-enhanced-select',
'css' => 'min-width:300px;',
'default' => 'menu_order',
'type' => 'select',
'options' => apply_filters( 'woocommerce_default_catalog_orderby_options', array(
'menu_order' => __( 'Default sorting (custom ordering + name)', 'woocommerce' ),
'popularity' => __( 'Popularity (sales)', 'woocommerce' ),
'rating' => __( 'Average rating', 'woocommerce' ),
'date' => __( 'Sort by most recent', 'woocommerce' ),
'price' => __( 'Sort by price (asc)', 'woocommerce' ),
'price-desc' => __( 'Sort by price (desc)', 'woocommerce' ),
) ),
'desc_tip' => true,
),
array(
'title' => __( 'Add to cart behaviour', 'woocommerce' ),
'desc' => __( 'Redirect to the cart page after successful addition', 'woocommerce' ),
'id' => 'woocommerce_cart_redirect_after_add',
'default' => 'no',
'type' => 'checkbox',
'checkboxgroup' => 'start',
),
array(
'desc' => __( 'Enable AJAX add to cart buttons on archives', 'woocommerce' ),
'id' => 'woocommerce_enable_ajax_add_to_cart',
'default' => 'yes',
'type' => 'checkbox',
'checkboxgroup' => 'end',
),
array(
'type' => 'sectionend',
'id' => 'catalog_options',
),
array(
'title' => __( 'Measurements', 'woocommerce' ),
'type' => 'title',
@ -520,7 +455,7 @@ class WC_Settings_Products extends WC_Settings_Page {
'id' => 'product_rating_options',
),
));
) ) );
}
return apply_filters( 'woocommerce_get_settings_' . $this->id, $settings, $current_section );

View File

@ -256,6 +256,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(
@ -296,7 +304,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.
*
@ -64,9 +71,10 @@ class WC_Query {
public function init_query_vars() {
// Query vars to add to WP.
$this->query_vars = array(
'product-page' => '',
// Checkout actions.
'order-pay' => get_option( 'woocommerce_checkout_pay_endpoint', 'order-pay' ),
'order-received' => get_option( 'woocommerce_checkout_order_received_endpoint', 'order-received' ),
'order-pay' => get_option( 'woocommerce_checkout_pay_endpoint', 'order-pay' ),
'order-received' => get_option( 'woocommerce_checkout_order_received_endpoint', 'order-received' ),
// My account actions.
'orders' => get_option( 'woocommerce_myaccount_orders_endpoint', 'orders' ),
'view-order' => get_option( 'woocommerce_myaccount_view_order_endpoint', 'view-order' ),
@ -201,6 +209,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;
@ -334,17 +343,6 @@ class WC_Query {
$this->remove_product_query();
}
/**
* Search post excerpt.
*
* @deprecated 3.2.0 - Not needed anymore since WordPress 4.5.
* @param string $deprecated Deprecated.
*/
public function search_post_excerpt( $deprecated = '' ) {
wc_deprecated_function( 'WC_Query::search_post_excerpt', '3.2.0', 'Excerpt added to search query by default since WordPress 4.5.' );
return $deprecated;
}
/**
* WP SEO meta description.
*
@ -388,10 +386,15 @@ class WC_Query {
// 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 );
}
@ -412,27 +415,25 @@ 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.
*
* @param string $orderby Order by.
* @param string $order Sorting 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.
if ( ! $orderby ) {
$orderby_value = isset( $_GET['orderby'] ) ? wc_clean( wp_unslash( (string) $_GET['orderby'] ) ) : apply_filters( 'woocommerce_default_catalog_orderby', get_option( 'woocommerce_default_catalog_orderby' ) ); // WPCS: input var ok, CSRF ok.
$orderby_value = isset( $_GET['orderby'] ) ? wc_clean( (string) wp_unslash( $_GET['orderby'] ) ) : ''; // WPCS: sanitization ok, input var ok.
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 );
@ -443,51 +444,51 @@ class WC_Query {
$orderby = strtolower( $orderby );
$order = strtoupper( $order );
$args = array(
'orderby' => 'relevance',
'order' => 'DESC',
'meta_key' => '', // WPCS: slow query ok.
'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'] = ''; // WPCS: slow query ok.
}
switch ( $orderby ) {
case 'rand':
$args['orderby'] = 'rand';
case 'menu_order' :
$args['orderby'] = 'menu_order title';
break;
case 'date':
case 'relevance' :
$args['orderby']= 'relevance';
$args['order'] = 'DESC';
break;
case 'rand' :
$args['orderby'] = 'rand'; // @codingStandardsIgnoreLine
break;
case 'date' :
$args['orderby'] = 'date ID';
$args['order'] = ( 'ASC' === $order ) ? 'ASC' : 'DESC';
break;
case 'price':
case 'price' :
if ( 'DESC' === $order ) {
add_filter( 'posts_clauses', array( $this, 'order_by_price_desc_post_clauses' ) );
} else {
add_filter( 'posts_clauses', array( $this, 'order_by_price_asc_post_clauses' ) );
}
break;
case 'popularity':
$args['meta_key'] = 'total_sales'; // WPCS: slow query ok.
case 'popularity' :
$args['meta_key'] = 'total_sales'; // @codingStandardsIgnoreLine
// 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'; // WPCS: slow query ok.
case 'rating' :
$args['meta_key'] = '_wc_average_rating'; // @codingStandardsIgnoreLine
$args['orderby'] = array(
'meta_value_num' => 'DESC',
'ID' => 'ASC',
);
break;
case 'title':
case 'title' :
$args['orderby'] = 'title';
$args['order'] = ( 'DESC' === $order ) ? 'DESC' : 'ASC';
break;
case 'relevance':
case 'relevance' :
$args['orderby'] = 'relevance';
$args['order'] = 'DESC';
break;
@ -569,30 +570,6 @@ class WC_Query {
return $args;
}
/**
* Order by rating post clauses.
*
* @deprecated 3.0.0
* @param array $args Query 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.
*
@ -692,35 +669,12 @@ class WC_Query {
}
/**
* Return a meta query for filtering by rating.
* Get the main query which product queries ran against.
*
* @deprecated 3.0.0 Replaced with taxonomy.
* @return array
*/
public function rating_filter_meta_query() {
return array();
}
/**
* Returns a meta query to handle product visibility.
*
* @deprecated 3.0.0 Replaced with taxonomy.
* @param string $compare Compare type.
* @return array
*/
public function visibility_meta_query( $compare = 'IN' ) {
return array();
}
/**
* Returns a meta query to handle product stock status.
*
* @deprecated 3.0.0 Replaced with taxonomy.
* @param string $status Status.
* @return array
*/
public function stock_status_meta_query( $status = 'instock' ) {
return array();
public static function get_main_query() {
return self::$product_query;
}
/**
@ -729,9 +683,7 @@ class WC_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();
$tax_query = isset( self::$product_query->tax_query, self::$product_query->tax_query->queries ) ? self::$product_query->tax_query->queries : array();
return $tax_query;
}
@ -742,9 +694,7 @@ class WC_Query {
* @return array
*/
public static function get_main_meta_query() {
global $wp_the_query;
$args = $wp_the_query->query_vars;
$args = self::$product_query->query_vars;
$meta_query = isset( $args['meta_query'] ) ? $args['meta_query'] : array();
return $meta_query;
@ -754,9 +704,9 @@ class WC_Query {
* Based on WP_Query::parse_search
*/
public static function get_main_search_query_sql() {
global $wp_the_query, $wpdb;
global $wpdb;
$args = $wp_the_query->query_vars;
$args = self::$product_query->query_vars;
$search_terms = isset( $args['search_terms'] ) ? $args['search_terms'] : array();
$sql = array();
@ -774,7 +724,7 @@ class WC_Query {
}
$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 ); // WPCS: db call ok, cache ok, unprepared SQL ok.
$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() ) {
@ -786,25 +736,22 @@ class WC_Query {
/**
* Layered Nav Init.
*
* @return array
*/
public static function get_layered_nav_chosen_attributes() {
if ( ! is_array( self::$_chosen_attributes ) ) {
self::$_chosen_attributes = array();
$attribute_taxonomies = wc_get_attribute_taxonomies();
if ( $attribute_taxonomies ) {
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: input var ok, CSRF ok.
$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( wp_unslash( $_GET[ 'query_type_' . $attribute ] ), array( 'and', 'or' ), true ) ? wc_clean( wp_unslash( $_GET[ 'query_type_' . $attribute ] ) ) : ''; // WPCS: input var ok, CSRF ok.
$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' );
}
@ -813,6 +760,73 @@ class WC_Query {
return self::$_chosen_attributes;
}
/**
* Remove the add-to-cart param from pagination urls.
*
* @param string $url URL.
* @return string
*/
public function remove_add_to_cart_pagination( $url ) {
return remove_query_arg( 'add-to-cart', $url );
}
// @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.
*
* @deprecated 3.0.0 Replaced with taxonomy.
* @return array
*/
public function rating_filter_meta_query() {
return array();
}
/**
* Returns a meta query to handle product visibility.
*
* @deprecated 3.0.0 Replaced with taxonomy.
* @param string $compare (default: 'IN')
* @return array
*/
public function visibility_meta_query( $compare = 'IN' ) {
return array();
}
/**
* Returns a meta query to handle product stock status.
*
* @deprecated 3.0.0 Replaced with taxonomy.
* @param string $status (default: 'instock')
* @return array
*/
public function stock_status_meta_query( $status = 'instock' ) {
return array();
}
/**
* Layered nav init.
*
@ -843,12 +857,21 @@ class WC_Query {
}
/**
* Remove the add-to-cart param from pagination urls.
* Search post excerpt.
*
* @param string $url URL.
* @return string
* @deprecated 3.2.0 - Not needed anymore since WordPress 4.5.
*/
public function remove_add_to_cart_pagination( $url ) {
return remove_query_arg( 'add-to-cart', $url );
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

@ -151,8 +151,6 @@ class WC_Shortcodes {
* @return string
*/
public static function product_categories( $atts ) {
global $woocommerce_loop;
if ( isset( $atts['number'] ) ) {
$atts['limit'] = $atts['number'];
}
@ -202,7 +200,8 @@ class WC_Shortcodes {
}
$columns = absint( $atts['columns'] );
$woocommerce_loop['columns'] = $columns;
wc_set_loop_prop( 'columns', $columns );
ob_start();
@ -498,6 +497,11 @@ class WC_Shortcodes {
$args['p'] = absint( $atts['id'] );
}
// Don't render titles if desired.
if ( isset( $atts['show_title'] ) && ! $atts['show_title'] ) {
remove_action( 'woocommerce_single_product_summary', 'woocommerce_template_single_title', 5 );
}
$single_product = new WP_Query( $args );
$preselected_id = '0';
@ -565,6 +569,11 @@ class WC_Shortcodes {
// @codingStandardsIgnoreEnd
wp_reset_postdata();
// Re-enable titles if they were removed.
if ( isset( $atts['show_title'] ) && ! $atts['show_title'] ) {
add_action( 'woocommerce_single_product_summary', 'woocommerce_template_single_title', 5 );
}
return '<div class="woocommerce">' . ob_get_clean() . '</div>';
}

View File

@ -1,26 +1,50 @@
<?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;
/**
* Store whether we're processing a product inside the_content filter.
*
* @var boolean
*/
private static $in_content_filter = false;
/**
* 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' );
// Supported themes.
if ( current_theme_supports( 'woocommerce' ) ) {
add_filter( 'template_include', array( __CLASS__, 'template_loader' ) );
add_filter( 'comments_template', array( __CLASS__, 'comments_template_loader' ) );
} else {
// Unsupported themes.
add_action( 'template_redirect', array( __CLASS__, 'unsupported_theme_init' ) );
}
}
/**
@ -35,7 +59,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 ) {
@ -71,15 +95,15 @@ class WC_Template_Loader {
if ( is_singular( 'product' ) ) {
$default_file = 'single-product.php';
} elseif ( is_product_taxonomy() ) {
$term = get_queried_object();
$object = get_queried_object();
if ( is_tax( 'product_cat' ) || is_tax( 'product_tag' ) ) {
$default_file = 'taxonomy-' . $term->taxonomy . '.php';
$default_file = 'taxonomy-' . $object->taxonomy . '.php';
} else {
$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 = '';
}
@ -94,31 +118,40 @@ class WC_Template_Loader {
* @return string[]
*/
private static function get_template_loader_files( $default_file ) {
$search_files = apply_filters( 'woocommerce_template_loader_files', array(), $default_file );
$search_files[] = 'woocommerce.php';
$templates = apply_filters( 'woocommerce_template_loader_files', array(), $default_file );
$templates[] = 'woocommerce.php';
if ( is_page_template() ) {
$search_files[] = get_page_template_slug();
$templates[] = get_page_template_slug();
}
if ( is_singular( 'product' ) ) {
$object = get_queried_object();
$name_decoded = urldecode( $object->post_name );
if ( $name_decoded !== $object->post_name ) {
$templates[] = "single-product-{$name_decoded}.php";
}
$templates[] = "single-product-{$object->post_name}.php";
}
if ( is_product_taxonomy() ) {
$term = get_queried_object();
$search_files[] = 'taxonomy-' . $term->taxonomy . '-' . $term->slug . '.php';
$search_files[] = WC()->template_path() . 'taxonomy-' . $term->taxonomy . '-' . $term->slug . '.php';
$search_files[] = 'taxonomy-' . $term->taxonomy . '.php';
$search_files[] = WC()->template_path() . 'taxonomy-' . $term->taxonomy . '.php';
$object = get_queried_object();
$templates[] = 'taxonomy-' . $object->taxonomy . '-' . $object->slug . '.php';
$templates[] = WC()->template_path() . 'taxonomy-' . $object->taxonomy . '-' . $object->slug . '.php';
$templates[] = 'taxonomy-' . $object->taxonomy . '.php';
$templates[] = WC()->template_path() . 'taxonomy-' . $object->taxonomy . '.php';
}
$search_files[] = $default_file;
$search_files[] = WC()->template_path() . $default_file;
$templates[] = $default_file;
$templates[] = WC()->template_path() . $default_file;
return array_unique( $search_files );
return array_unique( $templates );
}
/**
* Load comments template.
*
* @param mixed $template
* @param string $template template to load.
* @return string
*/
public static function comments_template_loader( $template ) {
@ -144,6 +177,315 @@ class WC_Template_Loader {
}
}
}
/**
* Unsupported theme compatibility methods.
*/
/**
* Hook in methods to enhance the unsupported theme experience on pages.
*
* @since 3.3.0
*/
public static function unsupported_theme_init() {
if ( self::$shop_page_id ) {
if ( is_product_taxonomy() ) {
self::unsupported_theme_tax_archive_init();
} elseif ( is_product() ) {
self::unsupported_theme_product_page_init();
} else {
self::unsupported_theme_shop_page_init();
}
}
}
/**
* Hook in methods to enhance the unsupported theme experience on the Shop page.
*
* @since 3.3.0
*/
private static function unsupported_theme_shop_page_init() {
add_filter( 'the_content', array( __CLASS__, 'unsupported_theme_shop_content_filter' ), 10 );
add_filter( 'the_title', array( __CLASS__, 'unsupported_theme_title_filter' ), 10, 2 );
add_filter( 'comments_number', '__return_empty_string' );
}
/**
* Hook in methods to enhance the unsupported theme experience on Product pages.
*
* @since 3.3.0
*/
private static function unsupported_theme_product_page_init() {
add_filter( 'the_content', array( __CLASS__, 'unsupported_theme_product_content_filter' ), 10 );
add_filter( 'post_thumbnail_html', array( __CLASS__, 'unsupported_theme_single_featured_image_filter' ) );
add_filter( 'woocommerce_product_tabs', array( __CLASS__, 'unsupported_theme_remove_review_tab' ) );
remove_action( 'woocommerce_before_main_content', 'woocommerce_output_content_wrapper', 10 );
remove_action( 'woocommerce_after_main_content', 'woocommerce_output_content_wrapper_end', 10 );
add_theme_support( 'wc-product-gallery-zoom' );
add_theme_support( 'wc-product-gallery-lightbox' );
add_theme_support( 'wc-product-gallery-slider' );
}
/**
* Enhance the unsupported theme experience on Product Category and Attribute pages by rendering
* those pages using the single template and shortcode-based content. To do this we make a dummy
* post and set a shortcode as the post content. This approach is adapted from bbPress.
*
* @since 3.3.0
*/
private static function unsupported_theme_tax_archive_init() {
global $wp_query, $post;
$queried_object = get_queried_object();
$args = self::get_current_shop_view_args();
$shortcode_args = array(
'page' => $args->page,
'columns' => $args->columns,
'rows' => $args->rows,
'orderby' => '',
'order' => '',
'paginate' => true,
'cache' => false,
);
if ( is_product_category() ) {
$shortcode_args['category'] = sanitize_title( $queried_object->slug );
} elseif ( taxonomy_is_product_attribute( $queried_object->taxonomy ) ) {
$shortcode_args['attribute'] = sanitize_title( $queried_object->taxonomy );
$shortcode_args['terms'] = sanitize_title( $queried_object->slug );
} elseif ( is_product_tag() ) {
$shortcode_args['tag'] = sanitize_title( $queried_object->slug );
} else {
// Default theme archive for all other taxonomies.
return;
}
$shortcode = new WC_Shortcode_Products( $shortcode_args );
$shop_page = get_post( self::$shop_page_id );
$dummy_post_properties = array(
'ID' => 0,
'post_status' => 'publish',
'post_author' => $shop_page->post_author,
'post_parent' => 0,
'post_type' => 'page',
'post_date' => $shop_page->post_date,
'post_date_gmt' => $shop_page->post_date_gmt,
'post_modified' => $shop_page->post_modified,
'post_modified_gmt' => $shop_page->post_modified_gmt,
'post_content' => $shortcode->get_content(),
'post_title' => wc_clean( $queried_object->name ),
'post_excerpt' => '',
'post_content_filtered' => '',
'post_mime_type' => '',
'post_password' => '',
'post_name' => $queried_object->slug,
'guid' => '',
'menu_order' => 0,
'pinged' => '',
'to_ping' => '',
'ping_status' => '',
'comment_status' => 'closed',
'comment_count' => 0,
'filter' => 'raw',
);
// Set the $post global.
$post = new WP_Post( (object) $dummy_post_properties );
// Copy the new post global into the main $wp_query.
$wp_query->post = $post;
$wp_query->posts = array( $post );
// Prevent comments form from appearing.
$wp_query->post_count = 1;
$wp_query->is_404 = false;
$wp_query->is_page = true;
$wp_query->is_single = true;
$wp_query->is_archive = false;
$wp_query->is_tax = false;
// Prepare everything for rendering.
setup_postdata( $post );
remove_all_filters( 'the_content' );
remove_all_filters( 'the_excerpt' );
add_filter( 'template_include', array( __CLASS__, 'force_single_template_filter' ) );
}
/**
* Force the loading of one of the single templates instead of whatever template was about to be loaded.
*
* @since 3.3.0
* @param string $template Path to template.
* @return string
*/
public static function force_single_template_filter( $template ) {
$possible_templates = array(
'page',
'single',
'singular',
'index',
);
foreach ( $possible_templates as $possible_template ) {
$path = get_query_template( $possible_template );
if ( $path ) {
return $path;
}
}
return $template;
}
/**
* 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 unsupported_theme_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 unsupported_theme_shop_content_filter( $content ) {
global $wp_query;
if ( current_theme_supports( 'woocommerce' ) || ! is_main_query() ) {
return $content;
}
self::$in_content_filter = true;
// Remove the filter we're in to avoid nested calls.
remove_filter( 'the_content', array( __CLASS__, 'the_content_filter' ) );
// Unsupported theme shop page.
if ( is_page( self::$shop_page_id ) ) {
$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' ) );
}
self::$in_content_filter = false;
return $content;
}
/**
* 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 unsupported_theme_product_content_filter( $content ) {
global $wp_query;
if ( current_theme_supports( 'woocommerce' ) || ! is_main_query() ) {
return $content;
}
self::$in_content_filter = true;
// Remove the filter we're in to avoid nested calls.
remove_filter( 'the_content', array( __CLASS__, 'the_content_filter' ) );
if ( is_product() ) {
$content = do_shortcode( '[product_page id="' . get_the_ID() . '" show_title=0]' );
}
self::$in_content_filter = false;
return $content;
}
/**
* Prevent the main featured image on product pages because there will be another featured image
* in the gallery.
*
* @since 3.3.0
* @param string $html Img element HTML.
* @return string
*/
public static function unsupported_theme_single_featured_image_filter( $html ) {
if ( self::$in_content_filter || ! is_product() || ! is_main_query() ) {
return $html;
}
return '';
}
/**
* Remove the Review tab and just use the regular comment form.
*
* @param array $tabs Tab info.
* @return array
*/
public static function unsupported_theme_remove_review_tab( $tabs ) {
unset( $tabs['reviews'] );
return $tabs;
}
}
WC_Template_Loader::init();
add_action( 'init', array( 'WC_Template_Loader', 'init' ) );

View File

@ -337,6 +337,7 @@ final class WooCommerce {
include_once( WC_ABSPATH . 'includes/class-wc-background-emailer.php' );
include_once( WC_ABSPATH . 'includes/class-wc-discounts.php' );
include_once( WC_ABSPATH . 'includes/class-wc-cart-totals.php' );
include_once( WC_ABSPATH . 'includes/customizer/class-wc-customizer.php' );
include_once( WC_ABSPATH . 'includes/class-wc-regenerate-images.php' ); // Image regeneration class.
/**
@ -400,13 +401,11 @@ final class WooCommerce {
}
/**
* Include classes sfor theme support.
* Include classes for 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':

View File

@ -0,0 +1,65 @@
<?php
/**
* Custom control for radio buttons with nested options.
*
* Used for our image cropping settings.
*
* @version 3.3.0
* @package WooCommerce
* @author WooCommerce
*/
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
/**
* WC_Customizer_Control_Cropping class.
*/
class WC_Customizer_Control_Cropping extends WP_Customize_Control {
/**
* Declare the control type.
*
* @var string
*/
public $type = 'woocommerce-cropping-control';
/**
* Render control.
*/
public function render_content() {
if ( empty( $this->choices ) ) {
return;
}
$value = $this->value( 'cropping' );
$custom_width = $this->value( 'custom_width' );
$custom_height = $this->value( 'custom_height' );
?>
<span class="customize-control-title">
<?php echo esc_html( $this->label ); ?>
</span>
<?php if ( ! empty( $this->description ) ) : ?>
<span class="description customize-control-description"><?php echo esc_html( $this->description ); ?></span>
<?php endif; ?>
<ul id="input_<?php echo esc_attr( $this->id ); ?>" class="woocommerce-cropping-control">
<?php foreach ( $this->choices as $key => $radio ) : ?>
<li>
<input type="radio" name="<?php echo esc_attr( $this->id ); ?>" value="<?php echo esc_attr( $key ); ?>" id="<?php echo esc_attr( $this->id . $key ); ?>" <?php $this->link( 'cropping' ); ?> <?php checked( $value, $key ); ?> />
<label for="<?php echo esc_attr( $this->id . $key ); ?>"><?php echo esc_html( $radio['label'] ); ?><br/><span class="description"><?php echo esc_html( $radio['description'] ); ?></span></label>
<?php if ( 'custom' === $key ) : ?>
<span class="woocommerce-cropping-control-aspect-ratio">
<input type="text" pattern="\d*" size="3" value="<?php echo esc_attr( $custom_width ); ?>" <?php $this->link( 'custom_width' ); ?> /> : <input type="text" pattern="\d*" size="3" value="<?php echo esc_attr( $custom_height ); ?>" <?php $this->link( 'custom_height' ); ?> />
</span>
<?php endif; ?>
</li>
<?php endforeach; ?>
</ul>
<?php
}
}

View File

@ -0,0 +1,386 @@
<?php
/**
* Adds options to the customizer for WooCommerce.
*
* @version 3.3.0
* @package WooCommerce
* @author WooCommerce
*/
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
/**
* WC_Customizer class.
*/
class WC_Customizer {
/**
* Constructor.
*/
public function __construct() {
add_action( 'customize_register', array( $this, 'add_sections' ) );
add_action( 'customize_controls_print_styles', array( $this, 'add_styles' ) );
add_action( 'customize_controls_print_scripts', array( $this, 'add_scripts' ), 30 );
}
/**
* Add settings to the customizer.
*
* @param WP_Customize_Manager $wp_customize Theme Customizer object.
*/
public function add_sections( $wp_customize ) {
$wp_customize->add_panel( 'woocommerce', array(
'priority' => 200,
'capability' => 'manage_woocommerce',
'theme_supports' => '',
'title' => __( 'WooCommerce', 'woocommerce' ),
) );
$this->add_store_notice_section( $wp_customize );
$this->add_product_grid_section( $wp_customize );
$this->add_product_images_section( $wp_customize );
}
/**
* CSS styles to improve our form.
*/
public function add_styles() {
?>
<style type="text/css">
.woocommerce-cropping-control {
margin: 0 40px 1em 0;
padding: 0;
display:inline-block;
vertical-align: top;
}
.woocommerce-cropping-control input[type=radio] {
margin-top: 1px;
}
.woocommerce-cropping-control span.woocommerce-cropping-control-aspect-ratio {
margin-top: .5em;
display:block;
}
.woocommerce-cropping-control span.woocommerce-cropping-control-aspect-ratio input {
width: auto;
display: inline-block;
}
</style>
<?php
}
/**
* Scripts to improve our form.
*/
public function add_scripts() {
?>
<script type="text/javascript">
jQuery( document ).ready( function( $ ) {
$( document.body ).on( 'change', '.woocommerce-cropping-control input[type="radio"]', function() {
var $wrapper = $( this ).closest( '.woocommerce-cropping-control' ),
value = $wrapper.find( 'input:checked' ).val();
if ( 'custom' === value ) {
$wrapper.find( '.woocommerce-cropping-control-aspect-ratio' ).slideDown( 200 );
} else {
$wrapper.find( '.woocommerce-cropping-control-aspect-ratio' ).hide();
}
return false;
} );
wp.customize.bind( 'ready', function() { // Ready?
$( '.woocommerce-cropping-control' ).find( 'input:checked' ).change();
} );
} );
</script>
<?php
}
/**
* Should our settings show?
*
* @return boolean
*/
public function is_active() {
return is_woocommerce() || wc_post_content_has_shortcode( 'products' ) || ! current_theme_supports( 'woocommerce' );
}
/**
* Store notice section.
*
* @param WP_Customize_Manager $wp_customize Theme Customizer object.
*/
private function add_store_notice_section( $wp_customize ) {
$wp_customize->add_section(
'woocommerce_store_notice',
array(
'title' => __( 'Store Notice', 'woocommerce' ),
'priority' => 10,
'panel' => 'woocommerce',
)
);
$wp_customize->add_setting(
'woocommerce_demo_store',
array(
'default' => 'no',
'type' => 'option',
'capability' => 'manage_woocommerce',
'sanitize_callback' => 'wc_bool_to_string',
'sanitize_js_callback' => 'wc_string_to_bool',
)
);
$wp_customize->add_setting(
'woocommerce_demo_store_notice',
array(
'default' => __( 'This is a demo store for testing purposes &mdash; no orders shall be fulfilled.', 'woocommerce' ),
'type' => 'option',
'capability' => 'manage_woocommerce',
'sanitize_callback' => 'wp_kses_post',
)
);
$wp_customize->add_control(
'woocommerce_demo_store_notice',
array(
'label' => __( 'Store notice', 'woocommerce' ),
'description' => __( 'If enabled, this text will be shown site-wide. You can use it to show events or promotions to visitors!', 'woocommerce' ),
'section' => 'woocommerce_store_notice',
'settings' => 'woocommerce_demo_store_notice',
'type' => 'textarea',
)
);
$wp_customize->add_control(
'woocommerce_demo_store',
array(
'label' => __( 'Enable store notice', 'woocommerce' ),
'section' => 'woocommerce_store_notice',
'settings' => 'woocommerce_demo_store',
'type' => 'checkbox',
)
);
}
/**
* Product grid section.
*
* @param WP_Customize_Manager $wp_customize Theme Customizer object.
*/
public function add_product_grid_section( $wp_customize ) {
if ( has_filter( 'loop_shop_columns' ) ) {
return;
}
$theme_support = get_theme_support( 'woocommerce' );
$theme_support = is_array( $theme_support ) ? $theme_support[0]: false;
$wp_customize->add_section(
'woocommerce_product_grid',
array(
'title' => __( 'Product Grid', 'woocommerce' ),
'priority' => 10,
'active_callback' => array( $this, 'is_active' ),
'panel' => 'woocommerce',
)
);
$wp_customize->add_setting(
'woocommerce_catalog_columns',
array(
'default' => 3,
'type' => 'option',
'capability' => 'manage_woocommerce',
'sanitize_callback' => 'absint',
'sanitize_js_callback' => 'absint',
)
);
$wp_customize->add_control(
'woocommerce_catalog_columns',
array(
'label' => __( 'Products per row', 'woocommerce' ),
'description' => __( 'How many products should be shown per row?', 'woocommerce' ),
'section' => 'woocommerce_product_grid',
'settings' => 'woocommerce_catalog_columns',
'type' => 'number',
'input_attrs' => 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,
),
)
);
$wp_customize->add_setting(
'woocommerce_catalog_rows',
array(
'default' => 4,
'type' => 'option',
'capability' => 'manage_woocommerce',
'sanitize_callback' => 'absint',
'sanitize_js_callback' => 'absint',
)
);
$wp_customize->add_control(
'woocommerce_catalog_rows',
array(
'label' => __( 'Rows per page', 'woocommerce' ),
'description' => __( 'How many rows of products should be shown per page?', 'woocommerce' ),
'section' => 'woocommerce_product_grid',
'settings' => 'woocommerce_catalog_rows',
'type' => 'number',
'input_attrs' => 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,
),
)
);
}
/**
* Product images section.
*
* @param WP_Customize_Manager $wp_customize Theme Customizer object.
*/
private function add_product_images_section( $wp_customize ) {
$theme_support = get_theme_support( 'woocommerce' );
$theme_support = is_array( $theme_support ) ? $theme_support[0]: false;
$wp_customize->add_section(
'woocommerce_product_images',
array(
'title' => __( 'Product Images', 'woocommerce' ),
'priority' => 20,
'active_callback' => array( $this, 'is_active' ),
'panel' => 'woocommerce',
)
);
if ( ! isset( $theme_support['single_image_width'] ) ) {
$wp_customize->add_setting(
'single_image_width',
array(
'default' => 600,
'type' => 'option',
'capability' => 'manage_woocommerce',
'sanitize_callback' => 'absint',
'sanitize_js_callback' => 'absint',
)
);
$wp_customize->add_control(
'single_image_width',
array(
'label' => __( 'Main image width', 'woocommerce' ),
'description' => __( 'This is the width used by the main image on single product pages. These images will remain uncropped.', 'woocommerce' ),
'section' => 'woocommerce_product_images',
'settings' => 'single_image_width',
'type' => 'number',
'input_attrs' => array(
'min' => 0,
'step' => 1,
),
)
);
}
if ( ! isset( $theme_support['thumbnail_image_width'] ) ) {
$wp_customize->add_setting(
'thumbnail_image_width',
array(
'default' => 300,
'type' => 'option',
'capability' => 'manage_woocommerce',
'sanitize_callback' => 'absint',
'sanitize_js_callback' => 'absint',
)
);
$wp_customize->add_control(
'thumbnail_image_width',
array(
'label' => __( 'Thumbnail width', 'woocommerce' ),
'description' => __( 'This size is used for product archives and product listings.', 'woocommerce' ),
'section' => 'woocommerce_product_images',
'settings' => 'thumbnail_image_width',
'type' => 'number',
'input_attrs' => array( 'min' => 0, 'step' => 1 ),
)
);
}
include_once( WC_ABSPATH . 'includes/customizer/class-wc-customizer-control-cropping.php' );
$wp_customize->add_setting(
'woocommerce_thumbnail_cropping',
array(
'default' => '1:1',
'type' => 'option',
'capability' => 'manage_woocommerce',
'sanitize_callback' => 'wc_clean',
)
);
$wp_customize->add_setting(
'woocommerce_thumbnail_cropping_custom_width',
array(
'default' => '4',
'type' => 'option',
'capability' => 'manage_woocommerce',
'sanitize_callback' => 'absint',
'sanitize_js_callback' => 'absint',
)
);
$wp_customize->add_setting(
'woocommerce_thumbnail_cropping_custom_height',
array(
'default' => '3',
'type' => 'option',
'capability' => 'manage_woocommerce',
'sanitize_callback' => 'absint',
'sanitize_js_callback' => 'absint',
)
);
$wp_customize->add_control(
new WC_Customizer_Control_Cropping(
$wp_customize,
'woocommerce_thumbnail_cropping',
array(
'section' => 'woocommerce_product_images',
'settings' => array(
'cropping' => 'woocommerce_thumbnail_cropping',
'custom_width' => 'woocommerce_thumbnail_cropping_custom_width',
'custom_height' => 'woocommerce_thumbnail_cropping_custom_height',
),
'label' => __( 'Thumbnail cropping', 'woocommerce' ),
'choices' => array(
'1:1' => array(
'label' => __( '1:1', 'woocommerce' ),
'description' => __( 'Images will be cropped into a square', 'woocommerce' ),
),
'custom' => array(
'label' => __( 'Custom', 'woocommerce' ),
'description' => __( 'Images will be cropped to a custom aspect ratio', 'woocommerce' ),
),
'uncropped' => array(
'label' => __( 'Uncropped', 'woocommerce' ),
'description' => __( 'Images will display using the aspect ratio in which they were uploaded', 'woocommerce' ),
),
),
)
)
);
}
}
new WC_Customizer();

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.
@ -124,8 +125,12 @@ class WC_Shortcode_Products {
'attribute' => '', // Single attribute slug.
'terms' => '', // Comma separated term slugs.
'terms_operator' => 'IN', // Operator to compare terms. Possible values are 'IN', 'NOT IN', 'AND'.
'tag' => '', // Comma separated tag slugs.
'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 +169,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( 'product-page', 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
@ -195,6 +217,9 @@ class WC_Shortcode_Products {
// Categories.
$this->set_categories_query_args( $query_args );
// Tags.
$this->set_tags_query_args( $query_args );
$query_args = apply_filters( 'woocommerce_shortcode_products_query', $query_args, $this->attributes, $this->type );
// Always query only IDs.
@ -263,11 +288,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'];
$query_args['meta_key'] = $ordering_args['meta_key']; // @codingStandardsIgnoreLine
$query_args['tax_query'][] = array(
'taxonomy' => 'product_cat',
'terms' => array_map( 'sanitize_title', explode( ',', $this->attributes['category'] ) ),
@ -277,6 +297,23 @@ class WC_Shortcode_Products {
}
}
/**
* Set tags query args.
*
* @since 3.3.0
* @param array $query_args Query args.
*/
protected function set_tags_query_args( &$query_args ) {
if ( ! empty( $this->attributes['tag'] ) ) {
$query_args['tax_query'][] = array(
'taxonomy' => 'product_tag',
'terms' => array_map( 'sanitize_title', explode( ',', $this->attributes['tag'] ) ),
'field' => 'slug',
'operator' => 'IN',
);
}
}
/**
* Set sale products query args.
*
@ -451,35 +488,44 @@ class WC_Shortcode_Products {
}
/**
* Get products IDs.
* Run the query and return an array of data, including queried ids and pagination information.
*
* @since 3.2.4
* @return array
* @since 3.3.0
* @return object Object with the following props; ids, per_page, found_posts, max_num_pages, current_page
*/
protected function get_products_ids() {
protected function get_query_results() {
$transient_name = $this->get_transient_name();
$ids = get_transient( $transient_name );
$cache = wc_string_to_bool( $this->attributes['cache'] ) === true;
$results = $cache ? get_transient( $transient_name ) : false;
if ( false === $ids ) {
if ( false === $results ) {
if ( 'top_rated_products' === $this->type ) {
add_filter( 'posts_clauses', array( __CLASS__, 'order_by_rating_post_clauses' ) );
$products = new WP_Query( $this->query_args );
$query = new WP_Query( $this->query_args );
remove_filter( 'posts_clauses', array( __CLASS__, 'order_by_rating_post_clauses' ) );
} else {
$products = new WP_Query( $this->query_args );
$query = new WP_Query( $this->query_args );
}
$ids = wp_parse_id_list( $products->posts );
$paginated = ! $query->get( 'no_found_rows' );
set_transient( $transient_name, $ids, DAY_IN_SECONDS * 30 );
$results = (object) array(
'ids' => wp_parse_id_list( $query->posts ),
'total' => $paginated ? (int) $query->found_posts : count( $query->posts ),
'total_pages' => $paginated ? (int) $query->max_num_pages : 1,
'per_page' => (int) $query->get( 'posts_per_page' ),
'current_page' => $paginated ? (int) max( 1, $query->get( 'paged', 1 ) ) : 1,
);
if ( $cache ) {
set_transient( $transient_name, $results, DAY_IN_SECONDS * 30 );
}
}
// Remove ordering query arguments.
if ( ! empty( $this->attributes['category'] ) ) {
WC()->query->remove_ordering_args();
}
return $ids;
return $results;
}
/**
@ -489,53 +535,65 @@ class WC_Shortcode_Products {
* @return string
*/
protected function product_loop() {
global $woocommerce_loop;
$columns = absint( $this->attributes['columns'] );
$classes = $this->get_wrapper_classes( $columns );
$woocommerce_loop['columns'] = $columns;
$woocommerce_loop['name'] = $this->type;
$products_ids = $this->get_products_ids();
$columns = absint( $this->attributes['columns'] );
$classes = $this->get_wrapper_classes( $columns );
$products = $this->get_query_results();
ob_start();
if ( $products_ids ) {
if ( $products && $products->ids ) {
// Prime meta cache to reduce future queries.
update_meta_cache( 'post', $products_ids );
update_object_term_cache( $products_ids, 'product' );
update_meta_cache( 'post', $products->ids );
update_object_term_cache( $products->ids, 'product' );
// Setup the loop.
wc_setup_loop( array(
'columns' => $columns,
'name' => $this->type,
'is_shortcode' => true,
'is_search' => false,
'is_paginated' => wc_string_to_bool( $this->attributes['paginate'] ),
'total' => $products->total,
'total_pages' => $products->total_pages,
'per_page' => $products->per_page,
'current_page' => $products->current_page,
) );
$original_post = $GLOBALS['post'];
do_action( "woocommerce_shortcode_before_{$this->type}_loop", $this->attributes );
do_action( 'woocommerce_before_shop_loop' );
woocommerce_product_loop_start();
foreach ( $products_ids as $product_id ) {
$GLOBALS['post'] = get_post( $product_id ); // WPCS: override ok.
setup_postdata( $GLOBALS['post'] );
if ( wc_get_loop_prop( 'total' ) ) {
foreach ( $products->ids as $product_id ) {
$GLOBALS['post'] = get_post( $product_id ); // WPCS: override ok.
setup_postdata( $GLOBALS['post'] );
// Set custom product visibility when quering hidden products.
add_action( 'woocommerce_product_is_visible', array( $this, 'set_product_as_visible' ) );
// Set custom product visibility when quering hidden products.
add_action( 'woocommerce_product_is_visible', array( $this, 'set_product_as_visible' ) );
// Render product template.
wc_get_template_part( 'content', 'product' );
// Render product template.
wc_get_template_part( 'content', 'product' );
// Restore product visibility.
remove_action( 'woocommerce_product_is_visible', array( $this, 'set_product_as_visible' ) );
// Restore product visibility.
remove_action( 'woocommerce_product_is_visible', array( $this, 'set_product_as_visible' ) );
}
}
$GLOBALS['post'] = $original_post; // WPCS: override ok.
woocommerce_product_loop_end();
do_action( 'woocommerce_after_shop_loop' );
do_action( "woocommerce_shortcode_after_{$this->type}_loop", $this->attributes );
wp_reset_postdata();
wc_reset_loop();
} else {
do_action( "woocommerce_shortcode_{$this->type}_loop_no_results", $this->attributes );
}
woocommerce_reset_loop();
return '<div class="' . esc_attr( implode( ' ', $classes ) ) . '">' . ob_get_clean() . '</div>';
}

View File

@ -260,7 +260,7 @@ if ( ! function_exists( 'is_store_notice_showing' ) ) {
* @return bool
*/
function is_store_notice_showing() {
return 'no' !== get_option( 'woocommerce_demo_store' );
return 'no' !== get_option( 'woocommerce_demo_store', 'no' );
}
}

View File

@ -688,8 +688,8 @@ function wc_get_image_size( $image_size ) {
$image_size = $size['width'] . '_' . $size['height'];
} elseif ( in_array( $image_size, array( 'single', 'shop_single', 'woocommerce_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' ];
if ( isset( $theme_support['single_image_width'] ) ) {
$size['width'] = $theme_support['single_image_width'];
} else {
$size['width'] = get_option( 'woocommerce_single_image_width', 600 );
}
@ -698,8 +698,8 @@ function wc_get_image_size( $image_size ) {
$image_size = 'single';
} elseif ( in_array( $image_size, array( 'thumbnail', 'shop_thumbnail', 'shop_catalog', 'woocommerce_thumbnail' ), 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' ];
if ( isset( $theme_support['thumbnail_image_width'] ) ) {
$size['width'] = $theme_support['thumbnail_image_width'];
} else {
$size['width'] = get_option( 'woocommerce_thumbnail_image_width', 300 );
}
@ -709,11 +709,16 @@ function wc_get_image_size( $image_size ) {
if ( 'uncropped' === $cropping ) {
$size['height'] = 9999999999;
$size['crop'] = 0;
} elseif ( 'custom' === $cropping ) {
$width = max( 1, get_option( 'woocommerce_thumbnail_cropping_custom_width', '4' ) );
$height = max( 1, get_option( 'woocommerce_thumbnail_cropping_custom_width', '3' ) );
$size['height'] = round( ( $size['width'] / $width ) * $height );
$size['crop'] = 1;
} 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 );
$width = max( 1, current( $cropping_split ) );
$height = max( 1, end( $cropping_split ) );
$size['height'] = round( ( $size['width'] / $width ) * $height );
$size['crop'] = 1;
}
$image_size = 'thumbnail';

View File

@ -20,7 +20,7 @@ if ( ! defined( 'ABSPATH' ) ) {
function wc_template_redirect() {
global $wp_query, $wp;
if ( ! empty( $_GET['page_id'] ) && '' === get_option( 'permalink_structure' ) && wc_get_page_id( 'shop' ) === absint( $_GET['page_id'] ) ) { // WPCS: input var ok, CSRF ok.
if ( ! empty( $_GET['page_id'] ) && '' === get_option( 'permalink_structure' ) && wc_get_page_id( 'shop' ) === absint( $_GET['page_id'] ) && get_post_type_archive_link( 'product' ) ) {
// When default permalinks are enabled, redirect shop page to post type archive url.
wp_safe_redirect( get_post_type_archive_link( 'product' ) );
@ -148,54 +148,81 @@ function wc_setup_product_data( $post ) {
}
add_action( 'the_post', 'wc_setup_product_data' );
if ( ! function_exists( 'woocommerce_reset_loop' ) ) {
/**
* Reset the loop's index and columns when we're done outputting a product loop.
*/
function woocommerce_reset_loop() {
$GLOBALS['woocommerce_loop'] = array(
'loop' => '',
'columns' => '',
'name' => '',
);
/**
* Sets up the woocommerce_loop global from the passed args or from the main query.
*
* @since 3.3.0
* @param array $args Args to pass into the global.
*/
function wc_setup_loop( $args = array() ) {
if ( isset( $GLOBALS['woocommerce_loop'] ) ) {
return; // If the loop has already been setup, bail.
}
$default_args = array(
'loop' => 0,
'columns' => wc_get_default_products_per_row(),
'name' => '',
'is_shortcode' => false,
'is_paginated' => true,
'is_search' => false,
'is_filtered' => false,
'total' => 0,
'total_pages' => 0,
'per_page' => 0,
'current_page' => 1,
);
// If this is a main WC query, use global args as defaults.
if ( $GLOBALS['wp_query']->get( 'wc_query' ) ) {
$default_args = array_merge( $default_args, array(
'is_search' => $GLOBALS['wp_query']->is_search(),
'is_filtered' => is_filtered(),
'total' => $GLOBALS['wp_query']->found_posts,
'total_pages' => $GLOBALS['wp_query']->max_num_pages,
'per_page' => $GLOBALS['wp_query']->get( 'posts_per_page' ),
'current_page' => max( 1, $GLOBALS['wp_query']->get( 'paged', 1 ) ),
) );
}
$GLOBALS['woocommerce_loop'] = wp_parse_args( $args, $default_args );
}
add_filter( 'loop_end', 'woocommerce_reset_loop' );
add_action( 'woocommerce_before_shop_loop', 'wc_setup_loop' );
/**
* Products RSS Feed.
* Resets the woocommerce_loop global.
*
* @deprecated 2.6
* @access public
* @since 3.3.0
*/
function wc_products_rss_feed() {
// Product RSS.
if ( is_post_type_archive( 'product' ) || is_singular( 'product' ) ) {
function wc_reset_loop() {
unset( $GLOBALS['woocommerce_loop'] );
}
add_action( 'woocommerce_after_shop_loop', 'woocommerce_reset_loop', 999 );
$feed = get_post_type_archive_feed_link( 'product' );
/**
* Gets a property from the woocommerce_loop global.
*
* @since 3.3.0
* @param string $prop Prop to get.
* @param string $default Default if the prop does not exist.
* @return mixed
*/
function wc_get_loop_prop( $prop, $default = '' ) {
return isset( $GLOBALS['woocommerce_loop'], $GLOBALS['woocommerce_loop'][ $prop ] ) ? $GLOBALS['woocommerce_loop'][ $prop ] : $default;
}
echo '<link rel="alternate" type="application/rss+xml" title="' . esc_attr__( 'New products', 'woocommerce' ) . '" href="' . esc_url( $feed ) . '" />';
} elseif ( is_tax( 'product_cat' ) ) {
$term = get_term_by( 'slug', esc_attr( get_query_var( 'product_cat' ) ), 'product_cat' );
if ( $term ) {
$feed = add_query_arg( 'product_cat', $term->slug, get_post_type_archive_feed_link( 'product' ) );
/* translators: %s: category name */
echo '<link rel="alternate" type="application/rss+xml" title="' . esc_attr( sprintf( __( 'New products added to %s', 'woocommerce' ), $term->name ) ) . '" href="' . esc_url( $feed ) . '" />';
}
} elseif ( is_tax( 'product_tag' ) ) {
$term = get_term_by( 'slug', esc_attr( get_query_var( 'product_tag' ) ), 'product_tag' );
if ( $term ) {
$feed = add_query_arg( 'product_tag', $term->slug, get_post_type_archive_feed_link( 'product' ) );
/* translators: %s: tag name */
echo '<link rel="alternate" type="application/rss+xml" title="' . sprintf( esc_attr__( 'New products tagged %s', 'woocommerce' ), rawurlencode( $term->name ) ) . '" href="' . esc_url( $feed ) . '" />';
}
/**
* Sets a property in the woocommerce_loop global.
*
* @since 3.3.0
* @param string $prop Prop to set.
* @param string $value Value to set.
*/
function wc_set_loop_prop( $prop, $value = '' ) {
if ( ! isset( $GLOBALS['woocommerce_loop'] ) ) {
wc_setup_loop();
}
$GLOBALS['woocommerce_loop'][ $prop ] = $value;
}
/**
@ -277,26 +304,81 @@ function wc_product_cat_class( $class = '', $category = null ) {
}
/**
* Get classname for loops based on $woocommerce_loop global.
* 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 woocommerce loops.
*
* @since 2.6.0
* @return string
*/
function wc_get_loop_class() {
global $woocommerce_loop;
$loop_index = wc_get_loop_prop( 'loop', 0 );
$columns = wc_get_loop_prop( 'columns', wc_get_default_products_per_row() );
$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 ) );
$loop_index ++;
wc_set_loop_prop( 'loop', $loop_index );
if ( 0 === ( $woocommerce_loop['loop'] - 1 ) % $woocommerce_loop['columns'] || 1 === $woocommerce_loop['columns'] ) {
if ( 0 === ( $loop_index - 1 ) % $columns || 1 === $columns ) {
return 'first';
} elseif ( 0 === $woocommerce_loop['loop'] % $woocommerce_loop['columns'] ) {
} elseif ( 0 === $loop_index % $columns ) {
return 'last';
} else {
return '';
}
}
/**
* Get the classes for the product cat div.
*
@ -459,30 +541,22 @@ if ( ! function_exists( 'woocommerce_content' ) ) {
<?php woocommerce_product_loop_start(); ?>
<?php woocommerce_product_subcategories(); ?>
<?php while ( have_posts() ) : ?>
<?php the_post(); ?>
<?php wc_get_template_part( 'content', 'product' ); ?>
<?php endwhile; // end of the loop. ?>
<?php while ( have_posts() ) : ?>
<?php the_post(); ?>
<?php wc_get_template_part( 'content', 'product' ); ?>
<?php endwhile; // end of the loop. ?>
<?php woocommerce_product_loop_end(); ?>
<?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' ); ?>
<?php
endif;
}
}
}
@ -593,12 +667,17 @@ if ( ! function_exists( 'woocommerce_product_loop_start' ) ) {
*/
function woocommerce_product_loop_start( $echo = true ) {
ob_start();
$GLOBALS['woocommerce_loop']['loop'] = 0;
wc_set_loop_prop( 'loop', 0 );
wc_get_template( 'loop/loop-start.php' );
$loop_start = apply_filters( 'woocommerce_product_loop_start', ob_get_clean() );
if ( $echo ) {
echo ob_get_clean(); // WPCS: XSS ok.
echo $loop_start; // WPCS: XSS ok.
} else {
return ob_get_clean();
return $loop_start;
}
}
}
@ -616,10 +695,12 @@ if ( ! function_exists( 'woocommerce_product_loop_end' ) ) {
wc_get_template( 'loop/loop-end.php' );
$loop_end = apply_filters( 'woocommerce_product_loop_end', ob_get_clean() );
if ( $echo ) {
echo ob_get_clean(); // WPCS: XSS ok.
echo $loop_end; // WPCS: XSS ok.
} else {
return ob_get_clean();
return $loop_end;
}
}
}
@ -819,7 +900,16 @@ if ( ! function_exists( 'woocommerce_result_count' ) ) {
* Output the result count text (Showing x - x of x results).
*/
function woocommerce_result_count() {
wc_get_template( 'loop/result-count.php' );
if ( ! wc_get_loop_prop( 'is_paginated' ) || ! woocommerce_products_will_display() ) {
return;
}
$args = array(
'total' => wc_get_loop_prop( 'total' ),
'per_page' => wc_get_loop_prop( 'per_page' ),
'current' => wc_get_loop_prop( 'current_page' ),
);
wc_get_template( 'loop/result-count.php', $args );
}
}
@ -829,13 +919,10 @@ if ( ! function_exists( 'woocommerce_catalog_ordering' ) ) {
* Output the product sorting options.
*/
function woocommerce_catalog_ordering() {
global $wp_query;
if ( 1 === (int) $wp_query->found_posts || ! woocommerce_products_will_display() ) {
if ( ! wc_get_loop_prop( 'is_paginated' ) || ! woocommerce_products_will_display() ) {
return;
}
$orderby = isset( $_GET['orderby'] ) ? wc_clean( wp_unslash( $_GET['orderby'] ) ) : apply_filters( 'woocommerce_default_catalog_orderby', get_option( 'woocommerce_default_catalog_orderby' ) ); // WPCS: input var ok, CSRF ok.
$orderby = isset( $_GET['orderby'] ) ? wc_clean( wp_unslash( $_GET['orderby'] ) ) : apply_filters( 'woocommerce_default_catalog_orderby', get_option( 'woocommerce_default_catalog_orderby' ) );
$show_default_orderby = 'menu_order' === apply_filters( 'woocommerce_default_catalog_orderby', get_option( 'woocommerce_default_catalog_orderby' ) );
$catalog_orderby_options = apply_filters( 'woocommerce_catalog_orderby', array(
'menu_order' => __( 'Default sorting', 'woocommerce' ),
@ -846,10 +933,8 @@ if ( ! function_exists( 'woocommerce_catalog_ordering' ) ) {
'price-desc' => __( 'Sort by price: high to low', 'woocommerce' ),
) );
if ( $wp_query->is_search() ) {
$catalog_orderby_options = array_merge( array(
'relevance' => __( 'Relevance', 'woocommerce' ),
), $catalog_orderby_options );
if ( wc_get_loop_prop( 'is_search' ) ) {
$catalog_orderby_options = array_merge( array( 'relevance' => __( 'Relevance', 'woocommerce' ) ), $catalog_orderby_options );
unset( $catalog_orderby_options['menu_order'] );
if ( 'menu_order' === $orderby ) {
$orderby = 'relevance';
@ -875,10 +960,25 @@ if ( ! function_exists( 'woocommerce_catalog_ordering' ) ) {
if ( ! function_exists( 'woocommerce_pagination' ) ) {
/**
* Output the pagination.
*/
* Output the pagination. */
function woocommerce_pagination() {
wc_get_template( 'loop/pagination.php' );
if ( ! wc_get_loop_prop( 'is_paginated' ) || ! woocommerce_products_will_display() ) {
return;
}
$args = array(
'total' => wc_get_loop_prop( 'total_pages' ),
'current' => wc_get_loop_prop( 'current_page' ),
);
if ( wc_get_loop_prop( 'is_shortcode' ) ) {
$args['base'] = esc_url_raw( add_query_arg( 'product-page', '%#%', false ) );
$args['format'] = '?product-page = %#%';
} else {
$args['base'] = esc_url_raw( str_replace( 999999999, '%#%', remove_query_arg( 'add-to-cart', get_pagenum_link( 999999999, false ) ) ) );
$args['format'] = '';
}
wc_get_template( 'loop/pagination.php', $args );
}
}
@ -1127,18 +1227,6 @@ if ( ! function_exists( 'woocommerce_product_additional_information_tab' ) ) {
wc_get_template( 'single-product/tabs/additional-information.php' );
}
}
if ( ! function_exists( 'woocommerce_product_reviews_tab' ) ) {
/**
* Output the reviews tab content.
*
* @deprecated 2.4.0 Unused.
*/
function woocommerce_product_reviews_tab() {
wc_deprecated_function( 'woocommerce_product_reviews_tab', '2.4' );
}
}
if ( ! function_exists( 'woocommerce_default_product_tabs' ) ) {
/**
@ -1313,7 +1401,7 @@ if ( ! function_exists( 'woocommerce_related_products' ) ) {
* @param array $args Provided arguments.
*/
function woocommerce_related_products( $args = array() ) {
global $product, $woocommerce_loop;
global $product;
if ( ! $product ) {
return;
@ -1335,8 +1423,8 @@ if ( ! function_exists( 'woocommerce_related_products' ) ) {
$args['related_products'] = wc_products_array_orderby( $args['related_products'], $args['orderby'], $args['order'] );
// Set global loop values.
$woocommerce_loop['name'] = 'related';
$woocommerce_loop['columns'] = apply_filters( 'woocommerce_related_products_columns', $args['columns'] );
wc_set_loop_prop( 'name', 'related' );
wc_set_loop_prop( 'columns', apply_filters( 'woocommerce_related_products_columns', $args['columns'] ) );
wc_get_template( 'single-product/related.php', $args );
}
@ -1353,7 +1441,7 @@ if ( ! function_exists( 'woocommerce_upsell_display' ) ) {
* @param string $order Sort direction.
*/
function woocommerce_upsell_display( $limit = '-1', $columns = 4, $orderby = 'rand', $order = 'desc' ) {
global $product, $woocommerce_loop;
global $product;
if ( ! $product ) {
return;
@ -1365,8 +1453,9 @@ if ( ! function_exists( 'woocommerce_upsell_display' ) ) {
'orderby' => $orderby,
'columns' => $columns,
) );
$woocommerce_loop['name'] = 'up-sells';
$woocommerce_loop['columns'] = apply_filters( 'woocommerce_upsells_columns', isset( $args['columns'] ) ? $args['columns'] : $columns );
wc_set_loop_prop( 'name', 'up-sells' );
wc_set_loop_prop( 'columns', apply_filters( 'woocommerce_upsells_columns', isset( $args['columns'] ) ? $args['columns'] : $columns ) );
$orderby = apply_filters( 'woocommerce_upsells_orderby', isset( $args['orderby'] ) ? $args['orderby'] : $orderby );
$limit = apply_filters( 'woocommerce_upsells_total', isset( $args['posts_per_page'] ) ? $args['posts_per_page'] : $limit );
@ -1421,15 +1510,13 @@ if ( ! function_exists( 'woocommerce_cross_sell_display' ) ) {
* @param string $order (default: 'desc').
*/
function woocommerce_cross_sell_display( $limit = 2, $columns = 2, $orderby = 'rand', $order = 'desc' ) {
global $woocommerce_loop;
if ( is_checkout() ) {
return;
}
// Get visible cross sells then sort them at random.
$cross_sells = array_filter( array_map( 'wc_get_product', WC()->cart->get_cross_sells() ), 'wc_products_array_filter_visible' );
$woocommerce_loop['name'] = 'cross-sells';
$woocommerce_loop['columns'] = apply_filters( 'woocommerce_cross_sells_columns', $columns );
wc_set_loop_prop( 'name', 'cross-sells' );
wc_set_loop_prop( 'columns', apply_filters( 'woocommerce_cross_sells_columns', $columns ) );
// Handle orderby and limit results.
$orderby = apply_filters( 'woocommerce_cross_sells_orderby', $orderby );
@ -1626,73 +1713,51 @@ if ( ! function_exists( 'woocommerce_products_will_display' ) ) {
* @return bool
*/
function woocommerce_products_will_display() {
global $wpdb;
return 0 < wc_get_loop_prop( 'total', 0 );
}
}
if ( ! function_exists( 'woocommerce_maybe_show_product_subcategories' ) ) {
/**
* Maybe display categories before, or instead of, a product loop.
*
* @since 3.3.0
* @param string $loop_html HTML.
* @return string
*/
function woocommerce_maybe_show_product_subcategories( $loop_html ) {
// Don't show when filtering, searching or when on page > 1.
if ( 1 < wc_get_loop_prop( 'current_page' ) || wc_get_loop_prop( 'is_search' ) || wc_get_loop_prop( 'is_filtered' ) ) {
return $loop_html;
}
$parent_id = 0;
$display_type = '';
// Check categories are enabled and see what level to query.
if ( is_shop() ) {
return 'subcategories' !== get_option( 'woocommerce_shop_page_display' ) || is_search();
$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 ( ! is_product_taxonomy() ) {
return false;
}
// If displaying categories, append to the loop.
if ( '' !== $display_type ) {
ob_start();
woocommerce_product_subcategories( array(
'parent_id' => $parent_id,
) );
$loop_html .= ob_get_clean();
if ( is_search() || is_filtered() || is_paged() ) {
return true;
}
$term = get_queried_object();
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':
return true;
default:
// Default - no setting.
if ( get_option( 'woocommerce_category_archive_display' ) !== 'subcategories' ) {
return true;
}
break;
if ( 'subcategories' === $display_type ) {
wc_set_loop_prop( 'total', 0 );
}
}
// 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' );
$products_will_display = get_transient( $transient_name );
if ( false === $products_will_display ) {
$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: db call ok, 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;
}
}
set_transient( $transient_name, $products_will_display, DAY_IN_SECONDS * 30 );
return $products_will_display;
return $loop_html;
}
}
@ -1702,57 +1767,18 @@ if ( ! function_exists( 'woocommerce_product_subcategories' ) ) {
* Display product sub categories as thumbnails.
*
* @param array $args Arguments.
* @return null|boolean
* @return boolean
*/
function woocommerce_product_subcategories( $args = array() ) {
global $wp_query;
$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 ) {
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;
}
// 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;
case '':
if ( '' === get_option( 'woocommerce_category_archive_display' ) ) {
return;
}
break;
}
}
$args = wp_parse_args( $args, array(
'before' => '',
'after' => '',
'parent_id' => 0,
) );
// 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.
$product_categories = get_categories( apply_filters( 'woocommerce_product_subcategories_args', array(
'parent' => $parent_id,
'parent' => $args['parent_id'],
'menu_order' => 'ASC',
'hide_empty' => 0,
'hierarchical' => 1,
@ -1761,47 +1787,24 @@ if ( ! function_exists( 'woocommerce_product_subcategories' ) ) {
) ) );
if ( apply_filters( 'woocommerce_product_subcategories_hide_empty', true ) ) {
$product_categories = wp_list_filter( $product_categories, array(
'count' => 0,
), 'NOT' );
$product_categories = wp_list_filter( $product_categories, array( 'count' => 0 ), 'NOT' );
}
if ( $product_categories ) {
echo wp_kses_post( $before );
foreach ( $product_categories as $category ) {
wc_get_template( 'content-product_cat.php', array(
'category' => $category,
) );
}
// 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 );
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;
if ( ! $product_categories ) {
return false;
}
echo wp_kses_post( $args['before'] );
foreach ( $product_categories as $category ) {
wc_get_template( 'content-product_cat.php', array(
'category' => $category,
) );
}
echo wp_kses_post( $args['after'] );
return true;
}
}
@ -2694,3 +2697,35 @@ add_action( 'wp_head', 'wc_page_noindex' );
function wc_get_theme_slug_for_templates() {
return apply_filters( 'woocommerce_theme_slug_for_templates', get_option( 'template' ) );
}
/**
* Products RSS Feed.
*
* @deprecated 2.6
*/
function wc_products_rss_feed() {
wc_deprecated_function( 'wc_products_rss_feed', '2.6' );
}
if ( ! function_exists( 'woocommerce_reset_loop' ) ) {
/**
* Reset the loop's index and columns when we're done outputting a product loop.
*
* @deprecated 3.3
*/
function woocommerce_reset_loop() {
wc_reset_loop();
}
}
if ( ! function_exists( 'woocommerce_product_reviews_tab' ) ) {
/**
* Output the reviews tab content.
*
* @deprecated 2.4.0 Unused.
*/
function woocommerce_product_reviews_tab() {
wc_deprecated_function( 'woocommerce_product_reviews_tab', '2.4' );
}
}

View File

@ -66,6 +66,11 @@ add_action( 'woocommerce_sidebar', 'woocommerce_get_sidebar', 10 );
add_action( 'woocommerce_archive_description', 'woocommerce_taxonomy_archive_description', 10 );
add_action( 'woocommerce_archive_description', 'woocommerce_product_archive_description', 10 );
/**
* Product loop start.
*/
add_filter( 'woocommerce_product_loop_start', 'woocommerce_maybe_show_product_subcategories' );
/**
* Products Loop.
*

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( false ) ) ), $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( false ) ) ), $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

@ -13,118 +13,100 @@
* @see https://docs.woocommerce.com/document/template-structure/
* @author WooThemes
* @package WooCommerce/Templates
* @version 2.0.0
* @version 3.3.0
*/
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();
<?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,7 @@
* @see https://docs.woocommerce.com/document/template-structure/
* @author WooThemes
* @package WooCommerce/Templates
* @version 2.0.0
* @version 3.3.0
*/
?>
<ul class="products">
<ul class="products columns-<?php echo esc_attr( wc_get_loop_prop( '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,27 +13,25 @@
* @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;
}
?>
<nav class="woocommerce-pagination">
<?php
echo paginate_links( apply_filters( 'woocommerce_pagination_args', array(
'base' => esc_url_raw( str_replace( 999999999, '%#%', remove_query_arg( 'add-to-cart', get_pagenum_link( 999999999, false ) ) ) ),
'format' => '',
'base' => $base,
'format' => $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

@ -165,32 +165,6 @@ class Settings extends WC_REST_Unit_Test_Case {
$response = $this->server->dispatch( new WP_REST_Request( 'GET', '/wc/v2/settings/invalid' ) );
$this->assertEquals( 404, $response->get_status() );
// test getting a valid group
$response = $this->server->dispatch( new WP_REST_Request( 'GET', '/wc/v2/settings/general' ) );
$data = $response->get_data();
$this->assertEquals( 200, $response->get_status() );
$this->assertContains( array(
'id' => 'woocommerce_demo_store',
'label' => 'Store notice',
'description' => 'Enable site-wide store notice text',
'type' => 'checkbox',
'default' => 'no',
'value' => 'no',
'_links' => array(
'self' => array(
array(
'href' => rest_url( '/wc/v2/settings/general/woocommerce_demo_store' ),
),
),
'collection' => array(
array(
'href' => rest_url( '/wc/v2/settings/general' ),
),
),
),
), $data );
// test getting a valid group with settings attached to it
$response = $this->server->dispatch( new WP_REST_Request( 'GET', '/wc/v2/settings/test' ) );
$data = $response->get_data();

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,
'tag' => '',
);
$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,11 @@ class WC_Test_Shortcode_Products extends WC_Unit_Test_Case {
'terms_operator' => 'IN',
'visibility' => 'visible',
'class' => '',
'rows' => '',
'page' => 1,
'paginate' => false,
'cache' => true,
'tag' => '',
);
$this->assertEquals( $expected2, $shortcode2->get_attributes() );
}
@ -67,7 +77,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,
'fields' => 'ids',
@ -86,7 +96,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,
'fields' => 'ids',
@ -104,7 +114,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' ),
@ -122,7 +132,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',
@ -132,12 +142,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' => '',
'fields' => 'ids',
);
$expected4['tax_query'][] = array(
@ -163,9 +172,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,
'fields' => 'ids',
@ -185,7 +194,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',
@ -281,7 +290,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,