Merge branch 'master' into feature/network-order-widget

This commit is contained in:
Chris Marslender 2017-11-15 18:43:34 -07:00
commit 961c24e373
No known key found for this signature in database
GPG Key ID: 5A3FF8E135EABA2C
34 changed files with 2274 additions and 1472 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

@ -1893,73 +1893,227 @@ ul.wc_coupon_list_block {
font-size: inherit;
margin: 3px 0;
}
}
.column-order_total,
.column-order_date {
width: 9%;
.post-type-shop_order {
.tablenav .one-page .displaying-num {
display: none;
}
.column-order_status {
width: 45px;
text-align: center;
mark {
@include ir();
background: none;
font-size: 1.4em;
margin: 0 auto;
.wp-list-table {
margin-top: 1em;
th {
padding: .75em 1em;
}
mark.pending,
mark.completed,
mark.on-hold,
mark.failed,
mark.cancelled,
mark.processing,
mark.refunded {
&::after {
@include icon;
th.sortable a, th.sorted a {
padding: 0;
}
.check-column {
width: 1px;
white-space: nowrap;
padding: 1em 1em 1em 1em !important;
vertical-align: middle;
input {
vertical-align: text-top;
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;
mark.pending::after {
content: '\e012';
color: $orange;
&::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;
}
}
}
mark.completed::after {
content: '\e015';
color: $blue;
.column-order_date {
width: 10ch;
}
mark.on-hold::after {
content: '\e033';
color: #999;
.column-order_number {
width: 35ch;
}
mark.failed::after {
content: '\e016';
color: #d0c21f;
.column-order_status {
width: 20ch;
}
mark.cancelled::after {
content: '\e013';
color: $red;
.column-order_total {
text-align: right;
width: 10ch;
a span {
float:right;
}
}
mark.processing::after {
content: '\e011';
color: #73a724;
.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;
}
td {
vertical-align: middle;
padding: 1em;
mark.refunded::after {
content: '\e014';
color: #999;
.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;
}
}
}
tr:hover:not(.status-trash) {
td, th {
cursor: pointer;
}
}
}
}
}
td.column-order_status {
padding-top: 9px;
// 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;
}
}
}
@media only screen and (max-width: 1200px) {
.post-type-shop_order .wp-list-table {
.column-shipping_address,
.column-order_total {
display:none;
visibility:hidden;
}
}
}
.wc-order-preview {
article {
padding: 0 !important;
}
.wc-order-preview__table {
width: 100%;
margin: 0;
border-bottom: 1px solid #ccc;
th, td {
padding: 1em 1.5em;
text-align: left;
border: 0;
border-bottom: 1px solid #eee;
margin: 0;
background: transparent;
box-shadow: none;
text-align: right;
vertical-align: top;
}
td:first-child,
th:first-child {
text-align: left;
}
th {
border-color: #ccc;
}
tr:last-child td {
border: 0;
}
.wc-order-item-sku {
margin-top: .5em;
}
.wc-order-item-meta {
margin-top: .5em;
th, td {
padding: 0;
border: 0;
text-align: left;
vertical-align: top;
}
td:last-child {
padding-left: .5em;
}
}
}
.wc-order-preview-addresses {
overflow:hidden;
.wc-order-preview-address {
width: 50%;
float: left;
padding: 1.5em;
box-sizing: border-box;
h2 {
margin-top: 0;
}
strong {
display: block;
margin-top: 1em;
}
}
}
}
@ -5418,20 +5572,6 @@ table.bar_chart {
.post-type-shop_order {
.wp-list-table {
.column-order_status {
display: none;
text-align: left;
padding-bottom: 0;
mark {
margin: 0;
}
&::before {
display: none !important;
}
}
.column-customer_message,
.column-order_notes {
text-align: inherit;
@ -5521,6 +5661,14 @@ table.bar_chart {
}
}
@media screen and (max-width: 782px) {
.wc-backbone-modal .wc-backbone-modal-content {
width: 100%;
height: 100%;
min-width: 100%;
}
}
.wc-backbone-modal-backdrop {
position: fixed;
top: 0;
@ -5716,7 +5864,7 @@ table.bar_chart {
}
select,
input {
line-height: 32px;
line-height: 1;
height: 32px;
}
.select2-container {

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -602,6 +602,7 @@ body {
.wc-wizard-service-enable input {
visibility: hidden;
position: relative;
cursor: pointer;
&:before {
content: "\f347"; // down chevron

View File

@ -9,8 +9,7 @@
*/
$.fn.WCBackboneModal = function( options ) {
return this.each( function() {
var WCeachBackboneModal = new $.WCBackboneModal( $( this ), options )
( WCeachBackboneModal() );
( new $.WCBackboneModal( $( this ), options ) );
});
};
@ -25,12 +24,10 @@
var settings = $.extend( {}, $.WCBackboneModal.defaultOptions, options );
if ( settings.template ) {
var BackboneModal = new $.WCBackboneModal.View({
target: settings.template,
string: settings.variable
});
BackboneModal();
new $.WCBackboneModal.View({
target: settings.template,
string: settings.variable
});
}
};

View File

@ -1 +1 @@
!function(e,t,n){"use strict";e.fn.WCBackboneModal=function(t){return this.each(function(){var n=new e.WCBackboneModal(e(this),t)(n())})},e.WCBackboneModal=function(t,n){var o=e.extend({},e.WCBackboneModal.defaultOptions,n);o.template&&new e.WCBackboneModal.View({target:o.template,string:o.variable})()},e.WCBackboneModal.defaultOptions={template:"",variable:{}},e.WCBackboneModal.View=t.View.extend({tagName:"div",id:"wc-backbone-modal-dialog",_target:undefined,_string:undefined,events:{"click .modal-close":"closeButton","click #btn-ok":"addButton","touchstart #btn-ok":"addButton",keydown:"keyboardActions"},resizeContent:function(){var t=e(".wc-backbone-modal-content").find("article"),n=.75*e(window).height();t.css({"max-height":n+"px"})},initialize:function(t){var o=this;this._target=t.target,this._string=t.string,n.bindAll(this,"render"),this.render(),e(window).resize(function(){o.resizeContent()})},render:function(){var t=wp.template(this._target);this.$el.append(t(this._string)),e(document.body).css({overflow:"hidden"}).append(this.$el),this.resizeContent(),this.$(".wc-backbone-modal-content").attr("tabindex","0").focus(),e(document.body).trigger("init_tooltips"),e(document.body).trigger("wc_backbone_modal_loaded",this._target)},closeButton:function(t){t.preventDefault(),e(document.body).trigger("wc_backbone_modal_before_remove",this._target),this.undelegateEvents(),e(document).off("focusin"),e(document.body).css({overflow:"auto"}),this.remove(),e(document.body).trigger("wc_backbone_modal_removed",this._target)},addButton:function(t){e(document.body).trigger("wc_backbone_modal_response",[this._target,this.getFormData()]),this.closeButton(t)},getFormData:function(){var t={};return e(document.body).trigger("wc_backbone_modal_before_update",this._target),e.each(e("form",this.$el).serializeArray(),function(n,o){-1!==o.name.indexOf("[]")?(o.name=o.name.replace("[]",""),t[o.name]=e.makeArray(t[o.name]),t[o.name].push(o.value)):t[o.name]=o.value}),t},keyboardActions:function(e){var t=e.keyCode||e.which;13!==t||e.target.tagName&&("input"===e.target.tagName.toLowerCase()||"textarea"===e.target.tagName.toLowerCase())||this.addButton(e),27===t&&this.closeButton(e)}})}(jQuery,Backbone,_);
!function(e,t,n){"use strict";e.fn.WCBackboneModal=function(t){return this.each(function(){new e.WCBackboneModal(e(this),t)})},e.WCBackboneModal=function(t,n){var o=e.extend({},e.WCBackboneModal.defaultOptions,n);o.template&&new e.WCBackboneModal.View({target:o.template,string:o.variable})},e.WCBackboneModal.defaultOptions={template:"",variable:{}},e.WCBackboneModal.View=t.View.extend({tagName:"div",id:"wc-backbone-modal-dialog",_target:undefined,_string:undefined,events:{"click .modal-close":"closeButton","click #btn-ok":"addButton","touchstart #btn-ok":"addButton",keydown:"keyboardActions"},resizeContent:function(){var t=e(".wc-backbone-modal-content").find("article"),n=.75*e(window).height();t.css({"max-height":n+"px"})},initialize:function(t){var o=this;this._target=t.target,this._string=t.string,n.bindAll(this,"render"),this.render(),e(window).resize(function(){o.resizeContent()})},render:function(){var t=wp.template(this._target);this.$el.append(t(this._string)),e(document.body).css({overflow:"hidden"}).append(this.$el),this.resizeContent(),this.$(".wc-backbone-modal-content").attr("tabindex","0").focus(),e(document.body).trigger("init_tooltips"),e(document.body).trigger("wc_backbone_modal_loaded",this._target)},closeButton:function(t){t.preventDefault(),e(document.body).trigger("wc_backbone_modal_before_remove",this._target),this.undelegateEvents(),e(document).off("focusin"),e(document.body).css({overflow:"auto"}),this.remove(),e(document.body).trigger("wc_backbone_modal_removed",this._target)},addButton:function(t){e(document.body).trigger("wc_backbone_modal_response",[this._target,this.getFormData()]),this.closeButton(t)},getFormData:function(){var t={};return e(document.body).trigger("wc_backbone_modal_before_update",this._target),e.each(e("form",this.$el).serializeArray(),function(n,o){-1!==o.name.indexOf("[]")?(o.name=o.name.replace("[]",""),t[o.name]=e.makeArray(t[o.name]),t[o.name].push(o.value)):t[o.name]=o.value}),t},keyboardActions:function(e){var t=e.keyCode||e.which;13!==t||e.target.tagName&&("input"===e.target.tagName.toLowerCase()||"textarea"===e.target.tagName.toLowerCase())||this.addButton(e),27===t&&this.closeButton(e)}})}(jQuery,Backbone,_);

View File

@ -0,0 +1,78 @@
/* global wc_orders_params */
jQuery( function( $ ) {
if ( typeof wc_orders_params === 'undefined' ) {
return false;
}
/**
* WCOrdersTable class.
*/
var WCOrdersTable = function() {
$( document )
.on( 'click', '.post-type-shop_order .wp-list-table tbody td', this.onRowClick )
.on( 'click', '.order-preview:not(.disabled)', this.onPreview );
};
/**
* Click a row.
*/
WCOrdersTable.prototype.onRowClick = function( e ) {
if ( $( e.target ).filter( 'a' ).length ) {
return true;
}
var $row = $( this ).closest( 'tr' ),
href = $row.find( 'a.order-view' ).attr( 'href' );
if ( href.length ) {
window.location = href;
}
};
/**
* Preview an order.
*/
WCOrdersTable.prototype.onPreview = function() {
var $previewButton = $( this ),
$order_id = $previewButton.data( 'order-id' );
if ( $previewButton.data( 'order-data' ) ) {
$( this ).WCBackboneModal({
template: 'wc-modal-view-order',
variable : $previewButton.data( 'order-data' )
});
} else {
$previewButton.addClass( 'disabled' );
$.ajax({
url: wc_orders_params.ajax_url,
data: {
order_id: $order_id,
action : 'woocommerce_get_order_details',
security: wc_orders_params.preview_nonce
},
type: 'GET',
success: function( response ) {
$( '.order-preview' ).removeClass( 'disabled' );
if ( response.success ) {
$previewButton.data( 'order-data', response.data );
$( this ).WCBackboneModal({
template: 'wc-modal-view-order',
variable : response.data
});
}
}
});
}
return false;
};
/**
* Init WCOrdersTable.
*/
new WCOrdersTable();
} );

1
assets/js/admin/wc-orders.min.js vendored Normal file
View File

@ -0,0 +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});

View File

@ -36,17 +36,23 @@ jQuery( function( $ ) {
} );
$( '.wc-wizard-services' ).on( 'click', '.wc-wizard-service-enable', function( e ) {
e.stopPropagation();
var eventTarget = $( e.target );
if ( eventTarget.is( 'input' ) ) {
e.stopPropagation();
return;
}
var $checkbox = $( this ).find( 'input[type="checkbox"]' );
var $checkbox = $( this ).find( '.wc-wizard-service-toggle input' );
$checkbox.prop( 'checked', ! $checkbox.prop( 'checked' ) ).change();
} );
$( '.wc-wizard-services-list-toggle' ).on( 'change', '.wc-wizard-service-enable input', function() {
$( this ).closest( '.wc-wizard-services-list-toggle' ).toggleClass( 'closed' );
$( this ).closest( '.wc-wizard-services' ).find( '.wc-wizard-service-item' )
.slideToggle()
.css( 'display', 'flex' );
$( this ).closest( '.wc-wizard-services-list-toggle' ).toggleClass( 'closed' );
$( this ).closest( '.wc-wizard-services' ).find( '.wc-wizard-service-item' )
.slideToggle()
.css( 'display', 'flex' );
} );
$( '.wc-wizard-services' ).on( 'change', '.wc-wizard-shipping-method-select .method', function( e ) {

View File

@ -1 +1 @@
jQuery(function(e){function i(){e(".wc-setup-content").block({message:null,overlayCSS:{background:"#fff",opacity:.6}})}function s(){e("form.activate-jetpack").submit()}function t(){wp.ajax.post("setup_wizard_check_jetpack").then(function(e){if(!e||!e.is_active||"yes"===e.is_active)return s();setTimeout(t,3e3)}).fail(function(){s()})}e(".button-next").on("click",function(){var s=e(this).parents("form").get(0);return("function"!=typeof s.checkValidity||s.checkValidity())&&i(),!0}),e(".wc-wizard-services").on("change",".wc-wizard-service-enable input",function(){e(this).is(":checked")?(e(this).closest(".wc-wizard-service-toggle").removeClass("disabled"),e(this).closest(".wc-wizard-service-item").addClass("checked"),e(this).closest(".wc-wizard-service-item").find(".wc-wizard-service-settings").removeClass("hide")):(e(this).closest(".wc-wizard-service-toggle").addClass("disabled"),e(this).closest(".wc-wizard-service-item").removeClass("checked"),e(this).closest(".wc-wizard-service-item").find(".wc-wizard-service-settings").addClass("hide"))}),e(".wc-wizard-services").on("click",".wc-wizard-service-enable",function(i){i.stopPropagation();var s=e(this).find(".wc-wizard-service-toggle input");s.prop("checked",!s.prop("checked")).change()}),e(".wc-wizard-services-list-toggle").on("change",".wc-wizard-service-enable input",function(){e(this).closest(".wc-wizard-services-list-toggle").toggleClass("closed"),e(this).closest(".wc-wizard-services").find(".wc-wizard-service-item").slideToggle().css("display","flex")}),e(".wc-wizard-services").on("change",".wc-wizard-shipping-method-select .method",function(i){var s=e(this).closest(".wc-wizard-service-description"),t=i.target.value,c=s.find(".shipping-method-descriptions");c.find(".shipping-method-description").addClass("hide"),c.find("."+t).removeClass("hide");var r=s.find(".shipping-method-settings");r.find(".shipping-method-setting").addClass("hide").find(".shipping-method-required-field").prop("required",!1),r.find("."+t).removeClass("hide").find(".shipping-method-required-field").prop("required",!0)}),e(".wc-wizard-services").on("change",".wc-wizard-shipping-method-enable",function(){var i=e(this).is(":checked");e(this).closest(".wc-wizard-service-item").find(".shipping-method-required-field").prop("required",i)}),e(".activate-jetpack").on("click",".button-primary",function(e){if(i(),"no"===wc_setup_params.pending_jetpack_install)return!0;e.preventDefault(),t()}),e(".wc-wizard-services").on("change","input#stripe_create_account",function(){e(this).is(":checked")?(e(this).closest(".wc-wizard-service-settings").find("input.payment-email-input").prop("required",!0),e(this).closest(".wc-wizard-service-settings").find(".wc-wizard-service-setting-stripe_email").show()):(e(this).closest(".wc-wizard-service-settings").find("input.payment-email-input").prop("required",!1),e(this).closest(".wc-wizard-service-settings").find(".wc-wizard-service-setting-stripe_email").hide())}),e(".wc-wizard-services input#stripe_create_account").change(),e("select#store_country_state").on("change",function(){var i=this.value.split(":")[0];e("select#currency_code").val(wc_setup_currencies[i]).change()})});
jQuery(function(e){function i(){e(".wc-setup-content").block({message:null,overlayCSS:{background:"#fff",opacity:.6}})}function s(){e("form.activate-jetpack").submit()}function t(){wp.ajax.post("setup_wizard_check_jetpack").then(function(e){if(!e||!e.is_active||"yes"===e.is_active)return s();setTimeout(t,3e3)}).fail(function(){s()})}e(".button-next").on("click",function(){var s=e(this).parents("form").get(0);return("function"!=typeof s.checkValidity||s.checkValidity())&&i(),!0}),e(".wc-wizard-services").on("change",".wc-wizard-service-enable input",function(){e(this).is(":checked")?(e(this).closest(".wc-wizard-service-toggle").removeClass("disabled"),e(this).closest(".wc-wizard-service-item").addClass("checked"),e(this).closest(".wc-wizard-service-item").find(".wc-wizard-service-settings").removeClass("hide")):(e(this).closest(".wc-wizard-service-toggle").addClass("disabled"),e(this).closest(".wc-wizard-service-item").removeClass("checked"),e(this).closest(".wc-wizard-service-item").find(".wc-wizard-service-settings").addClass("hide"))}),e(".wc-wizard-services").on("click",".wc-wizard-service-enable",function(i){if(e(i.target).is("input"))i.stopPropagation();else{var s=e(this).find('input[type="checkbox"]');s.prop("checked",!s.prop("checked")).change()}}),e(".wc-wizard-services-list-toggle").on("change",".wc-wizard-service-enable input",function(){e(this).closest(".wc-wizard-services-list-toggle").toggleClass("closed"),e(this).closest(".wc-wizard-services").find(".wc-wizard-service-item").slideToggle().css("display","flex")}),e(".wc-wizard-services").on("change",".wc-wizard-shipping-method-select .method",function(i){var s=e(this).closest(".wc-wizard-service-description"),t=i.target.value,c=s.find(".shipping-method-descriptions");c.find(".shipping-method-description").addClass("hide"),c.find("."+t).removeClass("hide");var r=s.find(".shipping-method-settings");r.find(".shipping-method-setting").addClass("hide").find(".shipping-method-required-field").prop("required",!1),r.find("."+t).removeClass("hide").find(".shipping-method-required-field").prop("required",!0)}),e(".wc-wizard-services").on("change",".wc-wizard-shipping-method-enable",function(){var i=e(this).is(":checked");e(this).closest(".wc-wizard-service-item").find(".shipping-method-required-field").prop("required",i)}),e(".activate-jetpack").on("click",".button-primary",function(e){if(i(),"no"===wc_setup_params.pending_jetpack_install)return!0;e.preventDefault(),t()}),e(".wc-wizard-services").on("change","input#stripe_create_account",function(){e(this).is(":checked")?(e(this).closest(".wc-wizard-service-settings").find("input.payment-email-input").prop("required",!0),e(this).closest(".wc-wizard-service-settings").find(".wc-wizard-service-setting-stripe_email").show()):(e(this).closest(".wc-wizard-service-settings").find("input.payment-email-input").prop("required",!1),e(this).closest(".wc-wizard-service-settings").find(".wc-wizard-service-setting-stripe_email").hide())}),e(".wc-wizard-services input#stripe_create_account").change(),e("select#store_country_state").on("change",function(){var i=this.value.split(":")[0];e("select#currency_code").val(wc_setup_currencies[i]).change()})});

View File

@ -184,7 +184,7 @@ jQuery( function( $ ) {
*
* @param {Object} evt The JQuery event.
*/
shipping_method_selected: function( evt ) {
shipping_method_selected: function() {
var shipping_methods = {};
$( 'select.shipping_method, input[name^=shipping_method][type=radio]:checked, input[name^=shipping_method][type=hidden]' ).each( function() {

File diff suppressed because one or more lines are too long

View File

@ -1672,7 +1672,7 @@ abstract class WC_Abstract_Order extends WC_Abstract_Legacy_Order {
}
}
/* translators: %s: shipping method */
/* translators: %s: method */
$shipping .= apply_filters( 'woocommerce_order_shipping_to_display_shipped_via', '&nbsp;<small class="shipped_via">' . sprintf( __( 'via %s', 'woocommerce' ), $this->get_shipping_method() ) . '</small>', $this );
} elseif ( $this->get_shipping_method() ) {

View File

@ -93,7 +93,6 @@ class WC_Admin_Assets {
wp_register_script( 'woocommerce_admin', WC()->plugin_url() . '/assets/js/admin/woocommerce_admin' . $suffix . '.js', array( 'jquery', 'jquery-blockui', 'jquery-ui-sortable', 'jquery-ui-widget', 'jquery-ui-core', 'jquery-tiptip' ), WC_VERSION );
wp_register_script( 'jquery-blockui', WC()->plugin_url() . '/assets/js/jquery-blockui/jquery.blockUI' . $suffix . '.js', array( 'jquery' ), '2.70', true );
wp_register_script( 'jquery-tiptip', WC()->plugin_url() . '/assets/js/jquery-tiptip/jquery.tipTip' . $suffix . '.js', array( 'jquery' ), WC_VERSION, true );
wp_register_script( 'accounting', WC()->plugin_url() . '/assets/js/accounting/accounting' . $suffix . '.js', array( 'jquery' ), '0.4.2' );
wp_register_script( 'round', WC()->plugin_url() . '/assets/js/round/round' . $suffix . '.js', array( 'jquery' ), WC_VERSION );
wp_register_script( 'wc-admin-meta-boxes', WC()->plugin_url() . '/assets/js/admin/meta-boxes' . $suffix . '.js', array( 'jquery', 'jquery-ui-datepicker', 'jquery-ui-sortable', 'accounting', 'round', 'wc-enhanced-select', 'plupload-all', 'stupidtable', 'jquery-tiptip' ), WC_VERSION );
wp_register_script( 'zeroclipboard', WC()->plugin_url() . '/assets/js/zeroclipboard/jquery.zeroclipboard' . $suffix . '.js', array( 'jquery' ), WC_VERSION );
@ -131,12 +130,18 @@ class WC_Admin_Assets {
'search_categories_nonce' => wp_create_nonce( 'search-categories' ),
) );
// Accounting
wp_register_script( 'accounting', WC()->plugin_url() . '/assets/js/accounting/accounting' . $suffix . '.js', array( 'jquery' ), '0.4.2' );
wp_localize_script( 'accounting', 'accounting_params', array(
'mon_decimal_point' => wc_get_price_decimal_separator(),
) );
// WooCommerce admin pages
wp_register_script( 'wc-orders', WC()->plugin_url() . '/assets/js/admin/wc-orders' . $suffix . '.js', array( 'jquery', 'wp-util', 'underscore', 'backbone', 'jquery-blockui' ), WC_VERSION );
wp_localize_script( 'wc-orders', 'wc_orders_params', array(
'ajax_url' => admin_url( 'admin-ajax.php' ),
'preview_nonce' => wp_create_nonce( 'woocommerce-preview-order' ),
) );
// WooCommerce admin pages.
if ( in_array( $screen_id, wc_get_screen_ids() ) ) {
wp_enqueue_script( 'iris' );
wp_enqueue_script( 'woocommerce_admin' );

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,278 @@
<?php
/**
* List tables.
*
* @author WooCommerce
* @category Admin
* @package WooCommerce/Admin
* @version 3.3.0
*/
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
if ( class_exists( 'WC_Admin_List_Table', false ) ) {
return;
}
/**
* WC_Admin_List_Table Class.
*/
abstract class WC_Admin_List_Table {
/**
* Post type.
*
* @var string
*/
protected $list_table_type = '';
/**
* Object being shown on the row.
*
* @var object|null
*/
protected $object = null;
/**
* Constructor.
*/
public function __construct() {
if ( $this->list_table_type ) {
add_action( 'manage_posts_extra_tablenav', array( $this, 'maybe_render_blank_state' ) );
add_filter( 'view_mode_post_types', array( $this, 'disable_view_mode' ) );
add_action( 'restrict_manage_posts', array( $this, 'restrict_manage_posts' ) );
add_filter( 'request', array( $this, 'request_query' ) );
add_filter( 'post_row_actions', array( $this, 'row_actions' ), 100, 2 );
add_filter( 'default_hidden_columns', array( $this, 'default_hidden_columns' ), 10, 2 );
add_filter( 'list_table_primary_column', array( $this, 'list_table_primary_column' ), 10, 2 );
add_filter( 'manage_edit-' . $this->list_table_type . '_sortable_columns', array( $this, 'define_sortable_columns' ) );
add_filter( 'manage_' . $this->list_table_type . '_posts_columns', array( $this, 'define_columns' ) );
add_filter( 'bulk_actions-edit-' . $this->list_table_type, array( $this, 'define_bulk_actions' ) );
add_action( 'manage_' . $this->list_table_type . '_posts_custom_column', array( $this, 'render_columns' ), 10, 2 );
add_filter( 'handle_bulk_actions-edit-' . $this->list_table_type, array( $this, 'handle_bulk_actions' ), 10, 3 );
}
}
/**
* Show blank slate.
*
* @param string $which String which tablenav is being shown.
*/
public function maybe_render_blank_state( $which ) {
global $post_type;
if ( $post_type === $this->list_table_type && 'bottom' === $which ) {
$counts = (array) wp_count_posts( $post_type );
unset( $counts['auto-draft'] );
$count = array_sum( $counts );
if ( 0 < $count ) {
return;
}
$this->render_blank_state();
echo '<style type="text/css">#posts-filter .wp-list-table, #posts-filter .tablenav.top, .tablenav.bottom .actions, .wrap .subsubsub { display: none; } </style>';
}
}
/**
* Render blank state. Extend to add content.
*/
protected function render_blank_state() {}
/**
* Removes this type from list of post types that support "View Mode" switching.
* View mode is seen on posts where you can switch between list or excerpt. Our post types don't support
* it, so we want to hide the useless UI from the screen options tab.
*
* @param array $post_types Array of post types supporting view mode.
* @return array Array of post types supporting view mode, without this type.
*/
public function disable_view_mode( $post_types ) {
unset( $post_types[ $this->list_table_type ] );
return $post_types;
}
/**
* See if we should render search filters or not.
*/
public function restrict_manage_posts() {
global $typenow;
if ( $this->list_table_type === $typenow ) {
$this->render_filters();
}
}
/**
* Handle any filters.
*
* @param array $query_vars Query vars.
* @return array
*/
public function request_query( $query_vars ) {
global $typenow;
if ( $this->list_table_type === $typenow ) {
return $this->query_filters( $query_vars );
}
return $query_vars;
}
/**
* Render any custom filters and search inputs for the list table.
*/
protected function render_filters() {}
/**
* Handle any custom filters.
*
* @param array $query_vars Query vars.
* @return array
*/
protected function query_filters( $query_vars ) {
return $query_vars;
}
/**
* Set row actions.
*
* @param array $actions Array of actions.
* @param WP_Post $post Current post object.
* @return array
*/
public function row_actions( $actions, $post ) {
if ( $this->list_table_type === $post->post_type ) {
return $this->get_row_actions( $actions, $post );
}
return $actions;
}
/**
* Get row actions to show in the list table.
*
* @param array $actions Array of actions.
* @param WP_Post $post Current post object.
* @return array
*/
protected function get_row_actions( $actions, $post ) {
return $actions;
}
/**
* Adjust which columns are displayed by default.
*
* @param array $hidden Current hidden columns.
* @param object $screen Current screen.
* @return array
*/
public function default_hidden_columns( $hidden, $screen ) {
if ( isset( $screen->id ) && 'edit-' . $this->list_table_type === $screen->id ) {
$hidden = array_merge( $hidden, $this->define_hidden_columns() );
}
return $hidden;
}
/**
* Set list table primary column.
*
* @param string $default Default value.
* @param string $screen_id Current screen ID.
* @return string
*/
public function list_table_primary_column( $default, $screen_id ) {
if ( 'edit-' . $this->list_table_type === $screen_id && $this->get_primary_column() ) {
return $this->get_primary_column();
}
return $default;
}
/**
* Define primary column.
*
* @return array
*/
protected function get_primary_column() {
return '';
}
/**
* Define hidden columns.
*
* @return array
*/
protected function define_hidden_columns() {
return array();
}
/**
* Define which columns are sortable.
*
* @param array $columns Existing columns.
* @return array
*/
public function define_sortable_columns( $columns ) {
return $columns;
}
/**
* Define which columns to show on this screen.
*
* @param array $columns Existing columns.
* @return array
*/
public function define_columns( $columns ) {
return $columns;
}
/**
* Define bulk actions.
*
* @param array $actions Existing actions.
* @return array
*/
public function define_bulk_actions( $actions ) {
return $actions;
}
/**
* Pre-fetch any data for the row each column has access to it.
*
* @param int $post_id Post ID being shown.
*/
protected function prepare_row_data( $post_id ) {}
/**
* Render individual columns.
*
* @param string $column Column ID to render.
* @param int $post_id Post ID being shown.
*/
public function render_columns( $column, $post_id ) {
$this->prepare_row_data( $post_id );
if ( ! $this->object ) {
return;
}
if ( is_callable( array( $this, 'render_' . $column . '_column' ) ) ) {
$this->{"render_{$column}_column"}();
}
}
/**
* Handle bulk actions.
*
* @param string $redirect_to URL to redirect to.
* @param string $action Action name.
* @param array $ids List of ids.
* @return string
*/
public function handle_bulk_actions( $redirect_to, $action, $ids ) {
return esc_url_raw( $redirect_to );
}
}

View File

@ -0,0 +1,237 @@
<?php
/**
* List tables: coupons.
*
* @author WooCommerce
* @category Admin
* @package WooCommerce/Admin
* @version 3.3.0
*/
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
if ( class_exists( 'WC_Admin_List_Table_Coupons', false ) ) {
new WC_Admin_List_Table_Coupons();
return;
}
if ( ! class_exists( 'WC_Admin_List_Table', false ) ) {
include_once( 'abstract-class-wc-admin-list-table.php' );
}
/**
* WC_Admin_List_Table_Coupons Class.
*/
class WC_Admin_List_Table_Coupons extends WC_Admin_List_Table {
/**
* Post type.
*
* @var string
*/
protected $list_table_type = 'shop_coupon';
/**
* Constructor.
*/
public function __construct() {
parent::__construct();
add_filter( 'disable_months_dropdown', '__return_true' );
}
/**
* Render blank state.
*/
protected function render_blank_state() {
echo '<div class="woocommerce-BlankState">';
echo '<h2 class="woocommerce-BlankState-message">' . esc_html__( 'Coupons are a great way to offer discounts and rewards to your customers. They will appear here once created.', 'woocommerce' ) . '</h2>';
echo '<a class="woocommerce-BlankState-cta button-primary button" target="_blank" href="https://docs.woocommerce.com/document/coupon-management/?utm_source=blankslate&utm_medium=product&utm_content=couponsdoc&utm_campaign=woocommerceplugin">' . esc_html__( 'Learn more about coupons', 'woocommerce' ) . '</a>';
echo '</div>';
}
/**
* Define primary column.
*
* @return array
*/
protected function get_primary_column() {
return 'coupon_code';
}
/**
* Get row actions to show in the list table.
*
* @param array $actions Array of actions.
* @param WP_Post $post Current post object.
* @return array
*/
protected function get_row_actions( $actions, $post ) {
unset( $actions['inline hide-if-no-js'] );
return $actions;
}
/**
* Define which columns to show on this screen.
*
* @param array $columns Existing columns.
* @return array
*/
public function define_columns( $columns ) {
$show_columns = array();
$show_columns['cb'] = $columns['cb'];
$show_columns['coupon_code'] = __( 'Code', 'woocommerce' );
$show_columns['type'] = __( 'Coupon type', 'woocommerce' );
$show_columns['amount'] = __( 'Coupon amount', 'woocommerce' );
$show_columns['description'] = __( 'Description', 'woocommerce' );
$show_columns['products'] = __( 'Product IDs', 'woocommerce' );
$show_columns['usage'] = __( 'Usage / Limit', 'woocommerce' );
$show_columns['expiry_date'] = __( 'Expiry date', 'woocommerce' );
return $show_columns;
}
/**
* Pre-fetch any data for the row each column has access to it. the_coupon global is there for bw compat.
*
* @param int $post_id Post ID being shown.
*/
protected function prepare_row_data( $post_id ) {
global $the_coupon;
if ( empty( $this->object ) || $this->object->get_id() !== $post_id ) {
$this->object = $the_coupon = new WC_Coupon( $post_id );
}
}
/**
* Render columm: coupon_code.
*/
protected function render_coupon_code_column() {
global $post;
$edit_link = get_edit_post_link( $this->object->get_id() );
$title = $this->object->get_code();
echo '<strong><a class="row-title" href="' . esc_url( $edit_link ) . '">' . esc_html( $title ) . '</a>';
_post_states( $post );
echo '</strong>';
}
/**
* Render columm: type.
*/
protected function render_type_column() {
echo esc_html( wc_get_coupon_type( $this->object->get_discount_type() ) );
}
/**
* Render columm: amount.
*/
protected function render_amount_column() {
echo esc_html( wc_format_localized_price( $this->object->get_amount() ) );
}
/**
* Render columm: products.
*/
protected function render_products_column() {
$product_ids = $this->object->get_product_ids();
if ( count( $product_ids ) > 0 ) {
echo esc_html( implode( ', ', $product_ids ) );
} else {
echo '&ndash;';
}
}
/**
* Render columm: usage_limit.
*/
protected function render_usage_limit_column() {
$usage_limit = $this->object->get_usage_limit();
if ( $usage_limit ) {
echo esc_html( $usage_limit );
} else {
echo '&ndash;';
}
}
/**
* Render columm: usage.
*/
protected function render_usage_column() {
$usage_count = $this->object->get_usage_count();
$usage_limit = $this->object->get_usage_limit();
/* translators: 1: count 2: limit */
printf(
__( '%1$s / %2$s', 'woocommerce' ),
esc_html( $usage_count ),
$usage_limit ? esc_html( $usage_limit ) : '&infin;'
);
}
/**
* Render columm: expiry_date.
*/
protected function render_expiry_date_column() {
$expiry_date = $this->object->get_date_expires();
if ( $expiry_date ) {
echo esc_html( $expiry_date->date_i18n( 'F j, Y' ) );
} else {
echo '&ndash;';
}
}
/**
* Render columm: description.
*/
protected function render_description_column() {
echo wp_kses_post( $this->object->get_description() ? $this->object->get_description() : '&ndash;' );
}
/**
* Render any custom filters and search inputs for the list table.
*/
protected function render_filters() {
?>
<select name="coupon_type" id="dropdown_shop_coupon_type">
<option value=""><?php esc_html_e( 'Show all types', 'woocommerce' ); ?></option>
<?php
$types = wc_get_coupon_types();
foreach ( $types as $name => $type ) {
echo '<option value="' . esc_attr( $name ) . '"';
if ( isset( $_GET['coupon_type'] ) ) { // WPCS: input var ok.
selected( $name, wc_clean( wp_unslash( $_GET['coupon_type'] ) ) ); // WPCS: input var ok, sanitization ok.
}
echo '>' . esc_html( $type ) . '</option>';
}
?>
</select>
<?php
}
/**
* Handle any custom filters.
*
* @param array $query_vars Query vars.
* @return array
*/
protected function query_filters( $query_vars ) {
if ( ! empty( $_GET['coupon_type'] ) ) { // WPCS: input var ok, sanitization ok.
// @codingStandardsIgnoreStart
$query_vars['meta_key'] = 'discount_type';
$query_vars['meta_value'] = wc_clean( wp_unslash( $_GET['coupon_type'] ) ); // WPCS: input var ok, sanitization ok.
// @codingStandardsIgnoreEnd
}
return $query_vars;
}
}
new WC_Admin_List_Table_Coupons();

View File

@ -0,0 +1,611 @@
<?php
/**
* List tables: orders.
*
* @author WooCommerce
* @category Admin
* @package WooCommerce/Admin
* @version 3.3.0
*/
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
if ( class_exists( 'WC_Admin_List_Table_Orders', false ) ) {
new WC_Admin_List_Table_Orders();
return;
}
if ( ! class_exists( 'WC_Admin_List_Table', false ) ) {
include_once( 'abstract-class-wc-admin-list-table.php' );
}
/**
* WC_Admin_List_Table_Orders Class.
*/
class WC_Admin_List_Table_Orders extends WC_Admin_List_Table {
/**
* Post type.
*
* @var string
*/
protected $list_table_type = 'shop_order';
/**
* Constructor.
*/
public function __construct() {
parent::__construct();
add_action( 'admin_notices', array( $this, 'bulk_admin_notices' ) );
add_action( 'admin_footer', array( $this, 'order_preview_template' ) );
add_filter( 'get_search_query', array( $this, 'search_label' ) );
add_filter( 'query_vars', array( $this, 'add_custom_query_var' ) );
add_action( 'parse_query', array( $this, 'search_custom_fields' ) );
}
/**
* Render blank state.
*/
protected function render_blank_state() {
echo '<div class="woocommerce-BlankState">';
echo '<h2 class="woocommerce-BlankState-message">' . esc_html__( 'When you receive a new order, it will appear here.', 'woocommerce' ) . '</h2>';
echo '<a class="woocommerce-BlankState-cta button-primary button" target="_blank" href="https://docs.woocommerce.com/document/managing-orders/?utm_source=blankslate&utm_medium=product&utm_content=ordersdoc&utm_campaign=woocommerceplugin">' . esc_html__( 'Learn more about orders', 'woocommerce' ) . '</a>';
echo '</div>';
}
/**
* Define primary column.
*
* @return array
*/
protected function get_primary_column() {
return 'order_number';
}
/**
* Get row actions to show in the list table.
*
* @param array $actions Array of actions.
* @param WP_Post $post Current post object.
* @return array
*/
protected function get_row_actions( $actions, $post ) {
return array();
}
/**
* Define hidden columns.
*
* @return array
*/
protected function define_hidden_columns() {
return array(
'shipping_address',
'billing_address',
);
}
/**
* Define which columns are sortable.
*
* @param array $columns Existing columns.
* @return array
*/
public function define_sortable_columns( $columns ) {
$custom = array(
'order_number' => 'ID',
'order_total' => 'order_total',
'order_date' => 'date',
);
unset( $columns['comments'] );
return wp_parse_args( $custom, $columns );
}
/**
* Define which columns to show on this screen.
*
* @param array $columns Existing columns.
* @return array
*/
public function define_columns( $columns ) {
$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['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' );
}
wp_enqueue_script( 'wc-orders' );
return $show_columns;
}
/**
* Define bulk actions.
*
* @param array $actions Existing actions.
* @return array
*/
public function define_bulk_actions( $actions ) {
if ( isset( $actions['edit'] ) ) {
unset( $actions['edit'] );
}
$actions['mark_processing'] = __( 'Mark processing', 'woocommerce' );
$actions['mark_on-hold'] = __( 'Mark on-hold', 'woocommerce' );
$actions['mark_completed'] = __( 'Mark complete', 'woocommerce' );
return $actions;
}
/**
* Pre-fetch any data for the row each column has access to it. the_order global is there for bw compat.
*
* @param int $post_id Post ID being shown.
*/
protected function prepare_row_data( $post_id ) {
global $the_order;
if ( empty( $this->object ) || $this->object->get_id() !== $post_id ) {
$this->object = $the_order = wc_get_order( $post_id );
}
}
/**
* Render columm: order_number.
*/
protected function render_order_number_column() {
$buyer = '';
if ( $this->object->get_billing_first_name() || $this->object->get_billing_last_name() ) {
/* translators: 1: first name 2: last name */
$buyer = trim( sprintf( _x( '%1$s %2$s', 'full name', 'woocommerce' ), $this->object->get_billing_first_name(), $this->object->get_billing_last_name() ) );
} elseif ( $this->object->get_billing_company() ) {
$buyer = trim( $this->object->get_billing_company() );
} elseif ( $this->object->get_customer_id() ) {
$user = get_user_by( 'id', $this->object->get_customer_id() );
$buyer = ucwords( $user->display_name );
}
if ( $this->object->get_status() === 'trash' ) {
echo '<strong>#' . esc_attr( $this->object->get_order_number() ) . ' ' . esc_html( $buyer ) . '</strong>';
} else {
echo '<a href="#" class="order-preview" data-order-id="' . absint( $this->object->get_id() ) . '" title="' . esc_attr( __( 'Preview', 'woocommerce' ) ) . '">' . esc_html( __( 'Preview', 'woocommerce' ) ) . '</a>';
echo '<a href="' . esc_url( admin_url( 'post.php?post=' . absint( $this->object->get_id() ) ) . '&action=edit' ) . '" class="order-view"><strong>#' . esc_attr( $this->object->get_order_number() ) . ' ' . esc_html( $buyer ) . '</strong></a>';
}
}
/**
* Render columm: order_status.
*/
protected function render_order_status_column() {
$tooltip = '';
$comment_count = absint( get_comment_count( $this->object->get_id() )['approved'] );
if ( $comment_count ) {
$latest_notes = wc_get_order_notes( array(
'order_id' => $this->object->get_id(),
'limit' => 1,
'orderby' => 'date_created_gmt',
) );
$latest_note = current( $latest_notes );
if ( isset( $latest_note->content ) && 1 === $comment_count ) {
$tooltip = wc_sanitize_tooltip( $latest_note->content );
} elseif ( isset( $latest_note->content ) ) {
/* translators: %d: notes count */
$tooltip = wc_sanitize_tooltip( $latest_note->content . '<br/><small style="display:block">' . sprintf( _n( 'Plus %d other note', 'Plus %d other notes', ( $comment_count - 1 ), 'woocommerce' ), $comment_count - 1 ) . '</small>' );
} else {
/* translators: %d: notes count */
$tooltip = wc_sanitize_tooltip( sprintf( _n( '%d note', '%d notes', $comment_count, 'woocommerce' ), $comment_count ) );
}
}
if ( $tooltip ) {
printf( '<mark class="order-status %s tips" data-tip="%s"><span>%s</span></mark>', esc_attr( sanitize_html_class( 'status-' . $this->object->get_status() ) ), wp_kses_post( $tooltip ), esc_html( wc_get_order_status_name( $this->object->get_status() ) ) );
} else {
printf( '<mark class="order-status %s"><span>%s</span></mark>', esc_attr( sanitize_html_class( 'status-' . $this->object->get_status() ) ), esc_html( wc_get_order_status_name( $this->object->get_status() ) ) );
}
}
/**
* Render columm: order_date.
*/
protected function render_order_date_column() {
$order_timestamp = $this->object->get_date_created()->getTimestamp();
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' ) ) );
}
printf(
'<time datetime="%1$s" title="%2$s">%3$s</time>',
esc_attr( $this->object->get_date_created()->date( 'c' ) ),
esc_html( $this->object->get_date_created()->date_i18n( get_option( 'date_format' ) . ' ' . get_option( 'time_format' ) ) ),
esc_html( $show_date )
);
}
/**
* Render columm: order_total.
*/
protected function render_order_total_column() {
if ( $this->object->get_payment_method_title() ) {
/* translators: %s: method */
echo '<span class="tips" data-tip="' . esc_attr( sprintf( __( 'via %s', 'woocommerce' ), $this->object->get_payment_method_title() ) ) . '">' . wp_kses_post( $this->object->get_formatted_order_total() ) . '</span>';
} else {
echo wp_kses_post( $this->object->get_formatted_order_total() );
}
}
/**
* Render columm: order_actions.
*/
protected function render_order_actions_column() {
echo '<p>';
do_action( 'woocommerce_admin_order_actions_start', $this->object );
$actions = array();
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',
);
}
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',
);
}
$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'] ) );
}
do_action( 'woocommerce_admin_order_actions_end', $this->object );
echo '</p>';
}
/**
* Render columm: billing_address.
*/
protected function render_billing_address_column() {
if ( $address = $this->object->get_formatted_billing_address() ) {
echo esc_html( preg_replace( '#<br\s*/?>#i', ', ', $address ) );
} else {
echo '&ndash;';
}
}
/**
* Render columm: shipping_address.
*/
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>';
} else {
echo '&ndash;';
}
}
/**
* Template for order preview.
*
* @since 3.3.0
*/
public function order_preview_template() {
?>
<script type="text/template" id="tmpl-wc-modal-view-order">
<div class="wc-backbone-modal wc-order-preview">
<div class="wc-backbone-modal-content">
<section class="wc-backbone-modal-main" role="main">
<header class="wc-backbone-modal-header">
<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>
</button>
</header>
<article>
{{{ data.item_html }}}
<div class="wc-order-preview-addresses">
<div class="wc-order-preview-address">
<h2><?php esc_html_e( 'Billing details', 'woocommerce' ); ?></h2>
{{{ data.formatted_billing_address }}}
<# if ( data.data.billing.email ) { #>
<strong><?php esc_html_e( 'Email', 'woocommerce' ); ?></strong>
<a href="mailto:{{ data.data.billing.email }}">{{ data.data.billing.email }}</a>
<# } #>
<# if ( data.data.billing.phone ) { #>
<strong><?php esc_html_e( 'Phone', 'woocommerce' ); ?></strong>
<a href="tel:{{ data.data.billing.phone }}">{{ data.data.billing.phone }}</a>
<# } #>
<# if ( data.payment_via ) { #>
<strong><?php esc_html_e( 'Payment via', 'woocommerce' ); ?></strong>
{{ data.payment_via }}
<# } #>
</div>
<# if ( data.needs_shipping ) { #>
<div class="wc-order-preview-address">
<h2><?php esc_html_e( 'Shipping details', 'woocommerce' ); ?></h2>
<# if ( data.ship_to_billing ) { #>
{{{ data.formatted_billing_address }}}
<# } else { #>
<a href="{{ data.shipping_address_map_url }}" target="_blank">{{{ data.formatted_shipping_address }}}</a>
<# } #>
<# if ( data.data.customer_note ) { #>
<strong><?php esc_html_e( 'Note', 'woocommerce' ); ?></strong>
{{ data.data.customer_note }}
<# } #>
<# if ( data.shipping_via ) { #>
<strong><?php esc_html_e( 'Shipping method', 'woocommerce' ); ?></strong>
{{ data.shipping_via }}
<# } #>
</div>
<# } #>
</div>
</article>
<footer>
<div class="inner">
<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>
</section>
</div>
</div>
<div class="wc-backbone-modal-backdrop modal-close"></div>
</script>
<?php
}
/**
* Handle bulk actions.
*
* @param string $redirect_to URL to redirect to.
* @param string $action Action name.
* @param array $ids List of ids.
* @return string
*/
public function handle_bulk_actions( $redirect_to, $action, $ids ) {
// Bail out if this is not a status-changing action.
if ( false === strpos( $action, 'mark_' ) ) {
return $redirect_to;
}
$order_statuses = wc_get_order_statuses();
$new_status = substr( $action, 5 ); // Get the status name from action.
$report_action = 'marked_' . $new_status;
// Sanity check: bail out if this is actually not a status, or is
// not a registered status.
if ( ! isset( $order_statuses[ 'wc-' . $new_status ] ) ) {
return $redirect_to;
}
$changed = 0;
$ids = array_map( 'absint', $ids );
foreach ( $ids as $id ) {
$order = wc_get_order( $id );
$order->update_status( $new_status, __( 'Order status changed by bulk edit:', 'woocommerce' ), true );
do_action( 'woocommerce_order_edit_status', $id, $new_status );
$changed++;
}
$redirect_to = add_query_arg( array(
'post_type' => $this->list_table_type,
$report_action => true,
'changed' => $changed,
'ids' => join( ',', $ids ),
), $redirect_to );
return esc_url_raw( $redirect_to );
}
/**
* Show confirmation message that order status changed for number of orders.
*/
public function bulk_admin_notices() {
global $post_type, $pagenow;
// Bail out if not on shop order list page.
if ( 'edit.php' !== $pagenow || 'shop_order' !== $post_type ) {
return;
}
$order_statuses = wc_get_order_statuses();
// Check if any status changes happened.
foreach ( $order_statuses as $slug => $name ) {
if ( isset( $_REQUEST[ 'marked_' . str_replace( 'wc-', '', $slug ) ] ) ) { // WPCS: input var ok.
$number = isset( $_REQUEST['changed'] ) ? absint( $_REQUEST['changed'] ) : 0; // WPCS: input var ok.
/* translators: %s: orders count */
$message = sprintf( _n( '%d order status changed.', '%d order statuses changed.', $number, 'woocommerce' ), number_format_i18n( $number ) );
echo '<div class="updated"><p>' . esc_html( $message ) . '</p></div>';
break;
}
}
}
/**
* See if we should render search filters or not.
*/
public function restrict_manage_posts() {
global $typenow;
if ( in_array( $typenow, wc_get_order_types( 'order-meta-boxes' ), true ) ) {
$this->render_filters();
}
}
/**
* Render any custom filters and search inputs for the list table.
*/
protected function render_filters() {
$user_string = '';
$user_id = '';
if ( ! empty( $_GET['_customer_user'] ) ) { // WPCS: input var ok.
$user_id = absint( $_GET['_customer_user'] ); // WPCS: input var ok, sanitization ok.
$user = get_user_by( 'id', $user_id );
/* translators: 1: user display name 2: user ID 3: user email */
$user_string = sprintf(
esc_html__( '%1$s (#%2$s &ndash; %3$s)', 'woocommerce' ),
$user->display_name,
absint( $user->ID ),
$user->user_email
);
}
?>
<select class="wc-customer-search" name="_customer_user" data-placeholder="<?php esc_attr_e( 'Search for a customer&hellip;', 'woocommerce' ); ?>" data-allow_clear="true">
<option value="<?php echo esc_attr( $user_id ); ?>" selected="selected"><?php echo wp_kses_post( $user_string ); ?><option>
</select>
<?php
}
/**
* Handle any filters.
*
* @param array $query_vars Query vars.
* @return array
*/
public function request_query( $query_vars ) {
global $typenow;
if ( in_array( $typenow, wc_get_order_types( 'order-meta-boxes' ), true ) ) {
return $this->query_filters( $query_vars );
}
return $query_vars;
}
/**
* Handle any custom filters.
*
* @param array $query_vars Query vars.
* @return array
*/
protected function query_filters( $query_vars ) {
global $wp_post_statuses;
// Filter the orders by the posted customer.
if ( ! empty( $_GET['_customer_user'] ) ) { // WPCS: input var ok.
// @codingStandardsIgnoreStart
$query_vars['meta_query'] = array(
array(
'key' => '_customer_user',
'value' => (int) $_GET['_customer_user'], // WPCS: input var ok, sanitization ok.
'compare' => '=',
),
);
// @codingStandardsIgnoreEnd
}
// Sorting.
if ( isset( $query_vars['orderby'] ) ) {
if ( 'order_total' === $query_vars['orderby'] ) {
// @codingStandardsIgnoreStart
$query_vars = array_merge( $query_vars, array(
'meta_key' => '_order_total',
'orderby' => 'meta_value_num',
) );
// @codingStandardsIgnoreEnd
}
}
// Status.
if ( ! isset( $query_vars['post_status'] ) ) {
$post_statuses = wc_get_order_statuses();
foreach ( $post_statuses as $status => $value ) {
if ( isset( $wp_post_statuses[ $status ] ) && false === $wp_post_statuses[ $status ]->show_in_admin_all_list ) {
unset( $post_statuses[ $status ] );
}
}
$query_vars['post_status'] = array_keys( $post_statuses );
}
return $query_vars;
}
/**
* Change the label when searching orders.
*
* @param mixed $query Current search query.
* @return string
*/
public function search_label( $query ) {
global $pagenow, $typenow;
if ( 'edit.php' !== $pagenow || 'shop_order' !== $typenow || ! get_query_var( 'shop_order_search' ) || ! isset( $_GET['s'] ) ) { // WPCS: input var ok.
return $query;
}
return wc_clean( wp_unslash( $_GET['s'] ) ); // WPCS: input var ok, sanitization ok.
}
/**
* Query vars for custom searches.
*
* @param mixed $public_query_vars Array of query vars.
* @return array
*/
public function add_custom_query_var( $public_query_vars ) {
$public_query_vars[] = 'shop_order_search';
return $public_query_vars;
}
/**
* Search custom fields as well as content.
*
* @param WP_Query $wp Query object.
*/
public function search_custom_fields( $wp ) {
global $pagenow;
if ( 'edit.php' !== $pagenow || empty( $wp->query_vars['s'] ) || 'shop_order' !== $wp->query_vars['post_type'] || ! isset( $_GET['s'] ) ) { // WPCS: input var ok.
return;
}
$post_ids = wc_order_search( wc_clean( wp_unslash( $_GET['s'] ) ) ); // WPCS: input var ok, sanitization ok.
if ( ! empty( $post_ids ) ) {
// Remove "s" - we don't want to search order name.
unset( $wp->query_vars['s'] );
// so we know we're doing this.
$wp->query_vars['shop_order_search'] = true;
// Search by found posts.
$wp->query_vars['post__in'] = array_merge( $post_ids, array( 0 ) );
}
}
}
new WC_Admin_List_Table_Orders();

View File

@ -0,0 +1,482 @@
<?php
/**
* List tables: products.
*
* @author WooCommerce
* @category Admin
* @package WooCommerce/Admin
* @version 3.3.0
*/
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
if ( class_exists( 'WC_Admin_List_Table_Products', false ) ) {
new WC_Admin_List_Table_Products();
return;
}
if ( ! class_exists( 'WC_Admin_List_Table', false ) ) {
include_once( 'abstract-class-wc-admin-list-table.php' );
}
/**
* WC_Admin_List_Table_Products Class.
*/
class WC_Admin_List_Table_Products extends WC_Admin_List_Table {
/**
* Post type.
*
* @var string
*/
protected $list_table_type = 'product';
/**
* Constructor.
*/
public function __construct() {
parent::__construct();
add_filter( 'disable_months_dropdown', '__return_true' );
add_filter( 'query_vars', array( $this, 'add_custom_query_var' ) );
add_filter( 'posts_search', array( $this, 'sku_search' ) );
add_filter( 'views_edit-product', array( $this, 'product_views' ) );
}
/**
* Render blank state.
*/
protected function render_blank_state() {
echo '<div class="woocommerce-BlankState">';
echo '<h2 class="woocommerce-BlankState-message">' . esc_html__( 'Ready to start selling something awesome?', 'woocommerce' ) . '</h2>';
echo '<a class="woocommerce-BlankState-cta button-primary button" href="' . esc_url( admin_url( 'post-new.php?post_type=product&tutorial=true' ) ) . '">' . esc_html__( 'Create your first product!', 'woocommerce' ) . '</a>';
echo '<a class="woocommerce-BlankState-cta button" href="' . esc_url( admin_url( 'edit.php?post_type=product&page=product_importer' ) ) . '">' . esc_html__( 'Import products from a CSV file', 'woocommerce' ) . '</a>';
echo '</div>';
}
/**
* Define primary column.
*
* @return array
*/
protected function get_primary_column() {
return 'name';
}
/**
* Define which columns are sortable.
*
* @param array $columns Existing columns.
* @return array
*/
public function define_sortable_columns( $columns ) {
$custom = array(
'price' => 'price',
'sku' => 'sku',
'name' => 'title',
);
return wp_parse_args( $custom, $columns );
}
/**
* Define which columns to show on this screen.
*
* @param array $columns Existing columns.
* @return array
*/
public function define_columns( $columns ) {
if ( empty( $columns ) && ! is_array( $columns ) ) {
$columns = array();
}
unset( $columns['title'], $columns['comments'], $columns['date'] );
$show_columns = array();
$show_columns['cb'] = '<input type="checkbox" />';
$show_columns['thumb'] = '<span class="wc-image tips" data-tip="' . esc_attr__( 'Image', 'woocommerce' ) . '">' . __( 'Image', 'woocommerce' ) . '</span>';
$show_columns['name'] = __( 'Name', 'woocommerce' );
if ( wc_product_sku_enabled() ) {
$show_columns['sku'] = __( 'SKU', 'woocommerce' );
}
if ( 'yes' === get_option( 'woocommerce_manage_stock' ) ) {
$show_columns['is_in_stock'] = __( 'Stock', 'woocommerce' );
}
$show_columns['price'] = __( 'Price', 'woocommerce' );
$show_columns['product_cat'] = __( 'Categories', 'woocommerce' );
$show_columns['product_tag'] = __( 'Tags', 'woocommerce' );
$show_columns['featured'] = '<span class="wc-featured parent-tips" data-tip="' . esc_attr__( 'Featured', 'woocommerce' ) . '">' . __( 'Featured', 'woocommerce' ) . '</span>';
$show_columns['product_type'] = '<span class="wc-type parent-tips" data-tip="' . esc_attr__( 'Type', 'woocommerce' ) . '">' . __( 'Type', 'woocommerce' ) . '</span>';
$show_columns['date'] = __( 'Date', 'woocommerce' );
return array_merge( $show_columns, $columns );
}
/**
* Pre-fetch any data for the row each column has access to it. the_product global is there for bw compat.
*
* @param int $post_id Post ID being shown.
*/
protected function prepare_row_data( $post_id ) {
global $the_product;
if ( empty( $this->object ) || $this->object->get_id() !== $post_id ) {
$this->object = $the_product = wc_get_product( $post_id );
}
}
/**
* Render columm: thumb.
*/
protected function render_thumb_column() {
echo '<a href="' . esc_url( get_edit_post_link( $this->object->get_id() ) ) . '">' . wp_kses_post( $this->object->get_image( 'thumbnail' ) ) . '</a>';
}
/**
* Render columm: name.
*/
protected function render_name_column() {
global $post;
$edit_link = get_edit_post_link( $this->object->get_id() );
$title = _draft_or_post_title();
echo '<strong><a class="row-title" href="' . esc_url( $edit_link ) . '">' . esc_html( $title ) . '</a>';
_post_states( $post );
echo '</strong>';
if ( $this->object->get_parent_id() > 0 ) {
echo '&nbsp;&nbsp;&larr; <a href="' . esc_url( get_edit_post_link( $this->object->get_parent_id() ) ) . '">' . get_the_title( $this->object->get_parent_id() ) . '</a>';
}
get_inline_data( $post );
/* Custom inline data for woocommerce. */
echo '
<div class="hidden" id="woocommerce_inline_' . absint( $this->object->get_id() ) . '">
<div class="menu_order">' . absint( $this->object->get_menu_order() ) . '</div>
<div class="sku">' . esc_html( $this->object->get_sku() ) . '</div>
<div class="regular_price">' . esc_html( $this->object->get_regular_price() ) . '</div>
<div class="sale_price">' . esc_html( $this->object->get_sale_price() ) . '</div>
<div class="weight">' . esc_html( $this->object->get_weight() ) . '</div>
<div class="length">' . esc_html( $this->object->get_length() ) . '</div>
<div class="width">' . esc_html( $this->object->get_width() ) . '</div>
<div class="height">' . esc_html( $this->object->get_height() ) . '</div>
<div class="shipping_class">' . esc_html( $this->object->get_shipping_class() ) . '</div>
<div class="visibility">' . esc_html( $this->object->get_catalog_visibility() ) . '</div>
<div class="stock_status">' . esc_html( $this->object->get_stock_status() ) . '</div>
<div class="stock">' . esc_html( $this->object->get_stock_quantity() ) . '</div>
<div class="manage_stock">' . esc_html( wc_bool_to_string( $this->object->get_manage_stock() ) ) . '</div>
<div class="featured">' . esc_html( wc_bool_to_string( $this->object->get_featured() ) ) . '</div>
<div class="product_type">' . esc_html( $this->object->get_type() ) . '</div>
<div class="product_is_virtual">' . esc_html( wc_bool_to_string( $this->object->get_virtual() ) ) . '</div>
<div class="tax_status">' . esc_html( $this->object->get_tax_status() ) . '</div>
<div class="tax_class">' . esc_html( $this->object->get_tax_class() ) . '</div>
<div class="backorders">' . esc_html( $this->object->get_backorders() ) . '</div>
</div>
';
}
/**
* Render columm: sku.
*/
protected function render_sku_column() {
echo $this->object->get_sku() ? esc_html( $this->object->get_sku() ) : '<span class="na">&ndash;</span>';
}
/**
* Render columm: product_type.
*/
protected function render_product_type_column() {
if ( $this->object->is_type( 'grouped' ) ) {
echo '<span class="product-type tips grouped" data-tip="' . esc_attr__( 'Grouped', 'woocommerce' ) . '"></span>';
} elseif ( $this->object->is_type( 'external' ) ) {
echo '<span class="product-type tips external" data-tip="' . esc_attr__( 'External/Affiliate', 'woocommerce' ) . '"></span>';
} elseif ( $this->object->is_type( 'simple' ) ) {
if ( $this->object->is_virtual() ) {
echo '<span class="product-type tips virtual" data-tip="' . esc_attr__( 'Virtual', 'woocommerce' ) . '"></span>';
} elseif ( $this->object->is_downloadable() ) {
echo '<span class="product-type tips downloadable" data-tip="' . esc_attr__( 'Downloadable', 'woocommerce' ) . '"></span>';
} else {
echo '<span class="product-type tips simple" data-tip="' . esc_attr__( 'Simple', 'woocommerce' ) . '"></span>';
}
} elseif ( $this->object->is_type( 'variable' ) ) {
echo '<span class="product-type tips variable" data-tip="' . esc_attr__( 'Variable', 'woocommerce' ) . '"></span>';
} else {
// Assuming that we have other types in future.
echo '<span class="product-type tips ' . esc_attr( sanitize_html_class( $this->object->get_type() ) ) . '" data-tip="' . esc_attr( ucfirst( $this->object->get_type() ) ) . '"></span>';
}
}
/**
* Render columm: price.
*/
protected function render_price_column() {
echo $this->object->get_price_html() ? wp_kses_post( $this->object->get_price_html() ) : '<span class="na">&ndash;</span>';
}
/**
* Render columm: product_cat.
*/
protected function render_product_cat_column() {
if ( ! $terms = get_the_terms( $this->object->get_id(), 'product_cat' ) ) {
echo '<span class="na">&ndash;</span>';
} else {
$termlist = array();
foreach ( $terms as $term ) {
$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.
}
}
/**
* Render columm: product_tag.
*/
protected function render_product_tag_column() {
if ( ! $terms = get_the_terms( $this->object->get_id(), 'product_tag' ) ) {
echo '<span class="na">&ndash;</span>';
} else {
$termlist = array();
foreach ( $terms as $term ) {
$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.
}
}
/**
* Render columm: featured.
*/
protected function render_featured_column() {
$url = wp_nonce_url( admin_url( 'admin-ajax.php?action=woocommerce_feature_product&product_id=' . $this->object->get_id() ), 'woocommerce-feature-product' );
echo '<a href="' . esc_url( $url ) . '" aria-label="' . esc_attr__( 'Toggle featured', 'woocommerce' ) . '">';
if ( $this->object->is_featured() ) {
echo '<span class="wc-featured tips" data-tip="' . esc_attr__( 'Yes', 'woocommerce' ) . '">' . esc_html__( 'Yes', 'woocommerce' ) . '</span>';
} else {
echo '<span class="wc-featured not-featured tips" data-tip="' . esc_attr__( 'No', 'woocommerce' ) . '">' . esc_html__( 'No', 'woocommerce' ) . '</span>';
}
echo '</a>';
}
/**
* Render columm: is_in_stock.
*/
protected function render_is_in_stock_column() {
if ( $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>';
}
if ( $this->object->managing_stock() ) {
$stock_html .= ' (' . wc_stock_amount( $this->object->get_stock_quantity() ) . ')';
}
echo wp_kses_post( apply_filters( 'woocommerce_admin_stock_html', $stock_html, $this->object ) );
}
/**
* Query vars for custom searches.
*
* @param mixed $public_query_vars Array of query vars.
* @return array
*/
public function add_custom_query_var( $public_query_vars ) {
$public_query_vars[] = 'sku';
return $public_query_vars;
}
/**
* Render any custom filters and search inputs for the list table.
*/
protected function render_filters() {
$current_category_slug = isset( $_REQUEST['product_cat'] ) ? wc_clean( wp_unslash( $_REQUEST['product_cat'] ) ) : false; // WPCS: input var ok, sanitization ok.
$current_product_type = isset( $_REQUEST['product_type'] ) ? wc_clean( wp_unslash( $_REQUEST['product_type'] ) ) : false; // WPCS: input var ok, sanitization ok.
// @codingStandardsIgnoreStart
$current_category = $current_category_slug ? get_term_by( 'slug', $current_category_slug, 'product_cat' ): false;
// @codingStandardsIgnoreEnd
?>
<select class="wc-category-search" name="product_cat" data-placeholder="<?php esc_attr_e( 'Filter by category', 'woocommerce' ); ?>" data-allow_clear="true">
<?php if ( $current_category_slug && $current_category ) : ?>
<option value="<?php echo esc_attr( $current_category_slug ); ?>" selected="selected"><?php echo esc_html( $current_category->name ); ?><option>
<?php endif; ?>
</select>
<?php
$terms = get_terms( 'product_type' );
$output = '<select name="product_type" id="dropdown_product_type">';
$output .= '<option value="">' . __( 'Filter by product type', 'woocommerce' ) . '</option>';
foreach ( $terms as $term ) {
$output .= '<option value="' . sanitize_title( $term->name ) . '" ';
$output .= selected( $term->slug, $current_product_type, false );
$output .= '>';
switch ( $term->name ) {
case 'grouped' :
$output .= __( 'Grouped product', 'woocommerce' );
break;
case 'external' :
$output .= __( 'External/Affiliate product', 'woocommerce' );
break;
case 'variable' :
$output .= __( 'Variable product', 'woocommerce' );
break;
case 'simple' :
$output .= __( 'Simple product', 'woocommerce' );
break;
default :
// Assuming that we have other types in future.
$output .= ucfirst( $term->name );
break;
}
$output .= '</option>';
if ( 'simple' === $term->name ) {
$output .= '<option value="downloadable" ';
if ( isset( $wp_query->query['product_type'] ) ) {
$output .= selected( 'downloadable', $current_product_type, false );
}
$output .= '> ' . ( is_rtl() ? '&larr;' : '&rarr;' ) . ' ' . __( 'Downloadable', 'woocommerce' ) . '</option>';
$output .= '<option value="virtual" ';
$output .= selected( 'virtual', $current_product_type, false );
$output .= '> ' . ( is_rtl() ? '&larr;' : '&rarr;' ) . ' ' . __( 'Virtual', 'woocommerce' ) . '</option>';
}
}
$output .= '</select>';
echo apply_filters( 'woocommerce_product_filters', $output ); // WPCS: XSS ok.
}
/**
* Handle any custom filters.
*
* @param array $query_vars Query vars.
* @return array
*/
protected function query_filters( $query_vars ) {
if ( isset( $query_vars['orderby'] ) ) {
if ( 'price' === $vars['orderby'] ) {
// @codingStandardsIgnoreStart
$query_vars = array_merge( $query_vars, array(
'meta_key' => '_price',
'orderby' => 'meta_value_num',
) );
// @codingStandardsIgnoreEnd
}
if ( 'sku' === $query_vars['orderby'] ) {
// @codingStandardsIgnoreStart
$query_vars = array_merge( $query_vars, array(
'meta_key' => '_sku',
'orderby' => 'meta_value',
) );
// @codingStandardsIgnoreEnd
}
}
if ( isset( $query_vars['product_type'] ) ) {
// @codingStandardsIgnoreStart
if ( 'downloadable' === $query_vars['product_type'] ) {
$query_vars['product_type'] = '';
$query_vars['meta_value'] = 'yes';
$query_vars['meta_key'] = '_downloadable';
} elseif ( 'virtual' === $query_vars['product_type'] ) {
$query_vars['product_type'] = '';
$query_vars['meta_value'] = 'yes';
$query_vars['meta_key'] = '_virtual';
}
// @codingStandardsIgnoreEnd
}
if ( isset( $_GET['product_shipping_class'] ) && '0' === $_GET['product_shipping_class'] ) { // WPCS: input var ok.
$query_vars['tax_query'][] = array(
'taxonomy' => 'product_shipping_class',
'field' => 'id',
'terms' => get_terms( 'product_shipping_class', array( 'fields' => 'ids' ) ),
'operator' => 'NOT IN',
);
}
return $query_vars;
}
/**
* Search by SKU or ID for products.
*
* @param string $where Where clause SQL.
* @return string
*/
public function sku_search( $where ) {
global $pagenow, $wpdb, $wp;
if ( 'edit.php' !== $pagenow || ! is_search() || ! isset( $wp->query_vars['s'] ) || 'product' !== $wp->query_vars['post_type'] ) {
return $where;
}
$search_ids = array();
$terms = explode( ',', $wp->query_vars['s'] );
foreach ( $terms as $term ) {
if ( is_numeric( $term ) ) {
$search_ids[] = absint( $term );
} else {
$id_from_sku = wc_get_product_id_by_sku( wc_clean( $term ) );
if ( $id_from_sku ) {
$search_ids[] = absint( $id_from_sku );
}
}
}
$search_ids = array_filter( array_unique( array_map( 'absint', $search_ids ) ) );
if ( count( $search_ids ) > 0 ) {
$where = str_replace( 'AND (((', "AND ( ({$wpdb->posts}.ID IN (" . implode( ',', $search_ids ) . ')) OR ((', $where );
}
return $where;
}
/**
* Change views on the edit product screen.
*
* @param array $views Array of views.
* @return array
*/
public function product_views( $views ) {
global $wp_query;
// Products do not have authors.
unset( $views['mine'] );
// Add sorting link.
if ( current_user_can( 'edit_others_pages' ) ) {
$class = ( isset( $wp_query->query['orderby'] ) && 'menu_order title' === $wp_query->query['orderby'] ) ? 'current' : '';
$query_string = remove_query_arg( array( 'orderby', 'order' ) );
$query_string = add_query_arg( 'orderby', rawurlencode( 'menu_order title' ), $query_string );
$query_string = add_query_arg( 'order', rawurlencode( 'ASC' ), $query_string );
$views['byorder'] = '<a href="' . esc_url( $query_string ) . '" class="' . esc_attr( $class ) . '">' . __( 'Sorting', 'woocommerce' ) . '</a>';
}
return $views;
}
}
new WC_Admin_List_Table_Products();

View File

@ -18,7 +18,7 @@ $thumbnail = $product ? apply_filters( 'woocommerce_admin_order_item_thumbnai
</td>
<td class="name" data-sort-value="<?php echo esc_attr( $item->get_name() ); ?>">
<?php
echo $product_link ? '<a href="' . esc_url( $product_link ) . '" class="wc-order-item-name">' . esc_html( $item->get_name() ) . '</a>' : '<div class="class="wc-order-item-name"">' . esc_html( $item->get_name() ) . '</div>';
echo $product_link ? '<a href="' . esc_url( $product_link ) . '" class="wc-order-item-name">' . esc_html( $item->get_name() ) . '</a>' : '<div class=""wc-order-item-name">' . esc_html( $item->get_name() ) . '</div>';
if ( $product && $product->get_sku() ) {
echo '<div class="wc-order-item-sku"><strong>' . __( 'SKU:', 'woocommerce' ) . '</strong> ' . esc_html( $product->get_sku() ) . '</div>';

View File

@ -308,6 +308,6 @@ if ( ! defined( 'ABSPATH' ) ) {
<?php do_action( 'woocommerce_product_bulk_edit_end' ); ?>
<input type="hidden" name="woocommerce_bulk_edit" value="1" />
<input type="hidden" name="woocommerce_bulk_edit_nonce" value="<?php echo wp_create_nonce( 'woocommerce_bulk_edit_nonce' ); ?>" />
<input type="hidden" name="woocommerce_quick_edit_nonce" value="<?php echo wp_create_nonce( 'woocommerce_quick_edit_nonce' ); ?>" />
</div>
</fieldset>

View File

@ -99,6 +99,7 @@ class WC_AJAX {
'get_customer_location' => true,
'feature_product' => false,
'mark_order_status' => false,
'get_order_details' => false,
'add_attribute' => false,
'add_new_attribute' => false,
'remove_variation' => false,
@ -472,6 +473,97 @@ class WC_AJAX {
exit;
}
/**
* Get order details.
*/
public static function get_order_details() {
check_admin_referer( 'woocommerce-preview-order', 'security' );
if ( ! current_user_can( 'edit_shop_orders' ) ) {
wp_die( -1 );
}
if ( $order = wc_get_order( absint( $_GET['order_id'] ) ) ) {
ob_start();
$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( 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(),
) );
}
exit;
}
/**
* Add an attribute row.
*/

View File

@ -32,11 +32,11 @@ class WC_Comments {
// Secure order notes
add_filter( 'comments_clauses', array( __CLASS__, 'exclude_order_comments' ), 10, 1 );
add_action( 'comment_feed_where', array( __CLASS__, 'exclude_order_comments_from_feed_where' ) );
add_filter( 'comment_feed_where', array( __CLASS__, 'exclude_order_comments_from_feed_where' ) );
// Secure webhook comments
add_filter( 'comments_clauses', array( __CLASS__, 'exclude_webhook_comments' ), 10, 1 );
add_action( 'comment_feed_where', array( __CLASS__, 'exclude_webhook_comments_from_feed_where' ) );
add_filter( 'comment_feed_where', array( __CLASS__, 'exclude_webhook_comments_from_feed_where' ) );
// Count comments
add_filter( 'wp_count_comments', array( __CLASS__, 'wp_count_comments' ), 10, 2 );

View File

@ -353,7 +353,8 @@ class WC_Discounts {
$price_to_discount = ( 'yes' === get_option( 'woocommerce_calc_discounts_sequentially', 'no' ) ) ? $discounted_price : $item->price;
// See how many and what price to apply to.
$apply_quantity = max( 0, ( $limit_usage_qty && ( $limit_usage_qty - $applied_count ) < $item->quantity ? $limit_usage_qty - $applied_count : $item->quantity ) );
$apply_quantity = $limit_usage_qty && ( $limit_usage_qty - $applied_count ) < $item->quantity ? $limit_usage_qty - $applied_count : $item->quantity;
$apply_quantity = max( 0, apply_filters( 'woocommerce_coupon_get_apply_quantity', $apply_quantity, $item, $coupon, $this ) );
$price_to_discount = ( $price_to_discount / $item->quantity ) * $apply_quantity;
// Run coupon calculations.
@ -416,10 +417,11 @@ class WC_Discounts {
// Run coupon calculations.
if ( $limit_usage_qty ) {
$apply_quantity = max( 0, ( $limit_usage_qty - $applied_count < $item->quantity ? $limit_usage_qty - $applied_count: $item->quantity ) );
$apply_quantity = $limit_usage_qty - $applied_count < $item->quantity ? $limit_usage_qty - $applied_count : $item->quantity;
$apply_quantity = max( 0, apply_filters( 'woocommerce_coupon_get_apply_quantity', $apply_quantity, $item, $coupon, $this ) );
$discount = min( $amount, $item->price / $item->quantity ) * $apply_quantity;
} else {
$apply_quantity = $item->quantity;
$apply_quantity = apply_filters( 'woocommerce_coupon_get_apply_quantity', $item->quantity, $item, $coupon, $this );
$discount = $amount * $apply_quantity;
}

View File

@ -359,7 +359,9 @@ class WC_Download_Handler {
* @return bool Success or fail
*/
public static function readfile_chunked( $file ) {
$chunksize = 1024 * 1024;
if ( ! defined( 'WC_CHUNK_SIZE' ) ) {
define( 'WC_CHUNK_SIZE', 1024 * 1024 );
}
$handle = @fopen( $file, 'r' );
if ( false === $handle ) {
@ -367,7 +369,7 @@ class WC_Download_Handler {
}
while ( ! @feof( $handle ) ) {
echo @fread( $handle, $chunksize );
echo @fread( $handle, (int) WC_CHUNK_SIZE );
if ( ob_get_length() ) {
ob_flush();

View File

@ -834,8 +834,8 @@ class WC_Form_Handler {
*/
private static function add_to_cart_handler_variable( $product_id ) {
try {
$variation_id = empty( $_REQUEST['variation_id'] ) ? '' : absint( $_REQUEST['variation_id'] );
$quantity = empty( $_REQUEST['quantity'] ) ? 1 : wc_stock_amount( $_REQUEST['quantity'] );
$variation_id = empty( $_REQUEST['variation_id'] ) ? '' : absint( wp_unslash( $_REQUEST['variation_id'] ) );
$quantity = empty( $_REQUEST['quantity'] ) ? 1 : wc_stock_amount( wp_unslash( $_REQUEST['quantity'] ) ); // WPCS: sanitization ok.
$missing_attributes = array();
$variations = array();
$adding_to_cart = wc_get_product( $product_id );
@ -873,19 +873,23 @@ class WC_Form_Handler {
continue;
}
$taxonomy = 'attribute_' . sanitize_title( $attribute['name'] );
// Get valid value from variation data.
$taxonomy = 'attribute_' . sanitize_title( $attribute['name'] );
$valid_value = isset( $variation_data[ $taxonomy ] ) ? $variation_data[ $taxonomy ] : '';
/**
* If the attribute value was posted, check if it's valid.
*
* If no attribute was posted, only error if the variation has an 'any' attribute which requires a value.
*/
if ( isset( $_REQUEST[ $taxonomy ] ) ) {
if ( $attribute['is_taxonomy'] ) {
// Don't use wc_clean as it destroys sanitized characters.
$value = sanitize_title( wp_unslash( $_REQUEST[ $taxonomy ] ) );
} else {
$value = wc_clean( wp_unslash( $_REQUEST[ $taxonomy ] ) );
$value = wc_clean( wp_unslash( $_REQUEST[ $taxonomy ] ) ); // WPCS: sanitization ok.
}
// Get valid value from variation data.
$valid_value = isset( $variation_data[ $taxonomy ] ) ? $variation_data[ $taxonomy ] : '';
// Allow if valid or show error.
if ( $valid_value === $value ) {
$variations[ $taxonomy ] = $value;
@ -895,7 +899,7 @@ class WC_Form_Handler {
} else {
throw new Exception( sprintf( __( 'Invalid value posted for %s', 'woocommerce' ), wc_attribute_label( $attribute['name'] ) ) );
}
} else {
} elseif ( '' === $valid_value ) {
$missing_attributes[] = wc_attribute_label( $attribute['name'] );
}
}

View File

@ -502,9 +502,25 @@ class WC_Query {
* @return array
*/
public function order_by_price_asc_post_clauses( $args ) {
global $wpdb;
$args['join'] .= " INNER JOIN ( SELECT post_id, min( meta_value+0 ) price FROM $wpdb->postmeta WHERE meta_key='_price' GROUP BY post_id ) as price_query ON $wpdb->posts.ID = price_query.post_id ";
$args['orderby'] = " price_query.price ASC ";
global $wpdb, $wp_query;
if ( isset( $wp_query->queried_object, $wp_query->queried_object->term_taxonomy_id, $wp_query->queried_object->taxonomy ) && is_a( $wp_query->queried_object, 'WP_Term' ) ) {
$search_within_terms = get_term_children( $wp_query->queried_object->term_taxonomy_id, $wp_query->queried_object->taxonomy );
$search_within_terms[] = $wp_query->queried_object->term_taxonomy_id;
$args['join'] .= " INNER JOIN (
SELECT post_id, max( meta_value+0 ) price
FROM $wpdb->postmeta
INNER JOIN (
SELECT $wpdb->term_relationships.object_id
FROM $wpdb->term_relationships
WHERE 1=1
AND $wpdb->term_relationships.term_taxonomy_id IN (" . implode( ',', array_map( 'absint', $search_within_terms ) ) . ")
) as products_within_terms ON $wpdb->postmeta.post_id = products_within_terms.object_id
WHERE meta_key='_price' GROUP BY post_id ) as price_query ON $wpdb->posts.ID = price_query.post_id ";
} else {
$args['join'] .= " INNER JOIN ( SELECT post_id, min( meta_value+0 ) price FROM $wpdb->postmeta WHERE meta_key='_price' GROUP BY post_id ) as price_query ON $wpdb->posts.ID = price_query.post_id ";
}
$args['orderby'] = ' price_query.price ASC ';
return $args;
}
@ -535,8 +551,7 @@ class WC_Query {
$args['join'] .= " INNER JOIN ( SELECT post_id, max( meta_value+0 ) price FROM $wpdb->postmeta WHERE meta_key='_price' GROUP BY post_id ) as price_query ON $wpdb->posts.ID = price_query.post_id ";
}
$args['orderby'] = " price_query.price DESC ";
$args['orderby'] = ' price_query.price DESC ';
return $args;
}

View File

@ -36,6 +36,11 @@ return array(
'desc_tip' => true,
'placeholder' => 'you@youremail.com',
),
'advanced' => array(
'title' => __( 'Advanced options', 'woocommerce' ),
'type' => 'title',
'description' => '',
),
'testmode' => array(
'title' => __( 'PayPal sandbox', 'woocommerce' ),
'type' => 'checkbox',
@ -53,14 +58,9 @@ return array(
'ipn_notification' => array(
'title' => __( 'IPN Email Notifications', 'woocommerce' ),
'type' => 'checkbox',
'label' => __( 'Enable IPN email notification', 'woocommerce' ),
'label' => __( 'Enable IPN email notifications', 'woocommerce' ),
'default' => 'yes',
'description' => __( 'Send an email to the user handling orders when an IPN is received from PayPal.', 'woocommerce' )
),
'advanced' => array(
'title' => __( 'Advanced options', 'woocommerce' ),
'type' => 'title',
'description' => '',
'description' => __( 'Send notifications when an IPN is received from PayPal indicating refunds, chargebacks and cancellations.', 'woocommerce' ),
),
'receiver_email' => array(
'title' => __( 'Receiver email', 'woocommerce' ),

View File

@ -222,7 +222,7 @@ if ( ! function_exists( 'is_add_payment_method_page' ) ) {
function is_add_payment_method_page() {
global $wp;
return ( is_page( wc_get_page_id( 'myaccount' ) ) && isset( $wp->query_vars['add-payment-method'] ) );
return ( is_page( wc_get_page_id( 'myaccount' ) ) && ( isset( $wp->query_vars['payment-methods'] ) || isset( $wp->query_vars['add-payment-method'] ) ) );
}
}

View File

@ -83,7 +83,7 @@ class WC_Widget_Recently_Viewed extends WC_Widget {
);
}
$r = new WP_Query( $query_args );
$r = new WP_Query( apply_filters( 'woocommerce_recently_viewed_products_widget_query_args', $query_args ) );
if ( $r->have_posts() ) {

View File

@ -55,4 +55,6 @@ if ( $available_gateways = WC()->payment_gateways->get_available_payment_gateway
</div>
</div>
</form>
<?php else : ?>
<p class="woocommerce-notice woocommerce-notice--info woocommerce-info"><?php esc_html_e( 'New payment methods can only be added during checkout. Please contact us if you require assistance.', 'woocommerce' ); ?></p>
<?php endif; ?>

View File

@ -76,4 +76,6 @@ do_action( 'woocommerce_before_account_payment_methods', $has_methods ); ?>
<?php do_action( 'woocommerce_after_account_payment_methods', $has_methods ); ?>
<a class="button" href="<?php echo esc_url( wc_get_endpoint_url( 'add-payment-method' ) ); ?>"><?php esc_html_e( 'Add payment method', 'woocommerce' ); ?></a>
<?php if ( WC()->payment_gateways->get_available_payment_gateways() ) : ?>
<a class="button" href="<?php echo esc_url( wc_get_endpoint_url( 'add-payment-method' ) ); ?>"><?php esc_html_e( 'Add payment method', 'woocommerce' ); ?></a>
<?php endif; ?>