Update from master
This commit is contained in:
commit
a3c2dcd8f2
|
@ -1,5 +1,20 @@
|
|||
== Changelog ==
|
||||
|
||||
= 3.5.6 - 2019-03-07 =
|
||||
* Fix - Removes invalid product structured data from archives, and include more data on single product pages. #22925
|
||||
Product structured data should only be generated for visible data, and not on archives when there are single
|
||||
product pages available, as per the documentation.
|
||||
Since this change removes structured data from archives, the filters `woocommerce_structured_data_product_limit`
|
||||
and `woocommerce_structured_data_product_limited` have also been removed.
|
||||
To customize product structured data, for example adding custom fields or include on archives, see this article:
|
||||
https://github.com/woocommerce/woocommerce/wiki/Structured-data-for-products.
|
||||
* Fix - Fix last item in breadcrumb structured data, and include on shop page. #22925
|
||||
* Fix - Get insert ID before running actions in `_insert_tax_rate`. #22868
|
||||
* Fix - Add precision to tax in the discount class so min spend checks work correctly. #22888
|
||||
* Fix - Update troubleshooting link in failed order email. #22943
|
||||
* Fix - Update Flexslider to 2.7.2.
|
||||
* Fix - Fill user's account first name and last name only when those fields are empty. #22783
|
||||
|
||||
= 3.5.5 - 2019-02-20 =
|
||||
* Fix - Fix allow product low stock threshold be the WC settings default. #22777
|
||||
* Fix - Fix error on product category when sorting by multiple fields. #22066
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/* jshint node:true */
|
||||
module.exports = function( grunt ) {
|
||||
'use strict';
|
||||
const sass = require( 'node-sass' );
|
||||
var sass = require( 'node-sass' );
|
||||
|
||||
grunt.initConfig({
|
||||
|
||||
|
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
@ -4352,6 +4352,10 @@ img.help_tip {
|
|||
content: "\f111";
|
||||
}
|
||||
|
||||
&.marketplace-suggestions_options a::before {
|
||||
content: none;
|
||||
}
|
||||
|
||||
&.variations_options a::before {
|
||||
content: "\f509";
|
||||
}
|
||||
|
@ -5950,6 +5954,27 @@ table.bar_chart {
|
|||
}
|
||||
}
|
||||
|
||||
.post-type-product .woocommerce-BlankState,
|
||||
.post-type-shop_order .woocommerce-BlankState {
|
||||
max-width: 764px;
|
||||
text-align: center;
|
||||
margin: auto;
|
||||
|
||||
.woocommerce-BlankState-message {
|
||||
color: #444;
|
||||
font-size: 1.5em;
|
||||
margin: 0 auto 1em;
|
||||
}
|
||||
|
||||
.woocommerce-BlankState-message::before {
|
||||
font-size: 120px;
|
||||
}
|
||||
|
||||
.woocommerce-BlankState-buttons {
|
||||
margin-bottom: 4em;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Small screen optimisation
|
||||
*/
|
||||
|
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
@ -0,0 +1,315 @@
|
|||
/**
|
||||
* marketplace-suggestions.scss
|
||||
* Styling for in-product marketplace suggestions.
|
||||
*/
|
||||
|
||||
@import "mixins";
|
||||
@import "variables";
|
||||
|
||||
$suggestions-pale-gray: #ddd;
|
||||
$suggestions-metabox-pale-gray: #eee;
|
||||
|
||||
$suggestions-copy-text: #444;
|
||||
|
||||
a.suggestion-dismiss {
|
||||
border: none;
|
||||
box-shadow: none;
|
||||
color: $suggestions-pale-gray;
|
||||
}
|
||||
|
||||
a.suggestion-dismiss:hover {
|
||||
color: #aaa;
|
||||
}
|
||||
|
||||
a.suggestion-dismiss::before {
|
||||
|
||||
@include iconbeforedashicons( "\f335" );
|
||||
|
||||
font-size: 1.5em;
|
||||
}
|
||||
|
||||
#woocommerce-product-data ul.wc-tabs li.marketplace-suggestions_tab {
|
||||
|
||||
a span {
|
||||
margin: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.marketplace-suggestions-container.showing-suggestion {
|
||||
text-align: left;
|
||||
|
||||
.marketplace-suggestion-container {
|
||||
align-items: flex-start;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
|
||||
// Allows us to position the dismiss x button
|
||||
// relative to container on mobile.
|
||||
position: relative;
|
||||
|
||||
img.marketplace-suggestion-icon {
|
||||
height: 40px;
|
||||
margin: 0;
|
||||
margin-right: 1.5em;
|
||||
flex: 0 0 40px;
|
||||
}
|
||||
|
||||
.marketplace-suggestion-container-content {
|
||||
flex: 1 1 60%;
|
||||
|
||||
h4 {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
p {
|
||||
margin: 0;
|
||||
margin-top: 4px;
|
||||
color: $suggestions-copy-text;
|
||||
}
|
||||
}
|
||||
|
||||
.marketplace-suggestion-container-cta {
|
||||
flex: 1 1 30%;
|
||||
min-width: 160px;
|
||||
text-align: right;
|
||||
|
||||
.suggestion-dismiss {
|
||||
text-decoration: none;
|
||||
position: absolute;
|
||||
top: 1em;
|
||||
right: 1em;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@media screen and (min-width: 600px) {
|
||||
|
||||
.marketplace-suggestion-container {
|
||||
align-items: center;
|
||||
flex-direction: row;
|
||||
|
||||
img.marketplace-suggestion-icon {
|
||||
// display: inline-block;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.marketplace-suggestions-container.showing-suggestion[data-marketplace-suggestions-context="products-list-empty-header"],
|
||||
.marketplace-suggestions-container.showing-suggestion[data-marketplace-suggestions-context="products-list-empty-footer"],
|
||||
.marketplace-suggestions-container.showing-suggestion[data-marketplace-suggestions-context="product-edit-meta-tab-header"],
|
||||
.marketplace-suggestions-container.showing-suggestion[data-marketplace-suggestions-context="product-edit-meta-tab-footer"],
|
||||
.marketplace-suggestions-container.showing-suggestion[data-marketplace-suggestions-context="orders-list-empty-header"],
|
||||
.marketplace-suggestions-container.showing-suggestion[data-marketplace-suggestions-context="orders-list-empty-footer"] {
|
||||
|
||||
.marketplace-suggestion-container {
|
||||
|
||||
.marketplace-suggestion-container-content {
|
||||
|
||||
h4 {
|
||||
font-size: 1.1em;
|
||||
margin: 0;
|
||||
margin-bottom: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Additional breathing space margin under empty-state footer.
|
||||
.marketplace-suggestions-container.showing-suggestion[data-marketplace-suggestions-context="products-list-empty-footer"],
|
||||
.marketplace-suggestions-container.showing-suggestion[data-marketplace-suggestions-context="orders-list-empty-footer"] {
|
||||
|
||||
margin-bottom: 6em;
|
||||
}
|
||||
|
||||
|
||||
// Optimise footer suggestion layout for left-aligned CTA link button only.
|
||||
.marketplace-suggestions-container.showing-suggestion[data-marketplace-suggestions-context="products-list-empty-footer"],
|
||||
.marketplace-suggestions-container.showing-suggestion[data-marketplace-suggestions-context="product-edit-meta-tab-footer"],
|
||||
.marketplace-suggestions-container.showing-suggestion[data-marketplace-suggestions-context="orders-list-empty-footer"] {
|
||||
|
||||
.marketplace-suggestion-container {
|
||||
|
||||
flex-direction: row-reverse;
|
||||
|
||||
.marketplace-suggestion-container-cta {
|
||||
|
||||
text-align: left;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
.marketplace-suggestions-container.showing-suggestion[data-marketplace-suggestions-context="product-edit-meta-tab-header"],
|
||||
.marketplace-suggestions-container.showing-suggestion[data-marketplace-suggestions-context="product-edit-meta-tab-footer"],
|
||||
.marketplace-suggestions-container.showing-suggestion[data-marketplace-suggestions-context="product-edit-meta-tab-body"] {
|
||||
|
||||
.marketplace-suggestion-container {
|
||||
padding: 1em 1.5em;
|
||||
|
||||
.marketplace-suggestion-container-content {
|
||||
|
||||
p {
|
||||
padding: 0;
|
||||
line-height: 1.5;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.marketplace-suggestions-container.showing-suggestion[data-marketplace-suggestions-context="products-list-inline"] {
|
||||
|
||||
// hide by default (mobile first)
|
||||
display: none;
|
||||
|
||||
td:first-child {
|
||||
border-left: 4px solid $woocommerce;
|
||||
}
|
||||
|
||||
.marketplace-suggestion-container {
|
||||
padding: 0.5em 0 0.5em 1em;
|
||||
|
||||
img.marketplace-suggestion-icon {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
.marketplace-suggestion-container-content {
|
||||
|
||||
h4 {
|
||||
margin: 0;
|
||||
font-size: 14px;
|
||||
}
|
||||
}
|
||||
|
||||
.marketplace-suggestion-container-cta {
|
||||
|
||||
.suggestion-dismiss {
|
||||
position: relative;
|
||||
top: 4px;
|
||||
right: auto;
|
||||
margin-left: 1em;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@media screen and (min-width: 800px) {
|
||||
|
||||
// Display inline table suggestion on desktop only.
|
||||
// The table columns are dynamic, so there's no good way to style the row
|
||||
// content correctly when columns are hidden.
|
||||
display: table-row;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
.marketplace-suggestions-container.showing-suggestion[data-marketplace-suggestions-context="products-list-empty-header"],
|
||||
.marketplace-suggestions-container.showing-suggestion[data-marketplace-suggestions-context="products-list-empty-footer"],
|
||||
.marketplace-suggestions-container.showing-suggestion[data-marketplace-suggestions-context="orders-list-empty-header"],
|
||||
.marketplace-suggestions-container.showing-suggestion[data-marketplace-suggestions-context="orders-list-empty-footer"] {
|
||||
|
||||
.marketplace-suggestion-container {
|
||||
padding: 1.5em;
|
||||
}
|
||||
}
|
||||
|
||||
.marketplace-suggestions-container.showing-suggestion[data-marketplace-suggestions-context="products-list-empty-body"],
|
||||
.marketplace-suggestions-container.showing-suggestion[data-marketplace-suggestions-context="orders-list-empty-body"] {
|
||||
|
||||
.marketplace-suggestion-container {
|
||||
padding: 0.75em 1.5em;
|
||||
|
||||
&:first-child {
|
||||
padding-top: 1.5em;
|
||||
}
|
||||
|
||||
&:last-child {
|
||||
padding-bottom: 1.5em;
|
||||
}
|
||||
|
||||
.marketplace-suggestion-container-content {
|
||||
|
||||
p:last-child {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.marketplace-suggestions-container.showing-suggestion[data-marketplace-suggestions-context="products-list-empty-header"],
|
||||
.marketplace-suggestions-container.showing-suggestion[data-marketplace-suggestions-context="products-list-empty-footer"],
|
||||
.marketplace-suggestions-container.showing-suggestion[data-marketplace-suggestions-context="products-list-empty-body"],
|
||||
.marketplace-suggestions-container.showing-suggestion[data-marketplace-suggestions-context="orders-list-empty-header"],
|
||||
.marketplace-suggestions-container.showing-suggestion[data-marketplace-suggestions-context="orders-list-empty-footer"],
|
||||
.marketplace-suggestions-container.showing-suggestion[data-marketplace-suggestions-context="orders-list-empty-body"],
|
||||
.marketplace-suggestions-container.showing-suggestion[data-marketplace-suggestions-context="product-edit-meta-tab-header"],
|
||||
.marketplace-suggestions-container.showing-suggestion[data-marketplace-suggestions-context="product-edit-meta-tab-footer"],
|
||||
.marketplace-suggestions-container.showing-suggestion[data-marketplace-suggestions-context="product-edit-meta-tab-body"] {
|
||||
|
||||
// hide by default (mobile first)
|
||||
display: none;
|
||||
|
||||
.marketplace-suggestion-container .marketplace-suggestion-container-cta {
|
||||
|
||||
a.button {
|
||||
display: inline-block;
|
||||
min-width: 120px;
|
||||
text-align: center;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
a.linkout {
|
||||
font-size: 1.1em;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
a.linkout .dashicons {
|
||||
margin-left: 4px;
|
||||
bottom: 2px;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.suggestion-dismiss {
|
||||
position: relative;
|
||||
top: 5px;
|
||||
right: auto;
|
||||
margin-left: 1em;
|
||||
}
|
||||
}
|
||||
|
||||
@media screen and (min-width: 600px) {
|
||||
|
||||
// Display onboarding table suggestion on desktop only. (for now)
|
||||
// There's limited room on mobile, and there are edge-case
|
||||
// styling issues in some browsers.
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
.marketplace-suggestions-container.showing-suggestion[data-marketplace-suggestions-context="product-edit-meta-tab-header"],
|
||||
.marketplace-suggestions-container.showing-suggestion[data-marketplace-suggestions-context="product-edit-meta-tab-footer"] {
|
||||
|
||||
border: none;
|
||||
}
|
||||
|
||||
.marketplace-suggestions-container.showing-suggestion[data-marketplace-suggestions-context="product-edit-meta-tab-body"] {
|
||||
|
||||
border: none;
|
||||
border-top: 1px solid $suggestions-metabox-pale-gray;
|
||||
border-bottom: 1px solid $suggestions-metabox-pale-gray;
|
||||
}
|
||||
|
||||
.marketplace-suggestions-container.showing-suggestion[data-marketplace-suggestions-context="products-list-empty-header"],
|
||||
.marketplace-suggestions-container.showing-suggestion[data-marketplace-suggestions-context="products-list-empty-footer"],
|
||||
.marketplace-suggestions-container.showing-suggestion[data-marketplace-suggestions-context="products-list-empty-body"],
|
||||
.marketplace-suggestions-container.showing-suggestion[data-marketplace-suggestions-context="orders-list-empty-header"],
|
||||
.marketplace-suggestions-container.showing-suggestion[data-marketplace-suggestions-context="orders-list-empty-footer"],
|
||||
.marketplace-suggestions-container.showing-suggestion[data-marketplace-suggestions-context="orders-list-empty-body"] {
|
||||
|
||||
border: 1px solid $suggestions-pale-gray;
|
||||
border-bottom: none;
|
||||
|
||||
&:last-child {
|
||||
border-bottom: 1px solid $suggestions-pale-gray;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,446 @@
|
|||
/* global marketplace_suggestions, ajaxurl, Cookies */
|
||||
( function( $, marketplace_suggestions, ajaxurl ) {
|
||||
$( function() {
|
||||
if ( 'undefined' === typeof marketplace_suggestions ) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Stand-in wcTracks.recordEvent in case tracks is not available (for any reason).
|
||||
window.wcTracks = window.wcTracks || {};
|
||||
window.wcTracks.recordEvent = window.wcTracks.recordEvent || function() { };
|
||||
|
||||
// Tracks events sent in this file:
|
||||
// - marketplace_suggestion_displayed
|
||||
// - marketplace_suggestion_clicked
|
||||
// - marketplace_suggestion_dismissed
|
||||
// All are prefixed by {WC_Tracks::PREFIX}.
|
||||
// All have one property for `suggestionSlug`, to identify the specific suggestion message.
|
||||
|
||||
// Dismiss the specified suggestion from the UI, and save the dismissal in settings.
|
||||
function dismissSuggestion( context, suggestionSlug ) {
|
||||
// hide the suggestion in the UI
|
||||
var selector = '[data-suggestion-slug=' + suggestionSlug + ']';
|
||||
$( selector ).fadeOut( function() {
|
||||
$( this ).remove();
|
||||
tidyProductEditMetabox();
|
||||
} );
|
||||
|
||||
// save dismissal in user settings
|
||||
jQuery.post(
|
||||
ajaxurl,
|
||||
{
|
||||
'action': 'woocommerce_add_dismissed_marketplace_suggestion',
|
||||
'_wpnonce': marketplace_suggestions.dismiss_suggestion_nonce,
|
||||
'slug': suggestionSlug
|
||||
}
|
||||
);
|
||||
|
||||
// if this is a high-use area, delay new suggestion that area for a short while
|
||||
var highUseSuggestionContexts = [ 'products-list-inline' ];
|
||||
if ( _.contains( highUseSuggestionContexts, context ) ) {
|
||||
Cookies.set( 'woocommerce_snooze_products_list_suggestions', '1', { expires: 2 } );
|
||||
}
|
||||
|
||||
window.wcTracks.recordEvent( 'marketplace_suggestion_dismissed', {
|
||||
suggestionSlug: suggestionSlug
|
||||
} );
|
||||
}
|
||||
|
||||
// Render DOM element for suggestion dismiss button.
|
||||
function renderDismissButton( context, suggestionSlug ) {
|
||||
var dismissButton = document.createElement( 'a' );
|
||||
|
||||
dismissButton.classList.add( 'suggestion-dismiss' );
|
||||
dismissButton.setAttribute( 'title', marketplace_suggestions.i18n_marketplace_suggestions_dismiss_tooltip );
|
||||
dismissButton.setAttribute( 'href', '#' );
|
||||
dismissButton.onclick = function( event ) {
|
||||
event.preventDefault();
|
||||
dismissSuggestion( context, suggestionSlug );
|
||||
};
|
||||
|
||||
return dismissButton;
|
||||
}
|
||||
|
||||
function addUTMParameters( context, url ) {
|
||||
var utmParams = {
|
||||
utm_source: 'unknown',
|
||||
utm_campaign: 'marketplacesuggestions',
|
||||
utm_medium: 'product'
|
||||
};
|
||||
var sourceContextMap = {
|
||||
'productstable': [
|
||||
'products-list-inline'
|
||||
],
|
||||
'productsempty': [
|
||||
'products-list-empty-header',
|
||||
'products-list-empty-footer',
|
||||
'products-list-empty-body'
|
||||
],
|
||||
'ordersempty': [
|
||||
'orders-list-empty-header',
|
||||
'orders-list-empty-footer',
|
||||
'orders-list-empty-body'
|
||||
],
|
||||
'editproduct': [
|
||||
'product-edit-meta-tab-header',
|
||||
'product-edit-meta-tab-footer',
|
||||
'product-edit-meta-tab-body'
|
||||
]
|
||||
};
|
||||
var utmSource = _.findKey( sourceContextMap, function( sourceInfo ) {
|
||||
return _.contains( sourceInfo, context );
|
||||
} );
|
||||
if ( utmSource ) {
|
||||
utmParams.utm_source = utmSource;
|
||||
}
|
||||
|
||||
return url + '?' + jQuery.param( utmParams );
|
||||
}
|
||||
|
||||
// Render DOM element for suggestion linkout, optionally with button style.
|
||||
function renderLinkout( context, slug, url, text, isButton ) {
|
||||
var linkoutButton = document.createElement( 'a' );
|
||||
|
||||
var utmUrl = addUTMParameters( context, url );
|
||||
linkoutButton.setAttribute( 'href', utmUrl );
|
||||
linkoutButton.setAttribute( 'target', 'blank' );
|
||||
linkoutButton.textContent = text;
|
||||
|
||||
linkoutButton.onclick = function() {
|
||||
window.wcTracks.recordEvent( 'marketplace_suggestion_clicked', {
|
||||
suggestionSlug: slug
|
||||
} );
|
||||
};
|
||||
|
||||
if ( isButton ) {
|
||||
linkoutButton.classList.add( 'button' );
|
||||
} else {
|
||||
linkoutButton.classList.add( 'linkout' );
|
||||
var linkoutIcon = document.createElement( 'span' );
|
||||
linkoutIcon.classList.add( 'dashicons', 'dashicons-external' );
|
||||
linkoutButton.appendChild( linkoutIcon );
|
||||
}
|
||||
|
||||
return linkoutButton;
|
||||
}
|
||||
|
||||
// Render DOM element for suggestion icon image.
|
||||
function renderSuggestionIcon( iconUrl ) {
|
||||
if ( ! iconUrl ) {
|
||||
return null;
|
||||
}
|
||||
|
||||
var image = document.createElement( 'img' );
|
||||
image.src = iconUrl;
|
||||
image.classList.add( 'marketplace-suggestion-icon' );
|
||||
|
||||
return image;
|
||||
}
|
||||
|
||||
// Render DOM elements for suggestion content.
|
||||
function renderSuggestionContent( title, copy ) {
|
||||
var container = document.createElement( 'div' );
|
||||
|
||||
container.classList.add( 'marketplace-suggestion-container-content' );
|
||||
|
||||
if ( title ) {
|
||||
var titleHeading = document.createElement( 'h4' );
|
||||
titleHeading.textContent = title;
|
||||
container.appendChild( titleHeading );
|
||||
}
|
||||
|
||||
if ( copy ) {
|
||||
var body = document.createElement( 'p' );
|
||||
body.textContent = copy;
|
||||
container.appendChild( body );
|
||||
}
|
||||
|
||||
return container;
|
||||
}
|
||||
|
||||
// Render DOM elements for suggestion call-to-action – button or link with dismiss 'x'.
|
||||
function renderSuggestionCTA( context, slug, url, linkText, linkIsButton, allowDismiss ) {
|
||||
var container = document.createElement( 'div' );
|
||||
|
||||
if ( ! linkText ) {
|
||||
linkText = marketplace_suggestions.i18n_marketplace_suggestions_default_cta;
|
||||
}
|
||||
|
||||
container.classList.add( 'marketplace-suggestion-container-cta' );
|
||||
if ( url && linkText ) {
|
||||
var linkoutElement = renderLinkout( context, slug, url, linkText, linkIsButton );
|
||||
container.appendChild( linkoutElement );
|
||||
}
|
||||
|
||||
if ( allowDismiss ) {
|
||||
container.appendChild( renderDismissButton( context, slug ) );
|
||||
}
|
||||
|
||||
return container;
|
||||
}
|
||||
|
||||
function getTableBannerColspan() {
|
||||
return $( 'table.wp-list-table.posts thead th:not(.hidden)' ).length + 1;
|
||||
}
|
||||
|
||||
// Render a "table banner" style suggestion.
|
||||
// These are used in admin lists, e.g. products list.
|
||||
function renderTableBanner( context, slug, iconUrl, title, copy, url, buttonText, allowDismiss ) {
|
||||
if ( ! title || ! url ) {
|
||||
return;
|
||||
}
|
||||
|
||||
var row = document.createElement( 'tr' );
|
||||
row.classList.add( 'marketplace-table-banner' );
|
||||
row.classList.add( 'marketplace-suggestions-container' );
|
||||
row.classList.add( 'showing-suggestion' );
|
||||
row.dataset.marketplaceSuggestionsContext = 'products-list-inline';
|
||||
row.dataset.suggestionSlug = slug;
|
||||
|
||||
var cell = document.createElement( 'td' );
|
||||
cell.classList.add( 'marketplace-table-banner-td' );
|
||||
cell.setAttribute( 'colspan', getTableBannerColspan() );
|
||||
|
||||
var container = document.createElement( 'div' );
|
||||
container.classList.add( 'marketplace-suggestion-container' );
|
||||
container.dataset.suggestionSlug = slug;
|
||||
|
||||
var icon = renderSuggestionIcon( iconUrl );
|
||||
if ( icon ) {
|
||||
container.appendChild( icon );
|
||||
}
|
||||
container.appendChild(
|
||||
renderSuggestionContent( title, copy )
|
||||
);
|
||||
container.appendChild(
|
||||
renderSuggestionCTA( context, slug, url, buttonText, true, allowDismiss )
|
||||
);
|
||||
|
||||
cell.appendChild( container );
|
||||
row.appendChild( cell );
|
||||
|
||||
return row;
|
||||
}
|
||||
|
||||
// Render a "list item" style suggestion.
|
||||
// These are used in onboarding style contexts, e.g. products list empty state.
|
||||
function renderListItem( context, slug, iconUrl, title, copy, url, linkText, linkIsButton, allowDismiss ) {
|
||||
var container = document.createElement( 'div' );
|
||||
container.classList.add( 'marketplace-suggestion-container' );
|
||||
container.dataset.suggestionSlug = slug;
|
||||
|
||||
var icon = renderSuggestionIcon( iconUrl );
|
||||
if ( icon ) {
|
||||
container.appendChild( icon );
|
||||
}
|
||||
container.appendChild(
|
||||
renderSuggestionContent( title, copy )
|
||||
);
|
||||
container.appendChild(
|
||||
renderSuggestionCTA( context, slug, url, linkText, linkIsButton, allowDismiss )
|
||||
);
|
||||
|
||||
return container;
|
||||
}
|
||||
|
||||
// Filter suggestion data to remove less-relevant suggestions.
|
||||
function getRelevantPromotions( marketplaceSuggestionsApiData, displayContext ) {
|
||||
// select based on display context
|
||||
var promos = _.filter( marketplaceSuggestionsApiData, function( promo ) {
|
||||
if ( _.isArray( promo.context ) ) {
|
||||
return _.contains( promo.context, displayContext );
|
||||
}
|
||||
return ( displayContext === promo.context );
|
||||
} );
|
||||
|
||||
// hide promos the user has dismissed
|
||||
promos = _.filter( promos, function( promo ) {
|
||||
return ! _.contains( marketplace_suggestions.dismissed_suggestions, promo.slug );
|
||||
} );
|
||||
|
||||
// hide promos for things the user already has installed
|
||||
promos = _.filter( promos, function( promo ) {
|
||||
return ! _.contains( marketplace_suggestions.active_plugins, promo['hide-if-active'] );
|
||||
} );
|
||||
|
||||
// hide promos that are not applicable based on user's installed extensions
|
||||
promos = _.filter( promos, function( promo ) {
|
||||
if ( ! promo['show-if-active'] ) {
|
||||
// this promotion is relevant to all
|
||||
return true;
|
||||
}
|
||||
|
||||
// if the user has any of the prerequisites, show the promo
|
||||
return ( _.intersection( marketplace_suggestions.active_plugins, promo['show-if-active'] ).length > 0 );
|
||||
} );
|
||||
|
||||
return promos;
|
||||
}
|
||||
|
||||
// Show and hide page elements dependent on suggestion state.
|
||||
function hidePageElementsForSuggestionState( usedSuggestionsContexts ) {
|
||||
var showingEmptyStateSuggestions = _.intersection(
|
||||
usedSuggestionsContexts,
|
||||
[ 'products-list-empty-body', 'orders-list-empty-body' ]
|
||||
).length > 0;
|
||||
|
||||
// Streamline onboarding UI if we're in 'empty state' welcome mode.
|
||||
if ( showingEmptyStateSuggestions ) {
|
||||
$( '#screen-meta-links' ).hide();
|
||||
$( '#wpfooter' ).hide();
|
||||
}
|
||||
|
||||
// Hide the header & footer, they don't make sense without specific promotion content
|
||||
if ( ! showingEmptyStateSuggestions ) {
|
||||
$( '.marketplace-suggestions-container[data-marketplace-suggestions-context="products-list-empty-header"]' ).hide();
|
||||
$( '.marketplace-suggestions-container[data-marketplace-suggestions-context="products-list-empty-footer"]' ).hide();
|
||||
$( '.marketplace-suggestions-container[data-marketplace-suggestions-context="orders-list-empty-header"]' ).hide();
|
||||
$( '.marketplace-suggestions-container[data-marketplace-suggestions-context="orders-list-empty-footer"]' ).hide();
|
||||
}
|
||||
}
|
||||
|
||||
// Streamline the product edit suggestions tab dependent on what's visible.
|
||||
function tidyProductEditMetabox() {
|
||||
var productMetaboxSuggestions = $(
|
||||
'.marketplace-suggestions-container[data-marketplace-suggestions-context="product-edit-meta-tab-body"]'
|
||||
).children();
|
||||
if ( 0 >= productMetaboxSuggestions.length ) {
|
||||
$( '.marketplace-suggestions-container[data-marketplace-suggestions-context="product-edit-meta-tab-header"]' ).slideUp();
|
||||
$( '.marketplace-suggestions-container[data-marketplace-suggestions-context="product-edit-meta-tab-body"]' ).fadeOut();
|
||||
}
|
||||
}
|
||||
|
||||
function refreshBannerColspanForScreenOptions( content ) {
|
||||
$( '#show-settings-link' ).on( 'focus.scroll-into-view', function() {
|
||||
$( '.marketplace-table-banner-td' ).attr( 'colspan', getTableBannerColspan() );
|
||||
});
|
||||
}
|
||||
|
||||
// Render suggestion data in appropriate places in UI.
|
||||
function displaySuggestions( marketplaceSuggestionsApiData ) {
|
||||
var usedSuggestionsContexts = [];
|
||||
|
||||
// iterate over all suggestions containers, rendering promos
|
||||
$( '.marketplace-suggestions-container' ).each( function() {
|
||||
// determine the context / placement we're populating
|
||||
var context = this.dataset.marketplaceSuggestionsContext;
|
||||
|
||||
// find promotions that target this context
|
||||
var promos = getRelevantPromotions( marketplaceSuggestionsApiData, context );
|
||||
|
||||
// shuffle/randomly select five suggestions to display
|
||||
var suggestionsToDisplay = _.sample( promos, 5 );
|
||||
|
||||
// render the promo content
|
||||
for ( var i in suggestionsToDisplay ) {
|
||||
|
||||
var linkText = suggestionsToDisplay[ i ]['link-text'];
|
||||
var linkoutIsButton = true;
|
||||
if ( suggestionsToDisplay[ i ]['link-text'] ) {
|
||||
linkText = suggestionsToDisplay[ i ]['link-text'];
|
||||
linkoutIsButton = false;
|
||||
}
|
||||
|
||||
// dismiss is allowed by default
|
||||
var allowDismiss = true;
|
||||
if ( suggestionsToDisplay[ i ]['allow-dismiss'] === false ) {
|
||||
allowDismiss = false;
|
||||
}
|
||||
|
||||
var content = renderListItem(
|
||||
context,
|
||||
suggestionsToDisplay[ i ].slug,
|
||||
suggestionsToDisplay[ i ].icon,
|
||||
suggestionsToDisplay[ i ].title,
|
||||
suggestionsToDisplay[ i ].copy,
|
||||
suggestionsToDisplay[ i ].url,
|
||||
linkText,
|
||||
linkoutIsButton,
|
||||
allowDismiss
|
||||
);
|
||||
$( this ).append( content );
|
||||
$( this ).addClass( 'showing-suggestion' );
|
||||
usedSuggestionsContexts.push( context );
|
||||
|
||||
window.wcTracks.recordEvent( 'marketplace_suggestion_displayed', {
|
||||
suggestionSlug: suggestionsToDisplay[ i ].slug
|
||||
} );
|
||||
}
|
||||
} );
|
||||
|
||||
// render inline promos in products list
|
||||
if ( 0 === usedSuggestionsContexts.length ) {
|
||||
$( '.wp-admin.admin-bar.edit-php.post-type-product table.wp-list-table.posts tbody').first().each( function() {
|
||||
var context = 'products-list-inline';
|
||||
|
||||
// product list banner suggestion is temporarily suppressed after a recent dismissal
|
||||
if ( Cookies.get( 'woocommerce_snooze_products_list_suggestions' ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
// find promotions that target this context
|
||||
var promos = getRelevantPromotions( marketplaceSuggestionsApiData, context );
|
||||
if ( ! promos || ! promos.length ) {
|
||||
return;
|
||||
}
|
||||
|
||||
// shuffle/randomly select the suggestion to display
|
||||
var suggestionToDisplay = _.sample( promos );
|
||||
|
||||
// dismiss is allowed by default
|
||||
var allowDismiss = true;
|
||||
if ( false === suggestionToDisplay['allow-dismiss'] ) {
|
||||
allowDismiss = false;
|
||||
}
|
||||
|
||||
// render first promo
|
||||
var content = renderTableBanner(
|
||||
context,
|
||||
suggestionToDisplay.slug,
|
||||
suggestionToDisplay.icon,
|
||||
suggestionToDisplay.title,
|
||||
suggestionToDisplay.copy,
|
||||
suggestionToDisplay.url,
|
||||
suggestionToDisplay['button-text'],
|
||||
allowDismiss
|
||||
);
|
||||
|
||||
if ( content ) {
|
||||
// where should we put it in the list?
|
||||
var rows = $( this ).children();
|
||||
var minRow = 3;
|
||||
|
||||
$( content ).hide();
|
||||
|
||||
if ( rows.length <= minRow ) {
|
||||
// if small number of rows, append at end
|
||||
$( this ).append( content );
|
||||
}
|
||||
else {
|
||||
// for more rows, insert
|
||||
$( rows[ minRow - 1 ] ).after( content );
|
||||
}
|
||||
|
||||
$( content ).fadeIn();
|
||||
|
||||
usedSuggestionsContexts.push( context );
|
||||
|
||||
refreshBannerColspanForScreenOptions( content );
|
||||
|
||||
window.wcTracks.recordEvent( 'marketplace_suggestion_displayed', {
|
||||
suggestionSlug: suggestionToDisplay.slug
|
||||
} );
|
||||
}
|
||||
} );
|
||||
}
|
||||
|
||||
hidePageElementsForSuggestionState( usedSuggestionsContexts );
|
||||
tidyProductEditMetabox();
|
||||
}
|
||||
|
||||
if ( marketplace_suggestions.suggestions_data ) {
|
||||
displaySuggestions( marketplace_suggestions.suggestions_data );
|
||||
}
|
||||
});
|
||||
|
||||
})( jQuery, marketplace_suggestions, ajaxurl );
|
File diff suppressed because one or more lines are too long
|
@ -343,4 +343,5 @@
|
|||
}
|
||||
});
|
||||
});
|
||||
|
||||
})( jQuery, woocommerce_admin );
|
||||
|
|
|
@ -0,0 +1,270 @@
|
|||
<?php
|
||||
/**
|
||||
* Calling codes.
|
||||
*
|
||||
* Returns an array of calling codes.
|
||||
*
|
||||
* @package WooCommerce/i18n
|
||||
*/
|
||||
|
||||
defined( 'ABSPATH' ) || exit;
|
||||
|
||||
return array(
|
||||
'BD' => '+880',
|
||||
'BE' => '+32',
|
||||
'BF' => '+226',
|
||||
'BG' => '+359',
|
||||
'BA' => '+387',
|
||||
'BB' => '+1246',
|
||||
'WF' => '+681',
|
||||
'BL' => '+590',
|
||||
'BM' => '+1441',
|
||||
'BN' => '+673',
|
||||
'BO' => '+591',
|
||||
'BH' => '+973',
|
||||
'BI' => '+257',
|
||||
'BJ' => '+229',
|
||||
'BT' => '+975',
|
||||
'JM' => '+1876',
|
||||
'BV' => '',
|
||||
'BW' => '+267',
|
||||
'WS' => '+685',
|
||||
'BQ' => '+599',
|
||||
'BR' => '+55',
|
||||
'BS' => '+1242',
|
||||
'JE' => '+441534',
|
||||
'BY' => '+375',
|
||||
'BZ' => '+501',
|
||||
'RU' => '+7',
|
||||
'RW' => '+250',
|
||||
'RS' => '+381',
|
||||
'TL' => '+670',
|
||||
'RE' => '+262',
|
||||
'TM' => '+993',
|
||||
'TJ' => '+992',
|
||||
'RO' => '+40',
|
||||
'TK' => '+690',
|
||||
'GW' => '+245',
|
||||
'GU' => '+1671',
|
||||
'GT' => '+502',
|
||||
'GS' => '',
|
||||
'GR' => '+30',
|
||||
'GQ' => '+240',
|
||||
'GP' => '+590',
|
||||
'JP' => '+81',
|
||||
'GY' => '+592',
|
||||
'GG' => '+441481',
|
||||
'GF' => '+594',
|
||||
'GE' => '+995',
|
||||
'GD' => '+1473',
|
||||
'GB' => '+44',
|
||||
'GA' => '+241',
|
||||
'SV' => '+503',
|
||||
'GN' => '+224',
|
||||
'GM' => '+220',
|
||||
'GL' => '+299',
|
||||
'GI' => '+350',
|
||||
'GH' => '+233',
|
||||
'OM' => '+968',
|
||||
'TN' => '+216',
|
||||
'JO' => '+962',
|
||||
'HR' => '+385',
|
||||
'HT' => '+509',
|
||||
'HU' => '+36',
|
||||
'HK' => '+852',
|
||||
'HN' => '+504',
|
||||
'HM' => '',
|
||||
'VE' => '+58',
|
||||
'PR' => array(
|
||||
'+1787',
|
||||
'+1939',
|
||||
),
|
||||
'PS' => '+970',
|
||||
'PW' => '+680',
|
||||
'PT' => '+351',
|
||||
'SJ' => '+47',
|
||||
'PY' => '+595',
|
||||
'IQ' => '+964',
|
||||
'PA' => '+507',
|
||||
'PF' => '+689',
|
||||
'PG' => '+675',
|
||||
'PE' => '+51',
|
||||
'PK' => '+92',
|
||||
'PH' => '+63',
|
||||
'PN' => '+870',
|
||||
'PL' => '+48',
|
||||
'PM' => '+508',
|
||||
'ZM' => '+260',
|
||||
'EH' => '+212',
|
||||
'EE' => '+372',
|
||||
'EG' => '+20',
|
||||
'ZA' => '+27',
|
||||
'EC' => '+593',
|
||||
'IT' => '+39',
|
||||
'VN' => '+84',
|
||||
'SB' => '+677',
|
||||
'ET' => '+251',
|
||||
'SO' => '+252',
|
||||
'ZW' => '+263',
|
||||
'SA' => '+966',
|
||||
'ES' => '+34',
|
||||
'ER' => '+291',
|
||||
'ME' => '+382',
|
||||
'MD' => '+373',
|
||||
'MG' => '+261',
|
||||
'MF' => '+590',
|
||||
'MA' => '+212',
|
||||
'MC' => '+377',
|
||||
'UZ' => '+998',
|
||||
'MM' => '+95',
|
||||
'ML' => '+223',
|
||||
'MO' => '+853',
|
||||
'MN' => '+976',
|
||||
'MH' => '+692',
|
||||
'MK' => '+389',
|
||||
'MU' => '+230',
|
||||
'MT' => '+356',
|
||||
'MW' => '+265',
|
||||
'MV' => '+960',
|
||||
'MQ' => '+596',
|
||||
'MP' => '+1670',
|
||||
'MS' => '+1664',
|
||||
'MR' => '+222',
|
||||
'IM' => '+441624',
|
||||
'UG' => '+256',
|
||||
'TZ' => '+255',
|
||||
'MY' => '+60',
|
||||
'MX' => '+52',
|
||||
'IL' => '+972',
|
||||
'FR' => '+33',
|
||||
'IO' => '+246',
|
||||
'SH' => '+290',
|
||||
'FI' => '+358',
|
||||
'FJ' => '+679',
|
||||
'FK' => '+500',
|
||||
'FM' => '+691',
|
||||
'FO' => '+298',
|
||||
'NI' => '+505',
|
||||
'NL' => '+31',
|
||||
'NO' => '+47',
|
||||
'NA' => '+264',
|
||||
'VU' => '+678',
|
||||
'NC' => '+687',
|
||||
'NE' => '+227',
|
||||
'NF' => '+672',
|
||||
'NG' => '+234',
|
||||
'NZ' => '+64',
|
||||
'NP' => '+977',
|
||||
'NR' => '+674',
|
||||
'NU' => '+683',
|
||||
'CK' => '+682',
|
||||
'XK' => '',
|
||||
'CI' => '+225',
|
||||
'CH' => '+41',
|
||||
'CO' => '+57',
|
||||
'CN' => '+86',
|
||||
'CM' => '+237',
|
||||
'CL' => '+56',
|
||||
'CC' => '+61',
|
||||
'CA' => '+1',
|
||||
'CG' => '+242',
|
||||
'CF' => '+236',
|
||||
'CD' => '+243',
|
||||
'CZ' => '+420',
|
||||
'CY' => '+357',
|
||||
'CX' => '+61',
|
||||
'CR' => '+506',
|
||||
'CW' => '+599',
|
||||
'CV' => '+238',
|
||||
'CU' => '+53',
|
||||
'SZ' => '+268',
|
||||
'SY' => '+963',
|
||||
'SX' => '+599',
|
||||
'KG' => '+996',
|
||||
'KE' => '+254',
|
||||
'SS' => '+211',
|
||||
'SR' => '+597',
|
||||
'KI' => '+686',
|
||||
'KH' => '+855',
|
||||
'KN' => '+1869',
|
||||
'KM' => '+269',
|
||||
'ST' => '+239',
|
||||
'SK' => '+421',
|
||||
'KR' => '+82',
|
||||
'SI' => '+386',
|
||||
'KP' => '+850',
|
||||
'KW' => '+965',
|
||||
'SN' => '+221',
|
||||
'SM' => '+378',
|
||||
'SL' => '+232',
|
||||
'SC' => '+248',
|
||||
'KZ' => '+7',
|
||||
'KY' => '+1345',
|
||||
'SG' => '+65',
|
||||
'SE' => '+46',
|
||||
'SD' => '+249',
|
||||
'DO' => array(
|
||||
'+1809',
|
||||
'+1829',
|
||||
'+1849',
|
||||
),
|
||||
'DM' => '+1767',
|
||||
'DJ' => '+253',
|
||||
'DK' => '+45',
|
||||
'VG' => '+1284',
|
||||
'DE' => '+49',
|
||||
'YE' => '+967',
|
||||
'DZ' => '+213',
|
||||
'US' => '+1',
|
||||
'UY' => '+598',
|
||||
'YT' => '+262',
|
||||
'UM' => '+1',
|
||||
'LB' => '+961',
|
||||
'LC' => '+1758',
|
||||
'LA' => '+856',
|
||||
'TV' => '+688',
|
||||
'TW' => '+886',
|
||||
'TT' => '+1868',
|
||||
'TR' => '+90',
|
||||
'LK' => '+94',
|
||||
'LI' => '+423',
|
||||
'LV' => '+371',
|
||||
'TO' => '+676',
|
||||
'LT' => '+370',
|
||||
'LU' => '+352',
|
||||
'LR' => '+231',
|
||||
'LS' => '+266',
|
||||
'TH' => '+66',
|
||||
'TF' => '',
|
||||
'TG' => '+228',
|
||||
'TD' => '+235',
|
||||
'TC' => '+1649',
|
||||
'LY' => '+218',
|
||||
'VA' => '+379',
|
||||
'VC' => '+1784',
|
||||
'AE' => '+971',
|
||||
'AD' => '+376',
|
||||
'AG' => '+1268',
|
||||
'AF' => '+93',
|
||||
'AI' => '+1264',
|
||||
'VI' => '+1340',
|
||||
'IS' => '+354',
|
||||
'IR' => '+98',
|
||||
'AM' => '+374',
|
||||
'AL' => '+355',
|
||||
'AO' => '+244',
|
||||
'AQ' => '',
|
||||
'AS' => '+1684',
|
||||
'AR' => '+54',
|
||||
'AU' => '+61',
|
||||
'AT' => '+43',
|
||||
'AW' => '+297',
|
||||
'IN' => '+91',
|
||||
'AX' => '+35818',
|
||||
'AZ' => '+994',
|
||||
'IE' => '+353',
|
||||
'ID' => '+62',
|
||||
'UA' => '+380',
|
||||
'QA' => '+974',
|
||||
'MZ' => '+258',
|
||||
);
|
|
@ -40,12 +40,14 @@ if ( ! class_exists( 'WC_Admin_Assets', false ) ) :
|
|||
wp_register_style( 'jquery-ui-style', WC()->plugin_url() . '/assets/css/jquery-ui/jquery-ui.min.css', array(), WC_VERSION );
|
||||
wp_register_style( 'woocommerce_admin_dashboard_styles', WC()->plugin_url() . '/assets/css/dashboard.css', array(), WC_VERSION );
|
||||
wp_register_style( 'woocommerce_admin_print_reports_styles', WC()->plugin_url() . '/assets/css/reports-print.css', array(), WC_VERSION, 'print' );
|
||||
wp_register_style( 'woocommerce_admin_marketplace_styles', WC()->plugin_url() . '/assets/css/marketplace-suggestions.css', array(), WC_VERSION );
|
||||
|
||||
// Add RTL support for admin styles.
|
||||
wp_style_add_data( 'woocommerce_admin_menu_styles', 'rtl', 'replace' );
|
||||
wp_style_add_data( 'woocommerce_admin_styles', 'rtl', 'replace' );
|
||||
wp_style_add_data( 'woocommerce_admin_dashboard_styles', 'rtl', 'replace' );
|
||||
wp_style_add_data( 'woocommerce_admin_print_reports_styles', 'rtl', 'replace' );
|
||||
wp_style_add_data( 'woocommerce_admin_marketplace_styles', 'rtl', 'replace' );
|
||||
|
||||
// Sitewide menu CSS.
|
||||
wp_enqueue_style( 'woocommerce_admin_menu_styles' );
|
||||
|
@ -70,6 +72,10 @@ if ( ! class_exists( 'WC_Admin_Assets', false ) ) :
|
|||
do_action( 'woocommerce_admin_css' );
|
||||
wc_deprecated_function( 'The woocommerce_admin_css action', '2.3', 'admin_enqueue_scripts' );
|
||||
}
|
||||
|
||||
if ( WC_Marketplace_Suggestions::show_suggestions_for_screen( $screen_id ) ) {
|
||||
wp_enqueue_style( 'woocommerce_admin_marketplace_styles' );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -108,6 +114,8 @@ if ( ! class_exists( 'WC_Admin_Assets', false ) ) :
|
|||
wp_register_script( 'select2', WC()->plugin_url() . '/assets/js/select2/select2.full' . $suffix . '.js', array( 'jquery' ), '4.0.3' );
|
||||
wp_register_script( 'selectWoo', WC()->plugin_url() . '/assets/js/selectWoo/selectWoo.full' . $suffix . '.js', array( 'jquery' ), '1.0.4' );
|
||||
wp_register_script( 'wc-enhanced-select', WC()->plugin_url() . '/assets/js/admin/wc-enhanced-select' . $suffix . '.js', array( 'jquery', 'selectWoo' ), WC_VERSION );
|
||||
wp_register_script( 'js-cookie', WC()->plugin_url() . '/assets/js/js-cookie/js.cookie' . $suffix . '.js', array(), '2.1.4', true );
|
||||
|
||||
wp_localize_script(
|
||||
'wc-enhanced-select',
|
||||
'wc_enhanced_select_params',
|
||||
|
@ -416,7 +424,35 @@ if ( ! class_exists( 'WC_Admin_Assets', false ) ) :
|
|||
)
|
||||
);
|
||||
}
|
||||
|
||||
if ( WC_Marketplace_Suggestions::show_suggestions_for_screen( $screen_id ) ) {
|
||||
$active_plugin_slugs = array_map( 'dirname', get_option( 'active_plugins' ) );
|
||||
wp_register_script(
|
||||
'marketplace-suggestions',
|
||||
WC()->plugin_url() . '/assets/js/admin/marketplace-suggestions' . $suffix . '.js',
|
||||
array( 'jquery', 'underscore', 'js-cookie' ),
|
||||
WC_VERSION,
|
||||
true
|
||||
);
|
||||
wp_localize_script(
|
||||
'marketplace-suggestions',
|
||||
'marketplace_suggestions',
|
||||
array(
|
||||
'dismiss_suggestion_nonce' => wp_create_nonce( 'add_dismissed_marketplace_suggestion' ),
|
||||
'active_plugins' => $active_plugin_slugs,
|
||||
'dismissed_suggestions' => WC_Marketplace_Suggestions::get_dismissed_suggestions(),
|
||||
'suggestions_data' => WC_Marketplace_Suggestions::get_suggestions_api_data(),
|
||||
'i18n_marketplace_suggestions_default_cta'
|
||||
=> esc_html__( 'Learn More', 'woocommerce' ),
|
||||
'i18n_marketplace_suggestions_dismiss_tooltip'
|
||||
=> esc_attr__( 'Dismiss this suggestion', 'woocommerce' ),
|
||||
)
|
||||
);
|
||||
wp_enqueue_script( 'marketplace-suggestions' );
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
endif;
|
||||
|
|
|
@ -26,9 +26,9 @@ class WC_Admin_Attributes {
|
|||
$action = '';
|
||||
|
||||
// Action to perform: add, edit, delete or none.
|
||||
if ( ! empty( $_POST['add_new_attribute'] ) ) {
|
||||
if ( ! empty( $_POST['add_new_attribute'] ) ) { // WPCS: CSRF ok.
|
||||
$action = 'add';
|
||||
} elseif ( ! empty( $_POST['save_attribute'] ) && ! empty( $_GET['edit'] ) ) {
|
||||
} elseif ( ! empty( $_POST['save_attribute'] ) && ! empty( $_GET['edit'] ) ) { // WPCS: CSRF ok.
|
||||
$action = 'edit';
|
||||
} elseif ( ! empty( $_GET['delete'] ) ) {
|
||||
$action = 'delete';
|
||||
|
@ -65,11 +65,11 @@ class WC_Admin_Attributes {
|
|||
*/
|
||||
private static function get_posted_attribute() {
|
||||
$attribute = array(
|
||||
'attribute_label' => isset( $_POST['attribute_label'] ) ? wc_clean( stripslashes( $_POST['attribute_label'] ) ) : '',
|
||||
'attribute_name' => isset( $_POST['attribute_name'] ) ? wc_sanitize_taxonomy_name( stripslashes( $_POST['attribute_name'] ) ) : '',
|
||||
'attribute_type' => isset( $_POST['attribute_type'] ) ? wc_clean( $_POST['attribute_type'] ) : 'select',
|
||||
'attribute_orderby' => isset( $_POST['attribute_orderby'] ) ? wc_clean( $_POST['attribute_orderby'] ) : '',
|
||||
'attribute_public' => isset( $_POST['attribute_public'] ) ? 1 : 0,
|
||||
'attribute_label' => isset( $_POST['attribute_label'] ) ? wc_clean( wp_unslash( $_POST['attribute_label'] ) ) : '', // WPCS: input var ok, CSRF ok.
|
||||
'attribute_name' => isset( $_POST['attribute_name'] ) ? wc_sanitize_taxonomy_name( wp_unslash( $_POST['attribute_name'] ) ) : '', // WPCS: input var ok, CSRF ok, sanitization ok.
|
||||
'attribute_type' => isset( $_POST['attribute_type'] ) ? wc_clean( wp_unslash( $_POST['attribute_type'] ) ) : 'select', // WPCS: input var ok, CSRF ok.
|
||||
'attribute_orderby' => isset( $_POST['attribute_orderby'] ) ? wc_clean( wp_unslash( $_POST['attribute_orderby'] ) ) : '', // WPCS: input var ok, CSRF ok.
|
||||
'attribute_public' => isset( $_POST['attribute_public'] ) ? 1 : 0, // WPCS: input var ok, CSRF ok.
|
||||
);
|
||||
|
||||
if ( empty( $attribute['attribute_type'] ) ) {
|
||||
|
@ -117,7 +117,7 @@ class WC_Admin_Attributes {
|
|||
* @return bool|WP_Error
|
||||
*/
|
||||
private static function process_edit_attribute() {
|
||||
$attribute_id = absint( $_GET['edit'] );
|
||||
$attribute_id = isset( $_GET['edit'] ) ? absint( $_GET['edit'] ) : 0;
|
||||
check_admin_referer( 'woocommerce-save-attribute_' . $attribute_id );
|
||||
|
||||
$attribute = self::get_posted_attribute();
|
||||
|
@ -135,7 +135,7 @@ class WC_Admin_Attributes {
|
|||
return $id;
|
||||
}
|
||||
|
||||
echo '<div class="updated"><p>' . __( 'Attribute updated successfully', 'woocommerce' ) . '</p><p><a href="' . esc_url( admin_url( 'edit.php?post_type=product&page=product_attributes' ) ) . '">' . __( 'Back to Attributes', 'woocommerce' ) . '</a></p></div>';
|
||||
echo '<div class="updated"><p>' . esc_html__( 'Attribute updated successfully', 'woocommerce' ) . '</p><p><a href="' . esc_url( admin_url( 'edit.php?post_type=product&page=product_attributes' ) ) . '">' . esc_html__( 'Back to Attributes', 'woocommerce' ) . '</a></p></div>';
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -146,7 +146,7 @@ class WC_Admin_Attributes {
|
|||
* @return bool
|
||||
*/
|
||||
private static function process_delete_attribute() {
|
||||
$attribute_id = absint( $_GET['delete'] );
|
||||
$attribute_id = isset( $_GET['delete'] ) ? absint( $_GET['delete'] ) : 0;
|
||||
check_admin_referer( 'woocommerce-delete-attribute_' . $attribute_id );
|
||||
|
||||
return wc_delete_attribute( $attribute_id );
|
||||
|
@ -160,9 +160,17 @@ class WC_Admin_Attributes {
|
|||
public static function edit_attribute() {
|
||||
global $wpdb;
|
||||
|
||||
$edit = absint( $_GET['edit'] );
|
||||
$edit = isset( $_GET['edit'] ) ? absint( $_GET['edit'] ) : 0;
|
||||
|
||||
$attribute_to_edit = $wpdb->get_row( 'SELECT attribute_type, attribute_label, attribute_name, attribute_orderby, attribute_public FROM ' . $wpdb->prefix . "woocommerce_attribute_taxonomies WHERE attribute_id = '$edit'" );
|
||||
$attribute_to_edit = $wpdb->get_row(
|
||||
$wpdb->prepare(
|
||||
"
|
||||
SELECT attribute_type, attribute_label, attribute_name, attribute_orderby, attribute_public
|
||||
FROM {$wpdb->prefix}woocommerce_attribute_taxonomies WHERE attribute_id = %d
|
||||
",
|
||||
$edit
|
||||
)
|
||||
);
|
||||
|
||||
?>
|
||||
<div class="wrap woocommerce">
|
||||
|
@ -297,7 +305,8 @@ class WC_Admin_Attributes {
|
|||
</thead>
|
||||
<tbody>
|
||||
<?php
|
||||
if ( $attribute_taxonomies = wc_get_attribute_taxonomies() ) :
|
||||
$attribute_taxonomies = wc_get_attribute_taxonomies();
|
||||
if ( $attribute_taxonomies ) :
|
||||
foreach ( $attribute_taxonomies as $tax ) :
|
||||
?>
|
||||
<tr>
|
||||
|
@ -333,21 +342,7 @@ class WC_Admin_Attributes {
|
|||
$taxonomy = wc_attribute_taxonomy_name( $tax->attribute_name );
|
||||
|
||||
if ( taxonomy_exists( $taxonomy ) ) {
|
||||
if ( 'menu_order' === wc_attribute_orderby( $taxonomy ) ) {
|
||||
$terms = get_terms( $taxonomy, 'hide_empty=0&menu_order=ASC' );
|
||||
} else {
|
||||
$terms = get_terms( $taxonomy, 'hide_empty=0&menu_order=false' );
|
||||
}
|
||||
|
||||
switch ( $tax->attribute_orderby ) {
|
||||
case 'name_num':
|
||||
usort( $terms, '_wc_get_product_terms_name_num_usort_callback' );
|
||||
break;
|
||||
case 'parent':
|
||||
usort( $terms, '_wc_get_product_terms_parent_usort_callback' );
|
||||
break;
|
||||
}
|
||||
|
||||
$terms = get_terms( $taxonomy, 'hide_empty=0' );
|
||||
$terms_string = implode( ', ', wp_list_pluck( $terms, 'name' ) );
|
||||
if ( $terms_string ) {
|
||||
echo esc_html( $terms_string );
|
||||
|
@ -370,7 +365,7 @@ class WC_Admin_Attributes {
|
|||
</tr>
|
||||
<?php
|
||||
endif;
|
||||
?>
|
||||
?>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
|
|
@ -91,7 +91,7 @@ if ( ! class_exists( 'WC_Admin_Dashboard', false ) ) :
|
|||
|
||||
$sales_by_date = new WC_Report_Sales_By_Date();
|
||||
$sales_by_date->start_date = strtotime( date( 'Y-m-01', current_time( 'timestamp' ) ) );
|
||||
$sales_by_date->end_date = current_time( 'timestamp' );
|
||||
$sales_by_date->end_date = strtotime( date( 'Y-m-d', current_time( 'timestamp' ) ) );
|
||||
$sales_by_date->chart_groupby = 'day';
|
||||
$sales_by_date->group_by_query = 'YEAR(posts.post_date), MONTH(posts.post_date), DAY(posts.post_date)';
|
||||
|
||||
|
|
|
@ -49,7 +49,6 @@ class WC_Admin_Taxonomies {
|
|||
|
||||
// Category/term ordering.
|
||||
add_action( 'create_term', array( $this, 'create_term' ), 5, 3 );
|
||||
add_action( 'delete_term', array( $this, 'delete_term' ), 5 );
|
||||
|
||||
// Add form.
|
||||
add_action( 'product_cat_add_form_fields', array( $this, 'add_category_fields' ) );
|
||||
|
@ -98,22 +97,17 @@ class WC_Admin_Taxonomies {
|
|||
|
||||
$meta_name = taxonomy_is_product_attribute( $taxonomy ) ? 'order_' . esc_attr( $taxonomy ) : 'order';
|
||||
|
||||
update_woocommerce_term_meta( $term_id, $meta_name, 0 );
|
||||
update_term_meta( $term_id, $meta_name, 0 );
|
||||
}
|
||||
|
||||
/**
|
||||
* When a term is deleted, delete its meta.
|
||||
*
|
||||
* @deprecated 3.6.0 No longer needed.
|
||||
* @param mixed $term_id Term ID.
|
||||
*/
|
||||
public function delete_term( $term_id ) {
|
||||
global $wpdb;
|
||||
|
||||
$term_id = absint( $term_id );
|
||||
|
||||
if ( $term_id && get_option( 'db_version' ) < 34370 ) {
|
||||
$wpdb->delete( $wpdb->woocommerce_termmeta, array( 'woocommerce_term_id' => $term_id ), array( '%d' ) );
|
||||
}
|
||||
wc_deprecated_function( 'delete_term', '3.6' );
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -219,8 +213,8 @@ class WC_Admin_Taxonomies {
|
|||
*/
|
||||
public function edit_category_fields( $term ) {
|
||||
|
||||
$display_type = get_woocommerce_term_meta( $term->term_id, 'display_type', true );
|
||||
$thumbnail_id = absint( get_woocommerce_term_meta( $term->term_id, 'thumbnail_id', true ) );
|
||||
$display_type = get_term_meta( $term->term_id, 'display_type', true );
|
||||
$thumbnail_id = absint( get_term_meta( $term->term_id, 'thumbnail_id', true ) );
|
||||
|
||||
if ( $thumbnail_id ) {
|
||||
$image = wp_get_attachment_thumb_url( $thumbnail_id );
|
||||
|
@ -314,10 +308,10 @@ class WC_Admin_Taxonomies {
|
|||
*/
|
||||
public function save_category_fields( $term_id, $tt_id = '', $taxonomy = '' ) {
|
||||
if ( isset( $_POST['display_type'] ) && 'product_cat' === $taxonomy ) { // WPCS: CSRF ok, input var ok.
|
||||
update_woocommerce_term_meta( $term_id, 'display_type', esc_attr( $_POST['display_type'] ) ); // WPCS: CSRF ok, sanitization ok, input var ok.
|
||||
update_term_meta( $term_id, 'display_type', esc_attr( $_POST['display_type'] ) ); // WPCS: CSRF ok, sanitization ok, input var ok.
|
||||
}
|
||||
if ( isset( $_POST['product_cat_thumbnail_id'] ) && 'product_cat' === $taxonomy ) { // WPCS: CSRF ok, input var ok.
|
||||
update_woocommerce_term_meta( $term_id, 'thumbnail_id', absint( $_POST['product_cat_thumbnail_id'] ) ); // WPCS: CSRF ok, input var ok.
|
||||
update_term_meta( $term_id, 'thumbnail_id', absint( $_POST['product_cat_thumbnail_id'] ) ); // WPCS: CSRF ok, input var ok.
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -440,7 +434,7 @@ class WC_Admin_Taxonomies {
|
|||
$columns .= wc_help_tip( __( 'This is the default category and it cannot be deleted. It will be automatically assigned to products with no category.', 'woocommerce' ) );
|
||||
}
|
||||
|
||||
$thumbnail_id = get_woocommerce_term_meta( $id, 'thumbnail_id', true );
|
||||
$thumbnail_id = get_term_meta( $id, 'thumbnail_id', true );
|
||||
|
||||
if ( $thumbnail_id ) {
|
||||
$image = wp_get_attachment_thumb_url( $thumbnail_id );
|
||||
|
@ -481,14 +475,14 @@ class WC_Admin_Taxonomies {
|
|||
return;
|
||||
}
|
||||
// Ensure the tooltip is displayed when the image column is disabled on product categories.
|
||||
wc_enqueue_js("
|
||||
(function( $ ) {
|
||||
wc_enqueue_js(
|
||||
"(function( $ ) {
|
||||
'use strict';
|
||||
var product_cat = $( 'tr#tag-" . absint( $this->default_cat_id ) . "' );
|
||||
product_cat.find( 'th' ).empty();
|
||||
product_cat.find( 'td.thumb span' ).detach( 'span' ).appendTo( product_cat.find( 'th' ) );
|
||||
})( jQuery );
|
||||
");
|
||||
})( jQuery );"
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -85,6 +85,10 @@ class WC_Admin {
|
|||
include_once dirname( __FILE__ ) . '/helper/class-wc-helper-plugin-info.php';
|
||||
include_once dirname( __FILE__ ) . '/helper/class-wc-helper-compat.php';
|
||||
include_once dirname( __FILE__ ) . '/helper/class-wc-helper.php';
|
||||
|
||||
// Marketplace suggestions & related REST API.
|
||||
include_once dirname( __FILE__ ) . '/marketplace-suggestions/class-wc-marketplace-suggestions.php';
|
||||
include_once dirname( __FILE__ ) . '/marketplace-suggestions/class-wc-marketplace-updater.php';
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -1007,7 +1007,7 @@ class WC_Helper {
|
|||
}
|
||||
|
||||
/**
|
||||
* Obtain a list of locally installed Woo extensions.
|
||||
* Obtain a list of data about locally installed Woo extensions.
|
||||
*/
|
||||
public static function get_local_woo_plugins() {
|
||||
if ( ! function_exists( 'get_plugins' ) ) {
|
||||
|
@ -1046,6 +1046,7 @@ class WC_Helper {
|
|||
$data['_product_id'] = absint( $product_id );
|
||||
$data['_file_id'] = $file_id;
|
||||
$data['_type'] = 'plugin';
|
||||
$data['slug'] = dirname( $filename );
|
||||
$woo_plugins[ $filename ] = $data;
|
||||
}
|
||||
|
||||
|
|
|
@ -47,9 +47,16 @@ class WC_Admin_List_Table_Orders extends WC_Admin_List_Table {
|
|||
*/
|
||||
protected function render_blank_state() {
|
||||
echo '<div class="woocommerce-BlankState">';
|
||||
|
||||
echo '<h2 class="woocommerce-BlankState-message">' . esc_html__( 'When you receive a new order, it will appear here.', 'woocommerce' ) . '</h2>';
|
||||
|
||||
echo '<div class="woocommerce-BlankState-buttons">';
|
||||
echo '<a class="woocommerce-BlankState-cta button-primary button" target="_blank" href="https://docs.woocommerce.com/document/managing-orders/?utm_source=blankslate&utm_medium=product&utm_content=ordersdoc&utm_campaign=woocommerceplugin">' . esc_html__( 'Learn more about orders', 'woocommerce' ) . '</a>';
|
||||
echo '</div>';
|
||||
|
||||
do_action( 'wc_marketplace_suggestions_orders_empty_state' );
|
||||
|
||||
echo '</div>';
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -48,9 +48,18 @@ class WC_Admin_List_Table_Products extends WC_Admin_List_Table {
|
|||
*/
|
||||
protected function render_blank_state() {
|
||||
echo '<div class="woocommerce-BlankState">';
|
||||
|
||||
echo '<h2 class="woocommerce-BlankState-message">' . esc_html__( 'Ready to start selling something awesome?', 'woocommerce' ) . '</h2>';
|
||||
echo '<a class="woocommerce-BlankState-cta button-primary button" href="' . esc_url( admin_url( 'post-new.php?post_type=product&tutorial=true' ) ) . '">' . esc_html__( 'Create your first product!', 'woocommerce' ) . '</a>';
|
||||
echo '<a class="woocommerce-BlankState-cta button" href="' . esc_url( admin_url( 'edit.php?post_type=product&page=product_importer' ) ) . '">' . esc_html__( 'Import products from a CSV file', 'woocommerce' ) . '</a>';
|
||||
|
||||
echo '<div class="woocommerce-BlankState-buttons">';
|
||||
|
||||
echo '<a class="woocommerce-BlankState-cta button-primary button" href="' . esc_url( admin_url( 'post-new.php?post_type=product&tutorial=true' ) ) . '">' . esc_html__( 'Create Product', 'woocommerce' ) . '</a>';
|
||||
echo '<a class="woocommerce-BlankState-cta button" href="' . esc_url( admin_url( 'edit.php?post_type=product&page=product_importer' ) ) . '">' . esc_html__( 'Start Import', 'woocommerce' ) . '</a>';
|
||||
|
||||
echo '</div>';
|
||||
|
||||
do_action( 'wc_marketplace_suggestions_products_empty_state' );
|
||||
|
||||
echo '</div>';
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,197 @@
|
|||
<?php
|
||||
/**
|
||||
* Marketplace suggestions
|
||||
*
|
||||
* Behaviour for displaying in-context suggestions for marketplace extensions.
|
||||
*
|
||||
* @package WooCommerce\Classes
|
||||
* @since 3.6.0
|
||||
*/
|
||||
|
||||
defined( 'ABSPATH' ) || exit;
|
||||
|
||||
/**
|
||||
* Marketplace suggestions core behaviour.
|
||||
*/
|
||||
class WC_Marketplace_Suggestions {
|
||||
|
||||
/**
|
||||
* Initialise.
|
||||
*/
|
||||
public static function init() {
|
||||
if ( ! self::allow_suggestions() ) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Add suggestions to the product tabs.
|
||||
add_action( 'woocommerce_product_data_tabs', array( __CLASS__, 'product_data_tabs' ) );
|
||||
add_action( 'woocommerce_product_data_panels', array( __CLASS__, 'product_data_panels' ) );
|
||||
|
||||
// Register ajax api handlers.
|
||||
add_action( 'wp_ajax_woocommerce_add_dismissed_marketplace_suggestion', array( __CLASS__, 'post_add_dismissed_suggestion_handler' ) );
|
||||
|
||||
// Register hooks for rendering suggestions container markup.
|
||||
add_action( 'wc_marketplace_suggestions_products_empty_state', array( __CLASS__, 'render_products_list_empty_state' ) );
|
||||
add_action( 'wc_marketplace_suggestions_orders_empty_state', array( __CLASS__, 'render_orders_list_empty_state' ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Product data tabs filter
|
||||
*
|
||||
* Adds a new Extensions tab to the product data meta box.
|
||||
*
|
||||
* @param array $tabs Existing tabs.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public static function product_data_tabs( $tabs ) {
|
||||
$tabs['marketplace-suggestions'] = array(
|
||||
'label' => _x( 'Get more options', 'Marketplace suggestions', 'woocommerce' ),
|
||||
'target' => 'marketplace_suggestions',
|
||||
'class' => array(),
|
||||
'priority' => 1000,
|
||||
);
|
||||
|
||||
return $tabs;
|
||||
}
|
||||
|
||||
/**
|
||||
* Render additional panels in the proudct data metabox.
|
||||
*/
|
||||
public static function product_data_panels() {
|
||||
include dirname( __FILE__ ) . '/templates/html-product-data-extensions.php';
|
||||
}
|
||||
|
||||
/**
|
||||
* Return an array of suggestions the user has dismissed.
|
||||
*/
|
||||
public static function get_dismissed_suggestions() {
|
||||
$dismissed_suggestions = array();
|
||||
|
||||
$dismissed_suggestions_data = get_user_meta( get_current_user_id(), 'wc_marketplace_suggestions_dismissed_suggestions', true );
|
||||
if ( $dismissed_suggestions_data ) {
|
||||
$dismissed_suggestions = $dismissed_suggestions_data;
|
||||
if ( ! is_array( $dismissed_suggestions ) ) {
|
||||
$dismissed_suggestions = array();
|
||||
}
|
||||
}
|
||||
|
||||
return $dismissed_suggestions;
|
||||
}
|
||||
|
||||
/**
|
||||
* POST handler for adding a dismissed suggestion.
|
||||
*/
|
||||
public static function post_add_dismissed_suggestion_handler() {
|
||||
if ( ! check_ajax_referer( 'add_dismissed_marketplace_suggestion' ) ) {
|
||||
wp_die();
|
||||
}
|
||||
|
||||
$post_data = wp_unslash( $_POST );
|
||||
$suggestion_slug = sanitize_text_field( $post_data['slug'] );
|
||||
if ( ! $suggestion_slug ) {
|
||||
wp_die();
|
||||
}
|
||||
|
||||
$dismissed_suggestions = self::get_dismissed_suggestions();
|
||||
|
||||
if ( in_array( $suggestion_slug, $dismissed_suggestions, true ) ) {
|
||||
wp_die();
|
||||
}
|
||||
|
||||
$dismissed_suggestions[] = $suggestion_slug;
|
||||
update_user_meta(
|
||||
get_current_user_id(),
|
||||
'wc_marketplace_suggestions_dismissed_suggestions',
|
||||
$dismissed_suggestions
|
||||
);
|
||||
|
||||
wp_die();
|
||||
}
|
||||
|
||||
/**
|
||||
* Render suggestions containers in products list empty state.
|
||||
*/
|
||||
public static function render_products_list_empty_state() {
|
||||
self::render_suggestions_container( 'products-list-empty-header' );
|
||||
self::render_suggestions_container( 'products-list-empty-body' );
|
||||
self::render_suggestions_container( 'products-list-empty-footer' );
|
||||
}
|
||||
|
||||
/**
|
||||
* Render suggestions containers in orders list empty state.
|
||||
*/
|
||||
public static function render_orders_list_empty_state() {
|
||||
self::render_suggestions_container( 'orders-list-empty-header' );
|
||||
self::render_suggestions_container( 'orders-list-empty-body' );
|
||||
self::render_suggestions_container( 'orders-list-empty-footer' );
|
||||
}
|
||||
|
||||
/**
|
||||
* Render a suggestions container element, with the specified context.
|
||||
*
|
||||
* @param string $context Suggestion context name (rendered as a css class).
|
||||
*/
|
||||
public static function render_suggestions_container( $context ) {
|
||||
include dirname( __FILE__ ) . '/views/container.php';
|
||||
}
|
||||
|
||||
/**
|
||||
* Should suggestions be displayed?
|
||||
*
|
||||
* @param string $screen_id The current admin screen.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public static function show_suggestions_for_screen( $screen_id ) {
|
||||
// We only show suggestions on certain admin screens.
|
||||
if ( ! in_array( $screen_id, array( 'edit-product', 'edit-shop_order', 'product' ), true ) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return self::allow_suggestions();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Should suggestions be displayed?
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public static function allow_suggestions() {
|
||||
// We currently only support English suggestions.
|
||||
$locale = get_locale();
|
||||
$suggestion_locales = array(
|
||||
'en_AU',
|
||||
'en_CA',
|
||||
'en_GB',
|
||||
'en_NZ',
|
||||
'en_US',
|
||||
'en_ZA',
|
||||
);
|
||||
if ( ! in_array( $locale, $suggestion_locales, true ) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Suggestions are only displayed if user can install plugins.
|
||||
if ( ! current_user_can( 'install_plugins' ) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// User can disabled all suggestions via filter.
|
||||
return apply_filters( 'woocommerce_allow_marketplace_suggestions', true );
|
||||
}
|
||||
|
||||
/**
|
||||
* Pull suggestion data from remote endpoint & cache in a transient.
|
||||
*
|
||||
* @return array of json API data
|
||||
*/
|
||||
public static function get_suggestions_api_data() {
|
||||
$data = get_option( 'woocommerce_marketplace_suggestions', array() );
|
||||
return ! empty( $data['suggestions'] ) ? $data['suggestions'] : array();
|
||||
}
|
||||
}
|
||||
|
||||
WC_Marketplace_Suggestions::init();
|
||||
|
|
@ -0,0 +1,86 @@
|
|||
<?php
|
||||
/**
|
||||
* Marketplace suggestions updater
|
||||
*
|
||||
* Uses WC_Queue to ensure marketplace suggestions data is up to date and cached locally.
|
||||
*
|
||||
* @package WooCommerce\Classes
|
||||
* @since 3.6.0
|
||||
*/
|
||||
|
||||
defined( 'ABSPATH' ) || exit;
|
||||
|
||||
/**
|
||||
* Marketplace Suggestions Updater
|
||||
*/
|
||||
class WC_Marketplace_Updater {
|
||||
|
||||
/**
|
||||
* Setup.
|
||||
*/
|
||||
public static function load() {
|
||||
add_action( 'init', array( __CLASS__, 'init' ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Schedule events and hook appropriate actions.
|
||||
*/
|
||||
public static function init() {
|
||||
$queue = WC()->queue();
|
||||
$next = $queue->get_next( 'woocommerce_update_marketplace_suggestions' );
|
||||
if ( ! $next ) {
|
||||
$queue->schedule_recurring( time(), WEEK_IN_SECONDS, 'woocommerce_update_marketplace_suggestions' );
|
||||
}
|
||||
|
||||
add_action( 'woocommerce_update_marketplace_suggestions', array( __CLASS__, 'update_marketplace_suggestions' ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetches new marketplace data, updates wc_marketplace_suggestions.
|
||||
*/
|
||||
public static function update_marketplace_suggestions() {
|
||||
$data = get_option(
|
||||
'woocommerce_marketplace_suggestions',
|
||||
array(
|
||||
'suggestions' => array(),
|
||||
'updated' => time(),
|
||||
)
|
||||
);
|
||||
|
||||
$data['updated'] = time();
|
||||
|
||||
$url = 'https://woocommerce.com/wp-json/wccom/marketplace-suggestions/1.0/suggestions.json';
|
||||
$request = wp_safe_remote_get( $url );
|
||||
|
||||
if ( is_wp_error( $request ) ) {
|
||||
self::retry();
|
||||
return update_option( 'woocommerce_marketplace_suggestions', $data, false );
|
||||
}
|
||||
|
||||
$body = wp_remote_retrieve_body( $request );
|
||||
if ( empty( $body ) ) {
|
||||
self::retry();
|
||||
return update_option( 'woocommerce_marketplace_suggestions', $data, false );
|
||||
}
|
||||
|
||||
$body = json_decode( $body, true );
|
||||
if ( empty( $body ) || ! is_array( $body ) ) {
|
||||
self::retry();
|
||||
return update_option( 'woocommerce_marketplace_suggestions', $data, false );
|
||||
}
|
||||
|
||||
$data['suggestions'] = $body;
|
||||
return update_option( 'woocommerce_marketplace_suggestions', $data, false );
|
||||
}
|
||||
|
||||
/**
|
||||
* Used when an error has occured when fetching suggestions.
|
||||
* Re-schedules the job earlier than the main weekly one.
|
||||
*/
|
||||
public static function retry() {
|
||||
WC()->queue()->cancel( 'woocommerce_update_marketplace_suggestions' );
|
||||
WC()->queue()->schedule_single( time() + DAY_IN_SECONDS, 'woocommerce_update_marketplace_suggestions' );
|
||||
}
|
||||
}
|
||||
|
||||
WC_Marketplace_Updater::load();
|
|
@ -0,0 +1,20 @@
|
|||
<?php
|
||||
/**
|
||||
* The marketplace suggestions tab HTML in the product tabs
|
||||
*
|
||||
* @package WooCommerce\Classes
|
||||
* @since 3.6.0
|
||||
*/
|
||||
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit;
|
||||
}
|
||||
|
||||
?>
|
||||
<div id="marketplace_suggestions" class="panel woocommerce_options_panel hidden">
|
||||
<?php
|
||||
WC_Marketplace_Suggestions::render_suggestions_container( 'product-edit-meta-tab-header' );
|
||||
WC_Marketplace_Suggestions::render_suggestions_container( 'product-edit-meta-tab-body' );
|
||||
WC_Marketplace_Suggestions::render_suggestions_container( 'product-edit-meta-tab-footer' );
|
||||
?>
|
||||
</div>
|
|
@ -0,0 +1,17 @@
|
|||
<?php
|
||||
/**
|
||||
* Marketplace suggestions container
|
||||
*
|
||||
* @package WooCommerce/Templates
|
||||
* @version 3.6.0
|
||||
*/
|
||||
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit;
|
||||
}
|
||||
|
||||
?>
|
||||
<div class="marketplace-suggestions-container"
|
||||
data-marketplace-suggestions-context="<?php echo esc_attr( $context ); ?>"
|
||||
>
|
||||
</div>
|
|
@ -34,10 +34,10 @@ class WC_REST_Product_Categories_Controller extends WC_REST_Product_Categories_V
|
|||
*/
|
||||
public function prepare_item_for_response( $item, $request ) {
|
||||
// Get category display type.
|
||||
$display_type = get_woocommerce_term_meta( $item->term_id, 'display_type' );
|
||||
$display_type = get_term_meta( $item->term_id, 'display_type' );
|
||||
|
||||
// Get category order.
|
||||
$menu_order = get_woocommerce_term_meta( $item->term_id, 'order' );
|
||||
$menu_order = get_term_meta( $item->term_id, 'order' );
|
||||
|
||||
$data = array(
|
||||
'id' => (int) $item->term_id,
|
||||
|
@ -52,7 +52,7 @@ class WC_REST_Product_Categories_Controller extends WC_REST_Product_Categories_V
|
|||
);
|
||||
|
||||
// Get category image.
|
||||
$image_id = get_woocommerce_term_meta( $item->term_id, 'thumbnail_id' );
|
||||
$image_id = get_term_meta( $item->term_id, 'thumbnail_id' );
|
||||
if ( $image_id ) {
|
||||
$attachment = get_post( $image_id );
|
||||
|
||||
|
|
|
@ -607,11 +607,11 @@ class WC_API_Products extends WC_API_Resource {
|
|||
$term_id = intval( $term->term_id );
|
||||
|
||||
// Get category display type
|
||||
$display_type = get_woocommerce_term_meta( $term_id, 'display_type' );
|
||||
$display_type = get_term_meta( $term_id, 'display_type' );
|
||||
|
||||
// Get category image
|
||||
$image = '';
|
||||
if ( $image_id = get_woocommerce_term_meta( $term_id, 'thumbnail_id' ) ) {
|
||||
if ( $image_id = get_term_meta( $term_id, 'thumbnail_id' ) ) {
|
||||
$image = wp_get_attachment_url( $image_id );
|
||||
}
|
||||
|
||||
|
|
|
@ -666,11 +666,11 @@ class WC_API_Products extends WC_API_Resource {
|
|||
$term_id = intval( $term->term_id );
|
||||
|
||||
// Get category display type
|
||||
$display_type = get_woocommerce_term_meta( $term_id, 'display_type' );
|
||||
$display_type = get_term_meta( $term_id, 'display_type' );
|
||||
|
||||
// Get category image
|
||||
$image = '';
|
||||
if ( $image_id = get_woocommerce_term_meta( $term_id, 'thumbnail_id' ) ) {
|
||||
if ( $image_id = get_term_meta( $term_id, 'thumbnail_id' ) ) {
|
||||
$image = wp_get_attachment_url( $image_id );
|
||||
}
|
||||
|
||||
|
@ -750,11 +750,11 @@ class WC_API_Products extends WC_API_Resource {
|
|||
|
||||
$id = $insert['term_id'];
|
||||
|
||||
update_woocommerce_term_meta( $id, 'display_type', 'default' === $data['display'] ? '' : sanitize_text_field( $data['display'] ) );
|
||||
update_term_meta( $id, 'display_type', 'default' === $data['display'] ? '' : sanitize_text_field( $data['display'] ) );
|
||||
|
||||
// Check if image_id is a valid image attachment before updating the term meta.
|
||||
if ( $image_id && wp_attachment_is_image( $image_id ) ) {
|
||||
update_woocommerce_term_meta( $id, 'thumbnail_id', $image_id );
|
||||
update_term_meta( $id, 'thumbnail_id', $image_id );
|
||||
}
|
||||
|
||||
do_action( 'woocommerce_api_create_product_category', $id, $data );
|
||||
|
@ -823,11 +823,11 @@ class WC_API_Products extends WC_API_Resource {
|
|||
}
|
||||
|
||||
if ( ! empty( $data['display'] ) ) {
|
||||
update_woocommerce_term_meta( $id, 'display_type', 'default' === $data['display'] ? '' : sanitize_text_field( $data['display'] ) );
|
||||
update_term_meta( $id, 'display_type', 'default' === $data['display'] ? '' : sanitize_text_field( $data['display'] ) );
|
||||
}
|
||||
|
||||
if ( isset( $image_id ) ) {
|
||||
update_woocommerce_term_meta( $id, 'thumbnail_id', $image_id );
|
||||
update_term_meta( $id, 'thumbnail_id', $image_id );
|
||||
}
|
||||
|
||||
do_action( 'woocommerce_api_edit_product_category', $id, $data );
|
||||
|
@ -861,11 +861,6 @@ class WC_API_Products extends WC_API_Resource {
|
|||
throw new WC_API_Exception( 'woocommerce_api_cannot_delete_product_category', __( 'Could not delete the category', 'woocommerce' ), 401 );
|
||||
}
|
||||
|
||||
// When a term is deleted, delete its meta.
|
||||
if ( get_option( 'db_version' ) < 34370 ) {
|
||||
$wpdb->delete( $wpdb->woocommerce_termmeta, array( 'woocommerce_term_id' => $id ), array( '%d' ) );
|
||||
}
|
||||
|
||||
do_action( 'woocommerce_api_delete_product_category', $id, $this );
|
||||
|
||||
return array( 'message' => sprintf( __( 'Deleted %s', 'woocommerce' ), 'product_category' ) );
|
||||
|
@ -2760,25 +2755,7 @@ class WC_API_Products extends WC_API_Resource {
|
|||
throw new WC_API_Exception( 'woocommerce_api_invalid_product_attribute_id', __( 'A product attribute with the provided ID could not be found', 'woocommerce' ), 404 );
|
||||
}
|
||||
|
||||
$args = array( 'hide_empty' => false );
|
||||
$orderby = wc_attribute_orderby( $taxonomy );
|
||||
|
||||
switch ( $orderby ) {
|
||||
case 'name' :
|
||||
$args['orderby'] = 'name';
|
||||
$args['menu_order'] = false;
|
||||
break;
|
||||
case 'id' :
|
||||
$args['orderby'] = 'id';
|
||||
$args['order'] = 'ASC';
|
||||
$args['menu_order'] = false;
|
||||
break;
|
||||
case 'menu_order' :
|
||||
$args['menu_order'] = 'ASC';
|
||||
break;
|
||||
}
|
||||
|
||||
$terms = get_terms( $taxonomy, $args );
|
||||
$terms = get_terms( $taxonomy, array( 'hide_empty' => false ) );
|
||||
$attribute_terms = array();
|
||||
|
||||
foreach ( $terms as $term ) {
|
||||
|
|
|
@ -134,7 +134,7 @@ class WC_REST_Product_Attribute_Terms_V1_Controller extends WC_REST_Terms_Contro
|
|||
*/
|
||||
public function prepare_item_for_response( $item, $request ) {
|
||||
// Get term order.
|
||||
$menu_order = get_woocommerce_term_meta( $item->term_id, 'order_' . $this->taxonomy );
|
||||
$menu_order = get_term_meta( $item->term_id, 'order_' . $this->taxonomy );
|
||||
|
||||
$data = array(
|
||||
'id' => (int) $item->term_id,
|
||||
|
@ -175,7 +175,7 @@ class WC_REST_Product_Attribute_Terms_V1_Controller extends WC_REST_Terms_Contro
|
|||
protected function update_term_meta_fields( $term, $request ) {
|
||||
$id = (int) $term->term_id;
|
||||
|
||||
update_woocommerce_term_meta( $id, 'order_' . $this->taxonomy, $request['menu_order'] );
|
||||
update_term_meta( $id, 'order_' . $this->taxonomy, $request['menu_order'] );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -52,10 +52,10 @@ class WC_REST_Product_Categories_V1_Controller extends WC_REST_Terms_Controller
|
|||
*/
|
||||
public function prepare_item_for_response( $item, $request ) {
|
||||
// Get category display type.
|
||||
$display_type = get_woocommerce_term_meta( $item->term_id, 'display_type' );
|
||||
$display_type = get_term_meta( $item->term_id, 'display_type' );
|
||||
|
||||
// Get category order.
|
||||
$menu_order = get_woocommerce_term_meta( $item->term_id, 'order' );
|
||||
$menu_order = get_term_meta( $item->term_id, 'order' );
|
||||
|
||||
$data = array(
|
||||
'id' => (int) $item->term_id,
|
||||
|
@ -70,7 +70,7 @@ class WC_REST_Product_Categories_V1_Controller extends WC_REST_Terms_Controller
|
|||
);
|
||||
|
||||
// Get category image.
|
||||
$image_id = get_woocommerce_term_meta( $item->term_id, 'thumbnail_id' );
|
||||
$image_id = get_term_meta( $item->term_id, 'thumbnail_id' );
|
||||
if ( $image_id ) {
|
||||
$attachment = get_post( $image_id );
|
||||
|
||||
|
@ -115,11 +115,11 @@ class WC_REST_Product_Categories_V1_Controller extends WC_REST_Terms_Controller
|
|||
$id = (int) $term->term_id;
|
||||
|
||||
if ( isset( $request['display'] ) ) {
|
||||
update_woocommerce_term_meta( $id, 'display_type', 'default' === $request['display'] ? '' : $request['display'] );
|
||||
update_term_meta( $id, 'display_type', 'default' === $request['display'] ? '' : $request['display'] );
|
||||
}
|
||||
|
||||
if ( isset( $request['menu_order'] ) ) {
|
||||
update_woocommerce_term_meta( $id, 'order', $request['menu_order'] );
|
||||
update_term_meta( $id, 'order', $request['menu_order'] );
|
||||
}
|
||||
|
||||
if ( isset( $request['image'] ) ) {
|
||||
|
@ -137,7 +137,7 @@ class WC_REST_Product_Categories_V1_Controller extends WC_REST_Terms_Controller
|
|||
|
||||
// Check if image_id is a valid image attachment before updating the term meta.
|
||||
if ( $image_id && wp_attachment_is_image( $image_id ) ) {
|
||||
update_woocommerce_term_meta( $id, 'thumbnail_id', $image_id );
|
||||
update_term_meta( $id, 'thumbnail_id', $image_id );
|
||||
|
||||
// Set the image alt.
|
||||
if ( ! empty( $request['image']['alt'] ) ) {
|
||||
|
@ -152,7 +152,7 @@ class WC_REST_Product_Categories_V1_Controller extends WC_REST_Terms_Controller
|
|||
) );
|
||||
}
|
||||
} else {
|
||||
delete_woocommerce_term_meta( $id, 'thumbnail_id' );
|
||||
delete_term_meta( $id, 'thumbnail_id' );
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -34,10 +34,10 @@ class WC_REST_Product_Categories_V2_Controller extends WC_REST_Product_Categorie
|
|||
*/
|
||||
public function prepare_item_for_response( $item, $request ) {
|
||||
// Get category display type.
|
||||
$display_type = get_woocommerce_term_meta( $item->term_id, 'display_type' );
|
||||
$display_type = get_term_meta( $item->term_id, 'display_type' );
|
||||
|
||||
// Get category order.
|
||||
$menu_order = get_woocommerce_term_meta( $item->term_id, 'order' );
|
||||
$menu_order = get_term_meta( $item->term_id, 'order' );
|
||||
|
||||
$data = array(
|
||||
'id' => (int) $item->term_id,
|
||||
|
@ -52,7 +52,7 @@ class WC_REST_Product_Categories_V2_Controller extends WC_REST_Product_Categorie
|
|||
);
|
||||
|
||||
// Get category image.
|
||||
$image_id = get_woocommerce_term_meta( $item->term_id, 'thumbnail_id' );
|
||||
$image_id = get_term_meta( $item->term_id, 'thumbnail_id' );
|
||||
if ( $image_id ) {
|
||||
$attachment = get_post( $image_id );
|
||||
|
||||
|
|
|
@ -698,10 +698,6 @@ class WC_REST_System_Status_V2_Controller extends WC_REST_Controller {
|
|||
)
|
||||
);
|
||||
|
||||
if ( get_option( 'db_version' ) < 34370 ) {
|
||||
$core_tables[] = 'woocommerce_termmeta';
|
||||
}
|
||||
|
||||
/**
|
||||
* Adding the prefix to the tables array, for backwards compatibility.
|
||||
*
|
||||
|
|
|
@ -90,6 +90,30 @@ class WC_Countries {
|
|||
return '';
|
||||
}
|
||||
|
||||
/**
|
||||
* Get calling code for a country code.
|
||||
*
|
||||
* @since 3.6.0
|
||||
* @param string $cc Country code.
|
||||
* @return string|array Some countries have multiple. The code will be stripped of - and spaces and always be prefixed with +.
|
||||
*/
|
||||
public function get_country_calling_code( $cc ) {
|
||||
$codes = wp_cache_get( 'calling-codes', 'countries' );
|
||||
|
||||
if ( ! $codes ) {
|
||||
$codes = include WC()->plugin_path() . '/i18n/phone.php';
|
||||
wp_cache_set( 'calling-codes', $codes, 'countries' );
|
||||
}
|
||||
|
||||
$calling_code = isset( $codes[ $cc ] ) ? $codes[ $cc ] : '';
|
||||
|
||||
if ( is_array( $calling_code ) ) {
|
||||
$calling_code = $calling_code[0];
|
||||
}
|
||||
|
||||
return $calling_code;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get continents that the store ships to.
|
||||
*
|
||||
|
|
|
@ -126,6 +126,7 @@ class WC_Install {
|
|||
),
|
||||
'3.6.0' => array(
|
||||
'wc_update_360_product_lookup_tables',
|
||||
'wc_update_360_term_meta',
|
||||
'wc_update_360_downloadable_product_permissions_index',
|
||||
'wc_update_360_db_version',
|
||||
),
|
||||
|
@ -539,7 +540,6 @@ class WC_Install {
|
|||
*
|
||||
* Tables:
|
||||
* woocommerce_attribute_taxonomies - Table for storing attribute taxonomies - these are user defined
|
||||
* woocommerce_termmeta - Term meta table - sadly WordPress does not have termmeta so we need our own
|
||||
* woocommerce_downloadable_product_permissions - Table for storing user and guest download permissions.
|
||||
* KEY(order_id, product_id, download_id) used for organizing downloads on the My Account page
|
||||
* woocommerce_order_items - Order line items are stored in a table to make them easily queryable for reports
|
||||
|
@ -844,23 +844,6 @@ CREATE TABLE {$wpdb->prefix}wc_product_meta_lookup (
|
|||
) $collate;
|
||||
";
|
||||
|
||||
/**
|
||||
* Term meta is only needed for old installs and is now @deprecated by WordPress term meta.
|
||||
*/
|
||||
if ( ! function_exists( 'get_term_meta' ) ) {
|
||||
$tables .= "
|
||||
CREATE TABLE {$wpdb->prefix}woocommerce_termmeta (
|
||||
meta_id BIGINT UNSIGNED NOT NULL auto_increment,
|
||||
woocommerce_term_id BIGINT UNSIGNED NOT NULL,
|
||||
meta_key varchar(255) default NULL,
|
||||
meta_value longtext NULL,
|
||||
PRIMARY KEY (meta_id),
|
||||
KEY woocommerce_term_id (woocommerce_term_id),
|
||||
KEY meta_key (meta_key(32))
|
||||
) $collate;
|
||||
";
|
||||
}
|
||||
|
||||
return $tables;
|
||||
}
|
||||
|
||||
|
@ -893,11 +876,6 @@ CREATE TABLE {$wpdb->prefix}woocommerce_termmeta (
|
|||
"{$wpdb->prefix}woocommerce_tax_rates",
|
||||
);
|
||||
|
||||
if ( ! function_exists( 'get_term_meta' ) ) {
|
||||
// This table is only needed for old installs and is now @deprecated by WordPress term meta.
|
||||
$tables[] = "{$wpdb->prefix}woocommerce_termmeta";
|
||||
}
|
||||
|
||||
/**
|
||||
* Filter the list of known WooCommerce tables.
|
||||
*
|
||||
|
|
|
@ -372,6 +372,7 @@ final class WooCommerce {
|
|||
include_once WC_ABSPATH . 'includes/class-wc-logger.php';
|
||||
include_once WC_ABSPATH . 'includes/queue/class-wc-action-queue.php';
|
||||
include_once WC_ABSPATH . 'includes/queue/class-wc-queue.php';
|
||||
include_once WC_ABSPATH . 'includes/admin/marketplace-suggestions/class-wc-marketplace-updater.php';
|
||||
|
||||
/**
|
||||
* Data stores - used to store and retrieve CRUD object data from the database.
|
||||
|
@ -712,12 +713,7 @@ final class WooCommerce {
|
|||
$wpdb->tables[] = 'woocommerce_order_itemmeta';
|
||||
|
||||
$wpdb->wc_product_meta_lookup = $wpdb->prefix . 'wc_product_meta_lookup';
|
||||
$wpdb->tables[] = 'wc_product_meta_lookup';
|
||||
|
||||
if ( get_option( 'db_version' ) < 34370 ) {
|
||||
$wpdb->woocommerce_termmeta = $wpdb->prefix . 'woocommerce_termmeta';
|
||||
$wpdb->tables[] = 'woocommerce_termmeta';
|
||||
}
|
||||
$wpdb->tables[] = 'wc_product_meta_lookup';
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -216,8 +216,9 @@ class WC_Gateway_Paypal_Request {
|
|||
* @return array
|
||||
*/
|
||||
protected function get_phone_number_args( $order ) {
|
||||
$phone_number = str_replace( array( '(', '-', ' ', ')', '.' ), '', $order->get_billing_phone() );
|
||||
|
||||
if ( in_array( $order->get_billing_country(), array( 'US', 'CA' ), true ) ) {
|
||||
$phone_number = str_replace( array( '(', '-', ' ', ')', '.' ), '', $order->get_billing_phone() );
|
||||
$phone_number = ltrim( $phone_number, '+1' );
|
||||
$phone_args = array(
|
||||
'night_phone_a' => substr( $phone_number, 0, 3 ),
|
||||
|
@ -225,8 +226,16 @@ class WC_Gateway_Paypal_Request {
|
|||
'night_phone_c' => substr( $phone_number, 6, 4 ),
|
||||
);
|
||||
} else {
|
||||
$calling_code = WC()->countries->get_country_calling_code( $order->get_billing_country() );
|
||||
$calling_code = is_array( $calling_code ) ? $calling_code[0] : $calling_code;
|
||||
|
||||
if ( $calling_code ) {
|
||||
$phone_number = str_replace( $calling_code, '', preg_replace( '/^0/', '', $order->get_billing_phone() ) );
|
||||
}
|
||||
|
||||
$phone_args = array(
|
||||
'night_phone_b' => $order->get_billing_phone(),
|
||||
'night_phone_a' => $calling_code,
|
||||
'night_phone_b' => $phone_number,
|
||||
);
|
||||
}
|
||||
return $phone_args;
|
||||
|
|
|
@ -531,9 +531,8 @@ function wc_create_attribute( $args ) {
|
|||
);
|
||||
|
||||
// Update taxonomy ordering term meta.
|
||||
$table_name = get_option( 'db_version' ) < 34370 ? $wpdb->prefix . 'woocommerce_termmeta' : $wpdb->termmeta;
|
||||
$wpdb->update(
|
||||
$table_name,
|
||||
$wpdb->termmeta,
|
||||
array( 'meta_key' => 'order_pa_' . sanitize_title( $data['attribute_name'] ) ), // WPCS: slow query ok.
|
||||
array( 'meta_key' => 'order_pa_' . sanitize_title( $old_slug ) ) // WPCS: slow query ok.
|
||||
);
|
||||
|
|
|
@ -1038,3 +1038,87 @@ function wc_get_min_max_price_meta_query( $args ) {
|
|||
$args
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* When a term is split, ensure meta data maintained.
|
||||
*
|
||||
* @deprecated 3.6.0
|
||||
* @param int $old_term_id Old term ID.
|
||||
* @param int $new_term_id New term ID.
|
||||
* @param string $term_taxonomy_id Term taxonomy ID.
|
||||
* @param string $taxonomy Taxonomy.
|
||||
*/
|
||||
function wc_taxonomy_metadata_update_content_for_split_terms( $old_term_id, $new_term_id, $term_taxonomy_id, $taxonomy ) {
|
||||
wc_deprecated_function( 'wc_taxonomy_metadata_update_content_for_split_terms', '3.6' );
|
||||
}
|
||||
|
||||
/**
|
||||
* WooCommerce Term Meta API.
|
||||
*
|
||||
* WC tables for storing term meta are deprecated from WordPress 4.4 since 4.4 has its own table.
|
||||
* This function serves as a wrapper, using the new table if present, or falling back to the WC table.
|
||||
*
|
||||
* @deprecated 3.6.0
|
||||
* @param int $term_id Term ID.
|
||||
* @param string $meta_key Meta key.
|
||||
* @param mixed $meta_value Meta value.
|
||||
* @param string $prev_value Previous value. (default: '').
|
||||
* @return bool
|
||||
*/
|
||||
function update_woocommerce_term_meta( $term_id, $meta_key, $meta_value, $prev_value = '' ) {
|
||||
wc_deprecated_function( 'update_woocommerce_term_meta', '3.6', 'update_term_meta' );
|
||||
return function_exists( 'update_term_meta' ) ? update_term_meta( $term_id, $meta_key, $meta_value, $prev_value ) : update_metadata( 'woocommerce_term', $term_id, $meta_key, $meta_value, $prev_value );
|
||||
}
|
||||
|
||||
/**
|
||||
* WooCommerce Term Meta API.
|
||||
*
|
||||
* WC tables for storing term meta are deprecated from WordPress 4.4 since 4.4 has its own table.
|
||||
* This function serves as a wrapper, using the new table if present, or falling back to the WC table.
|
||||
*
|
||||
* @deprecated 3.6.0
|
||||
* @param int $term_id Term ID.
|
||||
* @param string $meta_key Meta key.
|
||||
* @param mixed $meta_value Meta value.
|
||||
* @param bool $unique Make meta key unique. (default: false).
|
||||
* @return bool
|
||||
*/
|
||||
function add_woocommerce_term_meta( $term_id, $meta_key, $meta_value, $unique = false ) {
|
||||
wc_deprecated_function( 'add_woocommerce_term_meta', '3.6', 'add_term_meta' );
|
||||
return function_exists( 'add_term_meta' ) ? add_term_meta( $term_id, $meta_key, $meta_value, $unique ) : add_metadata( 'woocommerce_term', $term_id, $meta_key, $meta_value, $unique );
|
||||
}
|
||||
|
||||
/**
|
||||
* WooCommerce Term Meta API
|
||||
*
|
||||
* WC tables for storing term meta are deprecated from WordPress 4.4 since 4.4 has its own table.
|
||||
* This function serves as a wrapper, using the new table if present, or falling back to the WC table.
|
||||
*
|
||||
* @deprecated 3.6.0
|
||||
* @param int $term_id Term ID.
|
||||
* @param string $meta_key Meta key.
|
||||
* @param string $meta_value Meta value (default: '').
|
||||
* @param bool $deprecated Deprecated param (default: false).
|
||||
* @return bool
|
||||
*/
|
||||
function delete_woocommerce_term_meta( $term_id, $meta_key, $meta_value = '', $deprecated = false ) {
|
||||
wc_deprecated_function( 'delete_woocommerce_term_meta', '3.6', 'delete_term_meta' );
|
||||
return function_exists( 'delete_term_meta' ) ? delete_term_meta( $term_id, $meta_key, $meta_value ) : delete_metadata( 'woocommerce_term', $term_id, $meta_key, $meta_value );
|
||||
}
|
||||
|
||||
/**
|
||||
* WooCommerce Term Meta API
|
||||
*
|
||||
* WC tables for storing term meta are deprecated from WordPress 4.4 since 4.4 has its own table.
|
||||
* This function serves as a wrapper, using the new table if present, or falling back to the WC table.
|
||||
*
|
||||
* @deprecated 3.6.0
|
||||
* @param int $term_id Term ID.
|
||||
* @param string $key Meta key.
|
||||
* @param bool $single Whether to return a single value. (default: true).
|
||||
* @return mixed
|
||||
*/
|
||||
function get_woocommerce_term_meta( $term_id, $key, $single = true ) {
|
||||
wc_deprecated_function( 'get_woocommerce_term_meta', '3.6', 'get_term_meta' );
|
||||
return function_exists( 'get_term_meta' ) ? get_term_meta( $term_id, $key, $single ) : get_metadata( 'woocommerce_term', $term_id, $key, $single );
|
||||
}
|
||||
|
|
|
@ -2239,7 +2239,7 @@ if ( ! function_exists( 'woocommerce_get_loop_display_mode' ) ) {
|
|||
$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 = get_term_meta( $parent_id, 'display_type', true );
|
||||
$display_type = '' === $display_type ? get_option( 'woocommerce_category_archive_display', '' ) : $display_type;
|
||||
}
|
||||
|
||||
|
@ -2415,7 +2415,8 @@ if ( ! function_exists( 'woocommerce_get_product_subcategories' ) ) {
|
|||
*/
|
||||
function woocommerce_get_product_subcategories( $parent_id = 0 ) {
|
||||
$parent_id = absint( $parent_id );
|
||||
$product_categories = wp_cache_get( 'product-category-hierarchy-' . $parent_id, 'product_cat' );
|
||||
$cache_key = apply_filters( 'woocommerce_get_product_subcategories_cache_key', 'product-category-hierarchy-' . $parent_id, $parent_id );
|
||||
$product_categories = $cache_key ? wp_cache_get( $cache_key, 'product_cat' ) : false;
|
||||
|
||||
if ( false === $product_categories ) {
|
||||
// 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.
|
||||
|
@ -2424,7 +2425,6 @@ if ( ! function_exists( 'woocommerce_get_product_subcategories' ) ) {
|
|||
'woocommerce_product_subcategories_args',
|
||||
array(
|
||||
'parent' => $parent_id,
|
||||
'menu_order' => 'ASC',
|
||||
'hide_empty' => 0,
|
||||
'hierarchical' => 1,
|
||||
'taxonomy' => 'product_cat',
|
||||
|
@ -2433,7 +2433,9 @@ if ( ! function_exists( 'woocommerce_get_product_subcategories' ) ) {
|
|||
)
|
||||
);
|
||||
|
||||
wp_cache_set( 'product-category-hierarchy-' . $parent_id, $product_categories, 'product_cat' );
|
||||
if ( $cache_key ) {
|
||||
wp_cache_set( $cache_key, $product_categories, 'product_cat' );
|
||||
}
|
||||
}
|
||||
|
||||
if ( apply_filters( 'woocommerce_product_subcategories_hide_empty', true ) ) {
|
||||
|
@ -2454,7 +2456,7 @@ if ( ! function_exists( 'woocommerce_subcategory_thumbnail' ) ) {
|
|||
function woocommerce_subcategory_thumbnail( $category ) {
|
||||
$small_thumbnail_size = apply_filters( 'subcategory_archive_thumbnail_size', 'woocommerce_thumbnail' );
|
||||
$dimensions = wc_get_image_size( $small_thumbnail_size );
|
||||
$thumbnail_id = get_woocommerce_term_meta( $category->term_id, 'thumbnail_id', true );
|
||||
$thumbnail_id = get_term_meta( $category->term_id, 'thumbnail_id', true );
|
||||
|
||||
if ( $thumbnail_id ) {
|
||||
$image = wp_get_attachment_image_src( $thumbnail_id, $small_thumbnail_size );
|
||||
|
|
|
@ -10,6 +10,99 @@
|
|||
|
||||
defined( 'ABSPATH' ) || exit;
|
||||
|
||||
/**
|
||||
* Change get terms defaults for attributes to order by the sorting setting, or default to menu_order for sortable taxonomies.
|
||||
*
|
||||
* @since 3.6.0 Sorting options are now set as the default automatically, so you no longer have to request to orderby menu_order.
|
||||
*
|
||||
* @param array $defaults An array of default get_terms() arguments.
|
||||
* @param array $taxonomies An array of taxonomies.
|
||||
* @return array
|
||||
*/
|
||||
function wc_change_get_terms_defaults( $defaults, $taxonomies ) {
|
||||
if ( is_array( $taxonomies ) && 1 < count( $taxonomies ) ) {
|
||||
return $defaults;
|
||||
}
|
||||
$taxonomy = is_array( $taxonomies ) ? $taxonomies[0] : $taxonomies;
|
||||
$orderby = 'name';
|
||||
|
||||
if ( taxonomy_is_product_attribute( $taxonomy ) ) {
|
||||
$orderby = wc_attribute_orderby( $taxonomy );
|
||||
} elseif ( in_array( $taxonomy, apply_filters( 'woocommerce_sortable_taxonomies', array( 'product_cat' ) ), true ) ) {
|
||||
$orderby = 'menu_order';
|
||||
}
|
||||
|
||||
switch ( $orderby ) {
|
||||
case 'menu_order':
|
||||
$defaults['orderby'] = 'meta_value_num';
|
||||
$defaults['meta_key'] = 'order'; // phpcs:ignore
|
||||
$defaults['force_menu_order_sort'] = true;
|
||||
break;
|
||||
case 'name_num':
|
||||
$defaults['orderby'] = 'name';
|
||||
$defaults['force_numeric_name'] = true;
|
||||
break;
|
||||
case 'parent':
|
||||
$defaults['orderby'] = 'parent';
|
||||
break;
|
||||
}
|
||||
|
||||
return $defaults;
|
||||
}
|
||||
add_filter( 'get_terms_defaults', 'wc_change_get_terms_defaults', 10, 2 );
|
||||
|
||||
/**
|
||||
* Adds support to get_terms for menu_order argument.
|
||||
*
|
||||
* @since 3.6.0
|
||||
* @param WP_Term_Query $terms_query Instance of WP_Term_Query.
|
||||
*/
|
||||
function wc_change_pre_get_terms( $terms_query ) {
|
||||
$args = &$terms_query->query_vars;
|
||||
|
||||
if ( ! empty( $args['menu_order'] ) ) {
|
||||
$args['order'] = 'DESC' === strtoupper( $args['menu_order'] ) ? 'DESC' : 'ASC';
|
||||
$args['orderby'] = 'meta_value_num';
|
||||
$args['meta_key'] = 'order'; // phpcs:ignore
|
||||
$args['force_menu_order_sort'] = true;
|
||||
$terms_query->meta_query->parse_query_vars( $args );
|
||||
}
|
||||
|
||||
}
|
||||
add_action( 'pre_get_terms', 'wc_change_pre_get_terms', 10, 1 );
|
||||
|
||||
/**
|
||||
* Adjust term query to handle custom sorting parameters.
|
||||
*
|
||||
* @param array $clauses Clauses.
|
||||
* @param array $taxonomies Taxonomies.
|
||||
* @param array $args Arguments.
|
||||
* @return array
|
||||
*/
|
||||
function wc_terms_clauses( $clauses, $taxonomies, $args ) {
|
||||
global $wpdb;
|
||||
|
||||
// No need to filter when counting.
|
||||
if ( strpos( 'COUNT(*)', $clauses['fields'] ) !== false ) {
|
||||
return $clauses;
|
||||
}
|
||||
|
||||
// Force numeric sort if using name_num custom sorting param.
|
||||
if ( ! empty( $args['force_numeric_name'] ) ) {
|
||||
$clauses['orderby'] = str_replace( 'ORDER BY t.name', 'ORDER BY t.name+0', $clauses['orderby'] );
|
||||
}
|
||||
|
||||
// For sorting, force left join in case order meta is missing.
|
||||
if ( ! empty( $args['force_menu_order_sort'] ) ) {
|
||||
$clauses['join'] = str_replace( "INNER JOIN {$wpdb->termmeta} ON ( t.term_id = {$wpdb->termmeta}.term_id )", "LEFT JOIN {$wpdb->termmeta} ON ( t.term_id = {$wpdb->termmeta}.term_id AND {$wpdb->termmeta}.meta_key='order')", $clauses['join'] );
|
||||
$clauses['where'] = str_replace( "{$wpdb->termmeta}.meta_key = 'order'", "{$wpdb->termmeta}.meta_key = 'order' OR {$wpdb->termmeta}.meta_key IS NULL", $clauses['where'] );
|
||||
$clauses['orderby'] = 'DESC' === $args['order'] ? str_replace( 'meta_value+0', 'meta_value+0 DESC, t.name', $clauses['orderby'] ) : str_replace( 'meta_value+0', 'meta_value+0 ASC, t.name', $clauses['orderby'] );
|
||||
}
|
||||
|
||||
return $clauses;
|
||||
}
|
||||
add_filter( 'terms_clauses', 'wc_terms_clauses', 99, 3 );
|
||||
|
||||
/**
|
||||
* Helper to get cached object terms and filter by field using wp_list_pluck().
|
||||
* Works as a cached alternative for wp_get_post_terms() and wp_get_object_terms().
|
||||
|
@ -59,10 +152,7 @@ function _wc_get_cached_product_terms( $product_id, $taxonomy, $args = array() )
|
|||
}
|
||||
|
||||
/**
|
||||
* Wrapper for wp_get_post_terms which supports ordering by parent.
|
||||
*
|
||||
* NOTE: At this point in time, ordering by menu_order for example isn't possible with this function. wp_get_post_terms has no.
|
||||
* filters which we can utilise to modify it's query. https://core.trac.wordpress.org/ticket/19094.
|
||||
* Wrapper used to get terms for a product.
|
||||
*
|
||||
* @param int $product_id Product ID.
|
||||
* @param string $taxonomy Taxonomy slug.
|
||||
|
@ -74,65 +164,7 @@ function wc_get_product_terms( $product_id, $taxonomy, $args = array() ) {
|
|||
return array();
|
||||
}
|
||||
|
||||
if ( empty( $args['orderby'] ) && taxonomy_is_product_attribute( $taxonomy ) ) {
|
||||
$args['orderby'] = wc_attribute_orderby( $taxonomy );
|
||||
}
|
||||
|
||||
// Support ordering by parent.
|
||||
if ( ! empty( $args['orderby'] ) && in_array( $args['orderby'], array( 'name_num', 'parent' ), true ) ) {
|
||||
$fields = isset( $args['fields'] ) ? $args['fields'] : 'all';
|
||||
$orderby = $args['orderby'];
|
||||
|
||||
// Unset for wp_get_post_terms.
|
||||
unset( $args['orderby'] );
|
||||
unset( $args['fields'] );
|
||||
|
||||
$terms = _wc_get_cached_product_terms( $product_id, $taxonomy, $args );
|
||||
|
||||
switch ( $orderby ) {
|
||||
case 'name_num':
|
||||
usort( $terms, '_wc_get_product_terms_name_num_usort_callback' );
|
||||
break;
|
||||
case 'parent':
|
||||
usort( $terms, '_wc_get_product_terms_parent_usort_callback' );
|
||||
break;
|
||||
}
|
||||
|
||||
switch ( $fields ) {
|
||||
case 'names':
|
||||
$terms = wp_list_pluck( $terms, 'name' );
|
||||
break;
|
||||
case 'ids':
|
||||
$terms = wp_list_pluck( $terms, 'term_id' );
|
||||
break;
|
||||
case 'slugs':
|
||||
$terms = wp_list_pluck( $terms, 'slug' );
|
||||
break;
|
||||
}
|
||||
} elseif ( ! empty( $args['orderby'] ) && 'menu_order' === $args['orderby'] ) {
|
||||
// wp_get_post_terms doesn't let us use custom sort order.
|
||||
$args['include'] = wc_get_object_terms( $product_id, $taxonomy, 'term_id' );
|
||||
|
||||
if ( empty( $args['include'] ) ) {
|
||||
$terms = array();
|
||||
} else {
|
||||
// This isn't needed for get_terms.
|
||||
unset( $args['orderby'] );
|
||||
|
||||
// Set args for get_terms.
|
||||
$args['menu_order'] = isset( $args['order'] ) ? $args['order'] : 'ASC';
|
||||
$args['hide_empty'] = isset( $args['hide_empty'] ) ? $args['hide_empty'] : 0;
|
||||
$args['fields'] = isset( $args['fields'] ) ? $args['fields'] : 'names';
|
||||
|
||||
// Ensure slugs is valid for get_terms - slugs isn't supported.
|
||||
$args['fields'] = ( 'slugs' === $args['fields'] ) ? 'id=>slug' : $args['fields'];
|
||||
$terms = get_terms( $taxonomy, $args );
|
||||
}
|
||||
} else {
|
||||
$terms = _wc_get_cached_product_terms( $product_id, $taxonomy, $args );
|
||||
}
|
||||
|
||||
return apply_filters( 'woocommerce_get_product_terms', $terms, $product_id, $taxonomy, $args );
|
||||
return apply_filters( 'woocommerce_get_product_terms', _wc_get_cached_product_terms( $product_id, $taxonomy, $args ), $product_id, $taxonomy, $args );
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -176,7 +208,8 @@ function wc_product_dropdown_categories( $args = array() ) {
|
|||
global $wp_query;
|
||||
|
||||
$args = wp_parse_args(
|
||||
$args, array(
|
||||
$args,
|
||||
array(
|
||||
'pad_counts' => 1,
|
||||
'show_count' => 1,
|
||||
'hierarchical' => 1,
|
||||
|
@ -184,7 +217,6 @@ function wc_product_dropdown_categories( $args = array() ) {
|
|||
'show_uncategorized' => 1,
|
||||
'orderby' => 'name',
|
||||
'selected' => isset( $wp_query->query_vars['product_cat'] ) ? $wp_query->query_vars['product_cat'] : '',
|
||||
'menu_order' => false,
|
||||
'show_option_none' => __( 'Select a category', 'woocommerce' ),
|
||||
'option_none_value' => '',
|
||||
'value_field' => 'slug',
|
||||
|
@ -195,8 +227,8 @@ function wc_product_dropdown_categories( $args = array() ) {
|
|||
);
|
||||
|
||||
if ( 'order' === $args['orderby'] ) {
|
||||
$args['menu_order'] = 'asc';
|
||||
$args['orderby'] = 'name';
|
||||
$args['orderby'] = 'meta_value_num';
|
||||
$args['meta_key'] = 'order'; // phpcs:ignore
|
||||
}
|
||||
|
||||
wp_dropdown_categories( $args );
|
||||
|
@ -226,39 +258,6 @@ function wc_walk_category_dropdown_tree() {
|
|||
return call_user_func_array( array( &$walker, 'walk' ), $args );
|
||||
}
|
||||
|
||||
/**
|
||||
* When a term is split, ensure meta data maintained.
|
||||
*
|
||||
* @param int $old_term_id Old term ID.
|
||||
* @param int $new_term_id New term ID.
|
||||
* @param string $term_taxonomy_id Term taxonomy ID.
|
||||
* @param string $taxonomy Taxonomy.
|
||||
*/
|
||||
function wc_taxonomy_metadata_update_content_for_split_terms( $old_term_id, $new_term_id, $term_taxonomy_id, $taxonomy ) {
|
||||
global $wpdb;
|
||||
|
||||
if ( get_option( 'db_version' ) < 34370 ) {
|
||||
if ( 'product_cat' === $taxonomy || taxonomy_is_product_attribute( $taxonomy ) ) {
|
||||
$old_meta_data = $wpdb->get_results( $wpdb->prepare( "SELECT meta_key, meta_value FROM {$wpdb->prefix}woocommerce_termmeta WHERE woocommerce_term_id = %d;", $old_term_id ) );
|
||||
|
||||
// Copy across to split term.
|
||||
if ( $old_meta_data ) {
|
||||
foreach ( $old_meta_data as $meta_data ) {
|
||||
$wpdb->insert(
|
||||
"{$wpdb->prefix}woocommerce_termmeta",
|
||||
array(
|
||||
'woocommerce_term_id' => $new_term_id,
|
||||
'meta_key' => $meta_data->meta_key, // WPCS: slow query ok.
|
||||
'meta_value' => $meta_data->meta_value, // WPCS: slow query ok.
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
add_action( 'split_shared_term', 'wc_taxonomy_metadata_update_content_for_split_terms', 10, 4 );
|
||||
|
||||
/**
|
||||
* Migrate data from WC term meta to WP term meta.
|
||||
*
|
||||
|
@ -278,69 +277,6 @@ function wc_taxonomy_metadata_migrate_data( $wp_db_version, $wp_current_db_versi
|
|||
}
|
||||
add_action( 'wp_upgrade', 'wc_taxonomy_metadata_migrate_data', 10, 2 );
|
||||
|
||||
/**
|
||||
* WooCommerce Term Meta API.
|
||||
*
|
||||
* WC tables for storing term meta are @deprecated from WordPress 4.4 since 4.4 has its own table.
|
||||
* This function serves as a wrapper, using the new table if present, or falling back to the WC table.
|
||||
*
|
||||
* @param int $term_id Term ID.
|
||||
* @param string $meta_key Meta key.
|
||||
* @param mixed $meta_value Meta value.
|
||||
* @param string $prev_value Previous value. (default: '').
|
||||
* @return bool
|
||||
*/
|
||||
function update_woocommerce_term_meta( $term_id, $meta_key, $meta_value, $prev_value = '' ) {
|
||||
return function_exists( 'update_term_meta' ) ? update_term_meta( $term_id, $meta_key, $meta_value, $prev_value ) : update_metadata( 'woocommerce_term', $term_id, $meta_key, $meta_value, $prev_value );
|
||||
}
|
||||
|
||||
/**
|
||||
* WooCommerce Term Meta API.
|
||||
*
|
||||
* WC tables for storing term meta are @deprecated from WordPress 4.4 since 4.4 has its own table.
|
||||
* This function serves as a wrapper, using the new table if present, or falling back to the WC table.
|
||||
*
|
||||
* @param int $term_id Term ID.
|
||||
* @param string $meta_key Meta key.
|
||||
* @param mixed $meta_value Meta value.
|
||||
* @param bool $unique Make meta key unique. (default: false).
|
||||
* @return bool
|
||||
*/
|
||||
function add_woocommerce_term_meta( $term_id, $meta_key, $meta_value, $unique = false ) {
|
||||
return function_exists( 'add_term_meta' ) ? add_term_meta( $term_id, $meta_key, $meta_value, $unique ) : add_metadata( 'woocommerce_term', $term_id, $meta_key, $meta_value, $unique );
|
||||
}
|
||||
|
||||
/**
|
||||
* WooCommerce Term Meta API
|
||||
*
|
||||
* WC tables for storing term meta are @deprecated from WordPress 4.4 since 4.4 has its own table.
|
||||
* This function serves as a wrapper, using the new table if present, or falling back to the WC table.
|
||||
*
|
||||
* @param int $term_id Term ID.
|
||||
* @param string $meta_key Meta key.
|
||||
* @param string $meta_value Meta value (default: '').
|
||||
* @param bool $deprecated Deprecated param (default: false).
|
||||
* @return bool
|
||||
*/
|
||||
function delete_woocommerce_term_meta( $term_id, $meta_key, $meta_value = '', $deprecated = false ) {
|
||||
return function_exists( 'delete_term_meta' ) ? delete_term_meta( $term_id, $meta_key, $meta_value ) : delete_metadata( 'woocommerce_term', $term_id, $meta_key, $meta_value );
|
||||
}
|
||||
|
||||
/**
|
||||
* WooCommerce Term Meta API
|
||||
*
|
||||
* WC tables for storing term meta are @deprecated from WordPress 4.4 since 4.4 has its own table.
|
||||
* This function serves as a wrapper, using the new table if present, or falling back to the WC table.
|
||||
*
|
||||
* @param int $term_id Term ID.
|
||||
* @param string $key Meta key.
|
||||
* @param bool $single Whether to return a single value. (default: true).
|
||||
* @return mixed
|
||||
*/
|
||||
function get_woocommerce_term_meta( $term_id, $key, $single = true ) {
|
||||
return function_exists( 'get_term_meta' ) ? get_term_meta( $term_id, $key, $single ) : get_metadata( 'woocommerce_term', $term_id, $key, $single );
|
||||
}
|
||||
|
||||
/**
|
||||
* Move a term before the a given element of its hierarchy level.
|
||||
*
|
||||
|
@ -353,7 +289,7 @@ function get_woocommerce_term_meta( $term_id, $key, $single = true ) {
|
|||
*/
|
||||
function wc_reorder_terms( $the_term, $next_id, $taxonomy, $index = 0, $terms = null ) {
|
||||
if ( ! $terms ) {
|
||||
$terms = get_terms( $taxonomy, 'menu_order=ASC&hide_empty=0&parent=0' );
|
||||
$terms = get_terms( $taxonomy, 'hide_empty=0&parent=0&menu_order=ASC' );
|
||||
}
|
||||
if ( empty( $terms ) ) {
|
||||
return $index;
|
||||
|
@ -386,7 +322,7 @@ function wc_reorder_terms( $the_term, $next_id, $taxonomy, $index = 0, $terms =
|
|||
do_action( 'woocommerce_after_set_term_order', $term, $index, $taxonomy );
|
||||
|
||||
// If that term has children we walk through them.
|
||||
$children = get_terms( $taxonomy, "parent={$term_id}&menu_order=ASC&hide_empty=0" );
|
||||
$children = get_terms( $taxonomy, "parent={$term_id}&hide_empty=0&menu_order=ASC" );
|
||||
if ( ! empty( $children ) ) {
|
||||
$index = wc_reorder_terms( $the_term, $next_id, $taxonomy, $index, $children );
|
||||
}
|
||||
|
@ -414,20 +350,13 @@ function wc_set_term_order( $term_id, $index, $taxonomy, $recursive = false ) {
|
|||
$term_id = (int) $term_id;
|
||||
$index = (int) $index;
|
||||
|
||||
// Meta name.
|
||||
if ( taxonomy_is_product_attribute( $taxonomy ) ) {
|
||||
$meta_name = 'order_' . esc_attr( $taxonomy );
|
||||
} else {
|
||||
$meta_name = 'order';
|
||||
}
|
||||
|
||||
update_woocommerce_term_meta( $term_id, $meta_name, $index );
|
||||
update_term_meta( $term_id, 'order', $index );
|
||||
|
||||
if ( ! $recursive ) {
|
||||
return $index;
|
||||
}
|
||||
|
||||
$children = get_terms( $taxonomy, "parent=$term_id&menu_order=ASC&hide_empty=0" );
|
||||
$children = get_terms( $taxonomy, "parent=$term_id&hide_empty=0&menu_order=ASC" );
|
||||
|
||||
foreach ( $children as $term ) {
|
||||
$index++;
|
||||
|
@ -439,104 +368,6 @@ function wc_set_term_order( $term_id, $index, $taxonomy, $recursive = false ) {
|
|||
return $index;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add term ordering to get_terms.
|
||||
*
|
||||
* It enables the support a 'menu_order' parameter to get_terms for the product_cat taxonomy.
|
||||
* By default it is 'ASC'. It accepts 'DESC' too.
|
||||
*
|
||||
* To disable it, set it ot false (or 0).
|
||||
*
|
||||
* @param array $clauses Clauses.
|
||||
* @param array $taxonomies Taxonomies.
|
||||
* @param array $args Arguments.
|
||||
* @return array
|
||||
*/
|
||||
function wc_terms_clauses( $clauses, $taxonomies, $args ) {
|
||||
global $wpdb;
|
||||
|
||||
// No sorting when menu_order is false.
|
||||
if ( isset( $args['menu_order'] ) && ( false === $args['menu_order'] || 'false' === $args['menu_order'] ) ) {
|
||||
return $clauses;
|
||||
}
|
||||
|
||||
// No sorting when orderby is non default.
|
||||
if ( isset( $args['orderby'] ) && 'name' !== $args['orderby'] ) {
|
||||
return $clauses;
|
||||
}
|
||||
|
||||
// No sorting in admin when sorting by a column.
|
||||
if ( is_admin() && isset( $_GET['orderby'] ) ) { // WPCS: input var ok, CSRF ok.
|
||||
return $clauses;
|
||||
}
|
||||
|
||||
// No need to filter counts.
|
||||
if ( strpos( 'COUNT(*)', $clauses['fields'] ) !== false ) {
|
||||
return $clauses;
|
||||
}
|
||||
|
||||
// WordPress should give us the taxonomies asked when calling the get_terms function. Only apply to categories and pa_ attributes.
|
||||
$found = false;
|
||||
|
||||
foreach ( (array) $taxonomies as $taxonomy ) {
|
||||
if ( taxonomy_is_product_attribute( $taxonomy ) || in_array( $taxonomy, apply_filters( 'woocommerce_sortable_taxonomies', array( 'product_cat' ) ), true ) ) {
|
||||
|
||||
// Don't modify the orderby when we're ordering attributes by name.
|
||||
if ( taxonomy_is_product_attribute( $taxonomy ) && 'name' === wc_attribute_orderby( $taxonomy ) ) {
|
||||
return $clauses;
|
||||
}
|
||||
|
||||
$found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if ( ! $found ) {
|
||||
return $clauses;
|
||||
}
|
||||
|
||||
// Meta name.
|
||||
if ( ! empty( $taxonomies[0] ) && taxonomy_is_product_attribute( $taxonomies[0] ) ) {
|
||||
$meta_name = 'order_' . esc_attr( $taxonomies[0] );
|
||||
} else {
|
||||
$meta_name = 'order';
|
||||
}
|
||||
|
||||
// Query fields.
|
||||
$clauses['fields'] = $clauses['fields'] . ', tm.meta_value';
|
||||
|
||||
// Query join.
|
||||
if ( get_option( 'db_version' ) < 34370 ) {
|
||||
$clauses['join'] .= " LEFT JOIN {$wpdb->woocommerce_termmeta} AS tm ON (t.term_id = tm.woocommerce_term_id AND tm.meta_key = '" . esc_sql( $meta_name ) . "') ";
|
||||
} else {
|
||||
$clauses['join'] .= " LEFT JOIN {$wpdb->termmeta} AS tm ON (t.term_id = tm.term_id AND tm.meta_key = '" . esc_sql( $meta_name ) . "') ";
|
||||
}
|
||||
|
||||
// Default to ASC.
|
||||
if ( ! isset( $args['menu_order'] ) || ! in_array( strtoupper( $args['menu_order'] ), array( 'ASC', 'DESC' ), true ) ) {
|
||||
$args['menu_order'] = 'ASC';
|
||||
}
|
||||
|
||||
$order = 'ORDER BY tm.meta_value+0 ' . $args['menu_order'];
|
||||
|
||||
if ( $clauses['orderby'] ) {
|
||||
$clauses['orderby'] = str_replace( 'ORDER BY', $order . ',', $clauses['orderby'] );
|
||||
} else {
|
||||
$clauses['orderby'] = $order;
|
||||
}
|
||||
|
||||
// Grouping.
|
||||
if ( strstr( $clauses['fields'], 'tr.object_id' ) ) {
|
||||
$clauses['orderby'] = ' GROUP BY t.term_id, tr.object_id ' . $clauses['orderby'];
|
||||
} else {
|
||||
$clauses['orderby'] = ' GROUP BY t.term_id ' . $clauses['orderby'];
|
||||
}
|
||||
|
||||
return $clauses;
|
||||
}
|
||||
|
||||
add_filter( 'terms_clauses', 'wc_terms_clauses', 99, 3 );
|
||||
|
||||
/**
|
||||
* Function for recounting product terms, ignoring hidden products.
|
||||
*
|
||||
|
@ -632,7 +463,7 @@ function _wc_term_recount( $terms, $taxonomy, $callback = true, $terms_are_term_
|
|||
$count = $wpdb->get_var( implode( ' ', $term_query ) ); // WPCS: unprepared SQL ok.
|
||||
|
||||
// Update the count.
|
||||
update_woocommerce_term_meta( $term_id, 'product_count_' . $taxonomy->name, absint( $count ) );
|
||||
update_term_meta( $term_id, 'product_count_' . $taxonomy->name, absint( $count ) );
|
||||
}
|
||||
|
||||
delete_transient( 'wc_term_counts' );
|
||||
|
@ -697,7 +528,7 @@ function wc_change_term_counts( $terms, $taxonomies ) {
|
|||
|
||||
foreach ( $terms as &$term ) {
|
||||
if ( is_object( $term ) ) {
|
||||
$term_counts[ $term->term_id ] = isset( $term_counts[ $term->term_id ] ) ? $term_counts[ $term->term_id ] : get_woocommerce_term_meta( $term->term_id, 'product_count_' . $taxonomies[0], true );
|
||||
$term_counts[ $term->term_id ] = isset( $term_counts[ $term->term_id ] ) ? $term_counts[ $term->term_id ] : get_term_meta( $term->term_id, 'product_count_' . $taxonomies[0], true );
|
||||
|
||||
if ( '' !== $term_counts[ $term->term_id ] ) {
|
||||
$term->count = absint( $term_counts[ $term->term_id ] );
|
||||
|
@ -724,11 +555,11 @@ add_filter( 'get_terms', 'wc_change_term_counts', 10, 2 );
|
|||
* @return array
|
||||
*/
|
||||
function wc_get_term_product_ids( $term_id, $taxonomy ) {
|
||||
$product_ids = get_woocommerce_term_meta( $term_id, 'product_ids', true );
|
||||
$product_ids = get_term_meta( $term_id, 'product_ids', true );
|
||||
|
||||
if ( false === $product_ids || ! is_array( $product_ids ) ) {
|
||||
$product_ids = get_objects_in_term( $term_id, $taxonomy );
|
||||
update_woocommerce_term_meta( $term_id, 'product_ids', $product_ids );
|
||||
update_term_meta( $term_id, 'product_ids', $product_ids );
|
||||
}
|
||||
|
||||
return $product_ids;
|
||||
|
@ -746,10 +577,10 @@ function wc_get_term_product_ids( $term_id, $taxonomy ) {
|
|||
*/
|
||||
function wc_clear_term_product_ids( $object_id, $terms, $tt_ids, $taxonomy, $append, $old_tt_ids ) {
|
||||
foreach ( $old_tt_ids as $term_id ) {
|
||||
delete_woocommerce_term_meta( $term_id, 'product_ids' );
|
||||
delete_term_meta( $term_id, 'product_ids' );
|
||||
}
|
||||
foreach ( $tt_ids as $term_id ) {
|
||||
delete_woocommerce_term_meta( $term_id, 'product_ids' );
|
||||
delete_term_meta( $term_id, 'product_ids' );
|
||||
}
|
||||
}
|
||||
add_action( 'set_object_terms', 'wc_clear_term_product_ids', 10, 6 );
|
||||
|
@ -766,7 +597,8 @@ function wc_get_product_visibility_term_ids() {
|
|||
return array();
|
||||
}
|
||||
return array_map(
|
||||
'absint', wp_parse_args(
|
||||
'absint',
|
||||
wp_parse_args(
|
||||
wp_list_pluck(
|
||||
get_terms(
|
||||
array(
|
||||
|
|
|
@ -1940,6 +1940,15 @@ function wc_update_360_product_lookup_tables() {
|
|||
wc_update_product_lookup_tables();
|
||||
}
|
||||
|
||||
/**
|
||||
* Renames ordering meta to be consistent across taxonomies.
|
||||
*/
|
||||
function wc_update_360_term_meta() {
|
||||
global $wpdb;
|
||||
|
||||
$wpdb->query( "UPDATE {$wpdb->termmeta} SET meta_key = 'order' WHERE meta_key LIKE 'order_pa_%';" );
|
||||
}
|
||||
|
||||
/**
|
||||
* Add new user_order_remaining_expires to speed up user download permission fetching.
|
||||
*
|
||||
|
|
|
@ -167,40 +167,12 @@ class WC_Widget_Layered_Nav extends WC_Widget {
|
|||
return;
|
||||
}
|
||||
|
||||
$get_terms_args = array( 'hide_empty' => '1' );
|
||||
|
||||
$orderby = wc_attribute_orderby( $taxonomy );
|
||||
|
||||
switch ( $orderby ) {
|
||||
case 'name':
|
||||
$get_terms_args['orderby'] = 'name';
|
||||
$get_terms_args['menu_order'] = false;
|
||||
break;
|
||||
case 'id':
|
||||
$get_terms_args['orderby'] = 'id';
|
||||
$get_terms_args['order'] = 'ASC';
|
||||
$get_terms_args['menu_order'] = false;
|
||||
break;
|
||||
case 'menu_order':
|
||||
$get_terms_args['menu_order'] = 'ASC';
|
||||
break;
|
||||
}
|
||||
|
||||
$terms = get_terms( $taxonomy, $get_terms_args );
|
||||
$terms = get_terms( $taxonomy, array( 'hide_empty' => '1' ) );
|
||||
|
||||
if ( 0 === count( $terms ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
switch ( $orderby ) {
|
||||
case 'name_num':
|
||||
usort( $terms, '_wc_get_product_terms_name_num_usort_callback' );
|
||||
break;
|
||||
case 'parent':
|
||||
usort( $terms, '_wc_get_product_terms_parent_usort_callback' );
|
||||
break;
|
||||
}
|
||||
|
||||
ob_start();
|
||||
|
||||
$this->widget_start( $args, $instance );
|
||||
|
|
|
@ -119,9 +119,10 @@ class WC_Widget_Product_Categories extends WC_Widget {
|
|||
$list_args['depth'] = $max_depth;
|
||||
|
||||
if ( 'order' === $orderby ) {
|
||||
$list_args['menu_order'] = 'asc';
|
||||
} else {
|
||||
$list_args['orderby'] = 'title';
|
||||
$list_args['orderby'] = 'meta_value_num';
|
||||
$dropdown_args['orderby'] = 'meta_value_num';
|
||||
$list_args['meta_key'] = 'order';
|
||||
$dropdown_args['meta_key'] = 'order';
|
||||
}
|
||||
|
||||
$this->current_cat = false;
|
||||
|
@ -133,8 +134,11 @@ class WC_Widget_Product_Categories extends WC_Widget {
|
|||
|
||||
} elseif ( is_singular( 'product' ) ) {
|
||||
$terms = wc_get_product_terms(
|
||||
$post->ID, 'product_cat', apply_filters(
|
||||
'woocommerce_product_categories_widget_product_terms_args', array(
|
||||
$post->ID,
|
||||
'product_cat',
|
||||
apply_filters(
|
||||
'woocommerce_product_categories_widget_product_terms_args',
|
||||
array(
|
||||
'orderby' => 'parent',
|
||||
'order' => 'DESC',
|
||||
)
|
||||
|
@ -177,7 +181,8 @@ class WC_Widget_Product_Categories extends WC_Widget {
|
|||
if ( $this->cat_ancestors ) {
|
||||
foreach ( $this->cat_ancestors as $ancestor ) {
|
||||
$include = array_merge(
|
||||
$include, get_terms(
|
||||
$include,
|
||||
get_terms(
|
||||
'product_cat',
|
||||
array(
|
||||
'fields' => 'ids',
|
||||
|
@ -222,12 +227,13 @@ class WC_Widget_Product_Categories extends WC_Widget {
|
|||
if ( $dropdown ) {
|
||||
wc_product_dropdown_categories(
|
||||
apply_filters(
|
||||
'woocommerce_product_categories_widget_dropdown_args', wp_parse_args(
|
||||
$dropdown_args, array(
|
||||
'woocommerce_product_categories_widget_dropdown_args',
|
||||
wp_parse_args(
|
||||
$dropdown_args,
|
||||
array(
|
||||
'show_count' => $count,
|
||||
'hierarchical' => $hierarchical,
|
||||
'show_uncategorized' => 0,
|
||||
'orderby' => $orderby,
|
||||
'selected' => $this->current_cat ? $this->current_cat->slug : '',
|
||||
)
|
||||
)
|
||||
|
|
|
@ -49,7 +49,10 @@ do_action( 'woocommerce_email_order_meta', $order, $sent_to_admin, $plain_text,
|
|||
do_action( 'woocommerce_email_customer_details', $order, $sent_to_admin, $plain_text, $email );
|
||||
?>
|
||||
<p>
|
||||
<?php echo wp_kses_post( __( 'Hopefully they’ll be back. Read more about <a href="https://docs.woocommerce.com/document/managing-orders/">troubleshooting failed payments</a>.', 'woocommerce' ) ); ?>
|
||||
<?php
|
||||
/* translators: %s: documentation link */
|
||||
echo wp_kses_post( sprintf( __( 'Hopefully they’ll be back. Read more about <a href="%s">troubleshooting failed payments</a>.', 'woocommerce' ), 'https://docs.woocommerce.com/document/managing-orders/' ) );
|
||||
?>
|
||||
</p>
|
||||
<?php
|
||||
|
||||
|
|
|
@ -47,7 +47,8 @@ do_action( 'woocommerce_email_order_meta', $order, $sent_to_admin, $plain_text,
|
|||
*/
|
||||
do_action( 'woocommerce_email_customer_details', $order, $sent_to_admin, $plain_text, $email );
|
||||
|
||||
echo esc_html__( 'Hopefully they’ll be back. Read more about <a href="https://docs.woocommerce.com/document/managing-orders/">troubleshooting failed payments</a>.', 'woocommerce' ) . "\n\n";
|
||||
/* translators: %s: documentation link */
|
||||
printf( esc_html__( 'Hopefully they’ll be back. Read more about <a href="%s">troubleshooting failed payments</a>.', 'woocommerce' ), 'https://docs.woocommerce.com/document/managing-orders/' ) . "\n\n";
|
||||
|
||||
echo "\n=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=\n\n";
|
||||
|
||||
|
|
|
@ -6,6 +6,9 @@
|
|||
* @since 3.5.0
|
||||
*/
|
||||
|
||||
/**
|
||||
* WC_Tests_API_Product class.
|
||||
*/
|
||||
class WC_Tests_API_Product extends WC_REST_Unit_Test_Case {
|
||||
|
||||
/**
|
||||
|
@ -87,7 +90,8 @@ class WC_Tests_API_Product extends WC_REST_Unit_Test_Case {
|
|||
'status' => 'publish',
|
||||
'sku' => 'DUMMY EXTERNAL SKU',
|
||||
'regular_price' => 10,
|
||||
), $product
|
||||
),
|
||||
$product
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -157,7 +161,7 @@ class WC_Tests_API_Product extends WC_REST_Unit_Test_Case {
|
|||
public function test_update_product() {
|
||||
wp_set_current_user( $this->user );
|
||||
|
||||
// test simple products
|
||||
// test simple products.
|
||||
$product = WC_Helper_Product::create_simple_product();
|
||||
$response = $this->server->dispatch( new WP_REST_Request( 'GET', '/wc/v3/products/' . $product->get_id() ) );
|
||||
$data = $response->get_data();
|
||||
|
@ -196,7 +200,7 @@ class WC_Tests_API_Product extends WC_REST_Unit_Test_Case {
|
|||
$this->assertContains( 'test upload image', $data['images'][0]['alt'] );
|
||||
$product->delete( true );
|
||||
|
||||
// test variable product (variations are tested in product-variations.php)
|
||||
// test variable product (variations are tested in product-variations.php).
|
||||
$product = WC_Helper_Product::create_variation_product();
|
||||
$response = $this->server->dispatch( new WP_REST_Request( 'GET', '/wc/v3/products/' . $product->get_id() ) );
|
||||
$data = $response->get_data();
|
||||
|
@ -235,10 +239,14 @@ class WC_Tests_API_Product extends WC_REST_Unit_Test_Case {
|
|||
$data = $response->get_data();
|
||||
|
||||
$this->assertEquals( array( 'small' ), $data['attributes'][0]['options'] );
|
||||
$this->assertEquals( array( 'red', 'yellow' ), $data['attributes'][1]['options'] );
|
||||
|
||||
foreach ( array( 'red', 'yellow' ) as $term_name ) {
|
||||
$this->assertContains( $term_name, $data['attributes'][1]['options'] );
|
||||
}
|
||||
|
||||
$product->delete( true );
|
||||
|
||||
// test external product
|
||||
// test external product.
|
||||
$product = WC_Helper_Product::create_external_product();
|
||||
$response = $this->server->dispatch( new WP_REST_Request( 'GET', '/wc/v3/products/' . $product->get_id() ) );
|
||||
$data = $response->get_data();
|
||||
|
@ -313,7 +321,7 @@ class WC_Tests_API_Product extends WC_REST_Unit_Test_Case {
|
|||
$data = $response->get_data();
|
||||
$shipping_class_id = $data['id'];
|
||||
|
||||
// Create simple
|
||||
// Create simple.
|
||||
$request = new WP_REST_Request( 'POST', '/wc/v3/products' );
|
||||
$request->set_body_params(
|
||||
array(
|
||||
|
@ -335,7 +343,7 @@ class WC_Tests_API_Product extends WC_REST_Unit_Test_Case {
|
|||
$this->assertEquals( 'simple', $data['type'] );
|
||||
$this->assertEquals( $shipping_class_id, $data['shipping_class_id'] );
|
||||
|
||||
// Create external
|
||||
// Create external.
|
||||
$request = new WP_REST_Request( 'POST', '/wc/v3/products' );
|
||||
$request->set_body_params(
|
||||
array(
|
||||
|
@ -359,7 +367,7 @@ class WC_Tests_API_Product extends WC_REST_Unit_Test_Case {
|
|||
$this->assertEquals( 'Test Button', $data['button_text'] );
|
||||
$this->assertEquals( 'https://wordpress.org', $data['external_url'] );
|
||||
|
||||
// Create variable
|
||||
// Create variable.
|
||||
$request = new WP_REST_Request( 'POST', '/wc/v3/products' );
|
||||
$request->set_body_params(
|
||||
array(
|
||||
|
@ -468,7 +476,7 @@ class WC_Tests_API_Product extends WC_REST_Unit_Test_Case {
|
|||
$this->assertEquals( 3, count( $data ) );
|
||||
}
|
||||
|
||||
/*
|
||||
/**
|
||||
* Tests to make sure you can filter products post statuses by both
|
||||
* the status query arg and WP_Query.
|
||||
*
|
||||
|
@ -488,7 +496,7 @@ class WC_Tests_API_Product extends WC_REST_Unit_Test_Case {
|
|||
}
|
||||
}
|
||||
|
||||
// Test filtering with status=publish
|
||||
// Test filtering with status=publish.
|
||||
$request = new WP_REST_Request( 'GET', '/wc/v3/products' );
|
||||
$request->set_param( 'status', 'publish' );
|
||||
$response = $this->server->dispatch( $request );
|
||||
|
@ -499,7 +507,7 @@ class WC_Tests_API_Product extends WC_REST_Unit_Test_Case {
|
|||
$this->assertEquals( 'publish', $product['status'] );
|
||||
}
|
||||
|
||||
// Test filtering with status=draft
|
||||
// Test filtering with status=draft.
|
||||
$request = new WP_REST_Request( 'GET', '/wc/v3/products' );
|
||||
$request->set_param( 'status', 'draft' );
|
||||
$response = $this->server->dispatch( $request );
|
||||
|
@ -510,7 +518,7 @@ class WC_Tests_API_Product extends WC_REST_Unit_Test_Case {
|
|||
$this->assertEquals( 'draft', $product['status'] );
|
||||
}
|
||||
|
||||
// Test filtering with no filters - which should return 'any' (all 8)
|
||||
// Test filtering with no filters - which should return 'any' (all 8).
|
||||
$request = new WP_REST_Request( 'GET', '/wc/v3/products' );
|
||||
$response = $this->server->dispatch( $request );
|
||||
$products = $response->get_data();
|
||||
|
@ -573,7 +581,7 @@ class WC_Tests_API_Product extends WC_REST_Unit_Test_Case {
|
|||
$response_product = $response->get_data();
|
||||
|
||||
$this->assertEquals( 200, $response->get_status() );
|
||||
$this->assertCount( 1, $response_product['categories'] );
|
||||
$this->assertCount( 1, $response_product['categories'], print_r( $response_product, true ) );
|
||||
$this->assertEquals( 'uncategorized', $response_product['categories'][0]['slug'] );
|
||||
|
||||
}
|
||||
|
@ -749,7 +757,8 @@ class WC_Tests_API_Product extends WC_REST_Unit_Test_Case {
|
|||
|
||||
// Link the product to the term.
|
||||
$wpdb->insert(
|
||||
$wpdb->prefix . 'term_relationships', array(
|
||||
$wpdb->prefix . 'term_relationships',
|
||||
array(
|
||||
'object_id' => $product_2->get_id(),
|
||||
'term_taxonomy_id' => $term_large->term_id,
|
||||
'term_order' => 0,
|
||||
|
|
|
@ -6,6 +6,9 @@
|
|||
* @since 3.0.0
|
||||
*/
|
||||
|
||||
/**
|
||||
* Products_API_V2 class.
|
||||
*/
|
||||
class Products_API_V2 extends WC_REST_Unit_Test_Case {
|
||||
|
||||
/**
|
||||
|
@ -87,7 +90,8 @@ class Products_API_V2 extends WC_REST_Unit_Test_Case {
|
|||
'status' => 'publish',
|
||||
'sku' => 'DUMMY EXTERNAL SKU',
|
||||
'regular_price' => 10,
|
||||
), $product
|
||||
),
|
||||
$product
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -157,7 +161,7 @@ class Products_API_V2 extends WC_REST_Unit_Test_Case {
|
|||
public function test_update_product() {
|
||||
wp_set_current_user( $this->user );
|
||||
|
||||
// test simple products
|
||||
// test simple products.
|
||||
$product = WC_Helper_Product::create_simple_product();
|
||||
$response = $this->server->dispatch( new WP_REST_Request( 'GET', '/wc/v2/products/' . $product->get_id() ) );
|
||||
$data = $response->get_data();
|
||||
|
@ -193,37 +197,41 @@ class Products_API_V2 extends WC_REST_Unit_Test_Case {
|
|||
$this->assertContains( 'test upload image', $data['images'][0]['alt'] );
|
||||
$product->delete( true );
|
||||
|
||||
// test variable product (variations are tested in product-variations.php)
|
||||
// test variable product (variations are tested in product-variations.php).
|
||||
$product = WC_Helper_Product::create_variation_product();
|
||||
$response = $this->server->dispatch( new WP_REST_Request( 'GET', '/wc/v2/products/' . $product->get_id() ) );
|
||||
$data = $response->get_data();
|
||||
|
||||
$this->assertEquals( array( 'large', 'small' ), $data['attributes'][0]['options'] );
|
||||
foreach ( array( 'small', 'large' ) as $term_name ) {
|
||||
$this->assertContains( $term_name, $data['attributes'][0]['options'] );
|
||||
}
|
||||
|
||||
$request = new WP_REST_Request( 'PUT', '/wc/v2/products/' . $product->get_id() );
|
||||
$request->set_body_params( array(
|
||||
'attributes' => array(
|
||||
array(
|
||||
'id' => 0,
|
||||
'name' => 'pa_color',
|
||||
'options' => array(
|
||||
'red',
|
||||
'yellow',
|
||||
$request->set_body_params(
|
||||
array(
|
||||
'attributes' => array(
|
||||
array(
|
||||
'id' => 0,
|
||||
'name' => 'pa_color',
|
||||
'options' => array(
|
||||
'red',
|
||||
'yellow',
|
||||
),
|
||||
'visible' => false,
|
||||
'variation' => 1,
|
||||
),
|
||||
'visible' => false,
|
||||
'variation' => 1,
|
||||
),
|
||||
array(
|
||||
'id' => 0,
|
||||
'name' => 'pa_size',
|
||||
'options' => array(
|
||||
'small',
|
||||
array(
|
||||
'id' => 0,
|
||||
'name' => 'pa_size',
|
||||
'options' => array(
|
||||
'small',
|
||||
),
|
||||
'visible' => false,
|
||||
'variation' => 1,
|
||||
),
|
||||
'visible' => false,
|
||||
'variation' => 1,
|
||||
),
|
||||
),
|
||||
) );
|
||||
)
|
||||
);
|
||||
$response = $this->server->dispatch( $request );
|
||||
$data = $response->get_data();
|
||||
|
||||
|
@ -231,7 +239,7 @@ class Products_API_V2 extends WC_REST_Unit_Test_Case {
|
|||
$this->assertEquals( array( 'red', 'yellow' ), $data['attributes'][1]['options'] );
|
||||
$product->delete( true );
|
||||
|
||||
// test external product
|
||||
// test external product.
|
||||
$product = WC_Helper_Product::create_external_product();
|
||||
$response = $this->server->dispatch( new WP_REST_Request( 'GET', '/wc/v2/products/' . $product->get_id() ) );
|
||||
$data = $response->get_data();
|
||||
|
@ -307,7 +315,7 @@ class Products_API_V2 extends WC_REST_Unit_Test_Case {
|
|||
$data = $response->get_data();
|
||||
$shipping_class_id = $data['id'];
|
||||
|
||||
// Create simple
|
||||
// Create simple.
|
||||
$request = new WP_REST_Request( 'POST', '/wc/v2/products' );
|
||||
$request->set_body_params(
|
||||
array(
|
||||
|
@ -329,7 +337,7 @@ class Products_API_V2 extends WC_REST_Unit_Test_Case {
|
|||
$this->assertEquals( 'simple', $data['type'] );
|
||||
$this->assertEquals( $shipping_class_id, $data['shipping_class_id'] );
|
||||
|
||||
// Create external
|
||||
// Create external.
|
||||
$request = new WP_REST_Request( 'POST', '/wc/v2/products' );
|
||||
$request->set_body_params(
|
||||
array(
|
||||
|
@ -353,7 +361,7 @@ class Products_API_V2 extends WC_REST_Unit_Test_Case {
|
|||
$this->assertEquals( 'Test Button', $data['button_text'] );
|
||||
$this->assertEquals( 'https://wordpress.org', $data['external_url'] );
|
||||
|
||||
// Create variable
|
||||
// Create variable.
|
||||
$request = new WP_REST_Request( 'POST', '/wc/v2/products' );
|
||||
$request->set_body_params(
|
||||
array(
|
||||
|
@ -460,7 +468,7 @@ class Products_API_V2 extends WC_REST_Unit_Test_Case {
|
|||
$this->assertEquals( 3, count( $data ) );
|
||||
}
|
||||
|
||||
/*
|
||||
/**
|
||||
* Tests to make sure you can filter products post statuses by both
|
||||
* the status query arg and WP_Query.
|
||||
*
|
||||
|
@ -480,7 +488,7 @@ class Products_API_V2 extends WC_REST_Unit_Test_Case {
|
|||
}
|
||||
}
|
||||
|
||||
// Test filtering with status=publish
|
||||
// Test filtering with status=publish.
|
||||
$request = new WP_REST_Request( 'GET', '/wc/v2/products' );
|
||||
$request->set_param( 'status', 'publish' );
|
||||
$response = $this->server->dispatch( $request );
|
||||
|
@ -491,7 +499,7 @@ class Products_API_V2 extends WC_REST_Unit_Test_Case {
|
|||
$this->assertEquals( 'publish', $product['status'] );
|
||||
}
|
||||
|
||||
// Test filtering with status=draft
|
||||
// Test filtering with status=draft.
|
||||
$request = new WP_REST_Request( 'GET', '/wc/v2/products' );
|
||||
$request->set_param( 'status', 'draft' );
|
||||
$response = $this->server->dispatch( $request );
|
||||
|
@ -502,7 +510,7 @@ class Products_API_V2 extends WC_REST_Unit_Test_Case {
|
|||
$this->assertEquals( 'draft', $product['status'] );
|
||||
}
|
||||
|
||||
// Test filtering with no filters - which should return 'any' (all 8)
|
||||
// Test filtering with no filters - which should return 'any' (all 8).
|
||||
$request = new WP_REST_Request( 'GET', '/wc/v2/products' );
|
||||
$response = $this->server->dispatch( $request );
|
||||
$products = $response->get_data();
|
||||
|
|
Loading…
Reference in New Issue