Merge branch 'master' into feature/webhook-crud

This commit is contained in:
Claudio Sanches 2017-12-04 12:37:10 -02:00 committed by GitHub
commit 0f4f8a3f16
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
55 changed files with 4240 additions and 3446 deletions

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -1867,17 +1867,21 @@ ul.wc_coupon_list_block {
width: 11%;
}
.column-order_actions,
.column-user_actions,
.column-wc_actions {
width: 110px;
a.button {
float: left;
margin: 0 4px 2px 0;
cursor: pointer;
padding: 3px 4px;
height: auto;
@include ir();
display: inline-block;
margin: 2px 4px 2px 0;
padding: 0 !important;
height: 2em !important;
width: 2em;
&::after {
@include icon_dashicons;
line-height: 1.85;
}
img {
display: block;
@ -1885,6 +1889,32 @@ ul.wc_coupon_list_block {
height: auto;
}
}
a.edit::after {
content: '\f464';
}
a.link::after {
content: '\e00d';
}
a.view::after {
content: '\f177';
}
a.refresh::after {
font-family: 'WooCommerce';
content: '\e031';
}
a.processing::after {
font-family: 'WooCommerce';
content: '\e00f';
}
a.complete::after {
content: '\f147';
}
}
small.meta {
@ -1901,11 +1931,50 @@ ul.wc_coupon_list_block {
}
.wp-list-table {
margin-top: 1em;
th {
padding: .75em 1em;
thead,
tfoot {
th {
padding: .75em 1em;
}
th.sortable a, th.sorted a {
padding: 0;
}
th:first-child {
padding-left: 2em;
}
th:last-child {
padding-right: 2em;
}
}
th.sortable a, th.sorted a {
padding: 0;
tbody {
td,
th {
padding: 1em;
line-height: 26px;
}
td:first-child {
padding-left: 2em;
}
td:last-child {
padding-right: 2em;
}
}
tbody tr {
border-top: 1px solid #f5f5f5;
}
tbody tr:hover:not(.status-trash) td {
cursor: pointer;
}
// Columns.
td,
th {
width: 12ch;
vertical-align: middle;
p {
margin: 0;
}
}
.check-column {
width: 1px;
@ -1917,147 +1986,122 @@ ul.wc_coupon_list_block {
margin: 1px 0;
}
}
td.column-order_number {
line-height: 26px;
.order-preview {
float:right;
width: 16px;
padding: 20px 4px 4px 4px;
height: 0;
overflow: hidden;
position: relative;
border: 2px solid transparent;
border-radius: 4px;
&::before {
@include icon( '\e010' );
line-height: 16px;
font-size: 14px;
vertical-align:middle;
top: 4px;
}
&:hover {
border: 2px solid #00a0d2;
}
}
.order-preview.disabled {
&::before {
content: '';
background: url(../../../../../wp-includes/images/wpspin.gif) no-repeat center top;
}
}
}
.column-order_date {
width: 10ch;
}
.column-order_number {
width: 35ch;
}
.column-order_status {
width: 20ch;
}
.column-order_total {
width: 8ch;
text-align: right;
width: 10ch;
a span {
float:right;
}
}
.column-order_date,
.column-order_status {
width: 10ch;
}
.column-order_status {
width: 14ch;
}
.column-shipping_address,
.column-billing_address {
width: 20ch;
}
th:first-child,
td:first-child {
padding-left: 2em;
}
th:last-child,
td:last-child {
padding-right: 2em;
}
tbody {
th, td {
border-top: 1px solid #f5f5f5;
line-height: 1.5em;
.description {
display: block;
color: #999;
}
td {
vertical-align: middle;
padding: 1em;
}
.column-wc_actions {
text-align: right;
.post-row-actions {
display: none;
}
.order-status {
display: inline-flex;
padding: 0px 1em;
line-height: 2.5em;
color: #777;
background: #E5E5E5;
border-radius: 4px;
border-bottom: 1px solid rgba(0,0,0,0.05);
margin: -.5em 0;
cursor: inherit !important;
&.status-completed {
background: #C8D7E1;
color: #2e4453;
}
&.status-on-hold {
background: #f8dda7;
color: #94660c;
}
&.status-failed {
background: #eba3a3;
color: #761919;
}
&.status-processing {
background: #C6E1C6;
color: #5B841B;
}
&.status-trash {
background: #eba3a3;
color: #761919;
}
}
a.button {
text-indent: 9999px;
margin: 2px 0 2px 4px;
}
tr:hover:not(.status-trash) {
td, th {
cursor: pointer;
}
}
.order-preview {
float:right;
width: 16px;
padding: 20px 4px 4px 4px;
height: 0;
overflow: hidden;
position: relative;
border: 2px solid transparent;
border-radius: 4px;
&::before {
@include icon( '\e010' );
line-height: 16px;
font-size: 14px;
vertical-align:middle;
top: 4px;
}
&:hover {
border: 2px solid #00a0d2;
}
}
.order-preview.disabled {
&::before {
content: '';
background: url('../images/wpspin.gif') no-repeat center top;
}
}
}
}
// Hide some columns on smaller screens.
@media only screen and (max-width: 1400px) {
.post-type-shop_order .wp-list-table {
.column-billing_address {
display:none;
visibility:hidden;
}
.order-status {
display: inline-flex;
padding: 0px 1em;
line-height: 2.5em;
color: #777;
background: #E5E5E5;
border-radius: 4px;
border-bottom: 1px solid rgba(0,0,0,0.05);
margin: -.25em 0;
cursor: inherit !important;
white-space: nowrap;
&.status-completed {
background: #C8D7E1;
color: #2e4453;
}
}
@media only screen and (max-width: 1200px) {
.post-type-shop_order .wp-list-table {
.column-shipping_address,
.column-order_total {
display:none;
visibility:hidden;
}
&.status-on-hold {
background: #f8dda7;
color: #94660c;
}
&.status-failed {
background: #eba3a3;
color: #761919;
}
&.status-processing {
background: #C6E1C6;
color: #5B841B;
}
&.status-trash {
background: #eba3a3;
color: #761919;
}
}
.wc-order-preview {
.order-status {
float: right;
margin-right: 54px;
}
article {
padding: 0 !important;
}
.wc-order-preview__table {
.modal-close {
border-radius: 0;
}
.wc-order-preview-table {
width: 100%;
margin: 0;
border-bottom: 1px solid #ccc;
@ -2115,6 +2159,58 @@ ul.wc_coupon_list_block {
}
}
}
.wc-action-button,
.wc-action-button-group {
float: left;
margin-right: 4px;
}
}
@media screen and (max-width: 782px) {
.wc-action-button-group {
label {
display: none;
}
}
}
.wc-action-button-group {
vertical-align: middle;
line-height: 26px;
text-align: left;
margin-bottom: 4px;
label {
margin-right: 6px;
cursor: default;
font-weight: bold;
}
.wc-action-button-group__items {
white-space: nowrap;
}
.wc-action-button {
margin: -1px !important;
border: 1px solid #ccc;
padding: 1px 10px !important;
border-radius: 0 !important;
float: none;
line-height: 28px;
height: auto;
z-index: 1;
position:relative;
}
.wc-action-button:hover,
.wc-action-button:focus {
border: 1px solid #999;
z-index: 2;
}
.wc-action-button:first-child {
border-top-left-radius: 3px !important;
border-bottom-left-radius: 3px !important;
}
.wc-action-button:last-child {
border-top-right-radius: 3px !important;
border-bottom-right-radius: 3px !important;
}
}
.column-customer_message .note-on {
@ -2139,66 +2235,6 @@ ul.wc_coupon_list_block {
}
}
.order_actions {
.processing,
.complete,
.view {
@include ir();
padding: 0 !important;
height: 2em !important;
width: 2em;
}
.processing::after {
@include icon( '\e00f' );
line-height: 1.85;
}
.complete::after {
@include icon_dashicons( '\f147' );
line-height: 1.85;
}
.view::after {
@include icon_dashicons( '\f177' );
line-height: 1.85;
}
}
.user_actions {
.edit,
.link,
.view,
.refresh {
@include ir();
padding: 0 !important;
height: 2em !important;
width: 2em;
&::after {
@include icon;
line-height: 1.85;
}
}
.edit::after {
font-family: 'Dashicons';
content: '\f464';
}
.link::after {
content: '\e00d';
}
.view::after {
content: '\e010';
}
.refresh::after {
content: '\e031';
}
}
.attributes-table {
td,
th {
@ -2457,18 +2493,26 @@ table.wp-list-table {
}
}
mark.instock {
font-weight: 700;
color: $green;
background: transparent none;
line-height: 1;
}
mark {
&.instock,
&.outofstock,
&.onbackorder {
font-weight: 700;
background: transparent none;
line-height: 1;
}
mark.outofstock {
font-weight: 700;
color: #aa4444;
background: transparent none;
line-height: 1;
&.instock {
color: $green;
}
&.outofstock {
color: #aa4444;
}
&.onbackorder {
color: #eaa600;
}
}
.order-notes_head,
@ -5221,29 +5265,6 @@ img.ui-datepicker-trigger {
width: 49.5%;
float: right;
}
.column-wc_actions {
a.edit,
a.view {
@include ir();
padding: 0 !important;
height: 2em !important;
width: 2em;
&::after {
@include icon_dashicons;
line-height: 1.85;
}
}
a.edit::after {
content: '\f464';
}
a.view::after {
content: '\f177';
}
}
}
.woocommerce-wide-reports-wrap {
@ -5770,7 +5791,7 @@ table.bar_chart {
box-shadow: 0 -4px 4px -4px rgba(0, 0, 0, 0.1);
.inner {
float: right;
text-align: right;
line-height: 23px;
.button {

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

BIN
assets/images/wpspin-2x.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.9 KiB

BIN
assets/images/wpspin.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 KiB

View File

@ -232,8 +232,12 @@ jQuery( function( $ ) {
$( 'input#_manage_stock' ).change( function() {
if ( $( this ).is( ':checked' ) ) {
$( 'div.stock_fields' ).show();
$( 'p.stock_status_field' ).hide();
} else {
var product_type = $( 'select#product-type' ).val();
$( 'div.stock_fields' ).hide();
$( 'p.stock_status_field:not( .hide_if_' + product_type + ' )' ).show();
}
}).change();

File diff suppressed because one or more lines are too long

View File

@ -60,10 +60,12 @@ jQuery(function( $ ) {
}
if ( 'yes' === manage_stock ) {
$( '.stock_qty_field', '.inline-edit-row' ).show().removeAttr( 'style' );
$( '.stock_qty_field, .backorder_field', '.inline-edit-row' ).show().removeAttr( 'style' );
$( '.stock_status_field' ).hide();
$( 'input[name="_manage_stock"]', '.inline-edit-row' ).attr( 'checked', 'checked' );
} else {
$( '.stock_qty_field', '.inline-edit-row' ).hide();
$( '.stock_qty_field, .backorder_field', '.inline-edit-row' ).hide();
$( '.stock_status_field' ).show().removeAttr( 'style' );
$( 'input[name="_manage_stock"]', '.inline-edit-row' ).removeAttr( 'checked' );
}
@ -96,9 +98,11 @@ jQuery(function( $ ) {
$( '#the-list' ).on( 'change', '.inline-edit-row input[name="_manage_stock"]', function() {
if ( $( this ).is( ':checked' ) ) {
$( '.stock_qty_field', '.inline-edit-row' ).show().removeAttr( 'style' );
$( '.stock_qty_field, .backorder_field', '.inline-edit-row' ).show().removeAttr( 'style' );
$( '.stock_status_field' ).hide();
} else {
$( '.stock_qty_field', '.inline-edit-row' ).hide();
$( '.stock_qty_field, .backorder_field', '.inline-edit-row' ).hide();
$( '.stock_status_field' ).show().removeAttr( 'style' );
}
});

View File

@ -1 +1 @@
jQuery(function(e){e("#the-list").on("click",".editinline",function(){inlineEditPost.revert();var t=e(this).closest("tr").attr("id");t=t.replace("post-","");var i=e("#woocommerce_inline_"+t),n=i.find(".sku").text(),o=i.find(".regular_price").text(),l=i.find(".sale_price ").text(),d=i.find(".weight").text(),s=i.find(".length").text(),c=i.find(".width").text(),a=i.find(".height").text(),r=i.find(".shipping_class").text(),_=i.find(".visibility").text(),m=i.find(".stock_status").text(),p=i.find(".stock").text(),u=i.find(".featured").text(),w=i.find(".manage_stock").text(),h=i.find(".menu_order").text(),f=i.find(".tax_status").text(),v=i.find(".tax_class").text(),k=i.find(".backorders").text(),x=o.replace(".",woocommerce_admin.mon_decimal_point),g=l.replace(".",woocommerce_admin.mon_decimal_point);e('input[name="_sku"]',".inline-edit-row").val(n),e('input[name="_regular_price"]',".inline-edit-row").val(x),e('input[name="_sale_price"]',".inline-edit-row").val(g),e('input[name="_weight"]',".inline-edit-row").val(d),e('input[name="_length"]',".inline-edit-row").val(s),e('input[name="_width"]',".inline-edit-row").val(c),e('input[name="_height"]',".inline-edit-row").val(a),e('select[name="_shipping_class"] option:selected',".inline-edit-row").attr("selected",!1).change(),e('select[name="_shipping_class"] option[value="'+r+'"]').attr("selected","selected").change(),e('input[name="_stock"]',".inline-edit-row").val(p),e('input[name="menu_order"]',".inline-edit-row").val(h),e('select[name="_tax_status"] option, select[name="_tax_class"] option, select[name="_visibility"] option, select[name="_stock_status"] option, select[name="_backorders"] option').removeAttr("selected"),e('select[name="_tax_status"] option[value="'+f+'"]',".inline-edit-row").attr("selected","selected"),e('select[name="_tax_class"] option[value="'+v+'"]',".inline-edit-row").attr("selected","selected"),e('select[name="_visibility"] option[value="'+_+'"]',".inline-edit-row").attr("selected","selected"),e('select[name="_stock_status"] option[value="'+m+'"]',".inline-edit-row").attr("selected","selected"),e('select[name="_backorders"] option[value="'+k+'"]',".inline-edit-row").attr("selected","selected"),"yes"===u?e('input[name="_featured"]',".inline-edit-row").attr("checked","checked"):e('input[name="_featured"]',".inline-edit-row").removeAttr("checked"),"yes"===w?(e(".stock_qty_field",".inline-edit-row").show().removeAttr("style"),e('input[name="_manage_stock"]',".inline-edit-row").attr("checked","checked")):(e(".stock_qty_field",".inline-edit-row").hide(),e('input[name="_manage_stock"]',".inline-edit-row").removeAttr("checked"));var y=i.find(".product_type").text(),b=i.find(".product_is_virtual").text();"simple"===y||"external"===y?e(".price_fields",".inline-edit-row").show().removeAttr("style"):e(".price_fields",".inline-edit-row").hide(),"yes"===b?e(".dimension_fields",".inline-edit-row").hide():e(".dimension_fields",".inline-edit-row").show().removeAttr("style"),"grouped"===y?e(".stock_fields",".inline-edit-row").hide():e(".stock_fields",".inline-edit-row").show().removeAttr("style"),e('input[name="comment_status"]').parent().find(".checkbox-title").text(woocommerce_quick_edit.strings.allow_reviews)}),e("#the-list").on("change",'.inline-edit-row input[name="_manage_stock"]',function(){e(this).is(":checked")?e(".stock_qty_field",".inline-edit-row").show().removeAttr("style"):e(".stock_qty_field",".inline-edit-row").hide()}),e("#wpbody").on("click","#doaction, #doaction2",function(){e("input.text",".inline-edit-row").val(""),e("#woocommerce-fields").find("select").prop("selectedIndex",0),e("#woocommerce-fields-bulk").find(".inline-edit-group .change-input").hide()}),e("#wpbody").on("change","#woocommerce-fields-bulk .inline-edit-group .change_to",function(){0<e(this).val()?e(this).closest("div").find(".change-input").show():e(this).closest("div").find(".change-input").hide()}),e("#wpbody").on("click",".trash-product",function(){return window.confirm(woocommerce_admin.i18_delete_product_notice)})});
jQuery(function(e){e("#the-list").on("click",".editinline",function(){inlineEditPost.revert();var t=e(this).closest("tr").attr("id");t=t.replace("post-","");var i=e("#woocommerce_inline_"+t),n=i.find(".sku").text(),o=i.find(".regular_price").text(),d=i.find(".sale_price ").text(),l=i.find(".weight").text(),s=i.find(".length").text(),c=i.find(".width").text(),r=i.find(".height").text(),a=i.find(".shipping_class").text(),_=i.find(".visibility").text(),m=i.find(".stock_status").text(),p=i.find(".stock").text(),u=i.find(".featured").text(),w=i.find(".manage_stock").text(),f=i.find(".menu_order").text(),h=i.find(".tax_status").text(),k=i.find(".tax_class").text(),v=i.find(".backorders").text(),x=o.replace(".",woocommerce_admin.mon_decimal_point),g=d.replace(".",woocommerce_admin.mon_decimal_point);e('input[name="_sku"]',".inline-edit-row").val(n),e('input[name="_regular_price"]',".inline-edit-row").val(x),e('input[name="_sale_price"]',".inline-edit-row").val(g),e('input[name="_weight"]',".inline-edit-row").val(l),e('input[name="_length"]',".inline-edit-row").val(s),e('input[name="_width"]',".inline-edit-row").val(c),e('input[name="_height"]',".inline-edit-row").val(r),e('select[name="_shipping_class"] option:selected',".inline-edit-row").attr("selected",!1).change(),e('select[name="_shipping_class"] option[value="'+a+'"]').attr("selected","selected").change(),e('input[name="_stock"]',".inline-edit-row").val(p),e('input[name="menu_order"]',".inline-edit-row").val(f),e('select[name="_tax_status"] option, select[name="_tax_class"] option, select[name="_visibility"] option, select[name="_stock_status"] option, select[name="_backorders"] option').removeAttr("selected"),e('select[name="_tax_status"] option[value="'+h+'"]',".inline-edit-row").attr("selected","selected"),e('select[name="_tax_class"] option[value="'+k+'"]',".inline-edit-row").attr("selected","selected"),e('select[name="_visibility"] option[value="'+_+'"]',".inline-edit-row").attr("selected","selected"),e('select[name="_stock_status"] option[value="'+m+'"]',".inline-edit-row").attr("selected","selected"),e('select[name="_backorders"] option[value="'+v+'"]',".inline-edit-row").attr("selected","selected"),"yes"===u?e('input[name="_featured"]',".inline-edit-row").attr("checked","checked"):e('input[name="_featured"]',".inline-edit-row").removeAttr("checked"),"yes"===w?(e(".stock_qty_field, .backorder_field",".inline-edit-row").show().removeAttr("style"),e(".stock_status_field").hide(),e('input[name="_manage_stock"]',".inline-edit-row").attr("checked","checked")):(e(".stock_qty_field, .backorder_field",".inline-edit-row").hide(),e(".stock_status_field").show().removeAttr("style"),e('input[name="_manage_stock"]',".inline-edit-row").removeAttr("checked"));var y=i.find(".product_type").text(),b=i.find(".product_is_virtual").text();"simple"===y||"external"===y?e(".price_fields",".inline-edit-row").show().removeAttr("style"):e(".price_fields",".inline-edit-row").hide(),"yes"===b?e(".dimension_fields",".inline-edit-row").hide():e(".dimension_fields",".inline-edit-row").show().removeAttr("style"),"grouped"===y?e(".stock_fields",".inline-edit-row").hide():e(".stock_fields",".inline-edit-row").show().removeAttr("style"),e('input[name="comment_status"]').parent().find(".checkbox-title").text(woocommerce_quick_edit.strings.allow_reviews)}),e("#the-list").on("change",'.inline-edit-row input[name="_manage_stock"]',function(){e(this).is(":checked")?(e(".stock_qty_field, .backorder_field",".inline-edit-row").show().removeAttr("style"),e(".stock_status_field").hide()):(e(".stock_qty_field, .backorder_field",".inline-edit-row").hide(),e(".stock_status_field").show().removeAttr("style"))}),e("#wpbody").on("click","#doaction, #doaction2",function(){e("input.text",".inline-edit-row").val(""),e("#woocommerce-fields").find("select").prop("selectedIndex",0),e("#woocommerce-fields-bulk").find(".inline-edit-group .change-input").hide()}),e("#wpbody").on("change","#woocommerce-fields-bulk .inline-edit-group .change_to",function(){0<e(this).val()?e(this).closest("div").find(".change-input").show():e(this).closest("div").find(".change-input").hide()}),e("#wpbody").on("click",".trash-product",function(){return window.confirm(woocommerce_admin.i18_delete_product_notice)})});

View File

@ -26,7 +26,13 @@ jQuery( function( $ ) {
href = $row.find( 'a.order-view' ).attr( 'href' );
if ( href.length ) {
window.location = href;
e.preventDefault();
if ( e.metaKey ) {
window.open( href, '_blank' );
} else {
window.location = href;
}
}
};

View File

@ -1 +1 @@
jQuery(function(e){if("undefined"==typeof wc_orders_params)return!1;var r=function(){e(document).on("click",".post-type-shop_order .wp-list-table tbody td",this.onRowClick).on("click",".order-preview:not(.disabled)",this.onPreview)};r.prototype.onRowClick=function(r){if(e(r.target).filter("a").length)return!0;var a=e(this).closest("tr").find("a.order-view").attr("href");a.length&&(window.location=a)},r.prototype.onPreview=function(){var r=e(this),a=r.data("order-id");return r.data("order-data")?e(this).WCBackboneModal({template:"wc-modal-view-order",variable:r.data("order-data")}):(r.addClass("disabled"),e.ajax({url:wc_orders_params.ajax_url,data:{order_id:a,action:"woocommerce_get_order_details",security:wc_orders_params.preview_nonce},type:"GET",success:function(a){e(".order-preview").removeClass("disabled"),a.success&&(r.data("order-data",a.data),e(this).WCBackboneModal({template:"wc-modal-view-order",variable:a.data}))}})),!1},new r});
jQuery(function(e){if("undefined"==typeof wc_orders_params)return!1;var r=function(){e(document).on("click",".post-type-shop_order .wp-list-table tbody td",this.onRowClick).on("click",".order-preview:not(.disabled)",this.onPreview)};r.prototype.onRowClick=function(r){if(e(r.target).filter("a").length)return!0;var a=e(this).closest("tr").find("a.order-view").attr("href");a.length&&(r.preventDefault(),r.metaKey?window.open(a,"_blank"):window.location=a)},r.prototype.onPreview=function(){var r=e(this),a=r.data("order-id");return r.data("order-data")?e(this).WCBackboneModal({template:"wc-modal-view-order",variable:r.data("order-data")}):(r.addClass("disabled"),e.ajax({url:wc_orders_params.ajax_url,data:{order_id:a,action:"woocommerce_get_order_details",security:wc_orders_params.preview_nonce},type:"GET",success:function(a){e(".order-preview").removeClass("disabled"),a.success&&(r.data("order-data",a.data),e(this).WCBackboneModal({template:"wc-modal-view-order",variable:a.data}))}})),!1},new r});

View File

@ -1 +1 @@
!function(e,i,s,n){e(function(){var t=e(".wc-shipping-class-rows"),a=e(".wc-shipping-class-save"),o=s.template("wc-shipping-class-row"),d=s.template("wc-shipping-class-row-blank"),c=Backbone.Model.extend({changes:{},logChanges:function(e){var i=this.changes||{};_.each(e,function(e,s){i[s]=_.extend(i[s]||{term_id:s},e)}),this.changes=i,this.trigger("change:classes")},save:function(){_.size(this.changes)?e.post(n+(n.indexOf("?")>0?"&":"?")+"action=woocommerce_shipping_classes_save_changes",{wc_shipping_classes_nonce:i.wc_shipping_classes_nonce,changes:this.changes},this.onSaveResponse,"json"):r.trigger("saved:classes")},discardChanges:function(e){delete(this.changes||{})[e],0===_.size(this.changes)&&h.clearUnloadConfirmation()},onSaveResponse:function(e,s){"success"===s&&(e.success?(r.set("classes",e.data.shipping_classes),r.trigger("change:classes"),r.changes={},r.trigger("saved:classes")):e.data?window.alert(e.data):window.alert(i.strings.save_failed)),h.unblock()}}),l=Backbone.View.extend({rowTemplate:o,initialize:function(){this.listenTo(this.model,"change:classes",this.setUnloadConfirmation),this.listenTo(this.model,"saved:classes",this.clearUnloadConfirmation),this.listenTo(this.model,"saved:classes",this.render),t.on("change",{view:this},this.updateModelOnChange),e(window).on("beforeunload",{view:this},this.unloadConfirmation),a.on("click",{view:this},this.onSubmit),e(document.body).on("click",".wc-shipping-class-add",{view:this},this.onAddNewRow),e(document.body).on("click",".wc-shipping-class-save-changes",{view:this},this.onSubmit)},block:function(){e(this.el).block({message:null,overlayCSS:{background:"#fff",opacity:.6}})},unblock:function(){e(this.el).unblock()},render:function(){var i=_.indexBy(this.model.get("classes"),"term_id"),s=this;this.$el.empty(),this.unblock(),_.size(i)?(i=_.sortBy(i,function(e){return e.name}),e.each(i,function(e,i){s.renderRow(i)})):s.$el.append(d)},renderRow:function(e){var i=this;i.$el.append(i.rowTemplate(e)),i.initRow(e)},initRow:function(i){var s=this.$el.find('tr[data-id="'+i.term_id+'"]');s.find("select").each(function(){var s=e(this).data("attribute");e(this).find('option[value="'+i[s]+'"]').prop("selected",!0)}),s.find(".view").show(),s.find(".edit").hide(),s.find(".wc-shipping-class-edit").on("click",{view:this},this.onEditRow),s.find(".wc-shipping-class-delete").on("click",{view:this},this.onDeleteRow),s.find(".editing .wc-shipping-class-edit").trigger("click"),s.find(".wc-shipping-class-cancel-edit").on("click",{view:this},this.onCancelEditRow),!0===i.editing&&(s.addClass("editing"),s.find(".wc-shipping-class-edit").trigger("click"))},onSubmit:function(e){e.data.view.block(),e.data.view.model.save(),e.preventDefault()},onAddNewRow:function(s){s.preventDefault();var n=s.data.view,t=n.model,a=_.indexBy(t.get("classes"),"term_id"),o={},d=_.size(a),c=_.extend({},i.default_class,{term_id:"new-"+d+"-"+Date.now(),editing:!0,newRow:!0});o[c.term_id]=c,t.logChanges(o),n.renderRow(c),e(".wc-shipping-classes-blank-state").remove()},onEditRow:function(i){i.preventDefault(),e(this).closest("tr").addClass("editing"),e(this).closest("tr").find(".view").hide(),e(this).closest("tr").find(".edit").show(),i.data.view.model.trigger("change:classes")},onDeleteRow:function(i){var s=i.data.view,n=s.model,t=_.indexBy(n.get("classes"),"term_id"),a={},o=e(this).closest("tr").data("id");i.preventDefault(),t[o]&&(delete t[o],a[o]=_.extend(a[o]||{},{deleted:"deleted"}),n.set("classes",t),n.logChanges(a)),s.render()},onCancelEditRow:function(i){var s=i.data.view,n=s.model,t=e(this).closest("tr"),a=e(this).closest("tr").data("id"),o=_.indexBy(n.get("classes"),"term_id");i.preventDefault(),n.discardChanges(a),o[a]&&(o[a].editing=!1,t.after(s.rowTemplate(o[a])),s.initRow(o[a])),t.remove()},setUnloadConfirmation:function(){this.needsUnloadConfirm=!0,a.removeAttr("disabled")},clearUnloadConfirmation:function(){this.needsUnloadConfirm=!1,a.attr("disabled","disabled")},unloadConfirmation:function(e){if(e.data.view.needsUnloadConfirm)return e.returnValue=i.strings.unload_confirmation_msg,window.event.returnValue=i.strings.unload_confirmation_msg,i.strings.unload_confirmation_msg},updateModelOnChange:function(i){var s=i.data.view.model,n=e(i.target),t=n.closest("tr").data("id"),a=n.data("attribute"),o=n.val(),d=_.indexBy(s.get("classes"),"term_id"),c={};d[t]&&d[t][a]===o||(c[t]={},c[t][a]=o),s.logChanges(c)}}),r=new c({classes:i.classes}),h=new l({model:r,el:t});h.render()})}(jQuery,shippingClassesLocalizeScript,wp,ajaxurl);
!function(e,i,s,n){e(function(){var t=e(".wc-shipping-class-rows"),a=e(".wc-shipping-class-save"),o=s.template("wc-shipping-class-row"),d=s.template("wc-shipping-class-row-blank"),c=Backbone.Model.extend({changes:{},logChanges:function(e){var i=this.changes||{};_.each(e,function(e,s){i[s]=_.extend(i[s]||{term_id:s},e)}),this.changes=i,this.trigger("change:classes")},save:function(){_.size(this.changes)?e.post(n+(n.indexOf("?")>0?"&":"?")+"action=woocommerce_shipping_classes_save_changes",{wc_shipping_classes_nonce:i.wc_shipping_classes_nonce,changes:this.changes},this.onSaveResponse,"json"):r.trigger("saved:classes")},discardChanges:function(e){delete(this.changes||{})[e],0===_.size(this.changes)&&h.clearUnloadConfirmation()},onSaveResponse:function(e,s){"success"===s&&(e.success?(r.set("classes",e.data.shipping_classes),r.trigger("change:classes"),r.changes={},r.trigger("saved:classes")):e.data?window.alert(e.data):window.alert(i.strings.save_failed)),h.unblock()}}),l=Backbone.View.extend({rowTemplate:o,initialize:function(){this.listenTo(this.model,"change:classes",this.setUnloadConfirmation),this.listenTo(this.model,"saved:classes",this.clearUnloadConfirmation),this.listenTo(this.model,"saved:classes",this.render),t.on("change",{view:this},this.updateModelOnChange),e(window).on("beforeunload",{view:this},this.unloadConfirmation),a.on("click",{view:this},this.onSubmit),e(document.body).on("click",".wc-shipping-class-add",{view:this},this.onAddNewRow),e(document.body).on("click",".wc-shipping-class-save-changes",{view:this},this.onSubmit)},block:function(){e(this.el).block({message:null,overlayCSS:{background:"#fff",opacity:.6}})},unblock:function(){e(this.el).unblock()},render:function(){var i=_.indexBy(this.model.get("classes"),"term_id"),s=this;this.$el.empty(),this.unblock(),_.size(i)?(i=_.sortBy(i,function(e){return e.name}),e.each(i,function(e,i){s.renderRow(i)})):s.$el.append(d)},renderRow:function(e){var i=this;i.$el.append(i.rowTemplate(e)),i.initRow(e)},initRow:function(i){var s=this.$el.find('tr[data-id="'+i.term_id+'"]');s.find("select").each(function(){var s=e(this).data("attribute");e(this).find('option[value="'+i[s]+'"]').prop("selected",!0)}),s.find(".view").show(),s.find(".edit").hide(),s.find(".wc-shipping-class-edit").on("click",{view:this},this.onEditRow),s.find(".wc-shipping-class-delete").on("click",{view:this},this.onDeleteRow),s.find(".editing .wc-shipping-class-edit").trigger("click"),s.find(".wc-shipping-class-cancel-edit").on("click",{view:this},this.onCancelEditRow),!0===i.editing&&(s.addClass("editing"),s.find(".wc-shipping-class-edit").trigger("click"))},onSubmit:function(e){e.data.view.block(),e.data.view.model.save(),e.preventDefault()},onAddNewRow:function(s){s.preventDefault();var n=s.data.view,t=n.model,a=_.indexBy(t.get("classes"),"term_id"),o={},d=_.size(a),c=_.extend({},i.default_shipping_class,{term_id:"new-"+d+"-"+Date.now(),editing:!0,newRow:!0});o[c.term_id]=c,t.logChanges(o),n.renderRow(c),e(".wc-shipping-classes-blank-state").remove()},onEditRow:function(i){i.preventDefault(),e(this).closest("tr").addClass("editing"),e(this).closest("tr").find(".view").hide(),e(this).closest("tr").find(".edit").show(),i.data.view.model.trigger("change:classes")},onDeleteRow:function(i){var s=i.data.view,n=s.model,t=_.indexBy(n.get("classes"),"term_id"),a={},o=e(this).closest("tr").data("id");i.preventDefault(),t[o]&&(delete t[o],a[o]=_.extend(a[o]||{},{deleted:"deleted"}),n.set("classes",t),n.logChanges(a)),s.render()},onCancelEditRow:function(i){var s=i.data.view,n=s.model,t=e(this).closest("tr"),a=e(this).closest("tr").data("id"),o=_.indexBy(n.get("classes"),"term_id");i.preventDefault(),n.discardChanges(a),o[a]&&(o[a].editing=!1,t.after(s.rowTemplate(o[a])),s.initRow(o[a])),t.remove()},setUnloadConfirmation:function(){this.needsUnloadConfirm=!0,a.removeAttr("disabled")},clearUnloadConfirmation:function(){this.needsUnloadConfirm=!1,a.attr("disabled","disabled")},unloadConfirmation:function(e){if(e.data.view.needsUnloadConfirm)return e.returnValue=i.strings.unload_confirmation_msg,window.event.returnValue=i.strings.unload_confirmation_msg,i.strings.unload_confirmation_msg},updateModelOnChange:function(i){var s=i.data.view.model,n=e(i.target),t=n.closest("tr").data("id"),a=n.data("attribute"),o=n.val(),d=_.indexBy(s.get("classes"),"term_id"),c={};d[t]&&d[t][a]===o||(c[t]={},c[t][a]=o),s.logChanges(c)}}),r=new c({classes:i.classes}),h=new l({model:r,el:t});h.render()})}(jQuery,shippingClassesLocalizeScript,wp,ajaxurl);

View File

@ -134,18 +134,27 @@ jQuery( function ( $ ) {
})
.on( 'init_tooltips', function() {
var tiptip_args = {
$( '.tips, .help_tip, .woocommerce-help-tip' ).tipTip( {
'attribute': 'data-tip',
'fadeIn': 50,
'fadeOut': 50,
'delay': 200
};
} );
$( '.tips, .help_tip, .woocommerce-help-tip' ).tipTip( tiptip_args );
$( '.column-wc_actions .wc-action-button' ).tipTip( {
'fadeIn': 50,
'fadeOut': 50,
'delay': 200
} );
// Add tiptip to parent element for widefat tables
$( '.parent-tips' ).each( function() {
$( this ).closest( 'a, th' ).attr( 'data-tip', $( this ).data( 'tip' ) ).tipTip( tiptip_args ).css( 'cursor', 'help' );
$( this ).closest( 'a, th' ).attr( 'data-tip', $( this ).data( 'tip' ) ).tipTip( {
'attribute': 'data-tip',
'fadeIn': 50,
'fadeOut': 50,
'delay': 200
} ).css( 'cursor', 'help' );
});
});

File diff suppressed because one or more lines are too long

View File

@ -181,8 +181,6 @@ jQuery( function( $ ) {
/**
* Handles when a shipping method is selected.
*
* @param {Object} evt The JQuery event.
*/
shipping_method_selected: function() {
var shipping_methods = {};

File diff suppressed because one or more lines are too long

View File

@ -1475,8 +1475,14 @@ S2.define('select2/selection/base',[
}
var $element = $this.data('element');
$element.select2('close');
// Remove any focus when dropdown is closed by clicking outside the select area.
// Timeout of 1 required for close to finish wrapping up.
setTimeout(function(){
$this.find('*:focus').blur();
$target.focus();
}, 1);
});
});
};
@ -1675,6 +1681,11 @@ S2.define('select2/selection/multiple',[
container.open();
}
});
// Focus on the search field when the container is focused instead of the main container.
container.on( 'focus', function(){
self.focusOnSearch();
});
};
MultipleSelection.prototype.clear = function () {
@ -1700,8 +1711,25 @@ S2.define('select2/selection/multiple',[
return $container;
};
MultipleSelection.prototype.update = function (data) {
/**
* Focus on the search field instead of the main multiselect container.
*/
MultipleSelection.prototype.focusOnSearch = function() {
var self = this;
if ('undefined' !== typeof self.$search) {
// Needs 1 ms delay because of other 1 ms setTimeouts when rendering.
setTimeout(function(){
// Prevent the dropdown opening again when focused from this.
// This gets reset automatically when focus is triggered.
self._keyUpPrevented = true;
self.$search.focus();
}, 1);
}
}
MultipleSelection.prototype.update = function (data) {
this.clear();
if (data.length === 0) {
@ -1727,14 +1755,6 @@ S2.define('select2/selection/multiple',[
var $rendered = this.$selection.find('.select2-selection__rendered');
Utils.appendMany($rendered, $selections);
// Return cursor to search field after updating.
// Needs 1 ms delay because of other 1 ms setTimeouts when rendering.
if ('undefined' !== typeof this.$search) {
setTimeout(function(){
self.$search.focus();
}, 1);
}
};
return MultipleSelection;
@ -1980,6 +2000,9 @@ S2.define('select2/selection/search',[
evt.preventDefault();
}
} else if (evt.which === KEYS.ENTER) {
container.open();
evt.preventDefault();
}
});
@ -5480,18 +5503,9 @@ S2.define('select2/core',[
self.focusOnActiveElement();
}, 1000);
}
// If focus is in the search field, select the current active element on Enter key.
$searchField.on('keydown', function (evt) {
if (evt.which === KEYS.ENTER) {
self.trigger('results:select', {});
evt.preventDefault();
}
});
} else if (self.hasFocus()) {
if (key === KEYS.ENTER || key === KEYS.SPACE ||
(key === KEYS.DOWN && evt.altKey)) {
key === KEYS.DOWN) {
self.open();
evt.preventDefault();
}
@ -5501,7 +5515,7 @@ S2.define('select2/core',[
Select2.prototype.focusOnActiveElement = function () {
// Don't mess with the focus on touchscreens because it causes havoc with on-screen keyboards.
if (! Utils.isTouchscreen()) {
if (this.isOpen() && ! Utils.isTouchscreen()) {
this.$results.find('li.select2-results__option--highlighted').focus();
}
};

File diff suppressed because one or more lines are too long

View File

@ -1475,8 +1475,14 @@ S2.define('select2/selection/base',[
}
var $element = $this.data('element');
$element.select2('close');
// Remove any focus when dropdown is closed by clicking outside the select area.
// Timeout of 1 required for close to finish wrapping up.
setTimeout(function(){
$this.find('*:focus').blur();
$target.focus();
}, 1);
});
});
};
@ -1675,6 +1681,11 @@ S2.define('select2/selection/multiple',[
container.open();
}
});
// Focus on the search field when the container is focused instead of the main container.
container.on( 'focus', function(){
self.focusOnSearch();
});
};
MultipleSelection.prototype.clear = function () {
@ -1700,8 +1711,25 @@ S2.define('select2/selection/multiple',[
return $container;
};
MultipleSelection.prototype.update = function (data) {
/**
* Focus on the search field instead of the main multiselect container.
*/
MultipleSelection.prototype.focusOnSearch = function() {
var self = this;
if ('undefined' !== typeof self.$search) {
// Needs 1 ms delay because of other 1 ms setTimeouts when rendering.
setTimeout(function(){
// Prevent the dropdown opening again when focused from this.
// This gets reset automatically when focus is triggered.
self._keyUpPrevented = true;
self.$search.focus();
}, 1);
}
}
MultipleSelection.prototype.update = function (data) {
this.clear();
if (data.length === 0) {
@ -1727,14 +1755,6 @@ S2.define('select2/selection/multiple',[
var $rendered = this.$selection.find('.select2-selection__rendered');
Utils.appendMany($rendered, $selections);
// Return cursor to search field after updating.
// Needs 1 ms delay because of other 1 ms setTimeouts when rendering.
if ('undefined' !== typeof this.$search) {
setTimeout(function(){
self.$search.focus();
}, 1);
}
};
return MultipleSelection;
@ -1980,6 +2000,9 @@ S2.define('select2/selection/search',[
evt.preventDefault();
}
} else if (evt.which === KEYS.ENTER) {
container.open();
evt.preventDefault();
}
});
@ -5480,18 +5503,9 @@ S2.define('select2/core',[
self.focusOnActiveElement();
}, 1000);
}
// If focus is in the search field, select the current active element on Enter key.
$searchField.on('keydown', function (evt) {
if (evt.which === KEYS.ENTER) {
self.trigger('results:select', {});
evt.preventDefault();
}
});
} else if (self.hasFocus()) {
if (key === KEYS.ENTER || key === KEYS.SPACE ||
(key === KEYS.DOWN && evt.altKey)) {
key === KEYS.DOWN) {
self.open();
evt.preventDefault();
}
@ -5501,7 +5515,7 @@ S2.define('select2/core',[
Select2.prototype.focusOnActiveElement = function () {
// Don't mess with the focus on touchscreens because it causes havoc with on-screen keyboards.
if (! Utils.isTouchscreen()) {
if (this.isOpen() && ! Utils.isTouchscreen()) {
this.$results.find('li.select2-results__option--highlighted').focus();
}
};

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load Diff

View File

@ -945,8 +945,14 @@ class WC_Product extends WC_Abstract_Legacy_Product {
*
* @param string $status New status.
*/
public function set_stock_status( $status = '' ) {
$this->set_prop( 'stock_status', 'outofstock' === $status ? 'outofstock' : 'instock' );
public function set_stock_status( $status = 'instock' ) {
$valid_statuses = wc_get_product_stock_status_options();
if ( isset( $valid_statuses[ $status ] ) ) {
$this->set_prop( 'stock_status', $status );
} else {
$this->set_prop( 'stock_status', 'instock' );
}
}
/**
@ -1300,11 +1306,15 @@ class WC_Product extends WC_Abstract_Legacy_Product {
$this->set_backorders( 'no' );
// If we are stock managing and we don't have stock, force out of stock status.
} elseif ( $this->get_stock_quantity() <= get_option( 'woocommerce_notify_no_stock_amount' ) && 'no' === $this->get_backorders() ) {
} elseif ( $this->get_stock_quantity() <= get_option( 'woocommerce_notify_no_stock_amount', 0 ) && 'no' === $this->get_backorders() ) {
$this->set_stock_status( 'outofstock' );
// If we are stock managing, backorders are allowed, and we don't have stock, force on backorder status.
} elseif ( $this->get_stock_quantity() <= get_option( 'woocommerce_notify_no_stock_amount', 0 ) && 'no' !== $this->get_backorders() ) {
$this->set_stock_status( 'onbackorder' );
// If the stock level is changing and we do now have enough, force in stock status.
} elseif ( $this->get_stock_quantity() > get_option( 'woocommerce_notify_no_stock_amount' ) && array_key_exists( 'stock_quantity', $this->get_changes() ) ) {
} elseif ( $this->get_stock_quantity() > get_option( 'woocommerce_notify_no_stock_amount', 0 ) && array_key_exists( 'stock_quantity', $this->get_changes() ) ) {
$this->set_stock_status( 'instock' );
}
}
@ -1488,12 +1498,13 @@ class WC_Product extends WC_Abstract_Legacy_Product {
}
/**
* Returns whether or not the product is in stock.
* Returns whether or not the product can be purchased.
* This returns true for 'instock' and 'onbackorder' stock statuses.
*
* @return bool
*/
public function is_in_stock() {
return apply_filters( 'woocommerce_product_is_in_stock', 'instock' === $this->get_stock_status(), $this );
return apply_filters( 'woocommerce_product_is_in_stock', 'outofstock' !== $this->get_stock_status(), $this );
}
/**
@ -1560,6 +1571,10 @@ class WC_Product extends WC_Abstract_Legacy_Product {
* @return bool
*/
public function is_on_backorder( $qty_in_cart = 0 ) {
if ( 'onbackorder' === $this->get_stock_status() ) {
return true;
}
return $this->managing_stock() && $this->backorders_allowed() && ( $this->get_stock_quantity() - $qty_in_cart ) < 0 ? true : false;
}

View File

@ -111,7 +111,7 @@ class WC_Admin_Assets {
wp_register_script( 'wc-shipping-classes', WC()->plugin_url() . '/assets/js/admin/wc-shipping-classes' . $suffix . '.js', array( 'jquery', 'wp-util', 'underscore', 'backbone' ), WC_VERSION );
wp_register_script( 'wc-clipboard', WC()->plugin_url() . '/assets/js/admin/wc-clipboard' . $suffix . '.js', array( 'jquery' ), WC_VERSION );
wp_register_script( 'select2', WC()->plugin_url() . '/assets/js/select2/select2.full' . $suffix . '.js', array( 'jquery' ), '4.0.3' );
wp_register_script( 'selectWoo', WC()->plugin_url() . '/assets/js/selectWoo/selectWoo.full' . $suffix . '.js', array( 'jquery' ), '1.0.1' );
wp_register_script( 'selectWoo', WC()->plugin_url() . '/assets/js/selectWoo/selectWoo.full' . $suffix . '.js', array( 'jquery' ), '1.0.2' );
wp_register_script( 'wc-enhanced-select', WC()->plugin_url() . '/assets/js/admin/wc-enhanced-select' . $suffix . '.js', array( 'jquery', 'selectWoo' ), WC_VERSION );
wp_localize_script( 'wc-enhanced-select', 'wc_enhanced_select_params', array(
'i18n_no_matches' => _x( 'No matches found', 'enhanced select', 'woocommerce' ),

View File

@ -90,12 +90,15 @@ class WC_Admin_Post_Types {
switch ( $screen_id ) {
case 'edit-shop_order' :
include_once( 'list-tables/class-wc-admin-list-table-orders.php' );
new WC_Admin_List_Table_Orders();
break;
case 'edit-shop_coupon' :
include_once( 'list-tables/class-wc-admin-list-table-coupons.php' );
new WC_Admin_List_Table_Coupons();
break;
case 'edit-product' :
include_once( 'list-tables/class-wc-admin-list-table-products.php' );
new WC_Admin_List_Table_Products();
break;
}
}

View File

@ -13,7 +13,6 @@ if ( ! defined( 'ABSPATH' ) ) {
}
if ( class_exists( 'WC_Admin_List_Table_Coupons', false ) ) {
new WC_Admin_List_Table_Coupons();
return;
}
@ -233,5 +232,3 @@ class WC_Admin_List_Table_Coupons extends WC_Admin_List_Table {
return $query_vars;
}
}
new WC_Admin_List_Table_Coupons();

View File

@ -13,7 +13,6 @@ if ( ! defined( 'ABSPATH' ) ) {
}
if ( class_exists( 'WC_Admin_List_Table_Orders', false ) ) {
new WC_Admin_List_Table_Orders();
return;
}
@ -84,6 +83,7 @@ class WC_Admin_List_Table_Orders extends WC_Admin_List_Table {
return array(
'shipping_address',
'billing_address',
'wc_actions',
);
}
@ -114,15 +114,12 @@ class WC_Admin_List_Table_Orders extends WC_Admin_List_Table {
$show_columns = array();
$show_columns['cb'] = $columns['cb'];
$show_columns['order_number'] = __( 'Order', 'woocommerce' );
$show_columns['billing_address'] = __( 'Billing', 'woocommerce' );
$show_columns['shipping_address'] = __( 'Ship to', 'woocommerce' );
$show_columns['order_date'] = __( 'Date', 'woocommerce' );
$show_columns['order_status'] = __( 'Status', 'woocommerce' );
$show_columns['billing_address'] = __( 'Billing', 'woocommerce' );
$show_columns['shipping_address'] = __( 'Ship to', 'woocommerce' );
$show_columns['order_total'] = __( 'Total', 'woocommerce' );
if ( has_action( 'woocommerce_admin_order_actions_start' ) || has_action( 'woocommerce_admin_order_actions_end' ) || has_filter( 'woocommerce_admin_order_actions' ) ) {
$show_columns['order_actions'] = __( 'Actions', 'woocommerce' );
}
$show_columns['wc_actions'] = __( 'Actions', 'woocommerce' );
wp_enqueue_script( 'wc-orders' );
@ -140,9 +137,9 @@ class WC_Admin_List_Table_Orders extends WC_Admin_List_Table {
unset( $actions['edit'] );
}
$actions['mark_processing'] = __( 'Mark processing', 'woocommerce' );
$actions['mark_on-hold'] = __( 'Mark on-hold', 'woocommerce' );
$actions['mark_completed'] = __( 'Mark complete', 'woocommerce' );
$actions['mark_processing'] = __( 'Change status to processing', 'woocommerce' );
$actions['mark_on-hold'] = __( 'Change status to on-hold', 'woocommerce' );
$actions['mark_completed'] = __( 'Change status to completed', 'woocommerce' );
return $actions;
}
@ -227,7 +224,7 @@ class WC_Admin_List_Table_Orders extends WC_Admin_List_Table {
if ( $order_timestamp > strtotime( '-1 day', current_time( 'timestamp', true ) ) ) {
$show_date = sprintf( _x( '%s ago', '%s = human-readable time difference', 'woocommerce' ), human_time_diff( $this->object->get_date_created()->getTimestamp(), current_time( 'timestamp', true ) ) );
} else {
$show_date = $this->object->get_date_created()->date_i18n( apply_filters( 'woocommerce_admin_order_date_format', get_option( 'date_format' ) ) );
$show_date = $this->object->get_date_created()->date_i18n( apply_filters( 'woocommerce_admin_order_date_format', __( 'M j, Y', 'woocommerce' ) ) );
}
printf(
'<time datetime="%1$s" title="%2$s">%3$s</time>',
@ -250,9 +247,9 @@ class WC_Admin_List_Table_Orders extends WC_Admin_List_Table {
}
/**
* Render columm: order_actions.
* Render columm: wc_actions.
*/
protected function render_order_actions_column() {
protected function render_wc_actions_column() {
echo '<p>';
do_action( 'woocommerce_admin_order_actions_start', $this->object );
@ -261,25 +258,23 @@ class WC_Admin_List_Table_Orders extends WC_Admin_List_Table {
if ( $this->object->has_status( array( 'pending', 'on-hold' ) ) ) {
$actions['processing'] = array(
'url' => wp_nonce_url( admin_url( 'admin-ajax.php?action=woocommerce_mark_order_status&status=processing&order_id=' . $this->object->get_id() ), 'woocommerce-mark-order-status' ),
'name' => __( 'Processing', 'woocommerce' ),
'action' => 'processing',
'url' => wp_nonce_url( admin_url( 'admin-ajax.php?action = woocommerce_mark_order_status&status = processing&order_id = ' . $this->object->get_id() ), 'woocommerce-mark-order-status' ),
'name' => __( 'Processing', 'woocommerce' ),
'action' => 'processing',
);
}
if ( $this->object->has_status( array( 'pending', 'on-hold', 'processing' ) ) ) {
$actions['complete'] = array(
'url' => wp_nonce_url( admin_url( 'admin-ajax.php?action=woocommerce_mark_order_status&status=completed&order_id=' . $this->object->get_id() ), 'woocommerce-mark-order-status' ),
'name' => __( 'Complete', 'woocommerce' ),
'action' => 'complete',
'url' => wp_nonce_url( admin_url( 'admin-ajax.php?action = woocommerce_mark_order_status&status = completed&order_id = ' . $this->object->get_id() ), 'woocommerce-mark-order-status' ),
'name' => __( 'Complete', 'woocommerce' ),
'action' => 'complete',
);
}
$actions = apply_filters( 'woocommerce_admin_order_actions', $actions, $this->object );
foreach ( $actions as $action ) {
printf( '<a class="button tips %s" href="%s" data-tip="%s">%s</a>', esc_attr( $action['action'] ), esc_url( $action['url'] ), esc_attr( $action['name'] ), esc_attr( $action['name'] ) );
}
echo wc_render_action_buttons( $actions ); // WPCS: XSS ok.
do_action( 'woocommerce_admin_order_actions_end', $this->object );
@ -292,6 +287,11 @@ class WC_Admin_List_Table_Orders extends WC_Admin_List_Table {
protected function render_billing_address_column() {
if ( $address = $this->object->get_formatted_billing_address() ) {
echo esc_html( preg_replace( '#<br\s*/?>#i', ', ', $address ) );
if ( $this->object->get_payment_method() ) {
/* translators: %s: payment method */
echo '<span class="description">' . sprintf( __( 'via %s', 'woocommerce' ), esc_html( $this->object->get_payment_method_title() ) ) . '</span>';
}
} else {
echo '&ndash;';
}
@ -303,6 +303,10 @@ class WC_Admin_List_Table_Orders extends WC_Admin_List_Table {
protected function render_shipping_address_column() {
if ( $address = $this->object->get_formatted_shipping_address() ) {
echo '<a target="_blank" href="' . esc_url( $this->object->get_shipping_address_map_url() ) . '">' . esc_html( preg_replace( '#<br\s*/?>#i', ', ', $address ) ) . '</a>';
if ( $this->object->get_shipping_method() ) {
/* translators: %s: shipping method */
echo '<span class="description">' . sprintf( __( 'via %s', 'woocommerce' ), esc_html( $this->object->get_shipping_method() ) ) . '</span>';
}
} else {
echo '&ndash;';
}
@ -320,6 +324,7 @@ class WC_Admin_List_Table_Orders extends WC_Admin_List_Table {
<div class="wc-backbone-modal-content">
<section class="wc-backbone-modal-main" role="main">
<header class="wc-backbone-modal-header">
<mark class="order-status status-{{ data.status }}"><span>{{ data.status_name }}</span></mark>
<h1><?php echo esc_html( sprintf( __( 'Order #%s', 'woocommerce' ), '{{ data.order_number }}' ) ); ?></h1>
<button class="modal-close modal-close-link dashicons dashicons-no-alt">
<span class="screen-reader-text"><?php esc_html_e( 'Close modal panel', 'woocommerce' ); ?></span>
@ -328,8 +333,6 @@ class WC_Admin_List_Table_Orders extends WC_Admin_List_Table {
<article>
<?php do_action( 'woocommerce_admin_order_preview_start' ); ?>
{{{ data.item_html }}}
<div class="wc-order-preview-addresses">
<div class="wc-order-preview-address">
<h2><?php esc_html_e( 'Billing details', 'woocommerce' ); ?></h2>
@ -347,7 +350,7 @@ class WC_Admin_List_Table_Orders extends WC_Admin_List_Table {
<# if ( data.payment_via ) { #>
<strong><?php esc_html_e( 'Payment via', 'woocommerce' ); ?></strong>
{{ data.payment_via }}
{{{ data.payment_via }}}
<# } #>
</div>
<# if ( data.needs_shipping ) { #>
@ -371,10 +374,15 @@ class WC_Admin_List_Table_Orders extends WC_Admin_List_Table {
</div>
<# } #>
</div>
{{{ data.item_html }}}
<?php do_action( 'woocommerce_admin_order_preview_end' ); ?>
</article>
<footer>
<div class="inner">
{{{ data.actions_html }}}
<a class="button button-primary button-large" href="<?php echo esc_url( admin_url( 'post.php?action=edit' ) ); ?>&post={{ data.data.id }}"><?php esc_html_e( 'Edit order', 'woocommerce' ); ?></a>
</div>
</footer>
@ -386,6 +394,191 @@ class WC_Admin_List_Table_Orders extends WC_Admin_List_Table {
<?php
}
/**
* Get items to display in the preview as HTML.
*
* @param WC_Order $order Order object.
* @return string
*/
public static function get_order_preview_item_html( $order ) {
$hidden_order_itemmeta = apply_filters( 'woocommerce_hidden_order_itemmeta', array(
'_qty',
'_tax_class',
'_product_id',
'_variation_id',
'_line_subtotal',
'_line_subtotal_tax',
'_line_total',
'_line_tax',
'method_id',
'cost',
) );
$line_items = apply_filters( 'woocommerce_admin_order_preview_line_items', $order->get_items(), $order );
$columns = apply_filters( 'woocommerce_admin_order_preview_line_item_columns', array(
'product' => __( 'Product', 'woocommerce' ),
'quantity' => __( 'Quantity', 'woocommerce' ),
'tax' => __( 'Tax', 'woocommerce' ),
'total' => __( 'Total', 'woocommerce' ),
), $order );
if ( ! wc_tax_enabled() ) {
unset( $columns['tax'] );
}
$html = '
<div class="wc-order-preview-table-wrapper">
<table cellspacing="0" class="wc-order-preview-table">
<thead>
<tr>';
foreach ( $columns as $column => $label ) {
$html .= '<th class="wc-order-preview-table__column--' . esc_attr( $column ) . '">' . esc_html( $label ) . '</th>';
}
$html .= '
</tr>
</thead>
<tbody>';
foreach ( $line_items as $item_id => $item ) {
$product_object = is_callable( array( $item, 'get_product' ) ) ? $item->get_product() : null;
$html .= '<tr class="wc-order-preview-table__item wc-order-preview-table__item--' . esc_attr( $item_id ) . '">';
foreach ( $columns as $column => $label ) {
$html .= '<td class="wc-order-preview-table__column--' . esc_attr( $column ) . '">';
switch ( $column ) {
case 'product':
$html .= wp_kses_post( $item->get_name() );
if ( $product_object ) {
$html .= '<div class="wc-order-item-sku">' . esc_html( $product_object->get_sku() ) . '</div>';
}
if ( $meta_data = $item->get_formatted_meta_data( '' ) ) {
$html .= '<table cellspacing="0" class="wc-order-item-meta">';
foreach ( $meta_data as $meta_id => $meta ) {
if ( in_array( $meta->key, $hidden_order_itemmeta ) ) {
continue;
}
$html .= '<tr><th>' . wp_kses_post( $meta->display_key ) . ':</th><td>' . wp_kses_post( force_balance_tags( $meta->display_value ) ) . '</td></tr>';
}
$html .= '</table>';
}
break;
case 'quantity':
$html .= esc_html( $item->get_quantity() );
break;
case 'tax':
$html .= wc_price( $item->get_total_tax(), array( 'currency' => $order->get_currency() ) );
break;
case 'total':
$html .= wc_price( $item->get_total(), array( 'currency' => $order->get_currency() ) );
break;
default :
$html .= apply_filters( 'woocommerce_admin_order_preview_line_item_column_' . sanitize_key( $column ), '', $item, $item_id, $order );
break;
}
$html .= '</td>';
}
$html .= '</tr>';
}
$html .= '
</tbody>
</table>
</div>';
return $html;
}
/**
* Get actions to display in the preview as HTML.
*
* @param WC_Order $order Order object.
* @return string
*/
public static function get_order_preview_actions_html( $order ) {
$actions = array();
$status_actions = array();
if ( $order->has_status( array( 'pending' ) ) ) {
$status_actions['on-hold'] = array(
'url' => wp_nonce_url( admin_url( 'admin-ajax.php?action=woocommerce_mark_order_status&status=on-hold&order_id=' . $order->get_id() ), 'woocommerce-mark-order-status' ),
'name' => __( 'On-hold', 'woocommerce' ),
'action' => 'on-hold',
);
}
if ( $order->has_status( array( 'pending', 'on-hold' ) ) ) {
$status_actions['processing'] = array(
'url' => wp_nonce_url( admin_url( 'admin-ajax.php?action=woocommerce_mark_order_status&status=processing&order_id=' . $order->get_id() ), 'woocommerce-mark-order-status' ),
'name' => __( 'Processing', 'woocommerce' ),
'action' => 'processing',
);
}
if ( $order->has_status( array( 'pending', 'on-hold', 'processing' ) ) ) {
$status_actions['complete'] = array(
'url' => wp_nonce_url( admin_url( 'admin-ajax.php?action=woocommerce_mark_order_status&status=completed&order_id=' . $order->get_id() ), 'woocommerce-mark-order-status' ),
'name' => __( 'Completed', 'woocommerce' ),
'action' => 'complete',
);
}
if ( $status_actions ) {
$actions['status'] = array(
'group' => __( 'Change status: ', 'woocommerce' ),
'actions' => $status_actions,
);
}
return wc_render_action_buttons( apply_filters( 'woocommerce_admin_order_preview_actions', $actions, $order ) );
}
/**
* Get order details to send to the ajax endpoint for previews.
*
* @param WC_Order $order Order object.
* @return array
*/
public static function order_preview_get_order_details( $order ) {
if ( ! $order ) {
return array();
}
$payment_via = $order->get_payment_method_title();
$payment_method = $order->get_payment_method();
$payment_gateways = WC()->payment_gateways() ? WC()->payment_gateways->payment_gateways() : array();
if ( $transaction_id = $order->get_transaction_id() ) {
if ( isset( $payment_gateways[ $payment_method ] ) && ( $url = $payment_gateways[ $payment_method ]->get_transaction_url( $order ) ) ) {
$payment_via .= ' (<a href="' . esc_url( $url ) . '" target="_blank">' . esc_html( $transaction_id ) . '</a>)';
} else {
$payment_via .= ' (' . esc_html( $transaction_id ) . ')';
}
}
return apply_filters( 'woocommerce_admin_order_preview_get_order_details', array(
'data' => $order->get_data(),
'order_number' => $order->get_order_number(),
'item_html' => WC_Admin_List_Table_Orders::get_order_preview_item_html( $order ),
'actions_html' => WC_Admin_List_Table_Orders::get_order_preview_actions_html( $order ),
'ship_to_billing' => wc_ship_to_billing_address_only(),
'needs_shipping' => $order->needs_shipping_address(),
'formatted_billing_address' => ( $address = $order->get_formatted_billing_address() ) ? $address : __( 'N/A', 'woocommerce' ),
'formatted_shipping_address' => ( $address = $order->get_formatted_shipping_address() ) ? $address: __( 'N/A', 'woocommerce' ),
'shipping_address_map_url' => $order->get_shipping_address_map_url(),
'payment_via' => $payment_via,
'shipping_via' => $order->get_shipping_method(),
'status' => $order->get_status(),
'status_name' => wc_get_order_status_name( $order->get_status() ),
), $order );
}
/**
* Handle bulk actions.
*
@ -610,5 +803,3 @@ class WC_Admin_List_Table_Orders extends WC_Admin_List_Table {
}
}
}
new WC_Admin_List_Table_Orders();

View File

@ -13,7 +13,6 @@ if ( ! defined( 'ABSPATH' ) ) {
}
if ( class_exists( 'WC_Admin_List_Table_Products', false ) ) {
new WC_Admin_List_Table_Products();
return;
}
@ -233,7 +232,7 @@ class WC_Admin_List_Table_Products extends WC_Admin_List_Table {
$termlist[] = '<a href="' . esc_url( admin_url( 'edit.php?product_cat=' . $term->slug . '&post_type=product' ) ) . ' ">' . esc_html( $term->name ) . '</a>';
}
echo implode( ', ', $termlist ); // WPCS: XSS ok.
echo apply_filters( 'woocommerce_admin_product_term_list', implode( ', ', $termlist ), 'product_cat', $this->object->get_id(), $termlist, $terms ); // WPCS: XSS ok.
}
}
@ -249,7 +248,7 @@ class WC_Admin_List_Table_Products extends WC_Admin_List_Table {
$termlist[] = '<a href="' . esc_url( admin_url( 'edit.php?product_tag=' . $term->slug . '&post_type=product' ) ) . ' ">' . esc_html( $term->name ) . '</a>';
}
echo implode( ', ', $termlist ); // WPCS: XSS ok.
echo apply_filters( 'woocommerce_admin_product_term_list', implode( ', ', $termlist ), 'product_tag', $this->object->get_id(), $termlist, $terms ); // WPCS: XSS ok.
}
}
@ -271,7 +270,9 @@ class WC_Admin_List_Table_Products extends WC_Admin_List_Table {
* Render columm: is_in_stock.
*/
protected function render_is_in_stock_column() {
if ( $this->object->is_in_stock() ) {
if ( $this->object->is_on_backorder() ) {
$stock_html = '<mark class="onbackorder">' . __( 'On backorder', 'woocommerce' ) . '</mark>';
} elseif ( $this->object->is_in_stock() ) {
$stock_html = '<mark class="instock">' . __( 'In stock', 'woocommerce' ) . '</mark>';
} else {
$stock_html = '<mark class="outofstock">' . __( 'Out of stock', 'woocommerce' ) . '</mark>';
@ -299,7 +300,6 @@ class WC_Admin_List_Table_Products extends WC_Admin_List_Table {
* Render any custom filters and search inputs for the list table.
*/
protected function render_filters() {
// Category Filtering.
$categories_count = (int) wp_count_terms( 'product_cat' );
if ( $categories_count <= apply_filters( 'woocommerce_product_category_filter_threshold', 100 ) ) {
@ -318,7 +318,6 @@ class WC_Admin_List_Table_Products extends WC_Admin_List_Table {
<?php
}
// Product type filtering.
$current_product_type = isset( $_REQUEST['product_type'] ) ? wc_clean( wp_unslash( $_REQUEST['product_type'] ) ) : false; // WPCS: input var ok, sanitization ok.
$terms = get_terms( 'product_type' );
$output = '<select name="product_type" id="dropdown_product_type"><option value="">' . __( 'Filter by product type', 'woocommerce' ) . '</option>';
@ -369,6 +368,16 @@ class WC_Admin_List_Table_Products extends WC_Admin_List_Table {
$output .= '</select>';
$current_stock_status = isset( $_REQUEST['stock_status'] ) ? wc_clean( wp_unslash( $_REQUEST['stock_status'] ) ): false; // WPCS: input var ok, sanitization ok.
$stock_statuses = wc_get_product_stock_status_options();
$output .= '<select name="stock_status"><option value="">' . esc_html__( 'Filter by stock status', 'woocommerce' ) . '</option>';
foreach ( $stock_statuses as $status => $label ) {
$output .= '<option ' . selected( $status, $current_stock_status, false ) . ' value="' . esc_attr( $status ) . '">' . esc_html( $label ) . '</option>';
}
$output .= '</select>';
echo apply_filters( 'woocommerce_product_filters', $output ); // WPCS: XSS ok.
}
@ -379,6 +388,7 @@ class WC_Admin_List_Table_Products extends WC_Admin_List_Table {
* @return array
*/
protected function query_filters( $query_vars ) {
if ( isset( $query_vars['orderby'] ) ) {
if ( 'price' === $vars['orderby'] ) {
// @codingStandardsIgnoreStart
@ -421,6 +431,17 @@ class WC_Admin_List_Table_Products extends WC_Admin_List_Table {
);
}
if ( ! empty( $_GET['stock_status'] ) ) {
if ( ! isset( $query_vars['meta_query'] ) ) {
$query_vars['meta_query'] = array();
}
$query_vars['meta_query'][] = array(
'key' => '_stock_status',
'value' => wc_clean( wp_unslash( $_GET['stock_status'] ) ),
);
}
return $query_vars;
}
@ -485,5 +506,3 @@ class WC_Admin_List_Table_Products extends WC_Admin_List_Table {
return $views;
}
}
new WC_Admin_List_Table_Products();

View File

@ -188,9 +188,9 @@ class WC_Meta_Box_Order_Data {
if ( $transaction_id = $order->get_transaction_id() ) {
if ( isset( $payment_gateways[ $payment_method ] ) && ( $url = $payment_gateways[ $payment_method ]->get_transaction_url( $order ) ) ) {
$payment_method_string = ' (<a href="' . esc_url( $url ) . '" target="_blank">' . esc_html( $transaction_id ) . '</a>)';
$payment_method_string .= ' (<a href="' . esc_url( $url ) . '" target="_blank">' . esc_html( $transaction_id ) . '</a>)';
} else {
$payment_method_string = ' (' . esc_html( $transaction_id ) . ')';
$payment_method_string .= ' (' . esc_html( $transaction_id ) . ')';
}
}

View File

@ -11,8 +11,9 @@ if ( ! defined( 'ABSPATH' ) ) {
$product = $item->get_product();
$product_link = $product ? admin_url( 'post.php?post=' . $item->get_product_id() . '&action=edit' ) : '';
$thumbnail = $product ? apply_filters( 'woocommerce_admin_order_item_thumbnail', $product->get_image( 'thumbnail', array( 'title' => '' ), false ), $item_id, $item ) : '';
$row_class = apply_filters( 'woocommerce_admin_html_order_item_class', ! empty( $class ) ? $class : '', $item, $order );
?>
<tr class="item <?php echo esc_attr( apply_filters( 'woocommerce_admin_html_order_item_class', ( ! empty( $class ) ? $class : '' ), $item, $order ) ); ?>" data-order_item_id="<?php echo esc_attr( $item_id ); ?>">
<tr class="item <?php echo esc_attr( $row_class ); ?>" data-order_item_id="<?php echo esc_attr( $item_id ); ?>">
<td class="thumb">
<?php echo '<div class="wc-order-item-thumbnail">' . wp_kses_post( $thumbnail ) . '</div>'; ?>
</td>

View File

@ -65,7 +65,7 @@ if ( ! defined( 'ABSPATH' ) ) {
woocommerce_wp_select( array(
'id' => '_stock_status',
'value' => $product_object->get_stock_status( 'edit' ),
'wrapper_class' => 'hide_if_variable hide_if_external',
'wrapper_class' => 'stock_status_field hide_if_variable hide_if_external',
'label' => __( 'Stock status', 'woocommerce' ),
'options' => wc_get_product_stock_status_options(),
'desc_tip' => true,

View File

@ -9,7 +9,7 @@ if ( ! defined( 'ABSPATH' ) ) {
<?php if ( ! count( $variation_attributes ) ) : ?>
<div id="message" class="inline notice woocommerce-message">
<p><?php esc_html_e( 'Before you can add a variation you need to add some variation attributes on the <strong>Attributes</strong> tab.', 'woocommerce' ); ?></p>
<p><?php echo wp_kses_post( __( 'Before you can add a variation you need to add some variation attributes on the <strong>Attributes</strong> tab.', 'woocommerce' ) ); ?></p>
<p><a class="button-primary" href="<?php echo esc_url( apply_filters( 'woocommerce_docs_url', 'https://docs.woocommerce.com/document/variable-product/', 'product-variations' ) ); ?>" target="_blank"><?php esc_html_e( 'Learn more', 'woocommerce' ); ?></a></p>
</div>
@ -62,10 +62,11 @@ if ( ! defined( 'ABSPATH' ) ) {
<option value="variable_sale_schedule"><?php esc_html_e( 'Set scheduled sale dates', 'woocommerce' ); ?></option>
</optgroup>
<optgroup label="<?php esc_attr_e( 'Inventory', 'woocommerce' ); ?>">
<option value="toggle_manage_stock"><?php esc_html_e( 'Toggle &quot;Manage stock&quot;', 'woocommerce' ); ?></option>
<option value="variable_stock"><?php esc_html_e( 'Stock', 'woocommerce' ); ?></option>
<option value="variable_stock_status_instock"><?php esc_html_e( 'Set Status - In stock', 'woocommerce' ); ?></option>
<option value="variable_stock_status_outofstock"><?php esc_html_e( 'Set Status - Out of stock', 'woocommerce' ); ?></option>
<option value="toggle_manage_stock"><?php _e( 'Toggle &quot;Manage stock&quot;', 'woocommerce' ); ?></option>
<option value="variable_stock"><?php _e( 'Stock', 'woocommerce' ); ?></option>
<option value="variable_stock_status_instock"><?php _e( 'Set Status - In stock', 'woocommerce' ); ?></option>
<option value="variable_stock_status_outofstock"><?php _e( 'Set Status - Out of stock', 'woocommerce' ); ?></option>
<option value="variable_stock_status_onbackorder"><?php _e( 'Set Status - On backorder', 'woocommerce' ); ?></option>
</optgroup>
<optgroup label="<?php esc_attr_e( 'Shipping', 'woocommerce' ); ?>">
<option value="variable_length"><?php esc_html_e( 'Length', 'woocommerce' ); ?></option>

View File

@ -138,7 +138,7 @@ class WC_Report_Customer_List extends WP_List_Table {
break;
case 'user_actions' :
case 'wc_actions' :
ob_start();
?><p>
<?php
@ -210,7 +210,7 @@ class WC_Report_Customer_List extends WP_List_Table {
'orders' => __( 'Orders', 'woocommerce' ),
'spent' => __( 'Money spent', 'woocommerce' ),
'last_order' => __( 'Last order', 'woocommerce' ),
'user_actions' => __( 'Actions', 'woocommerce' ),
'wc_actions' => __( 'Actions', 'woocommerce' ),
);
return $columns;

View File

@ -108,7 +108,9 @@ class WC_Report_Stock extends WP_List_Table {
break;
case 'stock_status' :
if ( $product->is_in_stock() ) {
if ( $product->is_on_backorder() ) {
$stock_html = '<mark class="onbackorder">' . __( 'On backorder', 'woocommerce' ) . '</mark>';
} elseif ( $product->is_in_stock() ) {
$stock_html = '<mark class="instock">' . __( 'In stock', 'woocommerce' ) . '</mark>';
} else {
$stock_html = '<mark class="outofstock">' . __( 'Out of stock', 'woocommerce' ) . '</mark>';

View File

@ -12,14 +12,14 @@ if ( ! defined( 'ABSPATH' ) ) {
<fieldset class="inline-edit-col-left">
<div id="woocommerce-fields" class="inline-edit-col">
<h4><?php _e( 'Product data', 'woocommerce' ); ?></h4>
<h4><?php esc_html_e( 'Product data', 'woocommerce' ); ?></h4>
<?php do_action( 'woocommerce_product_quick_edit_start' ); ?>
<?php if ( wc_product_sku_enabled() ) : ?>
<label>
<span class="title"><?php _e( 'SKU', 'woocommerce' ); ?></span>
<span class="title"><?php esc_html_e( 'SKU', 'woocommerce' ); ?></span>
<span class="input-text-wrap">
<input type="text" name="_sku" class="text sku" value="">
</span>
@ -30,14 +30,14 @@ if ( ! defined( 'ABSPATH' ) ) {
<div class="price_fields">
<label>
<span class="title"><?php _e( 'Price', 'woocommerce' ); ?></span>
<span class="title"><?php esc_html_e( 'Price', 'woocommerce' ); ?></span>
<span class="input-text-wrap">
<input type="text" name="_regular_price" class="text wc_input_price regular_price" placeholder="<?php esc_attr_e( 'Regular price', 'woocommerce' ); ?>" value="">
</span>
</label>
<br class="clear" />
<label>
<span class="title"><?php _e( 'Sale', 'woocommerce' ); ?></span>
<span class="title"><?php esc_html_e( 'Sale', 'woocommerce' ); ?></span>
<span class="input-text-wrap">
<input type="text" name="_sale_price" class="text wc_input_price sale_price" placeholder="<?php esc_attr_e( 'Sale price', 'woocommerce' ); ?>" value="">
</span>
@ -47,7 +47,7 @@ if ( ! defined( 'ABSPATH' ) ) {
<?php if ( wc_tax_enabled() ) : ?>
<label class="alignleft">
<span class="title"><?php _e( 'Tax status', 'woocommerce' ); ?></span>
<span class="title"><?php esc_html_e( 'Tax status', 'woocommerce' ); ?></span>
<span class="input-text-wrap">
<select class="tax_status" name="_tax_status">
<?php
@ -57,7 +57,7 @@ if ( ! defined( 'ABSPATH' ) ) {
'none' => _x( 'None', 'Tax status', 'woocommerce' ),
);
foreach ( $options as $key => $value ) {
echo '<option value="' . esc_attr( $key ) . '">' . $value . '</option>';
echo '<option value="' . esc_attr( $key ) . '">' . esc_html( $value ) . '</option>';
}
?>
</select>
@ -65,7 +65,7 @@ if ( ! defined( 'ABSPATH' ) ) {
</label>
<br class="clear" />
<label class="alignleft">
<span class="title"><?php _e( 'Tax class', 'woocommerce' ); ?></span>
<span class="title"><?php esc_html_e( 'Tax class', 'woocommerce' ); ?></span>
<span class="input-text-wrap">
<select class="tax_class" name="_tax_class">
<?php
@ -96,7 +96,7 @@ if ( ! defined( 'ABSPATH' ) ) {
<?php if ( wc_product_weight_enabled() ) : ?>
<label>
<span class="title"><?php _e( 'Weight', 'woocommerce' ); ?></span>
<span class="title"><?php esc_html_e( 'Weight', 'woocommerce' ); ?></span>
<span class="input-text-wrap">
<input type="text" name="_weight" class="text weight" placeholder="<?php echo wc_format_localized_decimal( 0 ); ?>" value="">
</span>
@ -107,7 +107,7 @@ if ( ! defined( 'ABSPATH' ) ) {
<?php if ( wc_product_dimensions_enabled() ) : ?>
<div class="inline-edit-group dimensions">
<div>
<span class="title"><?php _e( 'L/W/H', 'woocommerce' ); ?></span>
<span class="title"><?php esc_html_e( 'L/W/H', 'woocommerce' ); ?></span>
<span class="input-text-wrap">
<input type="text" name="_length" class="text wc_input_decimal length" placeholder="<?php esc_attr_e( 'Length', 'woocommerce' ); ?>" value="">
<input type="text" name="_width" class="text wc_input_decimal width" placeholder="<?php esc_attr_e( 'Width', 'woocommerce' ); ?>" value="">
@ -120,51 +120,61 @@ if ( ! defined( 'ABSPATH' ) ) {
</div>
<?php endif; ?>
<label class="alignleft">
<span class="title"><?php _e( 'Shipping class', 'woocommerce' ); ?></span>
<div class="inline-edit-group">
<span class="title"><?php esc_html_e( 'Shipping class', 'woocommerce' ); ?></span>
<span class="input-text-wrap">
<select class="shipping_class" name="_shipping_class">
<option value="_no_shipping_class"><?php _e( 'No shipping class', 'woocommerce' ); ?></option>
<option value="_no_shipping_class"><?php esc_html_e( 'No shipping class', 'woocommerce' ); ?></option>
<?php
foreach ( $shipping_class as $key => $value ) {
echo '<option value="' . esc_attr( $value->slug ) . '">' . $value->name . '</option>';
echo '<option value="' . esc_attr( $value->slug ) . '">' . esc_html( $value->name ) . '</option>';
}
?>
</select>
</span>
</label>
<br class="clear" />
</div>
<label class="alignleft">
<span class="title"><?php _e( 'Visibility', 'woocommerce' ); ?></span>
<span class="input-text-wrap">
<select class="visibility" name="_visibility">
<?php
$options = apply_filters( 'woocommerce_product_visibility_options', array(
'visible' => __( 'Catalog &amp; search', 'woocommerce' ),
'catalog' => __( 'Catalog', 'woocommerce' ),
'search' => __( 'Search', 'woocommerce' ),
'hidden' => __( 'Hidden', 'woocommerce' ),
) );
foreach ( $options as $key => $value ) {
echo '<option value="' . esc_attr( $key ) . '">' . $value . '</option>';
}
?>
</select>
</span>
</label>
<label class="alignleft featured">
<input type="checkbox" name="_featured" value="1">
<span class="checkbox-title"><?php _e( 'Featured', 'woocommerce' ); ?></span>
</label>
<br class="clear" />
<label class="alignleft">
<span class="title"><?php _e( 'In stock?', 'woocommerce' ); ?></span>
<div class="inline-edit-group">
<label class="alignleft">
<span class="title"><?php esc_html_e( 'Visibility', 'woocommerce' ); ?></span>
<span class="input-text-wrap">
<select class="visibility" name="_visibility">
<?php
$options = apply_filters( 'woocommerce_product_visibility_options', array(
'visible' => __( 'Catalog &amp; search', 'woocommerce' ),
'catalog' => __( 'Catalog', 'woocommerce' ),
'search' => __( 'Search', 'woocommerce' ),
'hidden' => __( 'Hidden', 'woocommerce' ),
) );
foreach ( $options as $key => $value ) {
echo '<option value="' . esc_attr( $key ) . '">' . esc_html( $value ) . '</option>';
}
?>
</select>
</span>
</label>
<label class="alignleft featured">
<input type="checkbox" name="_featured" value="1">
<span class="checkbox-title"><?php esc_html_e( 'Featured', 'woocommerce' ); ?></span>
</label>
</div>
<?php if ( get_option( 'woocommerce_manage_stock' ) == 'yes' ) : ?>
<div class="inline-edit-group">
<label class="manage_stock">
<input type="checkbox" name="_manage_stock" value="1">
<span class="checkbox-title"><?php esc_html_e( 'Manage stock?', 'woocommerce' ); ?></span>
</label>
</div>
<?php endif; ?>
<label class="stock_status_field">
<span class="title"><?php esc_html_e( 'In stock?', 'woocommerce' ); ?></span>
<span class="input-text-wrap">
<select class="stock_status" name="_stock_status">
<?php
foreach ( wc_get_product_stock_status_options() as $key => $value ) {
echo '<option value="' . esc_attr( $key ) . '">' . $value . '</option>';
echo '<option value="' . esc_attr( $key ) . '">' . esc_html( $value ) . '</option>';
}
?>
</select>
@ -172,30 +182,23 @@ if ( ! defined( 'ABSPATH' ) ) {
</label>
<div class="stock_fields">
<?php if ( get_option( 'woocommerce_manage_stock' ) == 'yes' ) : ?>
<label class="alignleft manage_stock">
<input type="checkbox" name="_manage_stock" value="1">
<span class="checkbox-title"><?php _e( 'Manage stock?', 'woocommerce' ); ?></span>
</label>
<br class="clear" />
<label class="stock_qty_field">
<span class="title"><?php _e( 'Stock qty', 'woocommerce' ); ?></span>
<span class="title"><?php esc_html_e( 'Stock qty', 'woocommerce' ); ?></span>
<span class="input-text-wrap">
<input type="number" name="_stock" class="text stock" step="any" value="">
</span>
</label>
<?php endif; ?>
</div>
<label class="alignleft">
<span class="title"><?php _e( 'Backorders?', 'woocommerce' ); ?></span>
<label class="alignleft backorder_field">
<span class="title"><?php esc_html_e( 'Backorders?', 'woocommerce' ); ?></span>
<span class="input-text-wrap">
<select class="backorders" name="_backorders">
<?php
foreach ( wc_get_product_backorder_options() as $key => $value ) {
echo '<option value="' . esc_attr( $key ) . '">' . $value . '</option>';
echo '<option value="' . esc_attr( $key ) . '">' . esc_html( $value ) . '</option>';
}
?>
</select>

View File

@ -309,3 +309,24 @@ function wc_save_order_items( $order_id, $items ) {
// Inform other plugins that the items have been saved
do_action( 'woocommerce_saved_order_items', $order_id, $items );
}
/**
* Get HTML for some action buttons. Used in list tables.
*
* @since 3.3.0
* @param array $actions Actions to output.
* @return string
*/
function wc_render_action_buttons( $actions ) {
$actions_html = '';
foreach ( $actions as $action ) {
if ( isset( $action['group'] ) ) {
$actions_html .= '<div class="wc-action-button-group"><label>' . $action['group'] . '</label> <span class="wc-action-button-group__items">' . wc_render_action_buttons( $action['actions'] ) . '</span></div>';
} elseif ( isset( $action['action'], $action['url'], $action['name'] ) ) {
$actions_html .= sprintf( '<a class="button wc-action-button wc-action-button-%s %s" href="%s" title="%s">%s</a>', esc_attr( $action['action'] ), esc_attr( $action['action'] ), esc_url( $action['url'] ), esc_attr( $action['name'] ), esc_attr( $action['name'] ) );
}
}
return $actions_html;
}

View File

@ -483,83 +483,12 @@ class WC_AJAX {
wp_die( -1 );
}
if ( $order = wc_get_order( absint( $_GET['order_id'] ) ) ) {
$order = wc_get_order( absint( $_GET['order_id'] ) ); // WPCS: sanitization ok.
ob_start();
if ( $order ) {
include_once( 'admin/list-tables/class-wc-admin-list-table-orders.php' );
$hidden_order_itemmeta = apply_filters( 'woocommerce_hidden_order_itemmeta', array(
'_qty',
'_tax_class',
'_product_id',
'_variation_id',
'_line_subtotal',
'_line_subtotal_tax',
'_line_total',
'_line_tax',
'method_id',
'cost',
) );
?>
<div class="wc-order-preview__table-wrapper">
<table cellspacing="0" class="wc-order-preview__table">
<tr>
<th><?php _e( 'Product', 'woocommerce' ); ?></th>
<th><?php _e( 'Quantity', 'woocommerce' ); ?></th>
<th><?php _e( 'Tax', 'woocommerce' ); ?></th>
<th><?php _e( 'Total', 'woocommerce' ); ?></th>
</tr>
<?php
foreach ( $order->get_items() as $item_id => $item ) {
if ( apply_filters( 'woocommerce_order_item_visible', true, $item ) ) {
?>
<tr class="<?php echo esc_attr( apply_filters( 'woocommerce_order_item_class', 'order_item', $item, $order ) ); ?>">
<td><?php
echo apply_filters( 'woocommerce_order_item_name', $item->get_name(), $item, false );
if ( is_callable( array( $item, 'get_product' ) ) && ( $product = $item->get_product() ) && is_object( $product ) && $product->get_sku() ) {
echo '<div class="wc-order-item-sku">' . esc_html( $product->get_sku() ) . '</div>';
}
if ( $meta_data = $item->get_formatted_meta_data( '' ) ) : ?>
<table cellspacing="0" class="wc-order-item-meta">
<?php foreach ( $meta_data as $meta_id => $meta ) :
if ( in_array( $meta->key, $hidden_order_itemmeta ) ) {
continue;
}
?>
<tr>
<th><?php echo wp_kses_post( $meta->display_key ); ?>:</th>
<td><?php echo wp_kses_post( force_balance_tags( $meta->display_value ) ); ?></td>
</tr>
<?php endforeach; ?>
</table>
<?php endif;
?></td>
<td><?php echo esc_html( $item->get_quantity() ); ?></td>
<td><?php echo wc_price( $item->get_total_tax(), array( 'currency' => $order->get_currency() ) );; ?></td>
<td><?php echo wc_price( $item->get_total(), array( 'currency' => $order->get_currency() ) );; ?></td>
</tr>
<?php
}
}
?>
</table>
</div>
<?php
$item_html = ob_get_clean();
wp_send_json_success( apply_filters( 'woocommerce_ajax_get_order_details', array(
'data' => $order->get_data(),
'order_number' => $order->get_order_number(),
'item_html' => $item_html,
'ship_to_billing' => wc_ship_to_billing_address_only(),
'needs_shipping' => $order->needs_shipping_address(),
'formatted_billing_address' => ( $address = $order->get_formatted_billing_address() ) ? $address : __( 'N/A', 'woocommerce' ),
'formatted_shipping_address' => ( $address = $order->get_formatted_shipping_address() ) ? $address: __( 'N/A', 'woocommerce' ),
'shipping_address_map_url' => $order->get_shipping_address_map_url(),
'payment_via' => $order->get_payment_method_title() . ( $order->get_transaction_id() ? ' (' . $order->get_transaction_id() . ')' : '' ),
'shipping_via' => $order->get_shipping_method(),
), $order ) );
wp_send_json_success( WC_Admin_List_Table_Orders::order_preview_get_order_details( $order ) );
}
exit;
}
@ -2036,6 +1965,17 @@ class WC_AJAX {
self::variation_bulk_set( $variations, 'stock_status', 'outofstock' );
}
/**
* Bulk action - Set Stock Status as On Backorder.
* @access private
* @used-by bulk_edit_variations
* @param array $variations
* @param array $data
*/
private static function variation_bulk_action_variable_stock_status_onbackorder( $variations, $data ) {
self::variation_bulk_set( $variations, 'stock_status', 'onbackorder' );
}
/**
* Bulk action - Set Stock.
* @access private

View File

@ -220,7 +220,7 @@ class WC_Frontend_Scripts {
'selectWoo' => array(
'src' => self::get_asset_url( 'assets/js/selectWoo/selectWoo.full' . $suffix . '.js' ),
'deps' => array( 'jquery' ),
'version' => '1.0.1',
'version' => '1.0.2',
),
'wc-address-i18n' => array(
'src' => self::get_asset_url( 'assets/js/frontend/address-i18n' . $suffix . '.js' ),

View File

@ -97,6 +97,7 @@ class WC_Install {
'3.3.0' => array(
'wc_update_330_image_options',
'wc_update_330_webhooks',
'wc_update_330_product_stock_status',
'wc_update_330_set_default_product_cat',
'wc_update_330_db_version',
),

View File

@ -376,21 +376,21 @@ class WC_Product_Variable extends WC_Product {
if ( ! $this->get_manage_stock() ) {
$this->set_stock_quantity( '' );
$this->set_backorders( 'no' );
$this->set_stock_status( $this->child_is_in_stock() ? 'instock' : 'outofstock' );
$this->data_store->sync_stock_status( $this );
// If backorders are enabled, always in stock.
} elseif ( 'no' !== $this->get_backorders() ) {
$this->set_stock_status( 'instock' );
// If we are stock managing, backorders are allowed, and we don't have stock, force on backorder status.
} elseif ( $this->get_stock_quantity() <= get_option( 'woocommerce_notify_no_stock_amount', 0 ) && 'no' !== $this->get_backorders() ) {
$this->set_stock_status( 'onbackorder' );
// If we are stock managing and we don't have stock, force out of stock status.
} elseif ( $this->get_stock_quantity() <= get_option( 'woocommerce_notify_no_stock_amount' ) ) {
// If we are stock managing and we don't have stock, force out of stock status.
} elseif ( $this->get_stock_quantity() <= get_option( 'woocommerce_notify_no_stock_amount', 0 ) && 'no' === $this->get_backorders() ) {
$this->set_stock_status( 'outofstock' );
// If the stock level is changing and we do now have enough, force in stock status.
} elseif ( $this->get_stock_quantity() > get_option( 'woocommerce_notify_no_stock_amount' ) && array_key_exists( 'stock_quantity', $this->get_changes() ) ) {
// If the stock level is changing and we do now have enough, force in stock status.
} elseif ( $this->get_stock_quantity() > get_option( 'woocommerce_notify_no_stock_amount', 0 ) && array_key_exists( 'stock_quantity', $this->get_changes() ) ) {
$this->set_stock_status( 'instock' );
// Otherwise revert to status the children have.
// Otherwise revert to status the children have.
} else {
$this->set_stock_status( $this->child_is_in_stock() ? 'instock' : 'outofstock' );
}
@ -451,6 +451,16 @@ class WC_Product_Variable extends WC_Product {
return $this->data_store->child_is_in_stock( $this );
}
/**
* Is a child on backorder?
*
* @since 3.3.0
* @return boolean
*/
public function child_is_on_backorder() {
return $this->data_store->child_has_stock_status( $this, 'onbackorder' );
}
/**
* Does a child have a weight set?
* @return boolean

View File

@ -125,15 +125,19 @@ class WC_Product_Variable_Data_Store_CPT extends WC_Product_Data_Store_CPT imple
$children = get_transient( $children_transient_name );
if ( empty( $children ) || ! is_array( $children ) || ! isset( $children['all'] ) || ! isset( $children['visible'] ) || $force_read ) {
$all_args = $visible_only_args = array(
$all_args = array(
'post_parent' => $product->get_id(),
'post_type' => 'product_variation',
'orderby' => array( 'menu_order' => 'ASC', 'ID' => 'ASC' ),
'orderby' => array(
'menu_order' => 'ASC',
'ID' => 'ASC',
),
'fields' => 'ids',
'post_status' => array( 'publish', 'private' ),
'numberposts' => -1,
);
$visible_only_args = $all_args;
$visible_only_args['post_status'] = 'publish';
if ( 'yes' === get_option( 'woocommerce_hide_out_of_stock_items' ) ) {
@ -380,10 +384,24 @@ class WC_Product_Variable_Data_Store_CPT extends WC_Product_Data_Store_CPT imple
* @return boolean
*/
public function child_is_in_stock( $product ) {
return $this->child_has_stock_status( $product, 'instock' );
}
/**
* Does a child have a stock status?
*
* @since 3.3.0
* @param WC_Product $product Product object.
* @param string $status 'instock', 'outofstock', or 'onbackorder'.
* @return boolean
*/
public function child_has_stock_status( $product, $status ) {
global $wpdb;
$children = $product->get_children();
$oufofstock_children = $children ? $wpdb->get_var( "SELECT COUNT( post_id ) FROM $wpdb->postmeta WHERE meta_key = '_stock_status' AND meta_value = 'outofstock' AND post_id IN ( " . implode( ',', array_map( 'absint', $children ) ) . ' )' ) : 0;
return count( $children ) > $oufofstock_children;
$children = $product->get_children();
$children_with_status = $children ? $wpdb->get_var( "SELECT COUNT( post_id ) FROM $wpdb->postmeta WHERE meta_key = '_stock_status' AND meta_value = '" . esc_sql( $status ) . "' AND post_id IN ( " . implode( ',', array_map( 'absint', $children ) ) . ' )' ) : 0;
return (bool) $children_with_status;
}
/**
@ -474,7 +492,13 @@ class WC_Product_Variable_Data_Store_CPT extends WC_Product_Data_Store_CPT imple
* @param WC_Product $product Product object.
*/
public function sync_stock_status( &$product ) {
$product->set_stock_status( $product->child_is_in_stock() ? 'instock' : 'outofstock' );
if ( $product->child_is_in_stock() ) {
$product->set_stock_status( 'instock' );
} elseif ( $product->child_is_on_backorder() ) {
$product->set_stock_status( 'onbackorder' );
} else {
$product->set_stock_status( 'outofstock' );
}
}
/**

View File

@ -383,6 +383,11 @@ class WC_Product_CSV_Exporter extends WC_CSV_Batch_Exporter {
*/
protected function get_column_value_stock_status( $product ) {
$status = $product->get_stock_status( 'edit' );
if ( 'onbackorder' === $status ) {
return 'backorder';
}
return 'instock' === $status ? 1 : 0;
}

View File

@ -342,8 +342,12 @@ class WC_Gateway_BACS extends WC_Payment_Gateway {
$order = wc_get_order( $order_id );
// Mark as on-hold (we're awaiting the payment)
$order->update_status( 'on-hold', __( 'Awaiting BACS payment', 'woocommerce' ) );
if ( $order->get_total() > 0 ) {
// Mark as on-hold (we're awaiting the payment)
$order->update_status( 'on-hold', __( 'Awaiting BACS payment', 'woocommerce' ) );
} else {
$order->payment_complete();
}
// Reduce stock levels
wc_reduce_stock_levels( $order_id );

View File

@ -113,8 +113,12 @@ class WC_Gateway_Cheque extends WC_Payment_Gateway {
$order = wc_get_order( $order_id );
// Mark as on-hold (we're awaiting the cheque)
$order->update_status( 'on-hold', _x( 'Awaiting check payment', 'Check payment method', 'woocommerce' ) );
if ( $order->get_total() > 0 ) {
// Mark as on-hold (we're awaiting the cheque)
$order->update_status( 'on-hold', _x( 'Awaiting check payment', 'Check payment method', 'woocommerce' ) );
} else {
$order->payment_complete();
}
// Reduce stock levels
wc_reduce_stock_levels( $order_id );

View File

@ -178,8 +178,12 @@ class WC_Gateway_COD extends WC_Payment_Gateway {
public function process_payment( $order_id ) {
$order = wc_get_order( $order_id );
// Mark as processing or on-hold (payment won't be taken until delivery)
$order->update_status( apply_filters( 'woocommerce_cod_process_payment_order_status', $order->has_downloadable_item() ? 'on-hold' : 'processing', $order ), __( 'Payment to be made upon delivery.', 'woocommerce' ) );
if ( $order->get_total() > 0 ) {
// Mark as processing or on-hold (payment won't be taken until delivery)
$order->update_status( apply_filters( 'woocommerce_cod_process_payment_order_status', $order->has_downloadable_item() ? 'on-hold' : 'processing', $order ), __( 'Payment to be made upon delivery.', 'woocommerce' ) );
} else {
$order->payment_complete();
}
// Reduce stock levels
wc_reduce_stock_levels( $order_id );

View File

@ -726,4 +726,24 @@ abstract class WC_Product_Importer implements WC_Importer_Interface {
protected function explode_values_formatter( $value ) {
return trim( str_replace( '::separator::', ',', $value ) );
}
/**
* The exporter prepends a ' to fields that start with a - which causes
* issues with negative numbers. This removes the ' if the input is still a valid
* number after removal.
*
* @since 3.3.0
* @param string $value A numeric string that may or may not have ' prepended.
* @return string
*/
protected function unescape_negative_number( $value ) {
if ( 0 === strpos( $value, "'-" ) ) {
$unescaped = substr_replace( $value, '', 0, 1 );
if ( is_numeric( $unescaped ) ) {
return $unescaped;
}
}
return $value;
}
}

View File

@ -280,6 +280,9 @@ class WC_Product_CSV_Importer extends WC_Product_Importer {
return $value;
}
// Remove the ' prepended to fields that start with - if needed.
$value = $this->unescape_negative_number( $value );
return floatval( $value );
}
@ -294,6 +297,9 @@ class WC_Product_CSV_Importer extends WC_Product_Importer {
return $value;
}
// Remove the ' prepended to fields that start with - if needed.
$value = $this->unescape_negative_number( $value );
return wc_stock_amount( $value );
}
@ -633,17 +639,16 @@ class WC_Product_CSV_Importer extends WC_Product_Importer {
$data['stock_status'] = isset( $data['stock_status'] ) ? $data['stock_status'] : true;
} else {
$data['manage_stock'] = true;
// Only auto set status when stock_status is empty.
if ( ! isset( $data['stock_status'] ) || isset( $data['stock_status'] ) && '' === $data['stock_status'] ) {
$data['stock_status'] = 0 < $data['stock_quantity'];
}
}
}
// Stock is bool.
// Stock is bool or 'backorder'.
if ( isset( $data['stock_status'] ) ) {
$data['stock_status'] = $data['stock_status'] ? 'instock' : 'outofstock';
if ( 'backorder' === $data['stock_status'] ) {
$data['stock_status'] = 'onbackorder';
} else {
$data['stock_status'] = $data['stock_status'] ? 'instock' : 'outofstock';
}
}
// Prepare grouped products.

View File

@ -484,10 +484,14 @@ function wc_track_product_view() {
$viewed_products = (array) explode( '|', $_COOKIE['woocommerce_recently_viewed'] );
}
if ( ! in_array( $post->ID, $viewed_products ) ) {
$viewed_products[] = $post->ID;
// Unset if already in viewed products list.
$keys = array_flip( $viewed_products );
if ( isset( $keys[ $post->ID ] ) ) {
unset( $viewed_products[ $keys[ $post->ID ] ] );
}
$viewed_products[] = $post->ID;
if ( count( $viewed_products ) > 15 ) {
array_shift( $viewed_products );
}
@ -793,8 +797,9 @@ function wc_get_product_tax_class_options() {
*/
function wc_get_product_stock_status_options() {
return array(
'instock' => __( 'In stock', 'woocommerce' ),
'outofstock' => __( 'Out of stock', 'woocommerce' ),
'instock' => __( 'In stock', 'woocommerce' ),
'outofstock' => __( 'Out of stock', 'woocommerce' ),
'onbackorder' => __( 'On backorder', 'woocommerce' ),
);
}

View File

@ -1548,6 +1548,44 @@ function wc_update_330_set_default_product_cat() {
}
}
/**
* Update product stock status to use the new onbackorder status.
*/
function wc_update_330_product_stock_status() {
global $wpdb;
if ( 'yes' !== get_option( 'woocommerce_manage_stock' ) ) {
return;
}
$min_stock_amount = (int) get_option( 'woocommerce_notify_no_stock_amount', 0 );
// Get all products that have stock management enabled, stock less than or equal to min stock amount, and backorders enabled.
$post_ids = $wpdb->get_col( $wpdb->prepare( "
SELECT t1.post_id FROM $wpdb->postmeta t1
INNER JOIN $wpdb->postmeta t2
ON t1.post_id = t2.post_id
AND t1.meta_key = '_manage_stock' AND t1.meta_value = 'yes'
AND t2.meta_key = '_stock' AND t2.meta_value <= %d
INNER JOIN $wpdb->postmeta t3
ON t2.post_id = t3.post_id
AND t3.meta_key = '_backorders' AND ( t3.meta_value = 'yes' OR t3.meta_value = 'notify' )
", $min_stock_amount ) ); // WPCS: db call ok, unprepared SQL ok, cache ok.
if ( empty( $post_ids ) ) {
return;
}
$post_ids = array_map( 'absint', $post_ids );
// Set the status to onbackorder for those products.
$wpdb->query( "
UPDATE $wpdb->postmeta
SET meta_value = 'onbackorder'
WHERE meta_key = '_stock_status' AND post_id IN ( " . implode( ',', $post_ids ) . ' )
' ); // WPCS: db call ok, unprepared SQL ok, cache ok.
}
/**
* Update DB Version.
*/

View File

@ -449,6 +449,7 @@ function wc_get_customer_available_downloads( $customer_id ) {
'download_id' => $result->download_id,
'product_id' => $_product->get_id(),
'product_name' => $_product->get_name(),
'product_url' => $_product->is_visible() ? $_product->get_permalink() : '', // Since 3.3.0.
'download_name' => $download_name,
'order_id' => $order->get_id(),
'order_key' => $order->get_order_key(),

View File

@ -33,7 +33,7 @@ class WC_Widget_Recently_Viewed extends WC_Widget {
'type' => 'number',
'step' => 1,
'min' => 1,
'max' => '',
'max' => 15,
'std' => 10,
'label' => __( 'Number of products to show', 'woocommerce' ),
),

View File

@ -1,6 +1,13 @@
<?php
/**
* Unit tests for the product data methods.
*
* @package WooCommerce\Tests\Product
*/
/**
* Data Functions.
*
* @package WooCommerce\Tests\Product
* @since 3.0.0
*/
@ -8,13 +15,14 @@ class WC_Tests_Product_Data extends WC_Unit_Test_Case {
/**
* Test product setters and getters
*
* @since 3.0.0
*/
public function test_product_getters_and_setters() {
global $wpdb;
$attributes = array();
$attribute = new WC_Product_Attribute();
$attribute = new WC_Product_Attribute();
$attribute->set_id( 0 );
$attribute->set_name( 'Test Attribute' );
$attribute->set_options( array( 'Fish', 'Fingers' ) );
@ -57,7 +65,8 @@ class WC_Tests_Product_Data extends WC_Unit_Test_Case {
'download_expiry' => -1,
'download_limit' => 5,
'attributes' => $attributes,
);
);
$product = new WC_Product();
foreach ( $getters_and_setters as $function => $value ) {
$product->{"set_{$function}"}( $value );
@ -72,16 +81,86 @@ class WC_Tests_Product_Data extends WC_Unit_Test_Case {
$this->assertEquals( $product->get_date_on_sale_from()->getTimestamp(), 1475798400 );
$this->assertEquals( $product->get_date_on_sale_to()->getTimestamp(), 1477267200 );
$image_url = media_sideload_image( "https://cldup.com/Dr1Bczxq4q.png", $product->get_id(), '', 'src' );
$image_url = media_sideload_image( 'https://cldup.com/Dr1Bczxq4q.png', $product->get_id(), '', 'src' );
$image_id = $wpdb->get_col( $wpdb->prepare( "SELECT ID FROM {$wpdb->posts} WHERE guid='%s';", $image_url ) );
$product->set_image_id( $image_id[0] );
$product->save();
$this->assertEquals( $image_id[0], $product->get_image_id() );
$product->delete( true );
}
}
/**
* Test the onbackorder stock status.
*
* @since 3.3.0
*/
public function test_product_backorder_stock_status() {
$product = new WC_Product();
$product->set_stock_status( 'onbackorder' );
$this->assertEquals( 'onbackorder', $product->get_stock_status() );
$product->save();
$product = new WC_Product( $product->get_id() );
$this->assertEquals( 'onbackorder', $product->get_stock_status() );
}
/**
* Test the automatic stock status transitions done on product save.
*
* @since 3.3.0
*/
public function test_product_auto_stock_status() {
$product = new WC_Product();
// Product should not have quantity and stock status should not be updated automatically if not managing stock.
$product->set_manage_stock( false );
$product->set_stock_quantity( 5 );
$product->set_stock_status( 'instock' );
$product->save();
$this->assertEquals( '', $product->get_stock_quantity() );
$this->assertEquals( 'instock', $product->get_stock_status() );
$product->set_stock_status( 'outofstock' );
$product->save();
$this->assertEquals( 'outofstock', $product->get_stock_status() );
$product->set_manage_stock( true );
// Product should be out of stock if managing orders, no backorders allowed, and quantity too low.
$product->set_stock_quantity( 0 );
$product->set_stock_status( 'instock' );
$product->set_backorders( 'no' );
$product->save();
$this->assertEquals( 0, $product->get_stock_quantity() );
$this->assertEquals( 'outofstock', $product->get_stock_status() );
// Product should be on backorder if managing orders, backorders allowed, and quantity too low.
$product->set_stock_quantity( 0 );
$product->set_stock_status( 'instock' );
$product->set_backorders( 'yes' );
$product->save();
$this->assertEquals( 0, $product->get_stock_quantity() );
$this->assertEquals( 'onbackorder', $product->get_stock_status() );
// Product should go to in stock if backordered and inventory increases.
$product->set_stock_quantity( 5 );
$product->set_stock_status( 'onbackorder' );
$product->set_backorders( 'notify' );
$product->save();
$this->assertEquals( 5, $product->get_stock_quantity() );
$this->assertEquals( 'instock', $product->get_stock_status() );
// Product should go to in stock if out of stock and inventory increases.
$product->set_stock_quantity( 3 );
$product->set_stock_status( 'outofstock' );
$product->set_backorders( 'no' );
$product->save();
$this->assertEquals( 3, $product->get_stock_quantity() );
$this->assertEquals( 'instock', $product->get_stock_status() );
}
/**
* Test product term setters and getters
*
* @since 3.0.0
*/
public function test_product_term_getters_and_setters() {
@ -95,7 +174,9 @@ class WC_Tests_Product_Data extends WC_Unit_Test_Case {
'tag_ids' => array( $test_tag_1['term_id'], $test_tag_2['term_id'] ),
'category_ids' => array( $test_cat_1['term_id'], $test_cat_2['term_id'] ),
);
$product = new WC_Product_Simple;
$product = new WC_Product_Simple();
foreach ( $getters_and_setters as $function => $value ) {
$product->{"set_{$function}"}( $value );
}
@ -110,33 +191,37 @@ class WC_Tests_Product_Data extends WC_Unit_Test_Case {
*
* @since 3.0.0
*/
public function test_grouped_product_getters_and_setters() {
public function test_grouped_product_getters_and_setters() {
$getters_and_setters = array(
'children' => array( 1, 2, 3 ),
);
$product = new WC_Product_Grouped;
$product = new WC_Product_Grouped();
foreach ( $getters_and_setters as $function => $value ) {
$product->{"set_{$function}"}( $value );
$this->assertEquals( $value, $product->{"get_{$function}"}(), $function );
}
}
}
/**
* Test external product setters and getters
*
* @since 3.0.0
*/
public function test_external_product_getters_and_setters() {
$time = time();
$getters_and_setters = array(
'button_text' => 'Test Button Text',
'product_url' => 'https://wordpress.org',
);
$product = new WC_Product_External;
foreach ( $getters_and_setters as $function => $value ) {
$product->{"set_{$function}"}( $value );
$this->assertEquals( $value, $product->{"get_{$function}"}(), $function );
}
}
public function test_external_product_getters_and_setters() {
$time = time();
$getters_and_setters = array(
'button_text' => 'Test Button Text',
'product_url' => 'https://wordpress.org',
);
$product = new WC_Product_External();
foreach ( $getters_and_setters as $function => $value ) {
$product->{"set_{$function}"}( $value );
$this->assertEquals( $value, $product->{"get_{$function}"}(), $function );
}
}
}

View File

@ -1,9 +1,12 @@
<?php
/**
* Unit tests for the WC_Product_Variable class.
*
* @package WooCommerce\Tests\Product
*/
/**
* Class WC_Tests_Product_Variable.
*
* @package WooCommerce\Tests\Product
*/
class WC_Tests_Product_Variable extends WC_Unit_Test_Case {
@ -15,9 +18,117 @@ class WC_Tests_Product_Variable extends WC_Unit_Test_Case {
$product_id = $product->save();
$prices = $product->get_variation_prices();
$this->assertArrayHasKey( 'regular_price', $prices );
$this->assertArrayHasKey( 'sale_price', $prices );
$this->assertArrayHasKey( 'price', $prices );
$this->assertArrayHasKey( 'regular_price', $prices );
$this->assertArrayHasKey( 'sale_price', $prices );
$this->assertArrayHasKey( 'price', $prices );
$this->assertTrue( $product_id > 0 );
}
/**
* Test the automatic stock status transitions done on variable product save.
*
* @since 3.3.0
*/
public function test_variable_product_auto_stock_status() {
$product = new WC_Product_Variable();
// Product should not have quantity and stock status should be based on children stock status if not managing stock.
$product->set_manage_stock( false );
$product->set_stock_quantity( 5 );
$product->set_stock_status( 'instock' );
$product->save();
$this->assertEquals( '', $product->get_stock_quantity() );
$this->assertEquals( 'outofstock', $product->get_stock_status() );
$product->set_manage_stock( true );
// Product should be out of stock if managing orders, no backorders allowed, and quantity too low.
$product->set_stock_quantity( 0 );
$product->set_stock_status( 'instock' );
$product->set_backorders( 'no' );
$product->save();
$this->assertEquals( 0, $product->get_stock_quantity() );
$this->assertEquals( 'outofstock', $product->get_stock_status() );
// Product should be on backorder if managing orders, backorders allowed, and quantity too low.
$product->set_stock_quantity( 0 );
$product->set_stock_status( 'instock' );
$product->set_backorders( 'yes' );
$product->save();
$this->assertEquals( 0, $product->get_stock_quantity() );
$this->assertEquals( 'onbackorder', $product->get_stock_status() );
// Product should go to in stock if backordered and inventory increases.
$product->set_stock_quantity( 5 );
$product->set_stock_status( 'onbackorder' );
$product->set_backorders( 'notify' );
$product->save();
$this->assertEquals( 5, $product->get_stock_quantity() );
$this->assertEquals( 'instock', $product->get_stock_status() );
// Product should go to in stock if out of stock and inventory increases.
$product->set_stock_quantity( 3 );
$product->set_stock_status( 'outofstock' );
$product->set_backorders( 'no' );
$product->save();
$this->assertEquals( 3, $product->get_stock_quantity() );
$this->assertEquals( 'instock', $product->get_stock_status() );
}
/**
* Test that variable products have the correct status when syncing with their children.
*
* @since 3.3.0
*/
public function test_variable_product_stock_status_sync() {
$product = new WC_Product_Variable();
$product->save();
$child1 = new WC_Product_Variation();
$child1->set_parent_id( $product->get_id() );
$child1->save();
$child2 = new WC_Product_Variation();
$child2->set_parent_id( $product->get_id() );
$child2->save();
$product->set_children( array( $child1->get_id(), $child2->get_id() ) );
// Product should be in stock if a child is in stock.
$child1->set_stock_status( 'instock' );
$child1->save();
$child2->set_stock_status( 'outofstock' );
$child2->save();
WC_Product_Variable::sync( $product );
$this->assertEquals( 'instock', $product->get_stock_status() );
$child2->set_stock_status( 'onbackorder' );
$child2->save();
WC_Product_Variable::sync( $product );
$this->assertEquals( 'instock', $product->get_stock_status() );
// Product should be out of stock if all children are out of stock.
$child1->set_stock_status( 'outofstock' );
$child1->save();
$child2->set_stock_status( 'outofstock' );
$child2->save();
WC_Product_Variable::sync( $product );
$this->assertEquals( 'outofstock', $product->get_stock_status() );
// Product should be on backorder if all children are on backorder.
$child1->set_stock_status( 'onbackorder' );
$child1->save();
$child2->set_stock_status( 'onbackorder' );
$child2->save();
WC_Product_Variable::sync( $product );
$this->assertEquals( 'onbackorder', $product->get_stock_status() );
// Product should be on backorder if at least one child is on backorder and the rest are out of stock.
$child1->set_stock_status( 'outofstock' );
$child1->save();
$child2->set_stock_status( 'onbackorder' );
$child2->save();
WC_Product_Variable::sync( $product );
$this->assertEquals( 'onbackorder', $product->get_stock_status() );
}
}

View File

@ -8,7 +8,6 @@
/**
* Class Product_Variation.
*
* @package WooCommerce\Tests\Product
* @since 3.0
*/
class WC_Tests_Product_Variation extends WC_Unit_Test_Case {