Merge branch 'master' into feature/discounts-class

# Conflicts:
#	includes/abstracts/abstract-wc-data.php
#	woocommerce.php
This commit is contained in:
Mike Jolley 2017-08-08 15:49:59 +01:00
commit e9c3ebebdc
128 changed files with 2314 additions and 1314 deletions

View File

@ -15,24 +15,24 @@ engines:
- javascript
ratings:
paths:
- "includes/*"
- "includes/*"
exclude_paths:
- tests/*
- apigen/*
- dummy-data/*
- i18n/*
- includes/api/legacy/*
- includes/libraries/*
- includes/updates/*
- includes/gateways/simplify-commerce/*
- includes/shipping/legacy-*
- includes/wc-deprecated-functions.php
- includes/class-wc-legacy-api.php
- assets/js/accounting/**
- assets/js/jquery-*
- assets/js/prettyPhoto/*
- assets/js/round/*
- assets/js/select2/*
- assets/js/selectWoo/*
- assets/js/stupidtable/*
- assets/js/zeroclipboard/*
- "tests/"
- "apigen/"
- "dummy-data/"
- "i18n/"
- "includes/api/legacy/"
- "includes/libraries/"
- "includes/updates/"
- "includes/gateways/simplify-commerce/"
- "includes/shipping/legacy-*"
- "includes/wc-deprecated-functions.php"
- "includes/class-wc-legacy-api.php"
- "assets/js/accounting/"
- "assets/js/jquery-*"
- "assets/js/prettyPhoto/"
- "assets/js/round/"
- "assets/js/select2/"
- "assets/js/selectWoo/"
- "assets/js/stupidtable/"
- "assets/js/zeroclipboard/"

View File

@ -1,3 +0,0 @@
src_dir: .
coverage_clover: ./tmp/clover.xml
json_path: ./tmp/coveralls-upload.json

View File

@ -1,35 +1,56 @@
<!-- Hi there! This form is for reporting bugs and issues specific to the WooCommerce plugin. This is not a support portal. If you need technical support from a human being, please submit a ticket via the helpdesk instead: https://woocommerce.com/contact-us/ -->
<!-- Usage questions can also be directed to the public support forum here: https://wordpress.org/support/plugin/woocommerce, unless this is a question about a premium extension in which case you should use the helpdesk. -->
<!-- If you have a feature request, submit it to: http://ideas.woocommerce.com/forums/133476-woocommerce -->
<!-- Please be as descriptive as possible; issues lacking the below details, or for any other reason than to report a bug, may be closed without action. -->
## Prerequisites
<!-- Mark checked items with an [x] -->
<!-- Mark completed items with an [x] -->
- [ ] I have searched for similar issues in both open and closed tickets and cannot find a duplicate
- [ ] The issue still exists against the latest `master` branch of WooCommerce
- [ ] This is not a usage question (Those should be directed to the [community](https://wordpress.org/support/plugin/woocommerce), unless this is a question about a premium plugin in which you should [use the helpdesk](https://woocommerce.com/my-account/tickets/) for official extensions or contact the author of 3rd party extensions)
- [ ] The issue still exists against the latest `master` branch of WooCommerce on Github
- [ ] I have attempted to find the simplest possible steps to reproduce the issue
- [ ] I have included a failing test as a pull request (Optional)
## Steps to reproduce the issue
<!-- We need to be able to reproduce the bug in order to fix it so please be descriptive! -->
1.
2.
3.
## Expected behavior and actual behavior
## Expected/actual behavior
When I follow those steps, I see...
I was expecting...
I was expecting to see...
## Environment
<details>
```
Grab the system status report from WooCommerce > System Status and paste it here.
```
</details>
## Isolating the problem
<!-- Mark completed items with an [x] -->
- [ ] This bug happens with only WooCommerce plugin active
- [ ] This bug happens with a default WordPress theme active, or [Storefront](https://woocommerce.com/storefront/)
- [ ] I can reproduce this bug consistently
- [ ] I can reproduce this bug consistently using the steps above
## WordPress Environment
<details>
```
Copy and paste the system status report from **WooCommerce > System Status** in WordPress admin here.
```
</details>

View File

@ -1,32 +1,58 @@
filter:
excluded_paths:
- tests/*
- apigen/*
- dummy-data/*
- i18n/*
- includes/api/legacy/*
- includes/legacy/*
- includes/libraries/*
- includes/updates/*
- includes/gateways/simplify-commerce/*
- includes/shipping/legacy-*
- includes/wc-deprecated-functions.php
- includes/class-wc-legacy-api.php
build:
environment:
php: "7.1"
mysql: true
postgresql: false
redis: false
apache2:
modules:
- rewrite
variables:
WP_VERSION: latest
dependencies:
before:
- "bash tests/bin/install.sh woocommerce_test root '' localhost $WP_VERSION"
tests:
override:
-
command: "vendor/bin/phpunit -c phpunit.xml --coverage-clover=results"
coverage:
file: results
format: clover
tools:
php_code_sniffer:
config:
standard: WordPress
sensiolabs_security_checker: true
checks:
php:
avoid_closing_tag: false
avoid_superglobals: false
coding_standard:
name: WordPress
no_exit: false
no_global_keyword: false
one_class_per_file: false
psr2_class_declaration: false
psr2_control_structure_declaration: false
psr2_switch_declaration: false
variable_existence: false
verify_access_scope_valid: false
verify_argument_usable_as_reference: false
verify_property_names: false
no_global_keyword: false
psr2_switch_declaration: false
psr2_control_structure_declaration: false
psr2_class_declaration: false
one_class_per_file: false
no_exit: false
avoid_superglobals: false
avoid_closing_tag: false
tools:
sensiolabs_security_checker: true
filter:
excluded_paths:
- apigen/
- dummy-data/
- i18n/
- includes/api/legacy/
- includes/class-wc-legacy-api.php
- includes/gateways/simplify-commerce-deprecated/
- includes/gateways/simplify-commerce/includes/
- includes/legacy/
- includes/libraries/
- includes/shipping/legacy-*
- includes/updates/
- includes/vendor/
- includes/wc-deprecated-functions.php
- tests/

View File

@ -2,10 +2,8 @@ language: php
sudo: false
# Test main supported versions of PHP and HHVM against latest WP. 5.2 is min supported version.
# Test main supported versions of PHP and HHVM against latest WP.
php:
- 5.2
- 5.3
- 5.6
- 7.0
- 7.1
@ -18,6 +16,12 @@ matrix:
include:
- php: 5.6
env: WP_VERSION=latest WP_MULTISITE=1 PHP_LATEST_STABLE=7.1
- php: 5.3
env: WP_VERSION=latest WP_MULTISITE=0 PHP_LATEST_STABLE=7.1
dist: precise
- php: 5.2
env: WP_VERSION=latest WP_MULTISITE=0 PHP_LATEST_STABLE=7.1
dist: precise
before_script:
- export PATH="$HOME/.composer/vendor/bin:$PATH"
@ -25,8 +29,7 @@ before_script:
- bash tests/bin/travis.sh before
script:
- bash tests/bin/phpunit.sh
- bash tests/bin/travis.sh during
- phpunit -c phpunit.xml
after_script:
- bash tests/bin/travis.sh after

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -1006,6 +1006,14 @@ button.pswp__button--zoom:hover {
}
.colors-dark {
.page-numbers {
color: #444;
&.next, &.prev {
color: #ddd;
}
}
.checkout-button {
border: 2px solid #555;

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -79,7 +79,7 @@
render: function() {
var template = wp.template( this._target );
this.$el.attr( 'tabindex' , '0' ).append(
this.$el.append(
template( this._string )
);
@ -88,7 +88,8 @@
}).append( this.$el );
this.resizeContent();
this.$el.focus();
this.$( '.wc-backbone-modal-content' ).attr( 'tabindex' , '0' ).focus();
$( document.body ).trigger( 'init_tooltips' );
$( document.body ).trigger( 'wc_backbone_modal_loaded', this._target );

View File

@ -123,10 +123,10 @@ jQuery( function( $ ) {
dateFormat: 'yy-mm-dd',
numberOfMonths: 1,
showButtonPanel: true,
onSelect: function( selectedDate, instance ) {
onSelect: function() {
var option = $( this ).is( '.sale_price_dates_from' ) ? 'minDate' : 'maxDate',
dates = $( this ).closest( '.sale_price_dates_fields' ).find( 'input' ),
date = $.datepicker.parseDate( instance.settings.dateFormat || $.datepicker._defaults.dateFormat, selectedDate, instance.settings );
date = $( this ).datepicker( 'getDate' );
dates.not( this ).datepicker( 'option', option, date );
$( this ).change();

View File

@ -238,22 +238,26 @@ jQuery( function( $ ) {
}).change();
// DATE PICKER FIELDS.
function date_picker_select( datepicker ) {
var option = $( datepicker ).next().is( '.hasDatepicker' ) ? 'minDate' : 'maxDate',
otherDateField = 'minDate' === option ? $( datepicker ).next() : $( datepicker ).prev(),
date = $( datepicker ).datepicker( 'getDate' );
$( otherDateField ).datepicker( 'option', option, date );
$( datepicker ).change();
}
$( '.sale_price_dates_fields' ).each( function() {
$( this ).find( 'input' ).datepicker({
defaultDate: '',
dateFormat: 'yy-mm-dd',
numberOfMonths: 1,
showButtonPanel: true,
onSelect: function( selectedDate ) {
var option = $( this ).next().is('.hasDatepicker') ? 'minDate' : 'maxDate',
instance = $( this ).data( 'datepicker' ),
dates = $( this ).closest( '.sale_price_dates_fields' ).find( 'input' ),
date = $.datepicker.parseDate( instance.settings.dateFormat || $.datepicker._defaults.dateFormat, selectedDate, instance.settings );
dates.not( this ).datepicker( 'option', option, date );
$( this ).change();
onSelect: function() {
date_picker_select( $( this ) );
}
});
$( this ).find( 'input' ).each( function() { date_picker_select( $( this ) ) } );
});
// ATTRIBUTE TABLES.

View File

@ -115,10 +115,9 @@ jQuery(function( $ ) {
showButtonPanel: true,
showOn: 'focus',
buttonImageOnly: true,
onSelect: function( selectedDate ) {
onSelect: function() {
var option = $( this ).is( '.from' ) ? 'minDate' : 'maxDate',
instance = $( this ).data( 'datepicker' ),
date = $.datepicker.parseDate( instance.settings.dateFormat || $.datepicker._defaults.dateFormat, selectedDate, instance.settings );
date = $( this ).datepicker( 'getDate' );
dates.not( this ).datepicker( 'option', option, date );
}

View File

@ -102,9 +102,11 @@
if ( _.size( zones ) ) {
// Sort zones
zones = _.sortBy( zones, function( zone ) {
return parseInt( zone.zone_order, 10 );
} );
zones = _( zones )
.chain()
.sortBy( function ( zone ) { return parseInt( zone.zone_id, 10 ); } )
.sortBy( function ( zone ) { return parseInt( zone.zone_order, 10 ); } )
.value();
// Populate $tbody with the current zones
$.each( zones, function( id, rowData ) {

View File

@ -1 +1 @@
!function(e,n,i,o){e(function(){var t=e(".wc-shipping-zones"),s=e(".wc-shipping-zone-rows"),d=e(".wc-shipping-zone-save"),a=i.template("wc-shipping-zone-row"),r=i.template("wc-shipping-zone-row-blank"),l=Backbone.Model.extend({changes:{},logChanges:function(e){var n=this.changes||{};_.each(e,function(e,i){n[i]=_.extend(n[i]||{zone_id:i},e)}),this.changes=n,this.trigger("change:zones")},discardChanges:function(e){var n=this.changes||{},i=null,o=_.indexBy(this.get("zones"),"zone_id");n[e]&&n[e].zone_order!==undefined&&(i=n[e].zone_order),delete n[e],null!==i&&o[e]&&o[e].zone_order!==i&&(n[e]=_.extend(n[e]||{},{zone_id:e,zone_order:i})),this.changes=n,0===_.size(this.changes)&&p.clearUnloadConfirmation()},save:function(){_.size(this.changes)?e.post(o+(o.indexOf("?")>0?"&":"?")+"action=woocommerce_shipping_zones_save_changes",{wc_shipping_zones_nonce:n.wc_shipping_zones_nonce,changes:this.changes},this.onSaveResponse,"json"):h.trigger("saved:zones")},onSaveResponse:function(e,i){"success"===i&&(e.success?(h.set("zones",e.data.zones),h.trigger("change:zones"),h.changes={},h.trigger("saved:zones")):window.alert(n.strings.save_failed))}}),c=Backbone.View.extend({rowTemplate:a,initialize:function(){this.listenTo(this.model,"change:zones",this.setUnloadConfirmation),this.listenTo(this.model,"saved:zones",this.clearUnloadConfirmation),this.listenTo(this.model,"saved:zones",this.render),s.on("change",{view:this},this.updateModelOnChange),s.on("sortupdate",{view:this},this.updateModelOnSort),e(window).on("beforeunload",{view:this},this.unloadConfirmation),e(document.body).on("click",".wc-shipping-zone-add",{view:this},this.onAddNewRow)},block:function(){e(this.el).block({message:null,overlayCSS:{background:"#fff",opacity:.6}})},unblock:function(){e(this.el).unblock()},render:function(){var n=_.indexBy(this.model.get("zones"),"zone_id"),i=this;i.$el.empty(),i.unblock(),_.size(n)?(n=_.sortBy(n,function(e){return parseInt(e.zone_order,10)}),e.each(n,function(e,n){i.renderRow(n)})):i.$el.append(r),i.initRows()},renderRow:function(e){var n=this;n.$el.append(n.rowTemplate(e)),n.initRow(e)},initRow:function(e){var n=this,i=n.$el.find('tr[data-id="'+e.zone_id+'"]');n.renderShippingMethods(e.zone_id,e.shipping_methods),i.find(".wc-shipping-zone-delete").on("click",{view:this},this.onDeleteRow)},initRows:function(){0==e("tbody.wc-shipping-zone-rows tr").length%2?t.find("tbody.wc-shipping-zone-rows").next("tbody").find("tr").addClass("odd"):t.find("tbody.wc-shipping-zone-rows").next("tbody").find("tr").removeClass("odd"),e("#tiptip_holder").removeAttr("style"),e("#tiptip_arrow").removeAttr("style"),e(".tips").tipTip({attribute:"data-tip",fadeIn:50,fadeOut:50,delay:50})},renderShippingMethods:function(i,o){var t=e('.wc-shipping-zones tr[data-id="'+i+'"]').find(".wc-shipping-zone-methods ul");t.find(".wc-shipping-zone-method").remove(),_.size(o)?(o=_.sortBy(o,function(e){return parseInt(e.method_order,10)}),_.each(o,function(e){var n="method_disabled";"yes"===e.enabled&&(n="method_enabled"),t.append('<li class="wc-shipping-zone-method '+n+'">'+e.title+"</li>")})):t.append('<li class="wc-shipping-zone-method">'+n.strings.no_shipping_methods_offered+"</li>")},onDeleteRow:function(i){var o=i.data.view.model,t=_.indexBy(o.get("zones"),"zone_id"),s={},d=e(this).closest("tr").data("id");i.preventDefault(),window.confirm(n.strings.delete_confirmation_msg)&&t[d]&&(delete t[d],s[d]=_.extend(s[d]||{},{deleted:"deleted"}),o.set("zones",t),o.logChanges(s),i.data.view.block(),i.data.view.model.save())},setUnloadConfirmation:function(){this.needsUnloadConfirm=!0,d.prop("disabled",!1)},clearUnloadConfirmation:function(){this.needsUnloadConfirm=!1,d.prop("disabled",!0)},unloadConfirmation:function(e){if(e.data.view.needsUnloadConfirm)return e.returnValue=n.strings.unload_confirmation_msg,window.event.returnValue=n.strings.unload_confirmation_msg,n.strings.unload_confirmation_msg},updateModelOnChange:function(n){var i=n.data.view.model,o=e(n.target),t=o.closest("tr").data("id"),s=o.data("attribute"),d=o.val(),a=_.indexBy(i.get("zones"),"zone_id"),r={};a[t]&&a[t][s]===d||(r[t]={},r[t][s]=d),i.logChanges(r)},updateModelOnSort:function(n){var i=n.data.view.model,o=_.indexBy(i.get("zones"),"zone_id"),t=e("tbody.wc-shipping-zone-rows tr"),s={};_.each(t,function(n){var i=e(n).data("id"),t=null,d=parseInt(e(n).index(),10);o[i]&&(t=parseInt(o[i].zone_order,10)),t!==d&&(s[i]=_.extend(s[i]||{},{zone_order:d}))}),_.size(s)&&(i.logChanges(s),n.data.view.block(),n.data.view.model.save())}}),h=new l({zones:n.zones}),p=new c({model:h,el:s});p.render(),s.sortable({items:"tr",cursor:"move",axis:"y",handle:"td.wc-shipping-zone-sort",scrollSensitivity:40})})}(jQuery,shippingZonesLocalizeScript,wp,ajaxurl);
!function(e,n,i,o){e(function(){var t=e(".wc-shipping-zones"),s=e(".wc-shipping-zone-rows"),d=e(".wc-shipping-zone-save"),a=i.template("wc-shipping-zone-row"),r=i.template("wc-shipping-zone-row-blank"),l=Backbone.Model.extend({changes:{},logChanges:function(e){var n=this.changes||{};_.each(e,function(e,i){n[i]=_.extend(n[i]||{zone_id:i},e)}),this.changes=n,this.trigger("change:zones")},discardChanges:function(e){var n=this.changes||{},i=null,o=_.indexBy(this.get("zones"),"zone_id");n[e]&&n[e].zone_order!==undefined&&(i=n[e].zone_order),delete n[e],null!==i&&o[e]&&o[e].zone_order!==i&&(n[e]=_.extend(n[e]||{},{zone_id:e,zone_order:i})),this.changes=n,0===_.size(this.changes)&&p.clearUnloadConfirmation()},save:function(){_.size(this.changes)?e.post(o+(o.indexOf("?")>0?"&":"?")+"action=woocommerce_shipping_zones_save_changes",{wc_shipping_zones_nonce:n.wc_shipping_zones_nonce,changes:this.changes},this.onSaveResponse,"json"):h.trigger("saved:zones")},onSaveResponse:function(e,i){"success"===i&&(e.success?(h.set("zones",e.data.zones),h.trigger("change:zones"),h.changes={},h.trigger("saved:zones")):window.alert(n.strings.save_failed))}}),c=Backbone.View.extend({rowTemplate:a,initialize:function(){this.listenTo(this.model,"change:zones",this.setUnloadConfirmation),this.listenTo(this.model,"saved:zones",this.clearUnloadConfirmation),this.listenTo(this.model,"saved:zones",this.render),s.on("change",{view:this},this.updateModelOnChange),s.on("sortupdate",{view:this},this.updateModelOnSort),e(window).on("beforeunload",{view:this},this.unloadConfirmation),e(document.body).on("click",".wc-shipping-zone-add",{view:this},this.onAddNewRow)},block:function(){e(this.el).block({message:null,overlayCSS:{background:"#fff",opacity:.6}})},unblock:function(){e(this.el).unblock()},render:function(){var n=_.indexBy(this.model.get("zones"),"zone_id"),i=this;i.$el.empty(),i.unblock(),_.size(n)?(n=_(n).chain().sortBy(function(e){return-1*parseInt(e.zone_id,10)}).sortBy(function(e){return parseInt(e.zone_order,10)}).value(),e.each(n,function(e,n){i.renderRow(n)})):i.$el.append(r),i.initRows()},renderRow:function(e){var n=this;n.$el.append(n.rowTemplate(e)),n.initRow(e)},initRow:function(e){var n=this,i=n.$el.find('tr[data-id="'+e.zone_id+'"]');n.renderShippingMethods(e.zone_id,e.shipping_methods),i.find(".wc-shipping-zone-delete").on("click",{view:this},this.onDeleteRow)},initRows:function(){0==e("tbody.wc-shipping-zone-rows tr").length%2?t.find("tbody.wc-shipping-zone-rows").next("tbody").find("tr").addClass("odd"):t.find("tbody.wc-shipping-zone-rows").next("tbody").find("tr").removeClass("odd"),e("#tiptip_holder").removeAttr("style"),e("#tiptip_arrow").removeAttr("style"),e(".tips").tipTip({attribute:"data-tip",fadeIn:50,fadeOut:50,delay:50})},renderShippingMethods:function(i,o){var t=e('.wc-shipping-zones tr[data-id="'+i+'"]').find(".wc-shipping-zone-methods ul");t.find(".wc-shipping-zone-method").remove(),_.size(o)?(o=_.sortBy(o,function(e){return parseInt(e.method_order,10)}),_.each(o,function(e){var n="method_disabled";"yes"===e.enabled&&(n="method_enabled"),t.append('<li class="wc-shipping-zone-method '+n+'">'+e.title+"</li>")})):t.append('<li class="wc-shipping-zone-method">'+n.strings.no_shipping_methods_offered+"</li>")},onDeleteRow:function(i){var o=i.data.view.model,t=_.indexBy(o.get("zones"),"zone_id"),s={},d=e(this).closest("tr").data("id");i.preventDefault(),window.confirm(n.strings.delete_confirmation_msg)&&t[d]&&(delete t[d],s[d]=_.extend(s[d]||{},{deleted:"deleted"}),o.set("zones",t),o.logChanges(s),i.data.view.block(),i.data.view.model.save())},setUnloadConfirmation:function(){this.needsUnloadConfirm=!0,d.prop("disabled",!1)},clearUnloadConfirmation:function(){this.needsUnloadConfirm=!1,d.prop("disabled",!0)},unloadConfirmation:function(e){if(e.data.view.needsUnloadConfirm)return e.returnValue=n.strings.unload_confirmation_msg,window.event.returnValue=n.strings.unload_confirmation_msg,n.strings.unload_confirmation_msg},updateModelOnChange:function(n){var i=n.data.view.model,o=e(n.target),t=o.closest("tr").data("id"),s=o.data("attribute"),d=o.val(),a=_.indexBy(i.get("zones"),"zone_id"),r={};a[t]&&a[t][s]===d||(r[t]={},r[t][s]=d),i.logChanges(r)},updateModelOnSort:function(n){var i=n.data.view.model,o=_.indexBy(i.get("zones"),"zone_id"),t=e("tbody.wc-shipping-zone-rows tr"),s={};_.each(t,function(n){var i=e(n).data("id"),t=null,d=parseInt(e(n).index(),10);o[i]&&(t=parseInt(o[i].zone_order,10)),t!==d&&(s[i]=_.extend(s[i]||{},{zone_order:d}))}),_.size(s)&&(i.logChanges(s),n.data.view.block(),n.data.view.model.save())}}),h=new l({zones:n.zones}),p=new c({model:h,el:s});p.render(),s.sortable({items:"tr",cursor:"move",axis:"y",handle:"td.wc-shipping-zone-sort",scrollSensitivity:40})})}(jQuery,shippingZonesLocalizeScript,wp,ajaxurl);

View File

@ -1342,7 +1342,7 @@ S2.define('select2/selection/base',[
BaseSelection.prototype.render = function () {
var $selection = $(
'<span class="select2-selection" role="combobox" ' +
'<span class="select2-selection" ' +
' aria-haspopup="true" aria-expanded="false">' +
'</span>'
);
@ -1389,9 +1389,7 @@ S2.define('select2/selection/base',[
});
container.on('results:focus', function (params) {
if (searchHidden) {
self.$selection.attr('aria-activedescendant', params.data._resultId);
}
self.$selection.attr('aria-activedescendant', params.data._resultId);
});
container.on('selection:update', function (params) {
@ -1401,9 +1399,7 @@ S2.define('select2/selection/base',[
container.on('open', function () {
// When the dropdown is open, aria-expanded="true"
self.$selection.attr('aria-expanded', 'true');
if (searchHidden) {
self.$selection.attr('aria-owns', resultsId);
}
self.$selection.attr('aria-owns', resultsId);
self._attachCloseHandler(container);
});
@ -1534,6 +1530,9 @@ S2.define('select2/selection/single',[
.attr('aria-readonly', 'true');
this.$selection.attr('aria-labelledby', id);
// This makes single non-search selects work in screen readers. If it causes problems elsewhere, remove.
this.$selection.attr('role', 'combobox');
this.$selection.on('mousedown', function (evt) {
// Only respond to left clicks
if (evt.which !== 1) {
@ -1874,7 +1873,7 @@ S2.define('select2/selection/search',[
Search.prototype.render = function (decorated) {
var $search = $(
'<li class="select2-search select2-search--inline">' +
'<input class="select2-search__field" type="search" tabindex="-1"' +
'<input class="select2-search__field" type="text" tabindex="-1"' +
' autocomplete="off" autocorrect="off" autocapitalize="off"' +
' spellcheck="false" role="textbox" aria-autocomplete="list" />' +
'</li>'
@ -3940,7 +3939,7 @@ S2.define('select2/dropdown/search',[
'<span class="select2-search select2-search--dropdown">' +
'<input class="select2-search__field" type="text" tabindex="-1"' +
' autocomplete="off" autocorrect="off" autocapitalize="off"' +
' spellcheck="false" role="combobox" aria-autocomplete="list" />' +
' spellcheck="false" role="combobox" aria-autocomplete="list" aria-expanded="true" />' +
'</span>'
);

File diff suppressed because one or more lines are too long

View File

@ -1342,7 +1342,7 @@ S2.define('select2/selection/base',[
BaseSelection.prototype.render = function () {
var $selection = $(
'<span class="select2-selection" role="combobox" ' +
'<span class="select2-selection" ' +
' aria-haspopup="true" aria-expanded="false">' +
'</span>'
);
@ -1389,9 +1389,7 @@ S2.define('select2/selection/base',[
});
container.on('results:focus', function (params) {
if (searchHidden) {
self.$selection.attr('aria-activedescendant', params.data._resultId);
}
self.$selection.attr('aria-activedescendant', params.data._resultId);
});
container.on('selection:update', function (params) {
@ -1401,9 +1399,7 @@ S2.define('select2/selection/base',[
container.on('open', function () {
// When the dropdown is open, aria-expanded="true"
self.$selection.attr('aria-expanded', 'true');
if (searchHidden) {
self.$selection.attr('aria-owns', resultsId);
}
self.$selection.attr('aria-owns', resultsId);
self._attachCloseHandler(container);
});
@ -1534,6 +1530,9 @@ S2.define('select2/selection/single',[
.attr('aria-readonly', 'true');
this.$selection.attr('aria-labelledby', id);
// This makes single non-search selects work in screen readers. If it causes problems elsewhere, remove.
this.$selection.attr('role', 'combobox');
this.$selection.on('mousedown', function (evt) {
// Only respond to left clicks
if (evt.which !== 1) {
@ -1874,7 +1873,7 @@ S2.define('select2/selection/search',[
Search.prototype.render = function (decorated) {
var $search = $(
'<li class="select2-search select2-search--inline">' +
'<input class="select2-search__field" type="search" tabindex="-1"' +
'<input class="select2-search__field" type="text" tabindex="-1"' +
' autocomplete="off" autocorrect="off" autocapitalize="off"' +
' spellcheck="false" role="textbox" aria-autocomplete="list" />' +
'</li>'
@ -3940,7 +3939,7 @@ S2.define('select2/dropdown/search',[
'<span class="select2-search select2-search--dropdown">' +
'<input class="select2-search__field" type="text" tabindex="-1"' +
' autocomplete="off" autocorrect="off" autocapitalize="off"' +
' spellcheck="false" role="combobox" aria-autocomplete="list" />' +
' spellcheck="false" role="combobox" aria-autocomplete="list" aria-expanded="true" />' +
'</span>'
);

File diff suppressed because one or more lines are too long

View File

@ -10,7 +10,7 @@
"require-dev": {
"squizlabs/php_codesniffer": "*",
"wp-coding-standards/wpcs": "0.10.0",
"phpunit/phpunit": "5.7.19"
"phpunit/phpunit": "6.2.3"
},
"scripts": {
"post-install-cmd": [

471
composer.lock generated
View File

@ -4,20 +4,20 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file",
"This file is @generated automatically"
],
"content-hash": "3e1a8fa4256dcf3ef3caee1b027d6779",
"content-hash": "4028dd750463d5e5ad5f2099196a949a",
"packages": [
{
"name": "composer/installers",
"version": "v1.2.0",
"version": "v1.3.0",
"source": {
"type": "git",
"url": "https://github.com/composer/installers.git",
"reference": "d78064c68299743e0161004f2de3a0204e33b804"
"reference": "79ad876c7498c0bbfe7eed065b8651c93bfd6045"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/composer/installers/zipball/d78064c68299743e0161004f2de3a0204e33b804",
"reference": "d78064c68299743e0161004f2de3a0204e33b804",
"url": "https://api.github.com/repos/composer/installers/zipball/79ad876c7498c0bbfe7eed065b8651c93bfd6045",
"reference": "79ad876c7498c0bbfe7eed065b8651c93bfd6045",
"shasum": ""
},
"require": {
@ -59,12 +59,16 @@
"keywords": [
"Craft",
"Dolibarr",
"Eliasis",
"Hurad",
"ImageCMS",
"Kanboard",
"MODX Evo",
"Mautic",
"Maya",
"OXID",
"Plentymarkets",
"Porto",
"RadPHP",
"SMF",
"Thelia",
@ -87,9 +91,11 @@
"fuelphp",
"grav",
"installer",
"itop",
"joomla",
"kohana",
"laravel",
"lavalite",
"lithium",
"magento",
"mako",
@ -104,6 +110,7 @@
"roundcube",
"shopware",
"silverstripe",
"sydes",
"symfony",
"typo3",
"wordpress",
@ -111,7 +118,7 @@
"zend",
"zikula"
],
"time": "2016-08-13T20:53:52+00:00"
"time": "2017-04-24T06:37:16+00:00"
}
],
"packages-dev": [
@ -211,6 +218,108 @@
],
"time": "2017-04-12T18:52:22+00:00"
},
{
"name": "phar-io/manifest",
"version": "1.0.1",
"source": {
"type": "git",
"url": "https://github.com/phar-io/manifest.git",
"reference": "2df402786ab5368a0169091f61a7c1e0eb6852d0"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/phar-io/manifest/zipball/2df402786ab5368a0169091f61a7c1e0eb6852d0",
"reference": "2df402786ab5368a0169091f61a7c1e0eb6852d0",
"shasum": ""
},
"require": {
"ext-dom": "*",
"ext-phar": "*",
"phar-io/version": "^1.0.1",
"php": "^5.6 || ^7.0"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.0.x-dev"
}
},
"autoload": {
"classmap": [
"src/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"authors": [
{
"name": "Arne Blankerts",
"email": "arne@blankerts.de",
"role": "Developer"
},
{
"name": "Sebastian Heuer",
"email": "sebastian@phpeople.de",
"role": "Developer"
},
{
"name": "Sebastian Bergmann",
"email": "sebastian@phpunit.de",
"role": "Developer"
}
],
"description": "Component for reading phar.io manifest information from a PHP Archive (PHAR)",
"time": "2017-03-05T18:14:27+00:00"
},
{
"name": "phar-io/version",
"version": "1.0.1",
"source": {
"type": "git",
"url": "https://github.com/phar-io/version.git",
"reference": "a70c0ced4be299a63d32fa96d9281d03e94041df"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/phar-io/version/zipball/a70c0ced4be299a63d32fa96d9281d03e94041df",
"reference": "a70c0ced4be299a63d32fa96d9281d03e94041df",
"shasum": ""
},
"require": {
"php": "^5.6 || ^7.0"
},
"type": "library",
"autoload": {
"classmap": [
"src/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"authors": [
{
"name": "Arne Blankerts",
"email": "arne@blankerts.de",
"role": "Developer"
},
{
"name": "Sebastian Heuer",
"email": "sebastian@phpeople.de",
"role": "Developer"
},
{
"name": "Sebastian Bergmann",
"email": "sebastian@phpunit.de",
"role": "Developer"
}
],
"description": "Library for handling version information and constraints",
"time": "2017-03-05T17:38:23+00:00"
},
{
"name": "phpdocumentor/reflection-common",
"version": "1.0",
@ -267,22 +376,22 @@
},
{
"name": "phpdocumentor/reflection-docblock",
"version": "3.1.1",
"version": "3.2.0",
"source": {
"type": "git",
"url": "https://github.com/phpDocumentor/ReflectionDocBlock.git",
"reference": "8331b5efe816ae05461b7ca1e721c01b46bafb3e"
"reference": "46f7e8bb075036c92695b15a1ddb6971c751e585"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/phpDocumentor/ReflectionDocBlock/zipball/8331b5efe816ae05461b7ca1e721c01b46bafb3e",
"reference": "8331b5efe816ae05461b7ca1e721c01b46bafb3e",
"url": "https://api.github.com/repos/phpDocumentor/ReflectionDocBlock/zipball/46f7e8bb075036c92695b15a1ddb6971c751e585",
"reference": "46f7e8bb075036c92695b15a1ddb6971c751e585",
"shasum": ""
},
"require": {
"php": ">=5.5",
"phpdocumentor/reflection-common": "^1.0@dev",
"phpdocumentor/type-resolver": "^0.2.0",
"phpdocumentor/type-resolver": "^0.4.0",
"webmozart/assert": "^1.0"
},
"require-dev": {
@ -308,24 +417,24 @@
}
],
"description": "With this component, a library can provide support for annotations via DocBlocks or otherwise retrieve information that is embedded in a DocBlock.",
"time": "2016-09-30T07:12:33+00:00"
"time": "2017-07-15T11:38:20+00:00"
},
{
"name": "phpdocumentor/type-resolver",
"version": "0.2.1",
"version": "0.4.0",
"source": {
"type": "git",
"url": "https://github.com/phpDocumentor/TypeResolver.git",
"reference": "e224fb2ea2fba6d3ad6fdaef91cd09a172155ccb"
"reference": "9c977708995954784726e25d0cd1dddf4e65b0f7"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/phpDocumentor/TypeResolver/zipball/e224fb2ea2fba6d3ad6fdaef91cd09a172155ccb",
"reference": "e224fb2ea2fba6d3ad6fdaef91cd09a172155ccb",
"url": "https://api.github.com/repos/phpDocumentor/TypeResolver/zipball/9c977708995954784726e25d0cd1dddf4e65b0f7",
"reference": "9c977708995954784726e25d0cd1dddf4e65b0f7",
"shasum": ""
},
"require": {
"php": ">=5.5",
"php": "^5.5 || ^7.0",
"phpdocumentor/reflection-common": "^1.0"
},
"require-dev": {
@ -355,7 +464,7 @@
"email": "me@mikevanriel.com"
}
],
"time": "2016-11-25T06:54:22+00:00"
"time": "2017-07-14T14:27:02+00:00"
},
{
"name": "phpspec/prophecy",
@ -422,40 +531,41 @@
},
{
"name": "phpunit/php-code-coverage",
"version": "4.0.8",
"version": "5.2.1",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/php-code-coverage.git",
"reference": "ef7b2f56815df854e66ceaee8ebe9393ae36a40d"
"reference": "dc421f9ca5082a0c0cb04afb171c765f79add85b"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/ef7b2f56815df854e66ceaee8ebe9393ae36a40d",
"reference": "ef7b2f56815df854e66ceaee8ebe9393ae36a40d",
"url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/dc421f9ca5082a0c0cb04afb171c765f79add85b",
"reference": "dc421f9ca5082a0c0cb04afb171c765f79add85b",
"shasum": ""
},
"require": {
"ext-dom": "*",
"ext-xmlwriter": "*",
"php": "^5.6 || ^7.0",
"php": "^7.0",
"phpunit/php-file-iterator": "^1.3",
"phpunit/php-text-template": "^1.2",
"phpunit/php-token-stream": "^1.4.2 || ^2.0",
"phpunit/php-token-stream": "^1.4.11 || ^2.0",
"sebastian/code-unit-reverse-lookup": "^1.0",
"sebastian/environment": "^1.3.2 || ^2.0",
"sebastian/version": "^1.0 || ^2.0"
"sebastian/environment": "^3.0",
"sebastian/version": "^2.0",
"theseer/tokenizer": "^1.1"
},
"require-dev": {
"ext-xdebug": "^2.1.4",
"phpunit/phpunit": "^5.7"
"ext-xdebug": "^2.5",
"phpunit/phpunit": "^6.0"
},
"suggest": {
"ext-xdebug": "^2.5.1"
"ext-xdebug": "^2.5.3"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "4.0.x-dev"
"dev-master": "5.2.x-dev"
}
},
"autoload": {
@ -481,7 +591,7 @@
"testing",
"xunit"
],
"time": "2017-04-02T07:44:40+00:00"
"time": "2017-04-21T08:03:57+00:00"
},
{
"name": "phpunit/php-file-iterator",
@ -671,16 +781,16 @@
},
{
"name": "phpunit/phpunit",
"version": "5.7.19",
"version": "6.2.3",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/phpunit.git",
"reference": "69c4f49ff376af2692bad9cebd883d17ebaa98a1"
"reference": "fa5711d0559fc4b64deba0702be52d41434cbcb7"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/69c4f49ff376af2692bad9cebd883d17ebaa98a1",
"reference": "69c4f49ff376af2692bad9cebd883d17ebaa98a1",
"url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/fa5711d0559fc4b64deba0702be52d41434cbcb7",
"reference": "fa5711d0559fc4b64deba0702be52d41434cbcb7",
"shasum": ""
},
"require": {
@ -689,33 +799,35 @@
"ext-libxml": "*",
"ext-mbstring": "*",
"ext-xml": "*",
"myclabs/deep-copy": "~1.3",
"php": "^5.6 || ^7.0",
"phpspec/prophecy": "^1.6.2",
"phpunit/php-code-coverage": "^4.0.4",
"phpunit/php-file-iterator": "~1.4",
"phpunit/php-text-template": "~1.2",
"myclabs/deep-copy": "^1.3",
"phar-io/manifest": "^1.0.1",
"phar-io/version": "^1.0",
"php": "^7.0",
"phpspec/prophecy": "^1.7",
"phpunit/php-code-coverage": "^5.2",
"phpunit/php-file-iterator": "^1.4",
"phpunit/php-text-template": "^1.2",
"phpunit/php-timer": "^1.0.6",
"phpunit/phpunit-mock-objects": "^3.2",
"sebastian/comparator": "^1.2.4",
"sebastian/diff": "~1.2",
"sebastian/environment": "^1.3.4 || ^2.0",
"sebastian/exporter": "~2.0",
"sebastian/global-state": "^1.1",
"sebastian/object-enumerator": "~2.0",
"sebastian/resource-operations": "~1.0",
"sebastian/version": "~1.0.3|~2.0",
"symfony/yaml": "~2.1|~3.0"
"phpunit/phpunit-mock-objects": "^4.0",
"sebastian/comparator": "^2.0",
"sebastian/diff": "^1.4.3 || ^2.0",
"sebastian/environment": "^3.0.2",
"sebastian/exporter": "^3.1",
"sebastian/global-state": "^1.1 || ^2.0",
"sebastian/object-enumerator": "^3.0.2",
"sebastian/resource-operations": "^1.0",
"sebastian/version": "^2.0"
},
"conflict": {
"phpdocumentor/reflection-docblock": "3.0.2"
"phpdocumentor/reflection-docblock": "3.0.2",
"phpunit/dbunit": "<3.0"
},
"require-dev": {
"ext-pdo": "*"
},
"suggest": {
"ext-xdebug": "*",
"phpunit/php-invoker": "~1.1"
"phpunit/php-invoker": "^1.1"
},
"bin": [
"phpunit"
@ -723,7 +835,7 @@
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "5.7.x-dev"
"dev-master": "6.2.x-dev"
}
},
"autoload": {
@ -749,33 +861,33 @@
"testing",
"xunit"
],
"time": "2017-04-03T02:22:27+00:00"
"time": "2017-07-03T15:54:24+00:00"
},
{
"name": "phpunit/phpunit-mock-objects",
"version": "3.4.3",
"version": "4.0.2",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/phpunit-mock-objects.git",
"reference": "3ab72b65b39b491e0c011e2e09bb2206c2aa8e24"
"reference": "d8833b396dce9162bb2eb5d59aee5a3ab3cfa5b4"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/phpunit-mock-objects/zipball/3ab72b65b39b491e0c011e2e09bb2206c2aa8e24",
"reference": "3ab72b65b39b491e0c011e2e09bb2206c2aa8e24",
"url": "https://api.github.com/repos/sebastianbergmann/phpunit-mock-objects/zipball/d8833b396dce9162bb2eb5d59aee5a3ab3cfa5b4",
"reference": "d8833b396dce9162bb2eb5d59aee5a3ab3cfa5b4",
"shasum": ""
},
"require": {
"doctrine/instantiator": "^1.0.2",
"php": "^5.6 || ^7.0",
"php": "^7.0",
"phpunit/php-text-template": "^1.2",
"sebastian/exporter": "^1.2 || ^2.0"
"sebastian/exporter": "^3.0"
},
"conflict": {
"phpunit/phpunit": "<5.4.0"
"phpunit/phpunit": "<6.0"
},
"require-dev": {
"phpunit/phpunit": "^5.4"
"phpunit/phpunit": "^6.0"
},
"suggest": {
"ext-soap": "*"
@ -783,7 +895,7 @@
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "3.2.x-dev"
"dev-master": "4.0.x-dev"
}
},
"autoload": {
@ -808,7 +920,7 @@
"mock",
"xunit"
],
"time": "2016-12-08T20:27:08+00:00"
"time": "2017-06-30T08:15:21+00:00"
},
{
"name": "sebastian/code-unit-reverse-lookup",
@ -857,30 +969,30 @@
},
{
"name": "sebastian/comparator",
"version": "1.2.4",
"version": "2.0.0",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/comparator.git",
"reference": "2b7424b55f5047b47ac6e5ccb20b2aea4011d9be"
"reference": "20f84f468cb67efee293246e6a09619b891f55f0"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/2b7424b55f5047b47ac6e5ccb20b2aea4011d9be",
"reference": "2b7424b55f5047b47ac6e5ccb20b2aea4011d9be",
"url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/20f84f468cb67efee293246e6a09619b891f55f0",
"reference": "20f84f468cb67efee293246e6a09619b891f55f0",
"shasum": ""
},
"require": {
"php": ">=5.3.3",
"sebastian/diff": "~1.2",
"sebastian/exporter": "~1.2 || ~2.0"
"php": "^7.0",
"sebastian/diff": "^1.2",
"sebastian/exporter": "^3.0"
},
"require-dev": {
"phpunit/phpunit": "~4.4"
"phpunit/phpunit": "^6.0"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.2.x-dev"
"dev-master": "2.0.x-dev"
}
},
"autoload": {
@ -917,27 +1029,27 @@
"compare",
"equality"
],
"time": "2017-01-29T09:50:25+00:00"
"time": "2017-03-03T06:26:08+00:00"
},
{
"name": "sebastian/diff",
"version": "1.4.1",
"version": "1.4.3",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/diff.git",
"reference": "13edfd8706462032c2f52b4b862974dd46b71c9e"
"reference": "7f066a26a962dbe58ddea9f72a4e82874a3975a4"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/13edfd8706462032c2f52b4b862974dd46b71c9e",
"reference": "13edfd8706462032c2f52b4b862974dd46b71c9e",
"url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/7f066a26a962dbe58ddea9f72a4e82874a3975a4",
"reference": "7f066a26a962dbe58ddea9f72a4e82874a3975a4",
"shasum": ""
},
"require": {
"php": ">=5.3.3"
"php": "^5.3.3 || ^7.0"
},
"require-dev": {
"phpunit/phpunit": "~4.8"
"phpunit/phpunit": "^4.8.35 || ^5.7 || ^6.0"
},
"type": "library",
"extra": {
@ -969,32 +1081,32 @@
"keywords": [
"diff"
],
"time": "2015-12-08T07:14:41+00:00"
"time": "2017-05-22T07:24:03+00:00"
},
{
"name": "sebastian/environment",
"version": "2.0.0",
"version": "3.1.0",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/environment.git",
"reference": "5795ffe5dc5b02460c3e34222fee8cbe245d8fac"
"reference": "cd0871b3975fb7fc44d11314fd1ee20925fce4f5"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/5795ffe5dc5b02460c3e34222fee8cbe245d8fac",
"reference": "5795ffe5dc5b02460c3e34222fee8cbe245d8fac",
"url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/cd0871b3975fb7fc44d11314fd1ee20925fce4f5",
"reference": "cd0871b3975fb7fc44d11314fd1ee20925fce4f5",
"shasum": ""
},
"require": {
"php": "^5.6 || ^7.0"
"php": "^7.0"
},
"require-dev": {
"phpunit/phpunit": "^5.0"
"phpunit/phpunit": "^6.1"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "2.0.x-dev"
"dev-master": "3.1.x-dev"
}
},
"autoload": {
@ -1019,34 +1131,34 @@
"environment",
"hhvm"
],
"time": "2016-11-26T07:53:53+00:00"
"time": "2017-07-01T08:51:00+00:00"
},
{
"name": "sebastian/exporter",
"version": "2.0.0",
"version": "3.1.0",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/exporter.git",
"reference": "ce474bdd1a34744d7ac5d6aad3a46d48d9bac4c4"
"reference": "234199f4528de6d12aaa58b612e98f7d36adb937"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/ce474bdd1a34744d7ac5d6aad3a46d48d9bac4c4",
"reference": "ce474bdd1a34744d7ac5d6aad3a46d48d9bac4c4",
"url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/234199f4528de6d12aaa58b612e98f7d36adb937",
"reference": "234199f4528de6d12aaa58b612e98f7d36adb937",
"shasum": ""
},
"require": {
"php": ">=5.3.3",
"sebastian/recursion-context": "~2.0"
"php": "^7.0",
"sebastian/recursion-context": "^3.0"
},
"require-dev": {
"ext-mbstring": "*",
"phpunit/phpunit": "~4.4"
"phpunit/phpunit": "^6.0"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "2.0.x-dev"
"dev-master": "3.1.x-dev"
}
},
"autoload": {
@ -1086,27 +1198,27 @@
"export",
"exporter"
],
"time": "2016-11-19T08:54:04+00:00"
"time": "2017-04-03T13:19:02+00:00"
},
{
"name": "sebastian/global-state",
"version": "1.1.1",
"version": "2.0.0",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/global-state.git",
"reference": "bc37d50fea7d017d3d340f230811c9f1d7280af4"
"reference": "e8ba02eed7bbbb9e59e43dedd3dddeff4a56b0c4"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/bc37d50fea7d017d3d340f230811c9f1d7280af4",
"reference": "bc37d50fea7d017d3d340f230811c9f1d7280af4",
"url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/e8ba02eed7bbbb9e59e43dedd3dddeff4a56b0c4",
"reference": "e8ba02eed7bbbb9e59e43dedd3dddeff4a56b0c4",
"shasum": ""
},
"require": {
"php": ">=5.3.3"
"php": "^7.0"
},
"require-dev": {
"phpunit/phpunit": "~4.2"
"phpunit/phpunit": "^6.0"
},
"suggest": {
"ext-uopz": "*"
@ -1114,7 +1226,7 @@
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.0-dev"
"dev-master": "2.0-dev"
}
},
"autoload": {
@ -1137,33 +1249,34 @@
"keywords": [
"global state"
],
"time": "2015-10-12T03:26:01+00:00"
"time": "2017-04-27T15:39:26+00:00"
},
{
"name": "sebastian/object-enumerator",
"version": "2.0.1",
"version": "3.0.2",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/object-enumerator.git",
"reference": "1311872ac850040a79c3c058bea3e22d0f09cbb7"
"reference": "31dd3379d16446c5d86dec32ab1ad1f378581ad8"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/object-enumerator/zipball/1311872ac850040a79c3c058bea3e22d0f09cbb7",
"reference": "1311872ac850040a79c3c058bea3e22d0f09cbb7",
"url": "https://api.github.com/repos/sebastianbergmann/object-enumerator/zipball/31dd3379d16446c5d86dec32ab1ad1f378581ad8",
"reference": "31dd3379d16446c5d86dec32ab1ad1f378581ad8",
"shasum": ""
},
"require": {
"php": ">=5.6",
"sebastian/recursion-context": "~2.0"
"php": "^7.0",
"sebastian/object-reflector": "^1.0",
"sebastian/recursion-context": "^3.0"
},
"require-dev": {
"phpunit/phpunit": "~5"
"phpunit/phpunit": "^6.0"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "2.0.x-dev"
"dev-master": "3.0.x-dev"
}
},
"autoload": {
@ -1183,32 +1296,77 @@
],
"description": "Traverses array structures and object graphs to enumerate all referenced objects",
"homepage": "https://github.com/sebastianbergmann/object-enumerator/",
"time": "2017-02-18T15:18:39+00:00"
"time": "2017-03-12T15:17:29+00:00"
},
{
"name": "sebastian/recursion-context",
"version": "2.0.0",
"name": "sebastian/object-reflector",
"version": "1.1.1",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/recursion-context.git",
"reference": "2c3ba150cbec723aa057506e73a8d33bdb286c9a"
"url": "https://github.com/sebastianbergmann/object-reflector.git",
"reference": "773f97c67f28de00d397be301821b06708fca0be"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/2c3ba150cbec723aa057506e73a8d33bdb286c9a",
"reference": "2c3ba150cbec723aa057506e73a8d33bdb286c9a",
"url": "https://api.github.com/repos/sebastianbergmann/object-reflector/zipball/773f97c67f28de00d397be301821b06708fca0be",
"reference": "773f97c67f28de00d397be301821b06708fca0be",
"shasum": ""
},
"require": {
"php": ">=5.3.3"
"php": "^7.0"
},
"require-dev": {
"phpunit/phpunit": "~4.4"
"phpunit/phpunit": "^6.0"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "2.0.x-dev"
"dev-master": "1.1-dev"
}
},
"autoload": {
"classmap": [
"src/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"authors": [
{
"name": "Sebastian Bergmann",
"email": "sebastian@phpunit.de"
}
],
"description": "Allows reflection of object attributes, including inherited and non-public ones",
"homepage": "https://github.com/sebastianbergmann/object-reflector/",
"time": "2017-03-29T09:07:27+00:00"
},
{
"name": "sebastian/recursion-context",
"version": "3.0.0",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/recursion-context.git",
"reference": "5b0cd723502bac3b006cbf3dbf7a1e3fcefe4fa8"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/5b0cd723502bac3b006cbf3dbf7a1e3fcefe4fa8",
"reference": "5b0cd723502bac3b006cbf3dbf7a1e3fcefe4fa8",
"shasum": ""
},
"require": {
"php": "^7.0"
},
"require-dev": {
"phpunit/phpunit": "^6.0"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "3.0.x-dev"
}
},
"autoload": {
@ -1236,7 +1394,7 @@
],
"description": "Provides functionality to recursively process PHP variables",
"homepage": "http://www.github.com/sebastianbergmann/recursion-context",
"time": "2016-11-19T07:33:16+00:00"
"time": "2017-03-03T06:23:57+00:00"
},
{
"name": "sebastian/resource-operations",
@ -1325,16 +1483,16 @@
},
{
"name": "squizlabs/php_codesniffer",
"version": "2.7.0",
"version": "2.9.1",
"source": {
"type": "git",
"url": "https://github.com/squizlabs/PHP_CodeSniffer.git",
"reference": "571e27b6348e5b3a637b2abc82ac0d01e6d7bbed"
"reference": "dcbed1074f8244661eecddfc2a675430d8d33f62"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/squizlabs/PHP_CodeSniffer/zipball/571e27b6348e5b3a637b2abc82ac0d01e6d7bbed",
"reference": "571e27b6348e5b3a637b2abc82ac0d01e6d7bbed",
"url": "https://api.github.com/repos/squizlabs/PHP_CodeSniffer/zipball/dcbed1074f8244661eecddfc2a675430d8d33f62",
"reference": "dcbed1074f8244661eecddfc2a675430d8d33f62",
"shasum": ""
},
"require": {
@ -1399,62 +1557,47 @@
"phpcs",
"standards"
],
"time": "2016-09-01T23:53:02+00:00"
"time": "2017-05-22T02:43:20+00:00"
},
{
"name": "symfony/yaml",
"version": "v3.2.7",
"name": "theseer/tokenizer",
"version": "1.1.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/yaml.git",
"reference": "62b4cdb99d52cb1ff253c465eb1532a80cebb621"
"url": "https://github.com/theseer/tokenizer.git",
"reference": "cb2f008f3f05af2893a87208fe6a6c4985483f8b"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/yaml/zipball/62b4cdb99d52cb1ff253c465eb1532a80cebb621",
"reference": "62b4cdb99d52cb1ff253c465eb1532a80cebb621",
"url": "https://api.github.com/repos/theseer/tokenizer/zipball/cb2f008f3f05af2893a87208fe6a6c4985483f8b",
"reference": "cb2f008f3f05af2893a87208fe6a6c4985483f8b",
"shasum": ""
},
"require": {
"php": ">=5.5.9"
},
"require-dev": {
"symfony/console": "~2.8|~3.0"
},
"suggest": {
"symfony/console": "For validating YAML files using the lint command"
"ext-dom": "*",
"ext-tokenizer": "*",
"ext-xmlwriter": "*",
"php": "^7.0"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "3.2-dev"
}
},
"autoload": {
"psr-4": {
"Symfony\\Component\\Yaml\\": ""
},
"exclude-from-classmap": [
"/Tests/"
"classmap": [
"src/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
"BSD-3-Clause"
],
"authors": [
{
"name": "Fabien Potencier",
"email": "fabien@symfony.com"
},
{
"name": "Symfony Community",
"homepage": "https://symfony.com/contributors"
"name": "Arne Blankerts",
"email": "arne@blankerts.de",
"role": "Developer"
}
],
"description": "Symfony Yaml Component",
"homepage": "https://symfony.com",
"time": "2017-03-20T09:45:15+00:00"
"description": "A small library for converting tokenized PHP source code into XML and potentially other formats",
"time": "2017-04-07T12:08:54+00:00"
},
{
"name": "webmozart/assert",

View File

@ -200,8 +200,8 @@ abstract class WC_Data {
} else {
$this->data_store->create( $this );
}
return $this->get_id();
}
return $this->get_id();
}
/**
@ -268,6 +268,23 @@ abstract class WC_Data {
return array_filter( $this->meta_data, array( $this, 'filter_null_meta' ) );
}
/**
* Check if the key is an internal one.
*
* @since 3.2.0
* @param string $key
* @return bool true if it's an internal key, false otherwise
*/
protected function is_internal_meta_key( $key ) {
if ( $this->data_store && ! empty( $key ) && in_array( $key, $this->data_store->get_internal_meta_keys() ) ) {
wc_doing_it_wrong( __FUNCTION__, __( 'Meta properties should not be accessed directly. Use getters and setters.', 'woocommerce' ), '3.2.0' );
return true;
}
return false;
}
/**
* Get Meta Data by Key.
*
@ -278,6 +295,14 @@ abstract class WC_Data {
* @return mixed
*/
public function get_meta( $key = '', $single = true, $context = 'view' ) {
if ( $this->is_internal_meta_key( $key ) ) {
$function = 'get_' . $key;
if ( is_callable( array( $this, $function ) ) ) {
return $this->{$function}();
}
}
$this->maybe_read_meta_data();
$meta_data = $this->get_meta_data();
$array_keys = array_keys( wp_list_pluck( $meta_data, 'key' ), $key );
@ -324,11 +349,11 @@ abstract class WC_Data {
foreach ( $data as $meta ) {
$meta = (array) $meta;
if ( isset( $meta['key'], $meta['value'], $meta['id'] ) ) {
$this->meta_data[] = (object) array(
$this->meta_data[] = new WC_Meta_Data( array(
'id' => $meta['id'],
'key' => $meta['key'],
'value' => $meta['value'],
);
) );
}
}
}
@ -343,14 +368,22 @@ abstract class WC_Data {
* @param bool $unique Should this be a unique key?
*/
public function add_meta_data( $key, $value, $unique = false ) {
if ( $this->is_internal_meta_key( $key ) ) {
$function = 'set_' . $key;
if ( is_callable( array( $this, $function ) ) ) {
return $this->{$function}( $value );
}
}
$this->maybe_read_meta_data();
if ( $unique ) {
$this->delete_meta_data( $key );
}
$this->meta_data[] = (object) array(
$this->meta_data[] = new WC_Meta_Data( array(
'key' => $key,
'value' => $value,
);
) );
}
/**
@ -362,13 +395,22 @@ abstract class WC_Data {
* @param int $meta_id
*/
public function update_meta_data( $key, $value, $meta_id = '' ) {
if ( $this->is_internal_meta_key( $key ) ) {
$function = 'set_' . $key;
if ( is_callable( array( $this, $function ) ) ) {
return $this->{$function}( $value );
}
}
$this->maybe_read_meta_data();
if ( $array_key = $meta_id ? array_keys( wp_list_pluck( $this->meta_data, 'id' ), $meta_id ) : '' ) {
$this->meta_data[ current( $array_key ) ] = (object) array(
'id' => $meta_id,
'key' => $key,
'value' => $value,
);
$array_key = $meta_id ? array_keys( wp_list_pluck( $this->meta_data, 'id' ), $meta_id ) : '';
if ( $array_key ) {
$meta = $this->meta_data[ current( $array_key ) ];
$meta->key = $key;
$meta->value = $value;
} else {
$this->add_meta_data( $key, $value, true );
}
@ -382,7 +424,9 @@ abstract class WC_Data {
*/
public function delete_meta_data( $key ) {
$this->maybe_read_meta_data();
if ( $array_keys = array_keys( wp_list_pluck( $this->meta_data, 'key' ), $key ) ) {
$array_keys = array_keys( wp_list_pluck( $this->meta_data, 'key' ), $key );
if ( $array_keys ) {
foreach ( $array_keys as $array_key ) {
$this->meta_data[ $array_key ]->value = null;
}
@ -397,7 +441,9 @@ abstract class WC_Data {
*/
public function delete_meta_data_by_mid( $mid ) {
$this->maybe_read_meta_data();
if ( $array_keys = array_keys( wp_list_pluck( $this->meta_data, 'id' ), $mid ) ) {
$array_keys = array_keys( wp_list_pluck( $this->meta_data, 'id' ), $mid );
if ( $array_keys ) {
foreach ( $array_keys as $array_key ) {
$this->meta_data[ $array_key ]->value = null;
}
@ -449,11 +495,11 @@ abstract class WC_Data {
$raw_meta_data = $cache_loaded ? $cached_meta : $this->data_store->read_meta( $this );
if ( $raw_meta_data ) {
foreach ( $raw_meta_data as $meta ) {
$this->meta_data[] = (object) array(
$this->meta_data[] = new WC_Meta_Data( array(
'id' => (int) $meta->meta_id,
'key' => $meta->meta_key,
'value' => maybe_unserialize( $meta->meta_value ),
);
) );
}
if ( ! $cache_loaded && ! empty( $this->cache_group ) ) {
@ -478,10 +524,13 @@ abstract class WC_Data {
unset( $this->meta_data[ $array_key ] );
}
} elseif ( empty( $meta->id ) ) {
$new_meta_id = $this->data_store->add_meta( $this, $meta );
$this->meta_data[ $array_key ]->id = $new_meta_id;
$meta->id = $this->data_store->add_meta( $this, $meta );
$meta->apply_changes();
} else {
$this->data_store->update_meta( $this, $meta );
if ( $meta->get_changes() ) {
$this->data_store->update_meta( $this, $meta );
$meta->apply_changes();
}
}
}
if ( ! empty( $this->cache_group ) ) {
@ -509,7 +558,7 @@ abstract class WC_Data {
$this->data = $this->default_data;
$this->changes = array();
$this->set_object_read( false );
}
}
/**
* Set object read property.

View File

@ -992,8 +992,8 @@ abstract class WC_Abstract_Order extends WC_Abstract_Legacy_Order {
$found_tax_classes = array();
foreach ( $this->get_items() as $item ) {
if ( $_product = $item->get_product() ) {
$found_tax_classes[] = $_product->get_tax_class();
if ( ( $product = $item->get_product() ) && ( $product->is_taxable() || $product->is_shipping_taxable() ) ) {
$found_tax_classes[] = $product->get_tax_class();
}
}

View File

@ -456,4 +456,17 @@ abstract class WC_Payment_Gateway extends WC_Settings_API {
esc_html__( 'Save to account', 'woocommerce' )
);
}
/**
* Add payment method via account screen. This should be extended by gateway plugins.
*
* @since 3.2.0 Included here from 3.2.0, but supported from 3.0.0.
* @return array
*/
public function add_payment_method() {
return array(
'result' => 'failure',
'redirect' => wc_get_endpoint_url( 'payment-methods' ),
);
}
}

View File

@ -1280,6 +1280,7 @@ class WC_Product extends WC_Abstract_Legacy_Product {
* Save data (either create or update depending on if we are working on an existing product).
*
* @since 3.0.0
* @return int
*/
public function save() {
$this->validate_props();
@ -1296,8 +1297,8 @@ class WC_Product extends WC_Abstract_Legacy_Product {
if ( $this->get_parent_id() ) {
wc_deferred_product_sync( $this->get_parent_id() );
}
return $this->get_id();
}
return $this->get_id();
}
/*

View File

@ -89,7 +89,6 @@ abstract class WC_Settings_API {
* on the gateway's settings screen.
*
* @since 1.0.0
* @return string
*/
public function init_form_fields() {}

View File

@ -118,10 +118,8 @@ abstract class WC_Widget extends WP_Widget {
/**
* Output the html at the start of a widget.
*
* @param array $args
* @param array $args
* @param array $instance
*
* @return string
*/
public function widget_start( $args, $instance ) {
echo $args['before_widget'];
@ -135,7 +133,6 @@ abstract class WC_Widget extends WP_Widget {
* Output the html at the end of a widget.
*
* @param array $args
* @return string
*/
public function widget_end( $args ) {
echo $args['after_widget'];

View File

@ -88,158 +88,71 @@ class WC_Admin_Attributes {
return $attribute;
}
/**
* See if an attribute name is valid.
* @param string $attribute_name
* @return bool|WP_error result
*/
private static function valid_attribute_name( $attribute_name ) {
if ( strlen( $attribute_name ) > 28 ) {
/* translators: %s: attribute name */
return new WP_Error( 'error', sprintf( __( 'Slug "%s" is too long (28 characters max). Shorten it, please.', 'woocommerce' ), sanitize_title( $attribute_name ) ) );
} elseif ( wc_check_if_attribute_name_is_reserved( $attribute_name ) ) {
/* translators: %s: attribute name */
return new WP_Error( 'error', sprintf( __( 'Slug "%s" is not allowed because it is a reserved term. Change it, please.', 'woocommerce' ), sanitize_title( $attribute_name ) ) );
}
return true;
}
/**
* Add an attribute.
*
* @return bool|WP_Error
*/
private static function process_add_attribute() {
global $wpdb;
check_admin_referer( 'woocommerce-add-new_attribute' );
$attribute = self::get_posted_attribute();
$args = array(
'name' => $attribute['attribute_label'],
'slug' => $attribute['attribute_name'],
'type' => $attribute['attribute_type'],
'order_by' => $attribute['attribute_orderby'],
'has_archives' => $attribute['attribute_public'],
);
if ( empty( $attribute['attribute_name'] ) || empty( $attribute['attribute_label'] ) ) {
return new WP_Error( 'error', __( 'Please, provide an attribute name and slug.', 'woocommerce' ) );
} elseif ( ( $valid_attribute_name = self::valid_attribute_name( $attribute['attribute_name'] ) ) && is_wp_error( $valid_attribute_name ) ) {
return $valid_attribute_name;
} elseif ( taxonomy_exists( wc_attribute_taxonomy_name( $attribute['attribute_name'] ) ) ) {
/* translators: %s: attribute name */
return new WP_Error( 'error', sprintf( __( 'Slug "%s" is already in use. Change it, please.', 'woocommerce' ), sanitize_title( $attribute['attribute_name'] ) ) );
$id = wc_create_attribute( $args );
if ( is_wp_error( $id ) ) {
return $id;
}
$wpdb->insert( $wpdb->prefix . 'woocommerce_attribute_taxonomies', $attribute );
do_action( 'woocommerce_attribute_added', $wpdb->insert_id, $attribute );
wp_schedule_single_event( time(), 'woocommerce_flush_rewrite_rules' );
delete_transient( 'wc_attribute_taxonomies' );
return true;
}
/**
* Edit an attribute.
*
* @return bool|WP_Error
*/
private static function process_edit_attribute() {
global $wpdb;
$attribute_id = absint( $_GET['edit'] );
check_admin_referer( 'woocommerce-save-attribute_' . $attribute_id );
$attribute = self::get_posted_attribute();
$args = array(
'name' => $attribute['attribute_label'],
'slug' => $attribute['attribute_name'],
'type' => $attribute['attribute_type'],
'order_by' => $attribute['attribute_orderby'],
'has_archives' => $attribute['attribute_public'],
);
if ( empty( $attribute['attribute_name'] ) || empty( $attribute['attribute_label'] ) ) {
return new WP_Error( 'error', __( 'Please, provide an attribute name and slug.', 'woocommerce' ) );
} elseif ( ( $valid_attribute_name = self::valid_attribute_name( $attribute['attribute_name'] ) ) && is_wp_error( $valid_attribute_name ) ) {
return $valid_attribute_name;
}
$id = wc_update_attribute( $attribute_id, $args );
$taxonomy_exists = taxonomy_exists( wc_attribute_taxonomy_name( $attribute['attribute_name'] ) );
$old_attribute_name = $wpdb->get_var( "SELECT attribute_name FROM {$wpdb->prefix}woocommerce_attribute_taxonomies WHERE attribute_id = $attribute_id" );
if ( $old_attribute_name != $attribute['attribute_name'] && wc_sanitize_taxonomy_name( $old_attribute_name ) != $attribute['attribute_name'] && $taxonomy_exists ) {
/* translators: %s: attribute name */
return new WP_Error( 'error', sprintf( __( 'Slug "%s" is already in use. Change it, please.', 'woocommerce' ), sanitize_title( $attribute['attribute_name'] ) ) );
}
$wpdb->update( $wpdb->prefix . 'woocommerce_attribute_taxonomies', $attribute, array( 'attribute_id' => $attribute_id ) );
do_action( 'woocommerce_attribute_updated', $attribute_id, $attribute, $old_attribute_name );
if ( $old_attribute_name != $attribute['attribute_name'] && ! empty( $old_attribute_name ) ) {
// Update taxonomies in the wp term taxonomy table
$wpdb->update(
$wpdb->term_taxonomy,
array( 'taxonomy' => wc_attribute_taxonomy_name( $attribute['attribute_name'] ) ),
array( 'taxonomy' => 'pa_' . $old_attribute_name )
);
// Update taxonomy ordering term meta
if ( get_option( 'db_version' ) < 34370 ) {
$wpdb->update(
$wpdb->prefix . 'woocommerce_termmeta',
array( 'meta_key' => 'order_pa_' . sanitize_title( $attribute['attribute_name'] ) ),
array( 'meta_key' => 'order_pa_' . sanitize_title( $old_attribute_name ) )
);
} else {
$wpdb->update(
$wpdb->termmeta,
array( 'meta_key' => 'order_pa_' . sanitize_title( $attribute['attribute_name'] ) ),
array( 'meta_key' => 'order_pa_' . sanitize_title( $old_attribute_name ) )
);
}
// Update product attributes which use this taxonomy
$old_attribute_name_length = strlen( $old_attribute_name ) + 3;
$attribute_name_length = strlen( $attribute['attribute_name'] ) + 3;
$wpdb->query( $wpdb->prepare( "UPDATE {$wpdb->postmeta} SET meta_value = REPLACE( meta_value, %s, %s ) WHERE meta_key = '_product_attributes'",
's:' . $old_attribute_name_length . ':"pa_' . $old_attribute_name . '"',
's:' . $attribute_name_length . ':"pa_' . $attribute['attribute_name'] . '"'
) );
// Update variations which use this taxonomy
$wpdb->update(
$wpdb->postmeta,
array( 'meta_key' => 'attribute_pa_' . sanitize_title( $attribute['attribute_name'] ) ),
array( 'meta_key' => 'attribute_pa_' . sanitize_title( $old_attribute_name ) )
);
if ( is_wp_error( $id ) ) {
return $id;
}
echo '<div class="updated"><p>' . __( 'Attribute updated successfully', 'woocommerce' ) . '</p><p><a href="' . esc_url( admin_url( 'edit.php?post_type=product&amp;page=product_attributes' ) ) . '">' . __( 'Back to Attributes', 'woocommerce' ) . '</a></p></div>';
wp_schedule_single_event( time(), 'woocommerce_flush_rewrite_rules' );
delete_transient( 'wc_attribute_taxonomies' );
return true;
}
/**
* Delete an attribute.
*
* @return bool
*/
private static function process_delete_attribute() {
global $wpdb;
$attribute_id = absint( $_GET['delete'] );
check_admin_referer( 'woocommerce-delete-attribute_' . $attribute_id );
$attribute_name = $wpdb->get_var( "SELECT attribute_name FROM {$wpdb->prefix}woocommerce_attribute_taxonomies WHERE attribute_id = $attribute_id" );
$taxonomy = wc_attribute_taxonomy_name( $attribute_name );
do_action( 'woocommerce_before_attribute_delete', $attribute_id, $attribute_name, $taxonomy );
if ( $attribute_name && $wpdb->query( "DELETE FROM {$wpdb->prefix}woocommerce_attribute_taxonomies WHERE attribute_id = $attribute_id" ) ) {
if ( taxonomy_exists( $taxonomy ) ) {
$terms = get_terms( $taxonomy, 'orderby=name&hide_empty=0' );
foreach ( $terms as $term ) {
wp_delete_term( $term->term_id, $taxonomy );
}
}
do_action( 'woocommerce_attribute_deleted', $attribute_id, $attribute_name, $taxonomy );
delete_transient( 'wc_attribute_taxonomies' );
return true;
}
return false;
return wc_delete_attribute( $attribute_id );
}
/**

View File

@ -180,7 +180,7 @@ class WC_Admin_Help {
'title' => __( 'Guided Tour', 'woocommerce' ),
'content' =>
'<h2><a href="https://docs.woocommerce.com/document/woocommerce-guided-tour-videos/?utm_source=helptab&utm_medium=product&utm_content=videos&utm_campaign=woocommerceplugin">' . __( 'Guided Tour', 'woocommerce' ) . '</a> &ndash; ' . esc_html( $video_map[ $video_key ]['title'] ) . '</h2>' .
'<script src="//fast.wistia.net/assets/external/E-v1.js" aync></script>
'<script src="//fast.wistia.net/assets/external/E-v1.js" async></script>
<div class="wistia_embed wistia_async_' . esc_attr( $video_map[ $video_key ]['id'] ) . ' videoFoam=true seo=false" style="width:640px;height:360px;">&nbsp;</div>
',
) );

View File

@ -158,15 +158,13 @@ class WC_Admin_Importers {
// Create the taxonomy
if ( ! in_array( $attribute_name, wc_get_attribute_taxonomies() ) ) {
$attribute = array(
'attribute_label' => $attribute_name,
'attribute_name' => $attribute_name,
'attribute_type' => 'select',
'attribute_orderby' => 'menu_order',
'attribute_public' => 0,
);
$wpdb->insert( $wpdb->prefix . 'woocommerce_attribute_taxonomies', $attribute );
delete_transient( 'wc_attribute_taxonomies' );
wc_create_attribute( array(
'name' => $attribute_name,
'slug' => $attribute_name,
'type' => 'select',
'order_by' => 'menu_order',
'has_archives' => false,
) );
}
// Register the taxonomy now so that the import works!

View File

@ -86,8 +86,31 @@ class WC_Admin_Menus {
* Loads gateways and shipping methods into memory for use within settings.
*/
public function settings_page_init() {
global $current_tab, $current_section;
WC()->payment_gateways();
WC()->shipping();
// Include settings pages
WC_Admin_Settings::get_settings_pages();
// Get current tab/section
$current_tab = empty( $_GET['tab'] ) ? 'general' : sanitize_title( $_GET['tab'] );
$current_section = empty( $_REQUEST['section'] ) ? '' : sanitize_title( $_REQUEST['section'] );
// Save settings if data has been posted
if ( ! empty( $_POST ) ) {
WC_Admin_Settings::save();
}
// Add any posted messages
if ( ! empty( $_GET['wc_error'] ) ) {
WC_Admin_Settings::add_error( stripslashes( $_GET['wc_error'] ) );
}
if ( ! empty( $_GET['wc_message'] ) ) {
WC_Admin_Settings::add_message( stripslashes( $_GET['wc_message'] ) );
}
}
/**

View File

@ -178,7 +178,7 @@ class WC_Admin_Pointers {
'next' => 'product_catdiv',
'options' => array(
'content' => '<h3>' . esc_html__( 'Product tags', 'woocommerce' ) . '</h3>' .
'<p>' . esc_html__( 'You can optionally "tag" your products here. Tags as a method of labeling your products to make them easier for customers to find.', 'woocommerce' ) . '</p>',
'<p>' . esc_html__( 'You can optionally "tag" your products here. Tags are a method of labeling your products to make them easier for customers to find.', 'woocommerce' ) . '</p>',
'position' => array(
'edge' => 'right',
'align' => 'middle',

View File

@ -546,7 +546,12 @@ class WC_Admin_Post_Types {
printf( '<mark class="%s tips" data-tip="%s">%s</mark>', esc_attr( sanitize_html_class( $the_order->get_status() ) ), esc_attr( wc_get_order_status_name( $the_order->get_status() ) ), esc_html( wc_get_order_status_name( $the_order->get_status() ) ) );
break;
case 'order_date' :
printf( '<time datetime="%s">%s</time>', esc_attr( $the_order->get_date_created()->date( 'c' ) ), esc_html( $the_order->get_date_created()->date_i18n( apply_filters( 'woocommerce_admin_order_date_format', get_option( 'date_format' ) ) ) ) );
printf(
'<time datetime="%1$s" title="%2$s">%3$s</time>',
esc_attr( $the_order->get_date_created()->date( 'c' ) ),
esc_html( $the_order->get_date_created()->date_i18n( get_option( 'date_format' ) . ' ' . get_option( 'time_format' ) ) ),
esc_html( $the_order->get_date_created()->date_i18n( apply_filters( 'woocommerce_admin_order_date_format', get_option( 'date_format' ) ) ) )
);
break;
case 'customer_message' :
if ( $the_order->get_customer_note() ) {
@ -1027,40 +1032,33 @@ class WC_Admin_Post_Types {
$stock_status = ! empty( $_REQUEST['_stock_status'] ) ? wc_clean( $_REQUEST['_stock_status'] ) : 'instock';
$stock_amount = 'yes' === $manage_stock ? wc_stock_amount( $_REQUEST['_stock'] ) : '';
$product->set_manage_stock( $manage_stock );
$product->set_backorders( $backorders );
if ( 'yes' === get_option( 'woocommerce_manage_stock' ) ) {
// Apply product type constraints to stock status
if ( $product->is_type( 'external' ) ) {
// External always in stock
$stock_status = 'instock';
} elseif ( $product->is_type( 'variable' ) ) {
// Stock status is always determined by children
foreach ( $product->get_children() as $child_id ) {
$child = wc_get_product( $child_id );
if ( ! $product->get_manage_stock() ) {
$child->set_stock_status( $stock_status );
$child->save();
}
}
$product = WC_Product_Variable::sync( $product, false );
}
$product->set_manage_stock( $manage_stock );
$product->set_backorders( $backorders );
$product->save();
if ( ! $product->is_type( 'variable' ) ) {
wc_update_product_stock_status( $post_id, $stock_status );
}
wc_update_product_stock( $post_id, $stock_amount );
} else {
$product->save();
wc_update_product_stock_status( $post_id, $stock_status );
$product->set_stock_quantity( $stock_amount );
}
// Apply product type constraints to stock status.
if ( $product->is_type( 'external' ) ) {
// External products are always in stock.
$product->set_stock_status( 'instock' );
} elseif ( $product->is_type( 'variable' ) && ! $product->get_manage_stock() ) {
// Stock status is determined by children.
foreach ( $product->get_children() as $child_id ) {
$child = wc_get_product( $child_id );
if ( ! $product->get_manage_stock() ) {
$child->set_stock_status( $stock_status );
$child->save();
}
}
$product = WC_Product_Variable::sync( $product, false );
} else {
$product->set_stock_status( $stock_status );
}
$product->save();
do_action( 'woocommerce_product_quick_edit_save', $product );
}
@ -1238,52 +1236,44 @@ class WC_Admin_Post_Types {
$was_managing_stock = $product->get_manage_stock() ? 'yes' : 'no';
$stock_status = $product->get_stock_status();
$backorders = $product->get_backorders();
$backorders = ! empty( $_REQUEST['_backorders'] ) ? wc_clean( $_REQUEST['_backorders'] ) : $backorders;
$stock_status = ! empty( $_REQUEST['_stock_status'] ) ? wc_clean( $_REQUEST['_stock_status'] ) : $stock_status;
$backorders = ! empty( $_REQUEST['_backorders'] ) ? wc_clean( $_REQUEST['_backorders'] ) : $backorders;
$stock_status = ! empty( $_REQUEST['_stock_status'] ) ? wc_clean( $_REQUEST['_stock_status'] ) : $stock_status;
if ( ! empty( $_REQUEST['_manage_stock'] ) ) {
$manage_stock = 'yes' === wc_clean( $_REQUEST['_manage_stock'] ) && 'grouped' !== $product->product_type ? 'yes' : 'no';
$manage_stock = 'yes' === wc_clean( $_REQUEST['_manage_stock'] ) && 'grouped' !== $product->get_type() ? 'yes' : 'no';
} else {
$manage_stock = $was_managing_stock;
}
$stock_amount = 'yes' === $manage_stock && ! empty( $_REQUEST['change_stock'] ) ? wc_stock_amount( $_REQUEST['_stock'] ) : $product->get_stock_quantity();
$product->set_manage_stock( $manage_stock );
$product->set_backorders( $backorders );
if ( 'yes' === get_option( 'woocommerce_manage_stock' ) ) {
// Apply product type constraints to stock status
if ( $product->is_type( 'external' ) ) {
// External always in stock
$stock_status = 'instock';
} elseif ( $product->is_type( 'variable' ) ) {
// Stock status is always determined by children
foreach ( $product->get_children() as $child_id ) {
$child = wc_get_product( $child_id );
if ( ! $product->get_manage_stock() ) {
$child->set_stock_status( $stock_status );
$child->save();
}
}
$product = WC_Product_Variable::sync( $product, false );
}
$product->set_manage_stock( $manage_stock );
$product->set_backorders( $backorders );
$product->save();
if ( ! $product->is_type( 'variable' ) ) {
wc_update_product_stock_status( $post_id, $stock_status );
}
wc_update_product_stock( $post_id, $stock_amount );
} else {
$product->save();
wc_update_product_stock_status( $post_id, $stock_status );
$product->set_stock_quantity( $stock_amount );
}
// Apply product type constraints to stock status.
if ( $product->is_type( 'external' ) ) {
// External products are always in stock.
$product->set_stock_status( 'instock' );
} elseif ( $product->is_type( 'variable' ) && ! $product->get_manage_stock() ) {
// Stock status is determined by children.
foreach ( $product->get_children() as $child_id ) {
$child = wc_get_product( $child_id );
if ( ! $product->get_manage_stock() ) {
$child->set_stock_status( $stock_status );
$child->save();
}
}
$product = WC_Product_Variable::sync( $product, false );
} else {
$product->set_stock_status( $stock_status );
}
$product->save();
do_action( 'woocommerce_product_bulk_edit_save', $product );
}

View File

@ -110,7 +110,6 @@ class WC_Admin_Settings {
/**
* Output messages + errors.
* @return string
*/
public static function show_messages() {
if ( sizeof( self::$errors ) > 0 ) {
@ -142,27 +141,6 @@ class WC_Admin_Settings {
'i18n_nav_warning' => __( 'The changes you made will be lost if you navigate away from this page.', 'woocommerce' ),
) );
// Include settings pages
self::get_settings_pages();
// Get current tab/section
$current_tab = empty( $_GET['tab'] ) ? 'general' : sanitize_title( $_GET['tab'] );
$current_section = empty( $_REQUEST['section'] ) ? '' : sanitize_title( $_REQUEST['section'] );
// Save settings if data has been posted
if ( ! empty( $_POST ) ) {
self::save();
}
// Add any posted messages
if ( ! empty( $_GET['wc_error'] ) ) {
self::add_error( stripslashes( $_GET['wc_error'] ) );
}
if ( ! empty( $_GET['wc_message'] ) ) {
self::add_message( stripslashes( $_GET['wc_message'] ) );
}
// Get tabs for the settings page
$tabs = apply_filters( 'woocommerce_settings_tabs_array', array() );

View File

@ -176,8 +176,6 @@ class WC_Admin {
/**
* Preview email template.
*
* @return string
*/
public function preview_emails() {

View File

@ -357,7 +357,7 @@ class WC_Meta_Box_Product_Data {
'product_url' => esc_url_raw( $_POST['_product_url'] ),
'button_text' => wc_clean( $_POST['_button_text'] ),
'children' => 'grouped' === $product_type ? self::prepare_children() : null,
'reviews_allowed' => ! empty( $_POST['_reviews_allowed'] ),
'reviews_allowed' => ! empty( $_POST['comment_status'] ) && 'open' === $_POST['comment_status'],
'attributes' => $attributes,
'default_attributes' => self::prepare_set_attributes( $attributes, 'default_attribute_' ),
) );

View File

@ -37,7 +37,7 @@ if ( ! defined( 'ABSPATH' ) ) {
<div class="options_group reviews">
<?php
woocommerce_wp_checkbox( array(
'id' => '_reviews_allowed',
'id' => 'comment_status',
'value' => $product_object->get_reviews_allowed( 'edit' ) ? 'open' : 'closed',
'label' => __( 'Enable reviews', 'woocommerce' ),
'cbvalue' => 'open',

View File

@ -616,8 +616,6 @@ class WC_Admin_Report {
/**
* Get the main chart.
*
* @return string
*/
public function get_main_chart() {}

View File

@ -359,8 +359,6 @@ class WC_Report_Coupon_Usage extends WC_Admin_Report {
/**
* Get the main chart.
*
* @return string
*/
public function get_main_chart() {
global $wp_locale;

View File

@ -272,8 +272,6 @@ class WC_Report_Sales_By_Category extends WC_Admin_Report {
/**
* Get the main chart.
*
* @return string
*/
public function get_main_chart() {
global $wp_locale;

View File

@ -607,8 +607,6 @@ class WC_Report_Sales_By_Date extends WC_Admin_Report {
/**
* Get the main chart.
*
* @return string
*/
public function get_main_chart() {
global $wp_locale;

View File

@ -387,8 +387,6 @@ class WC_Report_Sales_By_Product extends WC_Admin_Report {
/**
* Get the main chart.
*
* @return string
*/
public function get_main_chart() {
global $wp_locale;

View File

@ -67,8 +67,6 @@ class WC_Report_Taxes_By_Code extends WC_Admin_Report {
/**
* Get the main chart.
*
* @return string
*/
public function get_main_chart() {
global $wpdb;

View File

@ -67,8 +67,6 @@ class WC_Report_Taxes_By_Date extends WC_Admin_Report {
/**
* Get the main chart.
*
* @return string
*/
public function get_main_chart() {
$query_data = array(

View File

@ -19,7 +19,6 @@ class WC_API_Authentication {
* Setup class
*
* @since 2.1
* @return WC_API_Authentication
*/
public function __construct() {

View File

@ -31,7 +31,6 @@ class WC_API_Customers extends WC_API_Resource {
*
* @since 2.1
* @param WC_API_Server $server
* @return WC_API_Customers
*/
public function __construct( WC_API_Server $server ) {

View File

@ -28,7 +28,6 @@ class WC_API_Resource {
*
* @since 2.1
* @param WC_API_Server $server
* @return WC_API_Resource
*/
public function __construct( WC_API_Server $server ) {

View File

@ -112,7 +112,6 @@ class WC_API_Server {
*
* @since 2.1
* @param $path
* @return WC_API_Server
*/
public function __construct( $path ) {

View File

@ -19,7 +19,6 @@ class WC_API_Authentication {
* Setup class
*
* @since 2.1
* @return WC_API_Authentication
*/
public function __construct() {

View File

@ -30,7 +30,6 @@ class WC_API_Customers extends WC_API_Resource {
*
* @since 2.1
* @param WC_API_Server $server
* @return WC_API_Customers
*/
public function __construct( WC_API_Server $server ) {

View File

@ -27,7 +27,6 @@ class WC_API_Resource {
*
* @since 2.1
* @param WC_API_Server $server
* @return WC_API_Resource
*/
public function __construct( WC_API_Server $server ) {

View File

@ -111,7 +111,6 @@ class WC_API_Server {
*
* @since 2.1
* @param $path
* @return WC_API_Server
*/
public function __construct( $path ) {

View File

@ -19,7 +19,6 @@ class WC_API_Authentication {
* Setup class
*
* @since 2.1
* @return WC_API_Authentication
*/
public function __construct() {

View File

@ -30,7 +30,6 @@ class WC_API_Customers extends WC_API_Resource {
*
* @since 2.1
* @param WC_API_Server $server
* @return WC_API_Customers
*/
public function __construct( WC_API_Server $server ) {

View File

@ -27,7 +27,6 @@ class WC_API_Resource {
*
* @since 2.1
* @param WC_API_Server $server
* @return WC_API_Resource
*/
public function __construct( WC_API_Server $server ) {

View File

@ -111,7 +111,6 @@ class WC_API_Server {
*
* @since 2.1
* @param $path
* @return WC_API_Server
*/
public function __construct( $path ) {

View File

@ -240,38 +240,20 @@ class WC_REST_Product_Attributes_V1_Controller extends WC_REST_Controller {
public function create_item( $request ) {
global $wpdb;
$args = array(
'attribute_label' => $request['name'],
'attribute_name' => wc_sanitize_taxonomy_name( stripslashes( $request['slug'] ) ),
'attribute_type' => ! empty( $request['type'] ) ? $request['type'] : 'select',
'attribute_orderby' => ! empty( $request['order_by'] ) ? $request['order_by'] : 'menu_order',
'attribute_public' => true === $request['has_archives'],
);
// Set the attribute slug.
if ( empty( $args['attribute_name'] ) ) {
$args['attribute_name'] = wc_sanitize_taxonomy_name( stripslashes( $args['attribute_label'] ) );
} else {
$args['attribute_name'] = preg_replace( '/^pa\_/', '', wc_sanitize_taxonomy_name( stripslashes( $args['attribute_name'] ) ) );
}
$valid_slug = $this->validate_attribute_slug( $args['attribute_name'], true );
if ( is_wp_error( $valid_slug ) ) {
return $valid_slug;
}
$insert = $wpdb->insert(
$wpdb->prefix . 'woocommerce_attribute_taxonomies',
$args,
array( '%s', '%s', '%s', '%s', '%d' )
);
$id = wc_create_attribute( array(
'name' => $request['name'],
'slug' => wc_sanitize_taxonomy_name( stripslashes( $request['slug'] ) ),
'type' => ! empty( $request['type'] ) ? $request['type'] : 'select',
'order_by' => ! empty( $request['order_by'] ) ? $request['order_by'] : 'menu_order',
'has_archives' => true === $request['has_archives'],
) );
// Checks for errors.
if ( is_wp_error( $insert ) ) {
return new WP_Error( 'woocommerce_rest_cannot_create', $insert->get_error_message(), array( 'status' => 400 ) );
if ( is_wp_error( $id ) ) {
return new WP_Error( 'woocommerce_rest_cannot_create', $id->get_error_message(), array( 'status' => 400 ) );
}
$attribute = $this->get_attribute( $wpdb->insert_id );
$attribute = $this->get_attribute( $id );
if ( is_wp_error( $attribute ) ) {
return $attribute;
@ -294,10 +276,6 @@ class WC_REST_Product_Attributes_V1_Controller extends WC_REST_Controller {
$response->set_status( 201 );
$response->header( 'Location', rest_url( '/' . $this->namespace . '/' . $this->rest_base . '/' . $attribute->attribute_id ) );
// Clear transients.
$this->flush_rewrite_rules();
delete_transient( 'wc_attribute_taxonomies' );
return $response;
}
@ -329,48 +307,17 @@ class WC_REST_Product_Attributes_V1_Controller extends WC_REST_Controller {
global $wpdb;
$id = (int) $request['id'];
$format = array( '%s', '%s', '%s', '%s', '%d' );
$args = array(
'attribute_label' => $request['name'],
'attribute_name' => wc_sanitize_taxonomy_name( stripslashes( $request['slug'] ) ),
'attribute_type' => $request['type'],
'attribute_orderby' => $request['order_by'],
'attribute_public' => $request['has_archives'],
);
$edited = wc_update_attribute( $id, array(
'name' => $request['name'],
'slug' => wc_sanitize_taxonomy_name( stripslashes( $request['slug'] ) ),
'type' => $request['type'],
'order_by' => $request['order_by'],
'has_archives' => $request['has_archives'],
) );
$i = 0;
foreach ( $args as $key => $value ) {
if ( empty( $value ) && ! is_bool( $value ) ) {
unset( $args[ $key ] );
unset( $format[ $i ] );
}
$i++;
}
// Set the attribute slug.
if ( ! empty( $args['attribute_name'] ) ) {
$args['attribute_name'] = preg_replace( '/^pa\_/', '', wc_sanitize_taxonomy_name( stripslashes( $args['attribute_name'] ) ) );
$valid_slug = $this->validate_attribute_slug( $args['attribute_name'], false );
if ( is_wp_error( $valid_slug ) ) {
return $valid_slug;
}
}
if ( $args ) {
$update = $wpdb->update(
$wpdb->prefix . 'woocommerce_attribute_taxonomies',
$args,
array( 'attribute_id' => $id ),
$format,
array( '%d' )
);
// Checks for errors.
if ( false === $update ) {
return new WP_Error( 'woocommerce_rest_cannot_edit', __( 'Could not edit the attribute.', 'woocommerce' ), array( 'status' => 400 ) );
}
// Checks for errors.
if ( is_wp_error( $edited ) ) {
return new WP_Error( 'woocommerce_rest_cannot_edit', $edited->get_error_message(), array( 'status' => 400 ) );
}
$attribute = $this->get_attribute( $id );
@ -393,10 +340,6 @@ class WC_REST_Product_Attributes_V1_Controller extends WC_REST_Controller {
$request->set_param( 'context', 'edit' );
$response = $this->prepare_item_for_response( $attribute, $request );
// Clear transients.
$this->flush_rewrite_rules();
delete_transient( 'wc_attribute_taxonomies' );
return rest_ensure_response( $response );
}
@ -407,8 +350,6 @@ class WC_REST_Product_Attributes_V1_Controller extends WC_REST_Controller {
* @return WP_REST_Response|WP_Error
*/
public function delete_item( $request ) {
global $wpdb;
$force = isset( $request['force'] ) ? (bool) $request['force'] : false;
// We don't support trashing for this type, error out.
@ -425,25 +366,12 @@ class WC_REST_Product_Attributes_V1_Controller extends WC_REST_Controller {
$request->set_param( 'context', 'edit' );
$response = $this->prepare_item_for_response( $attribute, $request );
$deleted = $wpdb->delete(
$wpdb->prefix . 'woocommerce_attribute_taxonomies',
array( 'attribute_id' => $attribute->attribute_id ),
array( '%d' )
);
$deleted = wc_delete_attribute( $attribute->attribute_id );
if ( false === $deleted ) {
return new WP_Error( 'woocommerce_rest_cannot_delete', __( 'The resource cannot be deleted.', 'woocommerce' ), array( 'status' => 500 ) );
}
$taxonomy = wc_attribute_taxonomy_name( $attribute->attribute_name );
if ( taxonomy_exists( $taxonomy ) ) {
$terms = get_terms( $taxonomy, 'orderby=name&hide_empty=0' );
foreach ( $terms as $term ) {
wp_delete_term( $term->term_id, $taxonomy );
}
}
/**
* Fires after a single attribute is deleted via the REST API.
*
@ -453,13 +381,6 @@ class WC_REST_Product_Attributes_V1_Controller extends WC_REST_Controller {
*/
do_action( 'woocommerce_rest_delete_product_attribute', $attribute, $response, $request );
// Fires woocommerce_attribute_deleted hook.
do_action( 'woocommerce_attribute_deleted', $attribute->attribute_id, $attribute->attribute_name, $taxonomy );
// Clear transients.
$this->flush_rewrite_rules();
delete_transient( 'wc_attribute_taxonomies' );
return $response;
}
@ -636,6 +557,7 @@ class WC_REST_Product_Attributes_V1_Controller extends WC_REST_Controller {
/**
* Validate attribute slug.
*
* @deprecated 3.2.0
* @param string $slug
* @param bool $new_data
* @return bool|WP_Error
@ -655,6 +577,7 @@ class WC_REST_Product_Attributes_V1_Controller extends WC_REST_Controller {
/**
* Schedule to flush rewrite rules.
*
* @deprecated 3.2.0
* @since 3.0.0
*/
protected function flush_rewrite_rules() {

View File

@ -1411,7 +1411,7 @@ class WC_AJAX {
$wpdb->update( $wpdb->posts, array( 'menu_order' => $menu_orders[ $sorting_id ] ), array( 'ID' => $sorting_id ) );
do_action( 'woocommerce_after_product_ordering' );
do_action( 'woocommerce_after_product_ordering', $sorting_id, $menu_orders );
wp_send_json( $menu_orders );
}

View File

@ -21,6 +21,7 @@ class WC_Cache_Helper {
public static function init() {
add_action( 'template_redirect', array( __CLASS__, 'geolocation_ajax_redirect' ) );
add_action( 'wp', array( __CLASS__, 'prevent_caching' ) );
add_filter( 'nocache_headers', array( __CLASS__, 'set_nocache_constants' ) );
add_action( 'admin_notices', array( __CLASS__, 'notices' ) );
add_action( 'delete_version_transients', array( __CLASS__, 'delete_version_transients' ) );
}
@ -155,19 +156,22 @@ class WC_Cache_Helper {
if ( ! is_blog_installed() ) {
return;
}
$page_ids = array_filter( array( wc_get_page_id( 'cart' ), wc_get_page_id( 'checkout' ), wc_get_page_id( 'myaccount' ) ) );
$current_page_id = get_queried_object_id();
$page_ids = array_filter( array( wc_get_page_id( 'cart' ), wc_get_page_id( 'checkout' ), wc_get_page_id( 'myaccount' ) ) );
if ( isset( $_GET['download_file'] ) || in_array( $current_page_id, $page_ids ) ) {
self::nocache();
if ( isset( $_GET['download_file'] ) || isset( $_GET['add-to-cart'] ) || is_page( $page_ids ) ) {
nocache_headers();
}
}
/**
* Set nocache constants and headers.
* @access private
* Set constants to prevent caching by some plugins.
*
* Hooked into nocache_headers filter but does not change headers.
*
* @param array $value
* @return array
*/
private static function nocache() {
public static function set_nocache_constants( $value ) {
if ( ! defined( 'DONOTCACHEPAGE' ) ) {
define( "DONOTCACHEPAGE", true );
}
@ -177,7 +181,7 @@ class WC_Cache_Helper {
if ( ! defined( 'DONOTCACHEDB' ) ) {
define( "DONOTCACHEDB", true );
}
nocache_headers();
return $value;
}
/**

View File

@ -796,7 +796,9 @@ class WC_Cart extends WC_Legacy_Cart {
$found_tax_classes = array();
foreach ( WC()->cart->get_cart() as $item ) {
$found_tax_classes[] = $item['data']->get_tax_class();
if ( $item['data'] && ( $item['data']->is_taxable() || $item['data']->is_shipping_taxable() ) ) {
$found_tax_classes[] = $item['data']->get_tax_class();
}
}
return array_unique( $found_tax_classes );

View File

@ -562,7 +562,7 @@ class WC_Checkout {
switch ( $type ) {
case 'checkbox' :
$value = (int) isset( $_POST[ $key ] );
$value = isset( $_POST[ $key ] ) ? 1 : '';
break;
case 'multiselect' :
$value = isset( $_POST[ $key ] ) ? implode( ', ', wc_clean( $_POST[ $key ] ) ) : '';

View File

@ -439,6 +439,17 @@ class WC_Customer extends WC_Legacy_Customer {
return $value;
}
/**
* Get billing.
*
* @since 3.2.0
* @param string $context
* @return array
*/
public function get_billing( $context = 'view' ) {
return $this->get_prop( 'billing', $context );
}
/**
* Get billing_first_name.
*
@ -559,6 +570,17 @@ class WC_Customer extends WC_Legacy_Customer {
return $this->get_address_prop( 'phone', 'billing', $context );
}
/**
* Get shipping.
*
* @since 3.2.0
* @param string $context
* @return array
*/
public function get_shipping( $context = 'view' ) {
return $this->get_prop( 'shipping', $context );
}
/**
* Get shipping_first_name.
*

View File

@ -189,13 +189,17 @@ class WC_Download_Handler {
$wp_uploads_dir = $wp_uploads['basedir'];
$wp_uploads_url = $wp_uploads['baseurl'];
// Replace uploads dir, site url etc with absolute counterparts if we can
/**
* Replace uploads dir, site url etc with absolute counterparts if we can.
* Note the str_replace on site_url is on purpose, so if https is forced
* via filters we can still do the string replacement on a HTTP file.
*/
$replacements = array(
$wp_uploads_url => $wp_uploads_dir,
network_site_url( '/', 'https' ) => ABSPATH,
network_site_url( '/', 'http' ) => ABSPATH,
site_url( '/', 'https' ) => ABSPATH,
site_url( '/', 'http' ) => ABSPATH,
$wp_uploads_url => $wp_uploads_dir,
network_site_url( '/', 'https' ) => ABSPATH,
str_replace( 'https:', 'http:', network_site_url( '/', 'http' ) ) => ABSPATH,
site_url( '/', 'https' ) => ABSPATH,
str_replace( 'https:', 'http:', site_url( '/', 'http' ) ) => ABSPATH,
);
$file_path = str_replace( array_keys( $replacements ), array_values( $replacements ), $file_path );

View File

@ -375,9 +375,8 @@ class WC_Emails {
* Add order meta to email templates.
*
* @param mixed $order
* @param bool $sent_to_admin (default: false)
* @param bool $plain_text (default: false)
* @return string
* @param bool $sent_to_admin (default: false)
* @param bool $plain_text (default: false)
*/
public function order_meta( $order, $sent_to_admin = false, $plain_text = false ) {
$fields = apply_filters( 'woocommerce_email_order_meta_fields', array(), $sent_to_admin, $order );

View File

@ -67,6 +67,8 @@ class WC_Form_Handler {
return;
}
nocache_headers();
$user_id = get_current_user_id();
if ( $user_id <= 0 ) {
@ -179,6 +181,8 @@ class WC_Form_Handler {
return;
}
nocache_headers();
$errors = new WP_Error();
$user = new stdClass();
@ -274,6 +278,7 @@ class WC_Form_Handler {
*/
public static function checkout_action() {
if ( isset( $_POST['woocommerce_checkout_place_order'] ) || isset( $_POST['woocommerce_checkout_update_totals'] ) ) {
nocache_headers();
if ( WC()->cart->is_empty() ) {
wp_redirect( wc_get_page_permalink( 'cart' ) );
@ -295,7 +300,7 @@ class WC_Form_Handler {
global $wp;
if ( isset( $_POST['woocommerce_pay'] ) && isset( $_POST['_wpnonce'] ) && wp_verify_nonce( $_POST['_wpnonce'], 'woocommerce-pay' ) ) {
nocache_headers();
ob_start();
// Pay for existing order
@ -374,27 +379,42 @@ class WC_Form_Handler {
*/
public static function add_payment_method_action() {
if ( isset( $_POST['woocommerce_add_payment_method'], $_POST['payment_method'], $_POST['_wpnonce'] ) && wp_verify_nonce( $_POST['_wpnonce'], 'woocommerce-add-payment-method' ) ) {
nocache_headers();
ob_start();
$payment_method = wc_clean( $_POST['payment_method'] );
$payment_method_id = wc_clean( wp_unslash( $_POST['payment_method'] ) );
$available_gateways = WC()->payment_gateways->get_available_payment_gateways();
// Validate
$available_gateways[ $payment_method ]->validate_fields();
// Process
if ( wc_notice_count( 'wc_errors' ) == 0 ) {
$result = $available_gateways[ $payment_method ]->add_payment_method();
// Redirect to success/confirmation/payment page
if ( isset( $available_gateways[ $payment_method_id ] ) ) {
$gateway = $available_gateways[ $payment_method_id ];
if ( ! $gateway->supports( 'add_payment_method' ) && ! $gateway->supports( 'tokenization' ) ) {
wc_add_notice( __( 'Invalid payment gateway.', 'woocommerce' ), 'error' );
return;
}
$gateway->validate_fields();
if ( wc_notice_count( 'error' ) > 0 ) {
return;
}
$result = $gateway->add_payment_method();
if ( 'success' === $result['result'] ) {
wc_add_notice( __( 'Payment method added.', 'woocommerce' ) );
wc_add_notice( __( 'Payment method successfully added.', 'woocommerce' ) );
}
if ( 'failure' === $result['result'] ) {
wc_add_notice( __( 'Unable to add payment method to your account.', 'woocommerce' ), 'error' );
}
if ( ! empty( $result['redirect'] ) ) {
wp_redirect( $result['redirect'] );
exit();
}
}
}
}
/**
@ -404,6 +424,7 @@ class WC_Form_Handler {
global $wp;
if ( isset( $wp->query_vars['delete-payment-method'] ) ) {
nocache_headers();
$token_id = absint( $wp->query_vars['delete-payment-method'] );
$token = WC_Payment_Tokens::get( $token_id );
@ -428,6 +449,7 @@ class WC_Form_Handler {
global $wp;
if ( isset( $wp->query_vars['set-default-payment-method'] ) ) {
nocache_headers();
$token_id = absint( $wp->query_vars['set-default-payment-method'] );
$token = WC_Payment_Tokens::get( $token_id );
@ -449,20 +471,19 @@ class WC_Form_Handler {
* Remove from cart/update.
*/
public static function update_cart_action() {
if ( ! ( isset( $_REQUEST['apply_coupon'] ) || isset( $_REQUEST['remove_coupon'] ) || isset( $_REQUEST['remove_item'] ) || isset( $_REQUEST['undo_item'] ) || isset( $_REQUEST['update_cart'] ) || isset( $_REQUEST['proceed'] ) ) ) {
return;
}
nocache_headers();
if ( ! empty( $_POST['apply_coupon'] ) && ! empty( $_POST['coupon_code'] ) ) {
// Add Discount
WC()->cart->add_discount( sanitize_text_field( $_POST['coupon_code'] ) );
} elseif ( isset( $_GET['remove_coupon'] ) ) {
// Remove Coupon Codes
WC()->cart->remove_coupon( wc_clean( $_GET['remove_coupon'] ) );
} elseif ( ! empty( $_GET['remove_item'] ) && isset( $_GET['_wpnonce'] ) && wp_verify_nonce( $_GET['_wpnonce'], 'woocommerce-cart' ) ) {
// Remove from cart
} elseif ( ! empty( $_GET['remove_item'] ) && wp_verify_nonce( wc_get_var( $_REQUEST['_wpnonce'] ), 'woocommerce-cart' ) ) {
$cart_item_key = sanitize_text_field( $_GET['remove_item'] );
if ( $cart_item = WC()->cart->get_cart_item( $cart_item_key ) ) {
@ -501,7 +522,7 @@ class WC_Form_Handler {
}
// Update Cart - checks apply_coupon too because they are in the same form
if ( ( ! empty( $_POST['apply_coupon'] ) || ! empty( $_POST['update_cart'] ) || ! empty( $_POST['proceed'] ) ) && isset( $_POST['_wpnonce'] ) && wp_verify_nonce( $_POST['_wpnonce'], 'woocommerce-cart' ) ) {
if ( ( ! empty( $_POST['apply_coupon'] ) || ! empty( $_POST['update_cart'] ) || ! empty( $_POST['proceed'] ) ) && wp_verify_nonce( wc_get_var( $_POST['_wpnonce'] ), 'woocommerce-cart' ) ) {
$cart_updated = false;
$cart_totals = isset( $_POST['cart'] ) ? $_POST['cart'] : '';
@ -563,12 +584,13 @@ class WC_Form_Handler {
* Place a previous order again.
*/
public static function order_again() {
// Nothing to do
if ( ! isset( $_GET['order_again'] ) || ! is_user_logged_in() || ! isset( $_GET['_wpnonce'] ) || ! wp_verify_nonce( $_GET['_wpnonce'], 'woocommerce-order_again' ) ) {
return;
}
nocache_headers();
if ( apply_filters( 'woocommerce_empty_cart_when_order_again', true ) ) {
WC()->cart->empty_cart();
}
@ -648,6 +670,7 @@ class WC_Form_Handler {
*/
public static function cancel_order() {
if ( isset( $_GET['cancel_order'] ) && isset( $_GET['order'] ) && isset( $_GET['order_id'] ) ) {
nocache_headers();
$order_key = $_GET['order'];
$order_id = absint( $_GET['order_id'] );
@ -694,6 +717,8 @@ class WC_Form_Handler {
return;
}
nocache_headers();
$product_id = apply_filters( 'woocommerce_add_to_cart_product_id', absint( $_REQUEST['add-to-cart'] ) );
$was_added_to_cart = false;
$adding_to_cart = wc_get_product( $product_id );
@ -773,16 +798,22 @@ class WC_Form_Handler {
// Add to cart validation
$passed_validation = apply_filters( 'woocommerce_add_to_cart_validation', true, $item, $quantity );
// Suppress total recalculation until finished.
remove_action( 'woocommerce_add_to_cart', array( WC()->cart, 'calculate_totals' ), 20, 0 );
if ( $passed_validation && WC()->cart->add_to_cart( $item, $quantity ) !== false ) {
$was_added_to_cart = true;
$added_to_cart[ $item ] = $quantity;
}
add_action( 'woocommerce_add_to_cart', array( WC()->cart, 'calculate_totals' ), 20, 0 );
}
if ( ! $was_added_to_cart && ! $quantity_set ) {
wc_add_notice( __( 'Please choose the quantity of items you wish to add to your cart&hellip;', 'woocommerce' ), 'error' );
} elseif ( $was_added_to_cart ) {
wc_add_to_cart_message( $added_to_cart );
WC()->cart->calculate_totals();
return true;
}
} elseif ( $product_id ) {

View File

@ -98,8 +98,8 @@ class WC_Geolocation {
* @return string
*/
public static function get_ip_address() {
if ( isset( $_SERVER['X-Real-IP'] ) ) {
return $_SERVER['X-Real-IP'];
if ( isset( $_SERVER['HTTP_X_REAL_IP'] ) ) {
return $_SERVER['HTTP_X_REAL_IP'];
} elseif ( isset( $_SERVER['HTTP_X_FORWARDED_FOR'] ) ) {
// Proxy servers can send through this header like this: X-Forwarded-For: client1, proxy1, proxy2
// Make sure we always only send through the first IP in the list which should always be the client IP.

View File

@ -0,0 +1,104 @@
<?php
/**
* Wraps an array (meta data for now) and tells if there was any changes.
*
* The main idea behind this class is to avoid doing unneeded
* SQL updates if nothing changed.
*
* @version 3.2.0
* @package WooCommerce
* @category Class
* @author crodas
*/
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
/**
* WC_Meta_Data class.
*/
class WC_Meta_Data {
/**
* Current data for metadata
*
* @since 3.2.0
* @var array
*/
protected $current_data;
/**
* Metadata data
*
* @since 3.2.0
* @var array
*/
protected $data;
/**
* Constructor.
*
* @param array $meta Data to wrap behind this function.
*/
public function __construct( $meta = array() ) {
$this->current_data = $meta;
$this->apply_changes();
}
/**
* Merge changes with data and clear.
*/
public function apply_changes() {
$this->data = $this->current_data;
}
/**
* Creates or updates a property in the metadata object.
*
* @param string $key Key to set.
* @param mixed $value Value to set.
*/
public function __set( $key, $value ) {
$this->current_data[ $key ] = $value;
}
/**
* Checks if a given key exists in our data. This is called internally
* by `empty` and `isset`.
*
* @param string $key Key to check if set.
*/
public function __isset( $key ) {
return array_key_exists( $key, $this->current_data );
}
/**
* Returns the value of any property.
*
* @param string $key Key to get.
* @return mixed Property value or NULL if it does not exists
*/
public function __get( $key ) {
if ( array_key_exists( $key, $this->current_data ) ) {
return $this->current_data[ $key ];
}
return null;
}
/**
* Return data changes only.
*
* @return array
*/
public function get_changes() {
$changes = array();
foreach ( $this->current_data as $id => $value ) {
if ( ! array_key_exists( $id, $this->data ) || $value !== $this->data[ $id ] ) {
$changes[ $id ] = $value;
}
}
return $changes;
}
}

View File

@ -165,9 +165,11 @@ class WC_Order_Item_Product extends WC_Order_Item {
*
* @param array $data Key/Value pairs
*/
public function set_variation( $data ) {
foreach ( $data as $key => $value ) {
$this->add_meta_data( str_replace( 'attribute_', '', $key ), $value, true );
public function set_variation( $data = array() ) {
if ( is_array( $data ) ) {
foreach ( $data as $key => $value ) {
$this->add_meta_data( str_replace( 'attribute_', '', $key ), $value, true );
}
}
}
@ -198,7 +200,7 @@ class WC_Order_Item_Product extends WC_Order_Item {
public function set_backorder_meta() {
$product = $this->get_product();
if ( $product && $product->backorders_require_notification() && $product->is_on_backorder( $this->get_quantity() ) ) {
$this->add_meta_data( apply_filters( 'woocommerce_backordered_item_meta_name', __( 'Backordered', 'woocommerce' ) ), $this->get_quantity() - max( 0, $product->get_stock_quantity() ), true );
$this->add_meta_data( apply_filters( 'woocommerce_backordered_item_meta_name', __( 'Backordered', 'woocommerce' ), $this ), $this->get_quantity() - max( 0, $product->get_stock_quantity() ), true );
}
}

View File

@ -154,9 +154,7 @@ class WC_Payment_Gateways {
if ( $gateway->is_available() ) {
if ( ! is_add_payment_method_page() ) {
$_available_gateways[ $gateway->id ] = $gateway;
} elseif ( $gateway->supports( 'add_payment_method' ) ) {
$_available_gateways[ $gateway->id ] = $gateway;
} elseif ( $gateway->supports( 'tokenization' ) ) {
} elseif ( $gateway->supports( 'add_payment_method' ) || $gateway->supports( 'tokenization' ) ) {
$_available_gateways[ $gateway->id ] = $gateway;
}
}

View File

@ -400,7 +400,9 @@ class WC_Post_Data {
if ( in_array( get_post_type( $order_id ), wc_get_order_types() ) ) {
// Clean up user.
$order = wc_get_order( $order_id );
$customer_id = $order->get_customer_id();
// Check for `get_customer_id`, since this may be e.g. a refund order (which doesn't implement it).
$customer_id = is_callable( array( $order, 'get_customer_id' ) ) ? $order->get_customer_id() : 0;
if ( $customer_id > 0 && 'shop_order' === $order->get_type() ) {
$customer = new WC_Customer( $customer_id );

View File

@ -0,0 +1,74 @@
<?php
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
/**
* Class for parameter-based Product querying.
* Args and usage: https://github.com/woocommerce/woocommerce/wiki/wc_get_products-and-WC_Product_Query
*
* @version 3.2.0
* @since 3.2.0
* @package WooCommerce/Classes
* @category Class
*/
class WC_Product_Query extends WC_Object_Query {
/**
* Valid query vars for products.
* @return array
*/
protected function get_default_query_vars() {
return array_merge(
parent::get_default_query_vars(),
array(
'status' => array( 'draft', 'pending', 'private', 'publish' ),
'type' => array_merge( array_keys( wc_get_product_types() ) ),
'limit' => get_option( 'posts_per_page' ),
'include' => array(),
'date_created' => '',
'date_modified' => '',
'featured' => '',
'visibility' => '',
'sku' => '',
'price' => '',
'regular_price' => '',
'sale_price' => '',
'date_on_sale_from' => '',
'date_on_sale_to' => '',
'total_sales' => '',
'tax_status' => '',
'tax_class' => '',
'manage_stock' => '',
'stock_quantity' => '',
'stock_status' => '',
'backorders' => '',
'sold_individually' => '',
'weight' => '',
'length' => '',
'width' => '',
'height' => '',
'reviews_allowed' => '',
'virtual' => '',
'downloadable' => '',
'category' => array(),
'tag' => array(),
'shipping_class' => array(),
'download_limit' => '',
'download_expiry' => '',
'average_rating' => '',
'review_count' => '',
)
);
}
/**
* Get products matching the current query vars.
* @return array of WC_Product objects
*/
public function get_products() {
$args = apply_filters( 'woocommerce_product_query_args', $this->get_query_vars() );
$results = WC_Data_Store::load( 'product' )->query( $args );
return apply_filters( 'woocommerce_product_query', $results, $args );
}
}

View File

@ -20,7 +20,7 @@ class WC_Product_Variation extends WC_Product_Simple {
* Post type.
* @var string
*/
public $post_type = 'product_variation';
protected $post_type = 'product_variation';
/**
* Parent data.
@ -426,16 +426,6 @@ class WC_Product_Variation extends WC_Product_Simple {
$this->set_prop( 'attributes', $attributes );
}
/**
* Returns array of attribute name value pairs. Keys are prefixed with attribute_, as stored.
*
* @param string $context
* @return array
*/
public function get_attributes( $context = 'view' ) {
return $this->get_prop( 'attributes', $context );
}
/**
* Returns whether or not the product has any visible attributes.
*

View File

@ -91,11 +91,8 @@ class WC_Structured_Data {
// Wrap the multiple values of each type inside a graph... Then add context to each type.
foreach ( $data as $type => $value ) {
if ( 1 < count( $value ) ) {
$data[ $type ] = apply_filters( 'woocommerce_structured_data_context', array( '@context' => 'https://schema.org/' ), $data, $type, $value ) + array( '@graph' => $value );
} else {
$data[ $type ] = $value[0];
}
$data[ $type ] = count( $value ) > 1 ? array( '@graph' => $value ) : $value[0];
$data[ $type ] = apply_filters( 'woocommerce_structured_data_context', array( '@context' => 'https://schema.org/' ), $data, $type, $value ) + $data[ $type ];
}
// If requested types, pick them up... Finally change the associative array to an indexed one.
@ -193,54 +190,63 @@ class WC_Structured_Data {
return;
}
$shop_name = get_bloginfo( 'name' );
$shop_url = home_url();
$currency = get_woocommerce_currency();
$markup = array();
$markup['@type'] = 'Product';
$markup['@id'] = get_permalink( $product->get_id() );
$markup['url'] = $markup['@id'];
$markup['name'] = $product->get_name();
$shop_name = get_bloginfo( 'name' );
$shop_url = home_url();
$currency = get_woocommerce_currency();
$markup = array(
'@type' => 'Product',
'@id' => get_permalink( $product->get_id() ),
'name' => $product->get_name(),
);
if ( apply_filters( 'woocommerce_structured_data_product_limit', is_product_taxonomy() || is_shop() ) ) {
$markup['url'] = $markup['@id'];
$this->set_data( apply_filters( 'woocommerce_structured_data_product_limited', $markup, $product ) );
return;
}
if ( '' !== $product->get_price() ) {
$markup_offer = array(
'@type' => 'Offer',
'priceCurrency' => $currency,
'availability' => 'https://schema.org/' . $stock = ( $product->is_in_stock() ? 'InStock' : 'OutOfStock' ),
'sku' => $product->get_sku(),
'image' => wp_get_attachment_url( $product->get_image_id() ),
'description' => $product->get_description(),
'seller' => array(
'@type' => 'Organization',
'name' => $shop_name,
'url' => $shop_url,
),
);
$markup['image'] = wp_get_attachment_url( $product->get_image_id() );
$markup['description'] = wpautop( do_shortcode( $product->get_short_description() ? $product->get_short_description() : $product->get_description() ) );
$markup['sku'] = $product->get_sku();
if ( '' !== $product->get_price() ) {
if ( $product->is_type( 'variable' ) ) {
$prices = $product->get_variation_prices();
$lowest = reset( $prices['price'] );
$highest = end( $prices['price'] );
if ( $lowest === $highest ) {
$markup_offer['price'] = wc_format_decimal( $product->get_price(), wc_get_price_decimals() );
$markup_offer = array(
'@type' => 'Offer',
'price' => wc_format_decimal( $lowest, wc_get_price_decimals() ),
);
} else {
$markup_offer['priceSpecification'] = array(
'price' => wc_format_decimal( $product->get_price(), wc_get_price_decimals() ),
'minPrice' => wc_format_decimal( $lowest, wc_get_price_decimals() ),
'maxPrice' => wc_format_decimal( $highest, wc_get_price_decimals() ),
'priceCurrency' => $currency,
$markup_offer = array(
'@type' => 'AggregateOffer',
'lowPrice' => wc_format_decimal( $lowest, wc_get_price_decimals() ),
'highPrice' => wc_format_decimal( $highest, wc_get_price_decimals() ),
);
}
} else {
$markup_offer['price'] = wc_format_decimal( $product->get_price(), wc_get_price_decimals() );
$markup_offer = array(
'@type' => 'Offer',
'price' => wc_format_decimal( $product->get_price(), wc_get_price_decimals() ),
);
}
$markup_offer += array(
'priceCurrency' => $currency,
'availability' => 'https://schema.org/' . ( $product->is_in_stock() ? 'InStock' : 'OutOfStock' ),
'url' => $markup['@id'],
'seller' => array(
'@type' => 'Organization',
'name' => $shop_name,
'url' => $shop_url,
),
);
$markup['offers'] = array( apply_filters( 'woocommerce_structured_data_product_offer', $markup_offer, $product ) );
}

View File

@ -561,11 +561,16 @@ class WC_Tax {
'tax_class' => $tax_class,
) );
} else {
} elseif ( WC()->cart->get_cart() ) {
// This will be per order shipping - loop through the order and find the highest tax class rate
$cart_tax_classes = WC()->cart->get_cart_item_tax_classes();
// No tax classes = no taxable items.
if ( empty( $cart_tax_classes ) ) {
return array();
}
// If multiple classes are found, use the first one found unless a standard rate item is found. This will be the first listed in the 'additional tax class' section.
if ( sizeof( $cart_tax_classes ) > 1 && ! in_array( '', $cart_tax_classes ) ) {
$tax_classes = self::get_tax_class_slugs();
@ -924,7 +929,6 @@ class WC_Tax {
*
* @param int $tax_rate_id
* @param string $postcodes String of postcodes separated by ; characters
* @return string
*/
public static function _update_tax_rate_postcodes( $tax_rate_id, $postcodes ) {
if ( ! is_array( $postcodes ) ) {
@ -947,7 +951,6 @@ class WC_Tax {
*
* @param int $tax_rate_id
* @param string $cities
* @return string
*/
public static function _update_tax_rate_cities( $tax_rate_id, $cities ) {
if ( ! is_array( $cities ) ) {
@ -969,8 +972,6 @@ class WC_Tax {
* @param int $tax_rate_id
* @param array $values
* @param string $type
*
* @return string
*/
private static function _update_tax_rate_locations( $tax_rate_id, $values, $type ) {
global $wpdb;

View File

@ -319,9 +319,11 @@ final class WooCommerce {
include_once( WC_ABSPATH . 'includes/class-wc-emails.php' );
include_once( WC_ABSPATH . 'includes/class-wc-data-exception.php' );
include_once( WC_ABSPATH . 'includes/class-wc-query.php' );
include_once( WC_ABSPATH . 'includes/class-wc-meta-data.php' ); // Meta data internal object
include_once( WC_ABSPATH . 'includes/class-wc-order-factory.php' ); // Order factory.
include_once( WC_ABSPATH . 'includes/class-wc-order-query.php' ); // Order query.
include_once( WC_ABSPATH . 'includes/class-wc-product-factory.php' ); // Product factory.
include_once( WC_ABSPATH . 'includes/class-wc-product-query.php' ); // Product query
include_once( WC_ABSPATH . 'includes/class-wc-payment-tokens.php' ); // Payment tokens controller.
include_once( WC_ABSPATH . 'includes/class-wc-shipping-zone.php' );
include_once( WC_ABSPATH . 'includes/gateways/class-wc-payment-gateway-cc.php' ); // CC Payment Gateway.

View File

@ -143,5 +143,6 @@ abstract class Abstract_WC_Order_Item_Type_Data_Store extends WC_Data_Store_WP i
*/
public function clear_cache( &$item ) {
wp_cache_delete( 'item-' . $item->get_id(), 'order-items' );
wp_cache_delete( 'order-items-' . $item->get_order_id(), 'orders' );
}
}

View File

@ -369,8 +369,9 @@ class WC_Customer_Data_Store extends WC_Data_Store_WP implements WC_Customer_Dat
/**
* Search customers and return customer IDs.
*
* @param string $term
* @oaram int|string $limit @since 3.0.7
* @param string $term
* @param int|string $limit @since 3.0.7
*
* @return array
*/
public function search_customers( $term, $limit = '' ) {

View File

@ -86,7 +86,6 @@ class WC_Data_Store_WP {
* @since 3.0.0
* @param WC_Data
* @param stdClass (containing at least ->id)
* @return array
*/
public function delete_meta( &$object, $meta ) {
delete_metadata_by_mid( $this->meta_type, $meta->id );
@ -419,4 +418,14 @@ class WC_Data_Store_WP {
return $wp_query_args;
}
/**
* Return list of internal meta keys.
*
* @since 3.2.0
* @return array
*/
public function get_internal_meta_keys() {
return $this->internal_meta_keys;
}
}

View File

@ -45,6 +45,8 @@ class WC_Product_Data_Store_CPT extends WC_Data_Store_WP implements WC_Object_Da
'_product_attributes',
'_virtual',
'_downloadable',
'_download_limit',
'_download_expiry',
'_featured',
'_downloadable_files',
'_wc_rating_count',
@ -1168,124 +1170,8 @@ class WC_Product_Data_Store_CPT extends WC_Data_Store_WP implements WC_Object_Da
* @return array|object
*/
public function get_products( $args = array() ) {
/**
* Generate WP_Query args.
*/
$wp_query_args = array(
'post_status' => $args['status'],
'posts_per_page' => $args['limit'],
'meta_query' => array(),
'orderby' => $args['orderby'],
'order' => $args['order'],
'tax_query' => array(),
);
if ( 'variation' === $args['type'] ) {
$wp_query_args['post_type'] = 'product_variation';
} elseif ( is_array( $args['type'] ) && in_array( 'variation', $args['type'] ) ) {
$wp_query_args['post_type'] = array( 'product_variation', 'product' );
$wp_query_args['tax_query'][] = array(
'relation' => 'OR',
array(
'taxonomy' => 'product_type',
'field' => 'slug',
'terms' => $args['type'],
),
array(
'taxonomy' => 'product_type',
'field' => 'id',
'operator' => 'NOT EXISTS',
),
);
} else {
$wp_query_args['post_type'] = 'product';
$wp_query_args['tax_query'][] = array(
'taxonomy' => 'product_type',
'field' => 'slug',
'terms' => $args['type'],
);
}
// Do not load unnecessary post data if the user only wants IDs.
if ( 'ids' === $args['return'] ) {
$wp_query_args['fields'] = 'ids';
}
if ( ! empty( $args['sku'] ) ) {
$wp_query_args['meta_query'][] = array(
'key' => '_sku',
'value' => $args['sku'],
'compare' => 'LIKE',
);
}
if ( ! empty( $args['category'] ) ) {
$wp_query_args['tax_query'][] = array(
'taxonomy' => 'product_cat',
'field' => 'slug',
'terms' => $args['category'],
);
}
if ( ! empty( $args['tag'] ) ) {
$wp_query_args['tax_query'][] = array(
'taxonomy' => 'product_tag',
'field' => 'slug',
'terms' => $args['tag'],
);
}
if ( ! empty( $args['shipping_class'] ) ) {
$wp_query_args['tax_query'][] = array(
'taxonomy' => 'product_shipping_class',
'field' => 'slug',
'terms' => $args['shipping_class'],
);
}
if ( ! is_null( $args['parent'] ) ) {
$wp_query_args['post_parent'] = absint( $args['parent'] );
}
if ( ! is_null( $args['offset'] ) ) {
$wp_query_args['offset'] = absint( $args['offset'] );
} else {
$wp_query_args['paged'] = absint( $args['page'] );
}
if ( ! empty( $args['include'] ) ) {
$wp_query_args['post__in'] = array_map( 'absint', $args['include'] );
}
if ( ! empty( $args['exclude'] ) ) {
$wp_query_args['post__not_in'] = array_map( 'absint', $args['exclude'] );
}
if ( ! $args['paginate'] ) {
$wp_query_args['no_found_rows'] = true;
}
// Get results.
$products = new WP_Query( $wp_query_args );
if ( 'objects' === $args['return'] ) {
// Prime caches before grabbing objects.
update_post_caches( $products->posts, array( 'product', 'product_variation' ) );
$return = array_filter( array_map( 'wc_get_product', $products->posts ) );
} else {
$return = $products->posts;
}
if ( $args['paginate'] ) {
return (object) array(
'products' => $return,
'total' => $products->found_posts,
'max_num_pages' => $products->max_num_pages,
);
} else {
return $return;
}
$query = new WC_Product_Query( $args );
return $query->get_products();
}
/**
@ -1372,4 +1258,295 @@ class WC_Product_Data_Store_CPT extends WC_Data_Store_WP implements WC_Object_Da
return false;
}
}
/**
* Add ability to get products by 'reviews_allowed' in WC_Product_Query.
*
* @since 3.2.0
* @param string $where where clause
* @param WP_Query $wp_query
*/
public function reviews_allowed_query_where( $where, $wp_query ) {
global $wpdb;
if ( isset( $wp_query->query_vars['reviews_allowed'] ) && is_bool( $wp_query->query_vars['reviews_allowed'] ) ) {
if ( $wp_query->query_vars['reviews_allowed'] ) {
$where .= " AND $wpdb->posts.comment_status = 'open'";
} else {
$where .= " AND $wpdb->posts.comment_status = 'closed'";
}
}
return $where;
}
/**
* Get valid WP_Query args from a WC_Product_Query's query variables.
*
* @since 3.2.0
* @param array $query_vars query vars from a WC_Product_Query
* @return array
*/
protected function get_wp_query_args( $query_vars ) {
// Map query vars to ones that get_wp_query_args or WP_Query recognize.
$key_mapping = array(
'status' => 'post_status',
'page' => 'paged',
'include' => 'post__in',
'stock_quantity' => 'stock',
'average_rating' => 'wc_average_rating',
'review_count' => 'wc_review_count',
);
foreach ( $key_mapping as $query_key => $db_key ) {
if ( isset( $query_vars[ $query_key ] ) ) {
$query_vars[ $db_key ] = $query_vars[ $query_key ];
unset( $query_vars[ $query_key ] );
}
}
// Map boolean queries that are stored as 'yes'/'no' in the DB to 'yes' or 'no'.
$boolean_queries = array(
'virtual',
'downloadable',
'sold_individually',
'manage_stock',
);
foreach ( $boolean_queries as $boolean_query ) {
if ( isset( $query_vars[ $boolean_query ] ) && '' !== $query_vars[ $boolean_query ] ) {
$query_vars[ $boolean_query ] = $query_vars[ $boolean_query ] ? 'yes' : 'no';
}
}
// These queries cannot be auto-generated so we have to remove them and build them manually.
$manual_queries = array(
'sku' => '',
'featured' => '',
'visibility' => '',
);
foreach ( $manual_queries as $key => $manual_query ) {
if ( isset( $query_vars[ $key ] ) ) {
$manual_queries[ $key ] = $query_vars[ $key ];
unset( $query_vars[ $key ] );
}
}
$wp_query_args = parent::get_wp_query_args( $query_vars );
if ( ! isset( $wp_query_args['date_query'] ) ) {
$wp_query_args['date_query'] = array();
}
if ( ! isset( $wp_query_args['meta_query'] ) ) {
$wp_query_args['meta_query'] = array();
}
// Handle product types.
if ( 'variation' === $query_vars['type'] ) {
$wp_query_args['post_type'] = 'product_variation';
} elseif ( is_array( $query_vars['type'] ) && in_array( 'variation', $query_vars['type'] ) ) {
$wp_query_args['post_type'] = array( 'product_variation', 'product' );
$wp_query_args['tax_query'][] = array(
'relation' => 'OR',
array(
'taxonomy' => 'product_type',
'field' => 'slug',
'terms' => $query_vars['type'],
),
array(
'taxonomy' => 'product_type',
'field' => 'id',
'operator' => 'NOT EXISTS',
),
);
} else {
$wp_query_args['post_type'] = 'product';
$wp_query_args['tax_query'][] = array(
'taxonomy' => 'product_type',
'field' => 'slug',
'terms' => $query_vars['type'],
);
}
// Handle product categories.
if ( ! empty( $query_vars['category'] ) ) {
$wp_query_args['tax_query'][] = array(
'taxonomy' => 'product_cat',
'field' => 'slug',
'terms' => $query_vars['category'],
);
}
// Handle product tags.
if ( ! empty( $query_vars['tag'] ) ) {
unset( $wp_query_args['tag'] );
$wp_query_args['tax_query'][] = array(
'taxonomy' => 'product_tag',
'field' => 'slug',
'terms' => $query_vars['tag'],
);
}
// Handle shipping classes.
if ( ! empty( $query_vars['shipping_class'] ) ) {
$wp_query_args['tax_query'][] = array(
'taxonomy' => 'product_shipping_class',
'field' => 'slug',
'terms' => $query_vars['shipping_class'],
);
}
// Handle total_sales.
// This query doesn't get auto-generated since the meta key doesn't have the underscore prefix.
if ( isset( $query_vars['total_sales'] ) && '' !== $query_vars['total_sales'] ) {
$wp_query_args['meta_query'][] = array(
'key' => 'total_sales',
'value' => absint( $query_vars['total_sales'] ),
'compare' => '=',
);
}
// Handle SKU.
if ( $manual_queries['sku'] ) {
$wp_query_args['meta_query'][] = array(
'key' => '_sku',
'value' => $manual_queries['sku'],
'compare' => 'LIKE',
);
}
// Handle featured.
if ( '' !== $manual_queries['featured'] ) {
$product_visibility_term_ids = wc_get_product_visibility_term_ids();
if ( $manual_queries['featured'] ) {
$wp_query_args['tax_query'][] = array(
'taxonomy' => 'product_visibility',
'field' => 'term_taxonomy_id',
'terms' => array( $product_visibility_term_ids['featured'] ),
);
$wp_query_args['tax_query'][] = array(
'taxonomy' => 'product_visibility',
'field' => 'term_taxonomy_id',
'terms' => array( $product_visibility_term_ids['exclude-from-catalog'] ),
'operator' => 'NOT IN',
);
} else {
$wp_query_args['tax_query'][] = array(
'taxonomy' => 'product_visibility',
'field' => 'term_taxonomy_id',
'terms' => array( $product_visibility_term_ids['featured'] ),
'operator' => 'NOT IN',
);
}
}
// Handle visibility.
if ( $manual_queries['visibility'] ) {
switch ( $manual_queries['visibility'] ) {
case 'search':
$wp_query_args['tax_query'][] = array(
'taxonomy' => 'product_visibility',
'field' => 'slug',
'terms' => array( 'exclude-from-search' ),
'operator' => 'NOT IN',
);
break;
case 'catalog':
$wp_query_args['tax_query'][] = array(
'taxonomy' => 'product_visibility',
'field' => 'slug',
'terms' => array( 'exclude-from-catalog' ),
'operator' => 'NOT IN',
);
break;
case 'visible':
$wp_query_args['tax_query'][] = array(
'taxonomy' => 'product_visibility',
'field' => 'slug',
'terms' => array( 'exclude-from-catalog', 'exclude-from-search' ),
'operator' => 'NOT IN',
);
break;
case 'hidden':
$wp_query_args['tax_query'][] = array(
'taxonomy' => 'product_visibility',
'field' => 'slug',
'terms' => array( 'exclude-from-catalog', 'exclude-from-search' ),
'operator' => 'AND',
);
break;
}
}
// Handle date queries.
$date_queries = array(
'date_created' => 'post_date',
'date_modified' => 'post_modified',
'date_on_sale_from' => '_sale_price_dates_from',
'date_on_sale_to' => '_sale_price_dates_to',
);
foreach ( $date_queries as $query_var_key => $db_key ) {
if ( isset( $query_vars[ $query_var_key ] ) && '' !== $query_vars[ $query_var_key ] ) {
// Remove any existing meta queries for the same keys to prevent conflicts.
$existing_queries = wp_list_pluck( $wp_query_args['meta_query'], 'key', true );
foreach ( $existing_queries as $query_index => $query_contents ) {
unset( $wp_query_args['meta_query'][ $query_index ] );
}
$wp_query_args = $this->parse_date_for_wp_query( $query_vars[ $query_var_key ], $db_key, $wp_query_args );
}
}
// Handle paginate.
if ( ! isset( $query_vars['paginate'] ) || ! $query_vars['paginate'] ) {
$wp_query_args['no_found_rows'] = true;
}
// Handle reviews_allowed.
if ( isset( $query_vars['reviews_allowed'] ) && is_bool( $query_vars['reviews_allowed'] ) ) {
add_filter( 'posts_where', array( $this, 'reviews_allowed_query_where' ), 10, 2 );
}
return apply_filters( 'woocommerce_product_data_store_cpt_get_products_query', $wp_query_args, $query_vars, $this );
}
/**
* Query for Products matching specific criteria.
*
* @since 3.2.0
*
* @param array $query_vars query vars from a WC_Product_Query
*
* @return array|object
*/
public function query( $query_vars ) {
$args = $this->get_wp_query_args( $query_vars );
if ( ! empty( $args['errors'] ) ) {
$query = (object) array(
'posts' => array(),
'found_posts' => 0,
'max_num_pages' => 0,
);
} else {
$query = new WP_Query( $args );
}
if ( isset( $query_vars['return'] ) && 'objects' === $query_vars['return'] && ! empty( $query->posts ) ) {
// Prime caches before grabbing objects.
update_post_caches( $products->posts, array( 'product', 'product_variation' ) );
}
$products = ( isset( $query_vars['return'] ) && 'ids' === $query_vars['return'] ) ? $query->posts : array_filter( array_map( 'wc_get_product', $query->posts ) );
if ( isset( $query_vars['paginate'] ) && $query_vars['paginate'] ) {
return (object) array(
'products' => $products,
'total' => $query->found_posts,
'max_num_pages' => $query->max_num_pages,
);
}
return $products;
}
}

View File

@ -29,6 +29,10 @@ class WC_Product_Variable_Data_Store_CPT extends WC_Product_Data_Store_CPT imple
protected function read_product_data( &$product ) {
parent::read_product_data( $product );
// Make sure data which does not apply to variables is unset.
$product->set_regular_price( '' );
$product->set_sale_price( '' );
// Set directly since individual data needs changed at the WC_Product_Variation level -- these datasets just pull.
$children = $this->read_children( $product );
$product->set_children( $children['all'] );

View File

@ -220,7 +220,7 @@ class WC_Shipping_Zone_Data_Store extends WC_Data_Store_WP implements WC_Shippin
SELECT zones.zone_id FROM {$wpdb->prefix}woocommerce_shipping_zones as zones
LEFT OUTER JOIN {$wpdb->prefix}woocommerce_shipping_zone_locations as locations ON zones.zone_id = locations.zone_id AND location_type != 'postcode'
WHERE " . implode( ' ', $criteria ) . "
ORDER BY zone_order ASC LIMIT 1
ORDER BY zone_order ASC, zone_id ASC LIMIT 1
" );
}
@ -232,7 +232,7 @@ class WC_Shipping_Zone_Data_Store extends WC_Data_Store_WP implements WC_Shippin
*/
public function get_zones() {
global $wpdb;
return $wpdb->get_results( "SELECT zone_id, zone_name, zone_order FROM {$wpdb->prefix}woocommerce_shipping_zones order by zone_order ASC;" );
return $wpdb->get_results( "SELECT zone_id, zone_name, zone_order FROM {$wpdb->prefix}woocommerce_shipping_zones order by zone_order ASC, zone_id ASC;" );
}

View File

@ -23,11 +23,16 @@ class WC_Email_Cancelled_Order extends WC_Email {
* Constructor.
*/
public function __construct() {
$this->id = 'cancelled_order';
$this->title = __( 'Cancelled order', 'woocommerce' );
$this->description = __( 'Cancelled order emails are sent to chosen recipient(s) when orders have been marked cancelled (if they were previously processing or on-hold).', 'woocommerce' );
$this->template_html = 'emails/admin-cancelled-order.php';
$this->template_plain = 'emails/plain/admin-cancelled-order.php';
$this->id = 'cancelled_order';
$this->title = __( 'Cancelled order', 'woocommerce' );
$this->description = __( 'Cancelled order emails are sent to chosen recipient(s) when orders have been marked cancelled (if they were previously processing or on-hold).', 'woocommerce' );
$this->template_html = 'emails/admin-cancelled-order.php';
$this->template_plain = 'emails/plain/admin-cancelled-order.php';
$this->placeholders = array(
'{site_title}' => $this->get_blogname(),
'{order_date}' => '',
'{order_number}' => '',
);
// Triggers for this email
add_action( 'woocommerce_order_status_processing_to_cancelled_notification', array( $this, 'trigger' ), 10, 2 );
@ -72,11 +77,9 @@ class WC_Email_Cancelled_Order extends WC_Email {
}
if ( is_a( $order, 'WC_Order' ) ) {
$this->object = $order;
$this->find['order-date'] = '{order_date}';
$this->find['order-number'] = '{order_number}';
$this->replace['order-date'] = wc_format_datetime( $this->object->get_date_created() );
$this->replace['order-number'] = $this->object->get_order_number();
$this->object = $order;
$this->placeholders['{order_date}'] = wc_format_datetime( $this->object->get_date_created() );
$this->placeholders['{order_number}'] = $this->object->get_order_number();
}
if ( ! $this->is_enabled() || ! $this->get_recipient() ) {

View File

@ -23,15 +23,17 @@ class WC_Email_Customer_Completed_Order extends WC_Email {
* Constructor.
*/
public function __construct() {
$this->id = 'customer_completed_order';
$this->customer_email = true;
$this->title = __( 'Completed order', 'woocommerce' );
$this->description = __( 'Order complete emails are sent to customers when their orders are marked completed and usually indicate that their orders have been shipped.', 'woocommerce' );
$this->template_html = 'emails/customer-completed-order.php';
$this->template_plain = 'emails/plain/customer-completed-order.php';
$this->placeholders = array(
'{site_title}' => $this->get_blogname(),
'{order_date}' => '',
'{order_number}' => '',
);
// Triggers for this email
add_action( 'woocommerce_order_status_completed_notification', array( $this, 'trigger' ), 10, 2 );
@ -52,14 +54,10 @@ class WC_Email_Customer_Completed_Order extends WC_Email {
}
if ( is_a( $order, 'WC_Order' ) ) {
$this->object = $order;
$this->recipient = $this->object->get_billing_email();
$this->find['order-date'] = '{order_date}';
$this->find['order-number'] = '{order_number}';
$this->replace['order-date'] = wc_format_datetime( $this->object->get_date_created() );
$this->replace['order-number'] = $this->object->get_order_number();
$this->object = $order;
$this->recipient = $this->object->get_billing_email();
$this->placeholders['{order_date}'] = wc_format_datetime( $this->object->get_date_created() );
$this->placeholders['{order_number}'] = $this->object->get_order_number();
}
if ( ! $this->is_enabled() || ! $this->get_recipient() ) {

View File

@ -37,14 +37,17 @@ class WC_Email_Customer_Invoice extends WC_Email {
* Constructor.
*/
public function __construct() {
$this->id = 'customer_invoice';
$this->customer_email = true;
$this->title = __( 'Customer invoice', 'woocommerce' );
$this->description = __( 'Customer invoice emails can be sent to customers containing their order information and payment links.', 'woocommerce' );
$this->template_html = 'emails/customer-invoice.php';
$this->template_plain = 'emails/plain/customer-invoice.php';
$this->placeholders = array(
'{site_title}' => $this->get_blogname(),
'{order_date}' => '',
'{order_number}' => '',
);
// Call parent constructor
parent::__construct();
@ -126,14 +129,10 @@ class WC_Email_Customer_Invoice extends WC_Email {
}
if ( is_a( $order, 'WC_Order' ) ) {
$this->object = $order;
$this->recipient = $this->object->get_billing_email();
$this->find['order-date'] = '{order_date}';
$this->find['order-number'] = '{order_number}';
$this->replace['order-date'] = wc_format_datetime( $this->object->get_date_created() );
$this->replace['order-number'] = $this->object->get_order_number();
$this->object = $order;
$this->recipient = $this->object->get_billing_email();
$this->placeholders['{order_date}'] = wc_format_datetime( $this->object->get_date_created() );
$this->placeholders['{order_number}'] = $this->object->get_order_number();
}
if ( ! $this->get_recipient() ) {

View File

@ -51,13 +51,10 @@ class WC_Email_Customer_New_Account extends WC_Email {
* Constructor.
*/
public function __construct() {
$this->id = 'customer_new_account';
$this->customer_email = true;
$this->title = __( 'New account', 'woocommerce' );
$this->description = __( 'Customer "new account" emails are sent to the customer when a customer signs up via checkout or account pages.', 'woocommerce' );
$this->template_html = 'emails/customer-new-account.php';
$this->template_plain = 'emails/plain/customer-new-account.php';

View File

@ -30,15 +30,17 @@ class WC_Email_Customer_Note extends WC_Email {
* Constructor.
*/
public function __construct() {
$this->id = 'customer_note';
$this->customer_email = true;
$this->title = __( 'Customer note', 'woocommerce' );
$this->description = __( 'Customer note emails are sent when you add a note to an order.', 'woocommerce' );
$this->template_html = 'emails/customer-note.php';
$this->template_plain = 'emails/plain/customer-note.php';
$this->placeholders = array(
'{site_title}' => $this->get_blogname(),
'{order_date}' => '',
'{order_number}' => '',
);
// Triggers
add_action( 'woocommerce_new_customer_note_notification', array( $this, 'trigger' ) );
@ -84,14 +86,10 @@ class WC_Email_Customer_Note extends WC_Email {
extract( $args );
if ( $order_id && ( $this->object = wc_get_order( $order_id ) ) ) {
$this->recipient = $this->object->get_billing_email();
$this->customer_note = $customer_note;
$this->find['order-date'] = '{order_date}';
$this->find['order-number'] = '{order_number}';
$this->replace['order-date'] = wc_format_datetime( $this->object->get_date_created() );
$this->replace['order-number'] = $this->object->get_order_number();
$this->recipient = $this->object->get_billing_email();
$this->customer_note = $customer_note;
$this->placeholders['{order_date}'] = wc_format_datetime( $this->object->get_date_created() );
$this->placeholders['{order_number}'] = $this->object->get_order_number();
} else {
return;
}

View File

@ -23,13 +23,17 @@ class WC_Email_Customer_On_Hold_Order extends WC_Email {
* Constructor.
*/
public function __construct() {
$this->id = 'customer_on_hold_order';
$this->customer_email = true;
$this->title = __( 'Order on-hold', 'woocommerce' );
$this->description = __( 'This is an order notification sent to customers containing order details after an order is placed on-hold.', 'woocommerce' );
$this->template_html = 'emails/customer-on-hold-order.php';
$this->template_plain = 'emails/plain/customer-on-hold-order.php';
$this->id = 'customer_on_hold_order';
$this->customer_email = true;
$this->title = __( 'Order on-hold', 'woocommerce' );
$this->description = __( 'This is an order notification sent to customers containing order details after an order is placed on-hold.', 'woocommerce' );
$this->template_html = 'emails/customer-on-hold-order.php';
$this->template_plain = 'emails/plain/customer-on-hold-order.php';
$this->placeholders = array(
'{site_title}' => $this->get_blogname(),
'{order_date}' => '',
'{order_number}' => '',
);
// Triggers for this email
add_action( 'woocommerce_order_status_pending_to_on-hold_notification', array( $this, 'trigger' ), 10, 2 );
@ -71,14 +75,10 @@ class WC_Email_Customer_On_Hold_Order extends WC_Email {
}
if ( is_a( $order, 'WC_Order' ) ) {
$this->object = $order;
$this->recipient = $this->object->get_billing_email();
$this->find['order-date'] = '{order_date}';
$this->find['order-number'] = '{order_number}';
$this->replace['order-date'] = wc_format_datetime( $this->object->get_date_created() );
$this->replace['order-number'] = $this->object->get_order_number();
$this->object = $order;
$this->recipient = $this->object->get_billing_email();
$this->placeholders['{order_date}'] = wc_format_datetime( $this->object->get_date_created() );
$this->placeholders['{order_number}'] = $this->object->get_order_number();
}
if ( ! $this->is_enabled() || ! $this->get_recipient() ) {

View File

@ -30,6 +30,11 @@ class WC_Email_Customer_Processing_Order extends WC_Email {
$this->description = __( 'This is an order notification sent to customers containing order details after payment.', 'woocommerce' );
$this->template_html = 'emails/customer-processing-order.php';
$this->template_plain = 'emails/plain/customer-processing-order.php';
$this->placeholders = array(
'{site_title}' => $this->get_blogname(),
'{order_date}' => '',
'{order_number}' => '',
);
// Triggers for this email
add_action( 'woocommerce_order_status_failed_to_processing_notification', array( $this, 'trigger' ), 10, 2 );
@ -72,14 +77,10 @@ class WC_Email_Customer_Processing_Order extends WC_Email {
}
if ( is_a( $order, 'WC_Order' ) ) {
$this->object = $order;
$this->recipient = $this->object->get_billing_email();
$this->find['order-date'] = '{order_date}';
$this->find['order-number'] = '{order_number}';
$this->replace['order-date'] = wc_format_datetime( $this->object->get_date_created() );
$this->replace['order-number'] = $this->object->get_order_number();
$this->object = $order;
$this->recipient = $this->object->get_billing_email();
$this->placeholders['{order_date}'] = wc_format_datetime( $this->object->get_date_created() );
$this->placeholders['{order_number}'] = $this->object->get_order_number();
}
if ( ! $this->is_enabled() || ! $this->get_recipient() ) {

View File

@ -43,6 +43,11 @@ class WC_Email_Customer_Refunded_Order extends WC_Email {
$this->description = __( 'Order refunded emails are sent to customers when their orders are refunded.', 'woocommerce' );
$this->template_html = 'emails/customer-refunded-order.php';
$this->template_plain = 'emails/plain/customer-refunded-order.php';
$this->placeholders = array(
'{site_title}' => $this->get_blogname(),
'{order_date}' => '',
'{order_number}' => '',
);
// Triggers for this email
add_action( 'woocommerce_order_fully_refunded_notification', array( $this, 'trigger_full' ), 10, 2 );
@ -74,9 +79,9 @@ class WC_Email_Customer_Refunded_Order extends WC_Email {
*/
public function get_default_heading( $partial = false ) {
if ( $partial ) {
return __( 'Order {order_number} details', 'woocommerce' );
} else {
return __( 'Your order has been partially refunded', 'woocommerce' );
} else {
return __( 'Order {order_number} details', 'woocommerce' );
}
}
@ -90,7 +95,7 @@ class WC_Email_Customer_Refunded_Order extends WC_Email {
if ( $this->partial_refund ) {
$subject = $this->get_option( 'subject_partial', $this->get_default_subject( true ) );
} else {
$subject = $this->get_option( 'subject_full', $this->get_default_heading() );
$subject = $this->get_option( 'subject_full', $this->get_default_subject() );
}
return apply_filters( 'woocommerce_email_subject_customer_refunded_order', $this->format_string( $subject ), $this->object );
}
@ -148,14 +153,10 @@ class WC_Email_Customer_Refunded_Order extends WC_Email {
$this->id = $this->partial_refund ? 'customer_partially_refunded_order' : 'customer_refunded_order';
if ( $order_id ) {
$this->object = wc_get_order( $order_id );
$this->recipient = $this->object->get_billing_email();
$this->find['order-date'] = '{order_date}';
$this->find['order-number'] = '{order_number}';
$this->replace['order-date'] = wc_format_datetime( $this->object->get_date_created() );
$this->replace['order-number'] = $this->object->get_order_number();
$this->object = wc_get_order( $order_id );
$this->recipient = $this->object->get_billing_email();
$this->placeholders['{order_date}'] = wc_format_datetime( $this->object->get_date_created() );
$this->placeholders['{order_number}'] = $this->object->get_order_number();
}
if ( ! empty( $refund_id ) ) {

View File

@ -23,11 +23,16 @@ class WC_Email_Failed_Order extends WC_Email {
* Constructor.
*/
public function __construct() {
$this->id = 'failed_order';
$this->title = __( 'Failed order', 'woocommerce' );
$this->description = __( 'Failed order emails are sent to chosen recipient(s) when orders have been marked failed (if they were previously processing or on-hold).', 'woocommerce' );
$this->template_html = 'emails/admin-failed-order.php';
$this->template_plain = 'emails/plain/admin-failed-order.php';
$this->id = 'failed_order';
$this->title = __( 'Failed order', 'woocommerce' );
$this->description = __( 'Failed order emails are sent to chosen recipient(s) when orders have been marked failed (if they were previously processing or on-hold).', 'woocommerce' );
$this->template_html = 'emails/admin-failed-order.php';
$this->template_plain = 'emails/plain/admin-failed-order.php';
$this->placeholders = array(
'{site_title}' => $this->get_blogname(),
'{order_date}' => '',
'{order_number}' => '',
);
// Triggers for this email
add_action( 'woocommerce_order_status_pending_to_failed_notification', array( $this, 'trigger' ), 10, 2 );
@ -72,11 +77,9 @@ class WC_Email_Failed_Order extends WC_Email {
}
if ( is_a( $order, 'WC_Order' ) ) {
$this->object = $order;
$this->find['order-date'] = '{order_date}';
$this->find['order-number'] = '{order_number}';
$this->replace['order-date'] = wc_format_datetime( $this->object->get_date_created() );
$this->replace['order-number'] = $this->object->get_order_number();
$this->object = $order;
$this->placeholders['{order_date}'] = wc_format_datetime( $this->object->get_date_created() );
$this->placeholders['{order_number}'] = $this->object->get_order_number();
}
if ( ! $this->is_enabled() || ! $this->get_recipient() ) {

View File

@ -23,11 +23,16 @@ class WC_Email_New_Order extends WC_Email {
* Constructor.
*/
public function __construct() {
$this->id = 'new_order';
$this->title = __( 'New order', 'woocommerce' );
$this->description = __( 'New order emails are sent to chosen recipient(s) when a new order is received.', 'woocommerce' );
$this->template_html = 'emails/admin-new-order.php';
$this->template_plain = 'emails/plain/admin-new-order.php';
$this->id = 'new_order';
$this->title = __( 'New order', 'woocommerce' );
$this->description = __( 'New order emails are sent to chosen recipient(s) when a new order is received.', 'woocommerce' );
$this->template_html = 'emails/admin-new-order.php';
$this->template_plain = 'emails/plain/admin-new-order.php';
$this->placeholders = array(
'{site_title}' => $this->get_blogname(),
'{order_date}' => '',
'{order_number}' => '',
);
// Triggers for this email
add_action( 'woocommerce_order_status_pending_to_processing_notification', array( $this, 'trigger' ), 10, 2 );
@ -76,11 +81,9 @@ class WC_Email_New_Order extends WC_Email {
}
if ( is_a( $order, 'WC_Order' ) ) {
$this->object = $order;
$this->find['order-date'] = '{order_date}';
$this->find['order-number'] = '{order_number}';
$this->replace['order-date'] = wc_format_datetime( $this->object->get_date_created() );
$this->replace['order-number'] = $this->object->get_order_number();
$this->object = $order;
$this->placeholders['{order_date}'] = wc_format_datetime( $this->object->get_date_created() );
$this->placeholders['{order_number}'] = $this->object->get_order_number();
}
if ( ! $this->is_enabled() || ! $this->get_recipient() ) {

View File

@ -95,18 +95,6 @@ class WC_Email extends WC_Settings_API {
*/
public $object;
/**
* Strings to find in subjects/headings.
* @var array
*/
public $find = array();
/**
* Strings to replace in subjects/headings.
* @var array
*/
public $replace = array();
/**
* Mime boundary (for multipart emails).
* @var string
@ -195,34 +183,54 @@ class WC_Email extends WC_Settings_API {
' ', // Runs of spaces, post-handling
);
/**
* Strings to find/replace in subjects/headings.
*
* @var array
*/
protected $placeholders = array();
/**
* Strings to find in subjects/headings.
*
* @deprecated 3.2.0 in favour of placeholders
* @var array
*/
public $find = array();
/**
* Strings to replace in subjects/headings.
*
* @deprecated 3.2.0 in favour of placeholders
* @var array
*/
public $replace = array();
/**
* Constructor.
*/
public function __construct() {
// Find/replace
if ( empty( $this->placeholders ) ) {
$this->placeholders = array(
'{site_title}' => $this->get_blogname(),
);
}
// Init settings
$this->init_form_fields();
$this->init_settings();
// Save settings hook
add_action( 'woocommerce_update_options_email_' . $this->id, array( $this, 'process_admin_options' ) );
// Default template base if not declared in child constructor
if ( is_null( $this->template_base ) ) {
$this->template_base = WC()->plugin_path() . '/templates/';
}
// Settings
$this->email_type = $this->get_option( 'email_type' );
$this->enabled = $this->get_option( 'enabled' );
// Find/replace
$this->find['blogname'] = '{blogname}';
$this->find['site-title'] = '{site_title}';
$this->replace['blogname'] = $this->get_blogname();
$this->replace['site-title'] = $this->get_blogname();
// For multipart messages
add_action( 'phpmailer_init', array( $this, 'handle_multipart' ) );
add_action( 'woocommerce_update_options_email_' . $this->id, array( $this, 'process_admin_options' ) );
}
/**
@ -246,14 +254,16 @@ class WC_Email extends WC_Settings_API {
* @return string
*/
public function format_string( $string ) {
return str_replace( apply_filters( 'woocommerce_email_format_string_find', $this->find, $this ), apply_filters( 'woocommerce_email_format_string_replace', $this->replace, $this ), $string );
// handle legacy find and replace.
$string = str_replace( $this->find, $this->replace, $string );
return str_replace( apply_filters( 'woocommerce_email_format_string_find', array_keys( $this->placeholders ), $this ), apply_filters( 'woocommerce_email_format_string_replace', array_values( $this->placeholders ), $this ), $string );
}
/**
* Set the locale to the store locale for customer emails to make sure emails are in the store language.
*/
public function setup_locale() {
if ( $this->is_customer_email() ) {
if ( $this->is_customer_email() && apply_filters( 'woocommerce_email_setup_locale', true ) ) {
wc_switch_to_site_locale();
}
}
@ -262,7 +272,7 @@ class WC_Email extends WC_Settings_API {
* Restore the locale to the default locale. Use after finished with setup_locale.
*/
public function restore_locale() {
if ( $this->is_customer_email() ) {
if ( $this->is_customer_email() && apply_filters( 'woocommerce_email_restore_locale', true ) ) {
wc_restore_locale();
}
}
@ -538,7 +548,7 @@ class WC_Email extends WC_Settings_API {
'type' => 'text',
'desc_tip' => true,
/* translators: %s: list of placeholders */
'description' => sprintf( __( 'Available placeholders: %s', 'woocommerce' ), '<code>{site_title}</code>' ),
'description' => sprintf( __( 'Available placeholders: %s', 'woocommerce' ), '<code>' . implode( '</code>, <code>', array_keys( $this->placeholders ) ) . '</code>' ),
'placeholder' => $this->get_default_subject(),
'default' => '',
),
@ -547,7 +557,7 @@ class WC_Email extends WC_Settings_API {
'type' => 'text',
'desc_tip' => true,
/* translators: %s: list of placeholders */
'description' => sprintf( __( 'Available placeholders: %s', 'woocommerce' ), '<code>{site_title}</code>' ),
'description' => sprintf( __( 'Available placeholders: %s', 'woocommerce' ), '<code>' . implode( '</code>, <code>', array_keys( $this->placeholders ) ) . '</code>' ),
'placeholder' => $this->get_default_heading(),
'default' => '',
),

View File

@ -124,7 +124,7 @@ class WC_Product_CSV_Exporter extends WC_CSV_Batch_Exporter {
*/
public function prepare_data_to_export() {
$columns = $this->get_column_names();
$products = wc_get_products( array(
$args = apply_filters( "woocommerce_product_export_{$this->export_type}_query_args", array(
'status' => array( 'private', 'publish' ),
'type' => $this->product_types_to_export,
'limit' => $this->get_limit(),
@ -135,6 +135,7 @@ class WC_Product_CSV_Exporter extends WC_CSV_Batch_Exporter {
'return' => 'objects',
'paginate' => true,
) );
$products = wc_get_products( $args );
$this->total_rows = $products->total;
$this->row_data = array();

View File

@ -393,7 +393,6 @@ class WC_Addons_Gateway_Simplify_Commerce extends WC_Gateway_Simplify_Commerce {
* @since 2.4
* @param string $payment_method_id The ID of the payment method to validate
* @param array $payment_meta associative array of meta data required for automatic payments
* @return array
* @throws Exception
*/
public function validate_subscription_payment_meta( $payment_method_id, $payment_meta ) {

View File

@ -293,7 +293,6 @@ abstract class WC_Product_Importer implements WC_Importer_Interface {
* @param WC_Product $product Product instance.
* @param array $data Item data.
*
* @return WC_Product|WP_Error
* @throws Exception
*/
protected function set_product_data( &$product, $data ) {
@ -587,43 +586,39 @@ abstract class WC_Product_Importer implements WC_Importer_Interface {
}
// If the attribute does not exist, create it.
$args = array(
'attribute_label' => $raw_name,
'attribute_name' => $attribute_name,
'attribute_type' => 'select',
'attribute_orderby' => 'menu_order',
'attribute_public' => 0,
);
$attribute_id = wc_create_attribute( array(
'name' => $raw_name,
'slug' => $attribute_name,
'type' => 'select',
'order_by' => 'menu_order',
'has_archives' => false,
) );
// Validate attribute.
if ( strlen( $attribute_name ) >= 28 ) {
throw new Exception( sprintf( __( 'Slug "%s" is too long (28 characters max). Shorten it, please.', 'woocommerce' ), $attribute_name ), 400 );
} elseif ( wc_check_if_attribute_name_is_reserved( $attribute_name ) ) {
throw new Exception( sprintf( __( 'Slug "%s" is not allowed because it is a reserved term. Change it, please.', 'woocommerce' ), $attribute_name ), 400 );
} elseif ( taxonomy_exists( wc_attribute_taxonomy_name( $attribute_name ) ) ) {
throw new Exception( sprintf( __( 'Slug "%s" is already in use. Change it, please.', 'woocommerce' ), $attribute_name ), 400 );
if ( is_wp_error( $attribute_id ) ) {
throw new Exception( $attribute_id->get_error_message(), 400 );
}
$result = $wpdb->insert( $wpdb->prefix . 'woocommerce_attribute_taxonomies', $args, array( '%s', '%s', '%s', '%s', '%d' ) );
// Pass errors.
if ( is_wp_error( $result ) ) {
throw new Exception( $result->get_error_message(), 400 );
}
$attribute_id = absint( $wpdb->insert_id );
// Delete transient.
delete_transient( 'wc_attribute_taxonomies' );
// Register as taxonomy while importing.
register_taxonomy( wc_attribute_taxonomy_name( $attribute_name ), array( 'product' ), array( 'labels' => array( 'name' => $raw_name ) ) );
$taxonomy_name = wc_attribute_taxonomy_name( $attribute_name );
register_taxonomy(
$taxonomy_name,
apply_filters( 'woocommerce_taxonomy_objects_' . $taxonomy_name, array( 'product' ) ),
apply_filters( 'woocommerce_taxonomy_args_' . $taxonomy_name, array(
'labels' => array(
'name' => $raw_name,
),
'hierarchical' => true,
'show_ui' => false,
'query_var' => true,
'rewrite' => false,
) )
);
// Set product attributes global.
$wc_product_attributes = array();
foreach ( wc_get_attribute_taxonomies() as $tax ) {
$wc_product_attributes[ wc_attribute_taxonomy_name( $attribute_name ) ] = $tax;
foreach ( wc_get_attribute_taxonomies() as $taxonomy ) {
$wc_product_attributes[ wc_attribute_taxonomy_name( $taxonomy['attribute_name'] ) ] = $taxonomy;
}
return $attribute_id;

Some files were not shown because too many files have changed in this diff Show More