Merge branch 'master' into fix/19175

This commit is contained in:
Mike Jolley 2018-03-13 18:14:36 +00:00
commit cb3c4849b4
168 changed files with 7381 additions and 5932 deletions

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -917,6 +917,18 @@ button.pswp__button--zoom:hover {
}
}
.woocommerce-no-js {
form.woocommerce-form-login,
form.woocommerce-form-coupon {
display: block !important;
}
.woocommerce-form-login-toggle,
.woocommerce-form-coupon-toggle,
.showcoupon {
display: none !important;
}
}
.woocommerce-terms-and-conditions {
border: 1px solid rgba(0,0,0,.2);
box-shadow: inset 0 1px 2px rgba(0,0,0,.1);

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -1300,7 +1300,7 @@ p.demo_store,
width: 100%;
margin: 0;
outline: 0;
line-height: 1;
line-height: normal;
}
textarea {
@ -1621,6 +1621,18 @@ p.demo_store,
}
}
.woocommerce-no-js {
form.woocommerce-form-login,
form.woocommerce-form-coupon {
display: block !important;
}
.woocommerce-form-login-toggle,
.woocommerce-form-coupon-toggle,
.showcoupon {
display: none !important;
}
}
/**
* Photoswipe
* 1. These styles are required to overwrite default theme button styles (Twenty Twelve adds gradients via background-image).
@ -1807,13 +1819,11 @@ button.pswp__button--zoom:hover {
padding: 6px 6px 5px;
margin: 0 4px 0 0;
outline: 0;
line-height: 1;
}
input {
margin: 0;
vertical-align: middle;
line-height: 1;
}
}

View File

@ -112,9 +112,6 @@ jQuery( function ( $ ) {
if ( ! $country_input.val() ) {
$country_input.val( woocommerce_admin_meta_boxes_order.default_country ).change();
}
if ( ! $state_input.val() ) {
$state_input.val( woocommerce_admin_meta_boxes_order.default_state ).change();
}

File diff suppressed because one or more lines are too long

View File

@ -13,6 +13,7 @@
this.variationData = $form.data( 'product_variations' );
this.useAjax = false === this.variationData;
this.xhr = false;
this.loading = true;
// Initial state.
this.$singleVariationWrap.show();
@ -41,6 +42,7 @@
setTimeout( function() {
$form.trigger( 'check_variations' );
$form.trigger( 'wc_variation_form' );
$form.loading = false;
}, 100 );
};
@ -145,8 +147,12 @@
form.$form.trigger( 'found_variation', [ variation ] );
} else {
form.$form.trigger( 'reset_data' );
form.$form.find( '.single_variation' ).after( '<p class="wc-no-matching-variations woocommerce-info">' + wc_add_to_cart_variation_params.i18n_no_matching_variations_text + '</p>' );
form.$form.find( '.wc-no-matching-variations' ).slideDown( 200 );
attributes.chosenCount = 0;
if ( ! form.loading ) {
form.$form.find( '.single_variation' ).after( '<p class="wc-no-matching-variations woocommerce-info">' + wc_add_to_cart_variation_params.i18n_no_matching_variations_text + '</p>' );
form.$form.find( '.wc-no-matching-variations' ).slideDown( 200 );
}
}
},
complete: function() {
@ -163,8 +169,12 @@
form.$form.trigger( 'found_variation', [ variation ] );
} else {
form.$form.trigger( 'reset_data' );
form.$form.find( '.single_variation' ).after( '<p class="wc-no-matching-variations woocommerce-info">' + wc_add_to_cart_variation_params.i18n_no_matching_variations_text + '</p>' );
form.$form.find( '.wc-no-matching-variations' ).slideDown( 200 );
attributes.chosenCount = 0;
if ( ! form.loading ) {
form.$form.find( '.single_variation' ).after( '<p class="wc-no-matching-variations woocommerce-info">' + wc_add_to_cart_variation_params.i18n_no_matching_variations_text + '</p>' );
form.$form.find( '.wc-no-matching-variations' ).slideDown( 200 );
}
}
}
} else {
@ -555,8 +565,9 @@
$product_link = $product_img_wrap.find( 'a' ).eq( 0 );
if ( variation && variation.image && variation.image.src && variation.image.src.length > 1 ) {
if ( $gallery_nav.find( 'li img[src="' + variation.image.thumb_src + '"]' ).length > 0 ) {
$gallery_nav.find( 'li img[src="' + variation.image.thumb_src + '"]' ).trigger( 'click' );
if ( $gallery_nav.find( 'li img[src="' + variation.image.gallery_thumbnail_src + '"]' ).length > 0 ) {
$form.wc_variations_image_reset();
$gallery_nav.find( 'li img[src="' + variation.image.gallery_thumbnail_src + '"]' ).trigger( 'click' );
$form.attr( 'current-image', variation.image_id );
return;
} else {
@ -572,24 +583,11 @@
$product_img.wc_set_variation_attr( 'data-large_image_width', variation.image.full_src_w );
$product_img.wc_set_variation_attr( 'data-large_image_height', variation.image.full_src_h );
$product_img_wrap.wc_set_variation_attr( 'data-thumb', variation.image.src );
$gallery_img.wc_set_variation_attr( 'src', variation.image.thumb_src );
$gallery_img.wc_set_variation_attr( 'src', variation.image.gallery_thumbnail_src );
$product_link.wc_set_variation_attr( 'href', variation.image.full_src );
}
} else {
$product_img.wc_reset_variation_attr( 'src' );
$product_img.wc_reset_variation_attr( 'width' );
$product_img.wc_reset_variation_attr( 'height' );
$product_img.wc_reset_variation_attr( 'srcset' );
$product_img.wc_reset_variation_attr( 'sizes' );
$product_img.wc_reset_variation_attr( 'title' );
$product_img.wc_reset_variation_attr( 'alt' );
$product_img.wc_reset_variation_attr( 'data-src' );
$product_img.wc_reset_variation_attr( 'data-large_image' );
$product_img.wc_reset_variation_attr( 'data-large_image_width' );
$product_img.wc_reset_variation_attr( 'data-large_image_height' );
$product_img_wrap.wc_reset_variation_attr( 'data-thumb' );
$gallery_img.wc_reset_variation_attr( 'src' );
$product_link.wc_reset_variation_attr( 'href' );
$form.wc_variations_image_reset();
}
window.setTimeout( function() {
@ -599,6 +597,35 @@
}, 20 );
};
/**
* Reset main image to defaults.
*/
$.fn.wc_variations_image_reset = function() {
var $form = this,
$product = $form.closest( '.product' ),
$product_gallery = $product.find( '.images' ),
$gallery_nav = $product.find( '.flex-control-nav' ),
$gallery_img = $gallery_nav.find( 'li:eq(0) img' ),
$product_img_wrap = $product_gallery.find( '.woocommerce-product-gallery__image, .woocommerce-product-gallery__image--placeholder' ).eq( 0 ),
$product_img = $product_img_wrap.find( '.wp-post-image' ),
$product_link = $product_img_wrap.find( 'a' ).eq( 0 );
$product_img.wc_reset_variation_attr( 'src' );
$product_img.wc_reset_variation_attr( 'width' );
$product_img.wc_reset_variation_attr( 'height' );
$product_img.wc_reset_variation_attr( 'srcset' );
$product_img.wc_reset_variation_attr( 'sizes' );
$product_img.wc_reset_variation_attr( 'title' );
$product_img.wc_reset_variation_attr( 'alt' );
$product_img.wc_reset_variation_attr( 'data-src' );
$product_img.wc_reset_variation_attr( 'data-large_image' );
$product_img.wc_reset_variation_attr( 'data-large_image_width' );
$product_img.wc_reset_variation_attr( 'data-large_image_height' );
$product_img_wrap.wc_reset_variation_attr( 'data-thumb' );
$gallery_img.wc_reset_variation_attr( 'src' );
$product_link.wc_reset_variation_attr( 'href' );
};
$(function() {
if ( typeof wc_add_to_cart_variation_params !== 'undefined' ) {
$( '.variations_form' ).each( function() {

File diff suppressed because one or more lines are too long

View File

@ -1,4 +1,10 @@
<?php
/**
* Class WC_Product_CSV_Importer_Controller file.
*
* @package WooCommerce\Admin\Importers
*/
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
@ -10,8 +16,6 @@ if ( ! class_exists( 'WP_Importer' ) ) {
/**
* Product importer controller - handles file upload and forms in admin.
*
* @author Automattic
* @category Admin
* @package WooCommerce/Admin/Importers
* @version 3.1.0
*/
@ -108,11 +112,13 @@ class WC_Product_CSV_Importer_Controller {
$this->steps = apply_filters( 'woocommerce_product_csv_importer_steps', $default_steps );
// phpcs:disable WordPress.CSRF.NonceVerification.NoNonceVerification
$this->step = isset( $_REQUEST['step'] ) ? sanitize_key( $_REQUEST['step'] ) : current( array_keys( $this->steps ) );
$this->file = isset( $_REQUEST['file'] ) ? wc_clean( $_REQUEST['file'] ) : '';
$this->file = isset( $_REQUEST['file'] ) ? wc_clean( wp_unslash( $_REQUEST['file'] ) ) : '';
$this->update_existing = isset( $_REQUEST['update_existing'] ) ? (bool) $_REQUEST['update_existing'] : false;
$this->delimiter = ! empty( $_REQUEST['delimiter'] ) ? wc_clean( $_REQUEST['delimiter'] ) : ',';
$this->delimiter = ! empty( $_REQUEST['delimiter'] ) ? wc_clean( wp_unslash( $_REQUEST['delimiter'] ) ) : ',';
$this->map_preferences = isset( $_REQUEST['map_preferences'] ) ? (bool) $_REQUEST['map_preferences'] : false;
// phpcs:enable
if ( $this->map_preferences ) {
add_filter( 'woocommerce_csv_product_import_mapped_columns', array( $this, 'auto_map_user_preferences' ), 9999 );
@ -122,7 +128,7 @@ class WC_Product_CSV_Importer_Controller {
/**
* Get the URL for the next step's screen.
*
* @param string step slug (default: current step)
* @param string $step slug (default: current step).
* @return string URL for next step if a next step exists.
* Admin URL if it's the last step.
* Empty string on failure.
@ -138,7 +144,7 @@ class WC_Product_CSV_Importer_Controller {
return admin_url();
}
$step_index = array_search( $step, $keys );
$step_index = array_search( $step, $keys, true );
if ( false === $step_index ) {
return '';
@ -217,6 +223,7 @@ class WC_Product_CSV_Importer_Controller {
* Dispatch current step and show correct view.
*/
public function dispatch() {
// phpcs:ignore WordPress.CSRF.NonceVerification.NoNonceVerification
if ( ! empty( $_POST['save_step'] ) && ! empty( $this->steps[ $this->step ]['handler'] ) ) {
call_user_func( $this->steps[ $this->step ]['handler'], $this );
}
@ -271,13 +278,16 @@ class WC_Product_CSV_Importer_Controller {
)
);
if ( empty( $_POST['file_url'] ) ) {
// phpcs:disable WordPress.CSRF.NonceVerification.NoNonceVerification -- Nonce already verified in WC_Product_CSV_Importer_Controller::upload_form_handler()
$file_url = isset( $_POST['file_url'] ) ? esc_url_raw( wp_unslash( $_POST['file_url'] ) ) : '';
if ( empty( $file_url ) ) {
if ( ! isset( $_FILES['import'] ) ) {
return new WP_Error( 'woocommerce_product_csv_importer_upload_file_empty', __( 'File is empty. Please upload something more substantial. This error could also be caused by uploads being disabled in your php.ini or by post_max_size being defined as smaller than upload_max_filesize in php.ini.', 'woocommerce' ) );
}
$filetype = wp_check_filetype( $_FILES['import']['name'], $valid_filetypes );
if ( ! in_array( $filetype['type'], $valid_filetypes ) ) {
$filetype = wp_check_filetype( wc_clean( wp_unslash( $_FILES['import']['name'] ) ), $valid_filetypes );
if ( ! in_array( $filetype['type'], $valid_filetypes, true ) ) {
return new WP_Error( 'woocommerce_product_csv_importer_upload_file_invalid', __( 'Invalid file type. The importer supports CSV and TXT file formats.', 'woocommerce' ) );
}
@ -285,7 +295,7 @@ class WC_Product_CSV_Importer_Controller {
'test_form' => false,
'mimes' => $valid_filetypes,
);
$upload = wp_handle_upload( $_FILES['import'], $overrides );
$upload = wp_handle_upload( wp_unslash( $_FILES['import'] ), $overrides );
if ( isset( $upload['error'] ) ) {
return new WP_Error( 'woocommerce_product_csv_importer_upload_error', $upload['error'] );
@ -311,14 +321,15 @@ class WC_Product_CSV_Importer_Controller {
wp_schedule_single_event( time() + DAY_IN_SECONDS, 'importer_scheduled_cleanup', array( $id ) );
return $upload['file'];
} elseif ( file_exists( ABSPATH . $_POST['file_url'] ) ) {
$filetype = wp_check_filetype( ABSPATH . $_POST['file_url'], $valid_filetypes );
if ( ! in_array( $filetype['type'], $valid_filetypes ) ) {
} elseif ( file_exists( ABSPATH . $file_url ) ) {
$filetype = wp_check_filetype( ABSPATH . $file_url, $valid_filetypes );
if ( ! in_array( $filetype['type'], $valid_filetypes, true ) ) {
return new WP_Error( 'woocommerce_product_csv_importer_upload_file_invalid', __( 'Invalid file type. The importer supports CSV and TXT file formats.', 'woocommerce' ) );
}
return ABSPATH . $_POST['file_url'];
return ABSPATH . $file_url;
}
// phpcs:enable
return new WP_Error( 'woocommerce_product_csv_importer_upload_invalid_file', __( 'Please upload or provide the link to a valid CSV file.', 'woocommerce' ) );
}
@ -365,7 +376,8 @@ class WC_Product_CSV_Importer_Controller {
return;
}
if ( ! empty( $_POST['map_to'] ) ) {
// phpcs:disable WordPress.CSRF.NonceVerification.NoNonceVerification -- Nonce already verified in WC_Admin_Importers::do_ajax_product_import()
if ( ! empty( $_POST['map_from'] ) && ! empty( $_POST['map_to'] ) ) {
$mapping_from = wc_clean( wp_unslash( $_POST['map_from'] ) );
$mapping_to = wc_clean( wp_unslash( $_POST['map_to'] ) );
@ -375,6 +387,7 @@ class WC_Product_CSV_Importer_Controller {
wp_redirect( esc_url_raw( $this->get_next_step_link( 'upload' ) ) );
exit;
}
// phpcs:enable
wp_localize_script(
'wc-product-import', 'wc_product_import_params', array(
@ -397,11 +410,13 @@ class WC_Product_CSV_Importer_Controller {
* Done step.
*/
protected function done() {
// phpcs:disable WordPress.CSRF.NonceVerification.NoNonceVerification
$imported = isset( $_GET['products-imported'] ) ? absint( $_GET['products-imported'] ) : 0;
$updated = isset( $_GET['products-updated'] ) ? absint( $_GET['products-updated'] ) : 0;
$failed = isset( $_GET['products-failed'] ) ? absint( $_GET['products-failed'] ) : 0;
$skipped = isset( $_GET['products-skipped'] ) ? absint( $_GET['products-skipped'] ) : 0;
$errors = array_filter( (array) get_user_option( 'product_import_error_log' ) );
// phpcs:enable
include_once dirname( __FILE__ ) . '/views/html-csv-import-done.php';
}
@ -435,7 +450,7 @@ class WC_Product_CSV_Importer_Controller {
include dirname( __FILE__ ) . '/mappings/mappings.php';
/**
/*
* @hooked wc_importer_generic_mappings - 10
* @hooked wc_importer_wordpress_mappings - 10
* @hooked wc_importer_default_english_mappings - 100
@ -460,9 +475,13 @@ class WC_Product_CSV_Importer_Controller {
__( 'Stock', 'woocommerce' ) => 'stock_quantity',
__( 'Backorders allowed?', 'woocommerce' ) => 'backorders',
__( 'Sold individually?', 'woocommerce' ) => 'sold_individually',
/* translators: %s: Weight unit */
sprintf( __( 'Weight (%s)', 'woocommerce' ), $weight_unit ) => 'weight',
/* translators: %s: Length unit */
sprintf( __( 'Length (%s)', 'woocommerce' ), $dimension_unit ) => 'length',
/* translators: %s: Width unit */
sprintf( __( 'Width (%s)', 'woocommerce' ), $dimension_unit ) => 'width',
/* translators: %s: Height unit */
sprintf( __( 'Height (%s)', 'woocommerce' ), $dimension_unit ) => 'height',
__( 'Allow customer reviews?', 'woocommerce' ) => 'reviews_allowed',
__( 'Purchase note', 'woocommerce' ) => 'purchase_note',
@ -490,13 +509,21 @@ class WC_Product_CSV_Importer_Controller {
apply_filters(
'woocommerce_csv_product_import_mapping_special_columns',
array(
/* translators: %d: Attribute number */
__( 'Attribute %d name', 'woocommerce' ) => 'attributes:name',
/* translators: %d: Attribute number */
__( 'Attribute %d value(s)', 'woocommerce' ) => 'attributes:value',
/* translators: %d: Attribute number */
__( 'Attribute %d visible', 'woocommerce' ) => 'attributes:visible',
/* translators: %d: Attribute number */
__( 'Attribute %d global', 'woocommerce' ) => 'attributes:taxonomy',
/* translators: %d: Attribute number */
__( 'Attribute %d default', 'woocommerce' ) => 'attributes:default',
/* translators: %d: Download number */
__( 'Download %d name', 'woocommerce' ) => 'downloads:name',
/* translators: %d: Download number */
__( 'Download %d URL', 'woocommerce' ) => 'downloads:url',
/* translators: %d: Meta number */
__( 'Meta: %s', 'woocommerce' ) => 'meta:',
)
)
@ -571,7 +598,7 @@ class WC_Product_CSV_Importer_Controller {
/**
* Get mapping options.
*
* @param string $item Item name
* @param string $item Item name.
* @return array
*/
protected function get_mapping_options( $item = '' ) {

View File

@ -3,9 +3,7 @@
* Tax importer class file
*
* @version 2.3.0
* @category Admin
* @package WooCommerce/Admin
* @author WooCommerce
*/
if ( ! defined( 'ABSPATH' ) ) {
@ -19,8 +17,6 @@ if ( ! class_exists( 'WP_Importer' ) ) {
/**
* Tax Rates importer - import tax rates and local tax rates into WooCommerce.
*
* @author WooThemes
* @category Admin
* @package WooCommerce/Admin/Importers
* @version 2.3.0
*/
@ -59,8 +55,7 @@ class WC_Tax_Rate_Importer extends WP_Importer {
*/
public function __construct() {
$this->import_page = 'woocommerce_tax_rate_csv';
// @codingStandardsIgnoreLine
$this->delimiter = empty( $_POST['delimiter'] ) ? ',' : (string) wc_clean( $_POST['delimiter'] );
$this->delimiter = empty( $_POST['delimiter'] ) ? ',' : (string) wc_clean( wp_unslash( $_POST['delimiter'] ) ); // WPCS: CSRF ok.
}
/**
@ -106,7 +101,7 @@ class WC_Tax_Rate_Importer extends WP_Importer {
*/
private function import_start() {
if ( function_exists( 'gc_enable' ) ) {
gc_enable();
gc_enable(); // phpcs:ignore PHPCompatibility.PHP.NewFunctions.gc_enableFound
}
wc_set_time_limit( 0 );
@ob_flush();
@ -137,15 +132,18 @@ class WC_Tax_Rate_Importer extends WP_Importer {
$this->import_start();
$loop = 0;
$loop = 0;
$handle = fopen( $file, 'r' );
if ( ( $handle = fopen( $file, 'r' ) ) !== false ) {
if ( false !== $handle ) {
$header = fgetcsv( $handle, 0, $this->delimiter );
if ( 10 === count( $header ) ) {
while ( ( $row = fgetcsv( $handle, 0, $this->delimiter ) ) !== false ) {
$row = fgetcsv( $handle, 0, $this->delimiter );
while ( false !== $row ) {
list( $country, $state, $postcode, $city, $rate, $name, $priority, $compound, $shipping, $class ) = $row;
@ -174,8 +172,8 @@ class WC_Tax_Rate_Importer extends WP_Importer {
// Show Result.
echo '<div class="updated settings-error"><p>';
/* translators: %s: tax rates count */
printf(
/* translators: %s: tax rates count */
esc_html__( 'Import complete - imported %s tax rates.', 'woocommerce' ),
'<strong>' . absint( $loop ) . '</strong>'
);
@ -200,9 +198,10 @@ class WC_Tax_Rate_Importer extends WP_Importer {
* @return bool False if error uploading or invalid file, true otherwise
*/
public function handle_upload() {
// @codingStandardsIgnoreLine
if ( empty( $_POST['file_url'] ) ) {
// phpcs:disable WordPress.CSRF.NonceVerification.NoNonceVerification -- Nonce already verified in WC_Tax_Rate_Importer::dispatch()
$file_url = isset( $_POST['file_url'] ) ? esc_url_raw( wp_unslash( $_POST['file_url'] ) ) : '';
if ( empty( $file_url ) ) {
$file = wp_import_handle_upload();
if ( isset( $file['error'] ) ) {
@ -210,13 +209,12 @@ class WC_Tax_Rate_Importer extends WP_Importer {
}
$this->id = absint( $file['id'] );
// @codingStandardsIgnoreLine
} elseif ( file_exists( ABSPATH . $_POST['file_url'] ) ) {
// @codingStandardsIgnoreLine
$this->file_url = esc_attr( $_POST['file_url'] );
} elseif ( file_exists( ABSPATH . $file_url ) ) {
$this->file_url = esc_attr( $file_url );
} else {
$this->import_error();
}
// phpcs:enable
return true;
}
@ -244,6 +242,7 @@ class WC_Tax_Rate_Importer extends WP_Importer {
echo '<div class="narrow">';
echo '<p>' . esc_html__( 'Hi there! Upload a CSV file containing tax rates to import the contents into your shop. Choose a .csv file to upload, then click "Upload file and import".', 'woocommerce' ) . '</p>';
/* translators: 1: Link to tax rates sample file */
echo '<p>' . sprintf( esc_html__( 'Tax rates need to be defined with columns in a specific order (10 columns). <a href="%s">Click here to download a sample</a>.', 'woocommerce' ), esc_url( WC()->plugin_url() ) . '/sample-data/sample_tax_rates.csv' ) . '</p>';
$action = 'admin.php?import=woocommerce_tax_rate_csv&step=1';
@ -271,8 +270,8 @@ class WC_Tax_Rate_Importer extends WP_Importer {
<input type="hidden" name="max_file_size" value="<?php echo absint( $bytes ); ?>" />
<small>
<?php
/* translators: %s: maximum upload size */
printf(
/* translators: %s: maximum upload size */
esc_html__( 'Maximum size: %s', 'woocommerce' ),
esc_attr( $size )
);
@ -307,7 +306,7 @@ class WC_Tax_Rate_Importer extends WP_Importer {
/**
* Show import error and quit.
*
* @param string $message Error messag.
* @param string $message Error message.
*/
private function import_error( $message = '' ) {
echo '<p><strong>' . esc_html__( 'Sorry, there has been an error.', 'woocommerce' ) . '</strong><br />';

View File

@ -1,4 +1,9 @@
<?php
/**
* Default mappings
*
* @package WooCommerce\Admin\Importers
*/
if ( ! defined( 'ABSPATH' ) ) {
exit;
@ -23,7 +28,7 @@ function wc_importer_current_locale() {
* Add English mapping placeholders when not using English as current language.
*
* @since 3.1.0
* @param array $mappings
* @param array $mappings Importer columns mappings.
* @return array
*/
function wc_importer_default_english_mappings( $mappings ) {
@ -82,7 +87,7 @@ add_filter( 'woocommerce_csv_product_import_mapping_default_columns', 'wc_import
* Add English special mapping placeholders when not using English as current language.
*
* @since 3.1.0
* @param array $mappings
* @param array $mappings Importer columns mappings.
* @return array
*/
function wc_importer_default_special_english_mappings( $mappings ) {

View File

@ -1,4 +1,9 @@
<?php
/**
* Generic mappings
*
* @package WooCommerce\Admin\Importers
*/
if ( ! defined( 'ABSPATH' ) ) {
exit;
@ -8,7 +13,7 @@ if ( ! defined( 'ABSPATH' ) ) {
* Add generic mappings.
*
* @since 3.1.0
* @param array $mappings
* @param array $mappings Importer columns mappings.
* @return array
*/
function wc_importer_generic_mappings( $mappings ) {

View File

@ -1,6 +1,8 @@
<?php
/**
* Load up extra automatic mappings for the CSV importer.
*
* @package WooCommerce\Admin\Importers
*/
if ( ! defined( 'ABSPATH' ) ) {

View File

@ -1,4 +1,9 @@
<?php
/**
* WordPress mappings
*
* @package WooCommerce\Admin\Importers
*/
if ( ! defined( 'ABSPATH' ) ) {
exit;
@ -8,7 +13,7 @@ if ( ! defined( 'ABSPATH' ) ) {
* Add mappings for WordPress tables.
*
* @since 3.1.0
* @param array $mappings
* @param array $mappings Importer columns mappings.
* @return array
*/
function wc_importer_wordpress_mappings( $mappings ) {

View File

@ -1,7 +1,10 @@
<?php
/**
* Admin View: Importer - Done!
*
* @package WooCommerce\Admin\Importers
*/
if ( ! defined( 'ABSPATH' ) ) {
exit;
}

View File

@ -1,7 +1,10 @@
<?php
/**
* Admin View: Header
*
* @package WooCommerce\Admin\Importers
*/
if ( ! defined( 'ABSPATH' ) ) {
exit;
}

View File

@ -1,7 +1,10 @@
<?php
/**
* Admin View: Header
*
* @package WooCommerce\Admin\Importers
*/
if ( ! defined( 'ABSPATH' ) ) {
exit;
}

View File

@ -2,7 +2,7 @@
/**
* Admin View: Importer - CSV mapping
*
* @package WooCommerce/Admin
* @package WooCommerce\Admin\Importers
*/
if ( ! defined( 'ABSPATH' ) ) {

View File

@ -1,7 +1,10 @@
<?php
/**
* Admin View: Importer - CSV import progress
*
* @package WooCommerce\Admin\Importers
*/
if ( ! defined( 'ABSPATH' ) ) {
exit;
}

View File

@ -1,7 +1,10 @@
<?php
/**
* Admin View: Steps
*
* @package WooCommerce\Admin\Importers
*/
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
@ -11,7 +14,7 @@ if ( ! defined( 'ABSPATH' ) ) {
<?php
if ( $step_key === $this->step ) {
$step_class = 'active';
} elseif ( array_search( $this->step, array_keys( $this->steps ) ) > array_search( $step_key, array_keys( $this->steps ) ) ) {
} elseif ( array_search( $this->step, array_keys( $this->steps ), true ) > array_search( $step_key, array_keys( $this->steps ), true ) ) {
$step_class = 'done';
}
?>

View File

@ -40,10 +40,10 @@ if ( ! defined( 'ABSPATH' ) ) {
<br>
<small>
<?php
/* translators: %s: maximum upload size */
printf(
/* translators: %s: maximum upload size */
esc_html__( 'Maximum size: %s', 'woocommerce' ),
$size
esc_html( $size )
);
?>
</small>

View File

@ -249,7 +249,7 @@ class WC_Meta_Box_Coupon_Data {
<?php echo wc_help_tip( __( 'Product categories that the coupon will not be applied to, or that cannot be in the cart in order for the "Fixed cart discount" to be applied.', 'woocommerce' ) ); ?>
</p>
</div>
<div class="options_group">';
<div class="options_group">
<?php
// Customers.
woocommerce_wp_text_input(
@ -257,7 +257,7 @@ class WC_Meta_Box_Coupon_Data {
'id' => 'customer_email',
'label' => __( 'Email restrictions', 'woocommerce' ),
'placeholder' => __( 'No restrictions', 'woocommerce' ),
'description' => __( 'List of allowed emails to check against the customer billing email when an order is placed. Separate email addresses with commas.', 'woocommerce' ),
'description' => __( 'List of allowed emails to check against the customer billing email when an order is placed. Separate email addresses with commas. You can also use an asterisk (*) to match parts of an email. For example "*@gmail.com" would match all gmail addresses.', 'woocommerce' ),
'value' => implode( ', ', (array) $coupon->get_email_restrictions() ),
'desc_tip' => true,
'type' => 'email',

View File

@ -360,6 +360,15 @@ class WC_Meta_Box_Order_Data {
if ( ! isset( $field['id'] ) ) {
$field['id'] = '_billing_' . $key;
}
$field_name = 'billing_' . $key;
if ( is_callable( array( $order, 'get_' . $field_name ) ) ) {
$field['value'] = $order->{"get_$field_name"}( 'edit' );
} else {
$field['value'] = $order->get_meta( '_' . $field_name );
}
switch ( $field['type'] ) {
case 'select':
woocommerce_wp_select( $field );
@ -462,6 +471,14 @@ class WC_Meta_Box_Order_Data {
$field['id'] = '_shipping_' . $key;
}
$field_name = 'shipping_' . $key;
if ( is_callable( array( $order, 'get_' . $field_name ) ) ) {
$field['value'] = $order->{"get_$field_name"}( 'edit' );
} else {
$field['value'] = $order->get_meta( '_' . $field_name );
}
switch ( $field['type'] ) {
case 'select':
woocommerce_wp_select( $field );

View File

@ -4,15 +4,11 @@
*
* Replaces the standard excerpt box.
*
* @author WooThemes
* @category Admin
* @package WooCommerce/Admin/Meta Boxes
* @version 2.1.0
*/
if ( ! defined( 'ABSPATH' ) ) {
exit; // Exit if accessed directly
}
defined( 'ABSPATH' ) || exit;
/**
* WC_Meta_Box_Product_Short_Description Class.
@ -22,7 +18,7 @@ class WC_Meta_Box_Product_Short_Description {
/**
* Output the metabox.
*
* @param WP_Post $post
* @param WP_Post $post Post object.
*/
public static function output( $post ) {
@ -36,6 +32,6 @@ class WC_Meta_Box_Product_Short_Description {
'editor_css' => '<style>#wp-excerpt-editor-container .wp-editor-area{height:175px; width:100%;}</style>',
);
wp_editor( htmlspecialchars_decode( $post->post_excerpt ), 'excerpt', apply_filters( 'woocommerce_product_short_description_editor_settings', $settings ) );
wp_editor( htmlspecialchars_decode( $post->post_excerpt, ENT_QUOTES ), 'excerpt', apply_filters( 'woocommerce_product_short_description_editor_settings', $settings ) );
}
}

View File

@ -222,7 +222,7 @@ class WC_Report_Sales_By_Category extends WC_Admin_Report {
$r['value'] = 'id';
$r['selected'] = $this->show_categories;
include_once WC()->plugin_path() . '/includes/walkers/class-product-cat-dropdown-walker.php';
include_once WC()->plugin_path() . '/includes/walkers/class-wc-product-cat-dropdown-walker.php';
echo wc_walk_category_dropdown_tree( $categories, 0, $r ); // @codingStandardsIgnoreLine
?>

View File

@ -200,12 +200,7 @@ $untested_plugins = $plugin_updates->get_untested_plugins( WC()->version, 'minor
<?php
if ( $wpdb->use_mysqli ) {
$ver = mysqli_get_server_info( $wpdb->dbh );
} else {
$ver = mysql_get_server_info(); // @codingStandardsIgnoreLine
}
if ( ! empty( $wpdb->is_mysql ) && ! stristr( $ver, 'MariaDB' ) ) :
if ( ! empty( $wpdb->is_mysql ) ) :
?>
<tr>
<td data-export-label="MySQL Version"><?php esc_html_e( 'MySQL version', 'woocommerce' ); ?>:</td>

View File

@ -214,6 +214,7 @@ function woocommerce_wp_select( $field ) {
$field_attributes['style'] = $field['style'];
$field_attributes['id'] = $field['id'];
$field_attributes['name'] = $field['name'];
$field_attributes['class'] = $field['class'];
$tooltip = ! empty( $field['description'] ) && false !== $field['desc_tip'] ? $field['description'] : '';
$description = ! empty( $field['description'] ) && false === $field['desc_tip'] ? $field['description'] : '';

File diff suppressed because it is too large Load Diff

View File

@ -61,6 +61,7 @@ final class WC_Cart_Session {
* @since 3.2.0
*/
public function get_cart_from_session() {
// Flag to indicate the stored cart should be updated.
$update_cart_session = false;
$totals = WC()->session->get( 'cart_totals', null );
$cart = WC()->session->get( 'cart', null );
@ -99,11 +100,17 @@ final class WC_Cart_Session {
if ( ! empty( $product ) && $product->exists() && $values['quantity'] > 0 ) {
if ( ! $product->is_purchasable() ) {
$update_cart_session = true; // Flag to indicate the stored cart should be updated.
$update_cart_session = true;
/* translators: %s: product name */
wc_add_notice( sprintf( __( '%s has been removed from your cart because it can no longer be purchased. Please contact us if you need assistance.', 'woocommerce' ), $product->get_name() ), 'error' );
do_action( 'woocommerce_remove_cart_item_from_session', $key, $values );
} elseif ( ! empty( $values['data_hash'] ) && ! hash_equals( $values['data_hash'], wc_get_cart_item_data_hash( $product ) ) ) {
$update_cart_session = true;
/* translators: %1$s: product name. %2$s product permalink */
wc_add_notice( sprintf( __( '%1$s has been removed from your cart because it has since been modified. You can add it back to your cart <a href="%2$s">here</a>.', 'woocommerce' ), $product->get_name(), $product->get_permalink() ), 'notice' );
do_action( 'woocommerce_remove_cart_item_from_session', $key, $values );
} else {
// Put session data into array. Run through filter so other plugins can load their own session data.
$session_data = array_merge( $values, array(

View File

@ -379,6 +379,9 @@ final class WC_Cart_Totals {
$coupon->sort = 0;
break;
}
// Allow plugins to override the default order.
$coupon->sort = apply_filters( 'woocommerce_coupon_sort', $coupon->sort, $coupon );
}
uasort( $this->coupons, array( $this, 'sort_coupons_callback' ) );

View File

@ -673,7 +673,9 @@ class WC_Cart extends WC_Legacy_Cart {
$weight = 0;
foreach ( $this->get_cart() as $cart_item_key => $values ) {
$weight += (float) $values['data']->get_weight() * $values['quantity'];
if ( $values['data']->has_weight() ) {
$weight += (float) $values['data']->get_weight() * $values['quantity'];
}
}
return apply_filters( 'woocommerce_cart_contents_weight', $weight );
@ -1112,6 +1114,7 @@ class WC_Cart extends WC_Legacy_Cart {
'variation' => $variation,
'quantity' => $quantity,
'data' => $product_data,
'data_hash' => wc_get_cart_item_data_hash( $product_data ),
) ), $cart_item_key );
}
@ -1450,7 +1453,7 @@ class WC_Cart extends WC_Legacy_Cart {
// Limit to defined email addresses.
$restrictions = $coupon->get_email_restrictions();
if ( is_array( $restrictions ) && 0 < count( $restrictions ) && 0 === count( array_intersect( $check_emails, $restrictions ) ) ) {
if ( is_array( $restrictions ) && 0 < count( $restrictions ) && ! $this->is_coupon_emails_allowed( $check_emails, $restrictions ) ) {
$coupon->add_coupon_message( WC_Coupon::E_WC_COUPON_NOT_YOURS_REMOVED );
$this->remove_coupon( $code );
}
@ -1497,6 +1500,37 @@ class WC_Cart extends WC_Legacy_Cart {
}
}
/**
* Checks if the given email address(es) matches the ones specified on the coupon.
*
* @param array $check_emails Array of customer email addresses.
* @param array $restrictions Array of allowed email addresses.
* @return bool
*/
public function is_coupon_emails_allowed( $check_emails, $restrictions ) {
foreach ( $check_emails as $check_email ) {
// With a direct match we return true.
if ( in_array( $check_email, $restrictions ) ) {
return true;
}
// Go through the allowed emails and return true if the email matches a wildcard.
foreach ( $restrictions as $restriction ) {
// Convert to PHP-regex syntax.
$regex = '/' . str_replace( '*', '(.+)?', $restriction ) . '/';
preg_match( $regex, $check_email, $match );
if ( ! empty( $match ) ) {
return true;
}
}
}
// No matches, this one isn't allowed.
return false;
}
/**
* Returns whether or not a discount has been applied.
*

View File

@ -379,7 +379,7 @@ class WC_Discounts {
}
}
$discount = wc_cart_round_discount( min( $discounted_price, $discount ), 0 );
$discount = wc_round_discount( min( $discounted_price, $discount ), 0 );
$cart_total = $cart_total + $price_to_discount;
$total_discount = $total_discount + $discount;
$applied_count = $applied_count + $apply_quantity;
@ -389,7 +389,7 @@ class WC_Discounts {
}
// Work out how much discount would have been given to the cart as a whole and compare to what was discounted on all line items.
$cart_total_discount = wc_cart_round_discount( $cart_total * ( $coupon_amount / 100 ), 0 );
$cart_total_discount = wc_round_discount( $cart_total * ( $coupon_amount / 100 ), 0 );
if ( $total_discount < $cart_total_discount && $adjust_final_discount ) {
$total_discount += $this->apply_coupon_remainder( $coupon, $items_to_apply, $cart_total_discount - $total_discount );

View File

@ -54,7 +54,10 @@ class WC_Download_Handler {
$order = wc_get_order( $order_id );
$email_address = is_a( $order, 'WC_Order' ) ? $order->get_billing_email() : null;
if ( is_null( $email_address ) || ! hash_equals( $_GET['uid'], hash( 'sha256', $email_address ) ) ) {
// Prepare email address hash.
$email_hash = function_exists( 'hash' ) ? hash( 'sha256', $email_address ) : sha1( $email_address );
if ( is_null( $email_address ) || ! hash_equals( $_GET['uid'], $email_hash ) ) {
self::download_error( __( 'Invalid download link.', 'woocommerce' ) );
}
}

View File

@ -463,7 +463,7 @@ class WC_Install {
}
}
$woocommerce_default_category = get_option( 'default_product_cat', 0 );
$woocommerce_default_category = (int) get_option( 'default_product_cat', 0 );
if ( ! $woocommerce_default_category || ! term_exists( $woocommerce_default_category, 'product_cat' ) ) {
$default_product_cat_id = 0;
@ -475,7 +475,7 @@ class WC_Install {
} else {
$result = wp_insert_term( _x( 'Uncategorized', 'Default category slug', 'woocommerce' ), 'product_cat', array( 'slug' => $default_product_cat_slug ) );
if ( ! empty( $result['term_taxonomy_id'] ) ) {
if ( ! is_wp_error( $result ) && ! empty( $result['term_taxonomy_id'] ) ) {
$default_product_cat_id = absint( $result['term_taxonomy_id'] );
}
}
@ -1045,15 +1045,16 @@ CREATE TABLE {$wpdb->prefix}woocommerce_termmeta (
}
/**
* Get slug from path
* Get slug from path and associate it with the path.
*
* @param string $key Plugin relative path. Example: woocommerce/woocommerce.php.
* @return string
* @param array $plugins Associative array of plugin slugs to paths.
* @param string $key Plugin relative path. Example: woocommerce/woocommerce.php.
*/
private static function format_plugin_slug( $key ) {
private static function associate_plugin_slug( $plugins, $key ) {
$slug = explode( '/', $key );
$slug = explode( '.', end( $slug ) );
return $slug[0];
$plugins[ $slug[0] ] = $key;
return $plugins;
}
/**
@ -1079,16 +1080,15 @@ CREATE TABLE {$wpdb->prefix}woocommerce_termmeta (
$skin = new Automatic_Upgrader_Skin();
$upgrader = new WP_Upgrader( $skin );
$installed_plugins = array_map( array( __CLASS__, 'format_plugin_slug' ), array_keys( get_plugins() ) );
$installed_plugins = array_reduce( array_keys( get_plugins() ), array( __CLASS__, 'associate_plugin_slug' ), array() );
$plugin_slug = $plugin_to_install['repo-slug'];
$plugin = $plugin_slug . '/' . $plugin_slug . '.php';
$installed = false;
$activate = false;
// See if the plugin is installed already.
if ( in_array( $plugin_to_install['repo-slug'], $installed_plugins ) ) {
if ( isset( $installed_plugins[ $plugin_slug ] ) ) {
$installed = true;
$activate = ! is_plugin_active( $plugin );
$activate = ! is_plugin_active( $installed_plugins[ $plugin_slug ] );
}
// Install this thing!
@ -1178,7 +1178,7 @@ CREATE TABLE {$wpdb->prefix}woocommerce_termmeta (
// Activate this thing.
if ( $activate ) {
try {
$result = activate_plugin( $plugin );
$result = activate_plugin( $installed_plugins[ $plugin_slug ] );
if ( is_wp_error( $result ) ) {
throw new Exception( $result->get_error_message() );

View File

@ -368,6 +368,7 @@ class WC_Order_Item_Product extends WC_Order_Item {
$product = $this->get_product();
$order = $this->get_order();
$product_id = $this->get_variation_id() ? $this->get_variation_id() : $this->get_product_id();
$email_hash = function_exists( 'hash' ) ? hash( 'sha256', $order->get_billing_email() ) : sha1( $order->get_billing_email() );
if ( $product && $order && $product->is_downloadable() && $order->is_download_permitted() ) {
$data_store = WC_Data_Store::load( 'customer-download' );
@ -387,7 +388,7 @@ class WC_Order_Item_Product extends WC_Order_Item {
$files[ $download_id ]['download_url'] = add_query_arg( array(
'download_file' => $product_id,
'order' => $order->get_order_key(),
'uid' => hash( 'sha256', $order->get_billing_email() ),
'uid' => $email_hash,
'key' => $download_id,
), trailingslashit( home_url() ) );
}

View File

@ -93,16 +93,17 @@ class WC_Order extends WC_Abstract_Order {
* Sales are also recorded for products.
* Finally, record the date of payment.
*
* Order must exist.
*
* @param string $transaction_id Optional transaction id to store in post meta.
* @return bool success
*/
public function payment_complete( $transaction_id = '' ) {
if ( ! $this->get_id() ) { // Order must exist.
return false;
}
try {
if ( ! $this->get_id() ) {
return false;
}
wc_transaction_query( 'start' );
do_action( 'woocommerce_pre_payment_complete', $this->get_id() );
if ( WC()->session ) {
@ -123,12 +124,17 @@ class WC_Order extends WC_Abstract_Order {
} else {
do_action( 'woocommerce_payment_complete_order_status_' . $this->get_status(), $this->get_id() );
}
wc_transaction_query( 'commit' );
} catch ( Exception $e ) {
wc_transaction_query( 'rollback' );
$logger = wc_get_logger();
$logger->error( sprintf( 'Payment complete of order #%d failed!', $this->get_id() ), array(
'order' => $this,
'error' => $e,
) );
$this->add_order_note( __( 'Payment complete event failed.', 'woocommerce' ) . ' ' . $e->getMessage() );
return false;
}
@ -208,19 +214,31 @@ class WC_Order extends WC_Abstract_Order {
* @return int order ID
*/
public function save() {
$this->maybe_set_user_billing_email();
if ( $this->data_store ) {
// Trigger action before saving to the DB. Allows you to adjust object props before save.
do_action( 'woocommerce_before_' . $this->object_type . '_object_save', $this, $this->data_store );
try {
$this->maybe_set_user_billing_email();
if ( $this->get_id() ) {
$this->data_store->update( $this );
} else {
$this->data_store->create( $this );
if ( $this->data_store ) {
// Trigger action before saving to the DB. Allows you to adjust object props before save.
do_action( 'woocommerce_before_' . $this->object_type . '_object_save', $this, $this->data_store );
if ( $this->get_id() ) {
$this->data_store->update( $this );
} else {
$this->data_store->create( $this );
}
}
$this->save_items();
$this->status_transition();
} catch ( Exception $e ) {
$logger = wc_get_logger();
$logger->error( sprintf( 'Error saving order #%d', $this->get_id() ), array(
'order' => $this,
'error' => $e,
) );
$this->add_order_note( __( 'Error saving order.', 'woocommerce' ) . ' ' . $e->getMessage() );
}
$this->save_items();
$this->status_transition();
return $this->get_id();
}
@ -284,7 +302,7 @@ class WC_Order extends WC_Abstract_Order {
}
/**
* Updates status of order immediately. Order must exist.
* Updates status of order immediately.
*
* @uses WC_Order::set_status()
* @param string $new_status Status to change the order to. No internal wc- prefix is required.
@ -293,19 +311,26 @@ class WC_Order extends WC_Abstract_Order {
* @return bool
*/
public function update_status( $new_status, $note = '', $manual = false ) {
if ( ! $this->get_id() ) { // Order must exist.
return false;
}
try {
if ( ! $this->get_id() ) {
return false;
}
wc_transaction_query( 'start' );
$this->set_status( $new_status, $note, $manual );
$this->save();
wc_transaction_query( 'commit' );
} catch ( Exception $e ) {
wc_transaction_query( 'rollback' );
$logger = wc_get_logger();
$logger->error( sprintf( 'Update status of order #%d failed!', $this->get_id() ), array(
'order' => $this,
'error' => $e,
) );
$this->add_order_note( __( 'Update status event failed.', 'woocommerce' ) . ' ' . $e->getMessage() );
return false;
}
return true;
@ -321,21 +346,30 @@ class WC_Order extends WC_Abstract_Order {
$this->status_transition = false;
if ( $status_transition ) {
do_action( 'woocommerce_order_status_' . $status_transition['to'], $this->get_id(), $this );
try {
do_action( 'woocommerce_order_status_' . $status_transition['to'], $this->get_id(), $this );
if ( ! empty( $status_transition['from'] ) ) {
/* translators: 1: old order status 2: new order status */
$transition_note = sprintf( __( 'Order status changed from %1$s to %2$s.', 'woocommerce' ), wc_get_order_status_name( $status_transition['from'] ), wc_get_order_status_name( $status_transition['to'] ) );
if ( ! empty( $status_transition['from'] ) ) {
/* translators: 1: old order status 2: new order status */
$transition_note = sprintf( __( 'Order status changed from %1$s to %2$s.', 'woocommerce' ), wc_get_order_status_name( $status_transition['from'] ), wc_get_order_status_name( $status_transition['to'] ) );
do_action( 'woocommerce_order_status_' . $status_transition['from'] . '_to_' . $status_transition['to'], $this->get_id(), $this );
do_action( 'woocommerce_order_status_changed', $this->get_id(), $status_transition['from'], $status_transition['to'], $this );
} else {
/* translators: %s: new order status */
$transition_note = sprintf( __( 'Order status set to %s.', 'woocommerce' ), wc_get_order_status_name( $status_transition['to'] ) );
do_action( 'woocommerce_order_status_' . $status_transition['from'] . '_to_' . $status_transition['to'], $this->get_id(), $this );
do_action( 'woocommerce_order_status_changed', $this->get_id(), $status_transition['from'], $status_transition['to'], $this );
} else {
/* translators: %s: new order status */
$transition_note = sprintf( __( 'Order status set to %s.', 'woocommerce' ), wc_get_order_status_name( $status_transition['to'] ) );
}
// Note the transition occurred.
$this->add_order_note( trim( $status_transition['note'] . ' ' . $transition_note ), 0, $status_transition['manual'] );
} catch ( Exception $e ) {
$logger = wc_get_logger();
$logger->error( sprintf( 'Status transition of order #%d errored!', $this->get_id() ), array(
'order' => $this,
'error' => $e,
) );
$this->add_order_note( __( 'Error during status transition.', 'woocommerce' ) . ' ' . $e->getMessage() );
}
// Note the transition occurred.
$this->add_order_note( trim( $status_transition['note'] . ' ' . $transition_note ), 0, $status_transition['manual'] );
}
}

View File

@ -8,10 +8,10 @@ if ( ! defined( 'ABSPATH' ) ) {
*
* The WooCommerce product class handles individual product data.
*
* @version 3.0.0
* @package WooCommerce/Classes/Products
* @category Class
* @author WooThemes
* @version 3.0.0
* @package WooCommerce/Classes/Products
* @category Class
* @author WooThemes
*/
class WC_Product_Variable extends WC_Product {
@ -74,7 +74,8 @@ class WC_Product_Variable extends WC_Product {
/**
* Get an array of all sale and regular prices from all variations. This is used for example when displaying the price range at variable product level or seeing if the variable product is on sale.
*
* @param bool $for_display If true, prices will be adapted for display based on the `woocommerce_tax_display_shop` setting (including or excluding taxes).
* @param bool $for_display If true, prices will be adapted for display based on the `woocommerce_tax_display_shop` setting (including or excluding taxes).
*
* @return array Array of RAW prices, regular prices, and sale prices with keys set to variation ID.
*/
public function get_variation_prices( $for_display = false ) {
@ -90,39 +91,45 @@ class WC_Product_Variable extends WC_Product {
/**
* Get the min or max variation regular price.
*
* @param string $min_or_max Min or max price.
* @param string $min_or_max Min or max price.
* @param boolean $for_display If true, prices will be adapted for display based on the `woocommerce_tax_display_shop` setting (including or excluding taxes).
*
* @return string
*/
public function get_variation_regular_price( $min_or_max = 'min', $for_display = false ) {
$prices = $this->get_variation_prices( $for_display );
$price = 'min' === $min_or_max ? current( $prices['regular_price'] ) : end( $prices['regular_price'] );
return apply_filters( 'woocommerce_get_variation_regular_price', $price, $this, $min_or_max, $for_display );
}
/**
* Get the min or max variation sale price.
*
* @param string $min_or_max Min or max price.
* @param string $min_or_max Min or max price.
* @param boolean $for_display If true, prices will be adapted for display based on the `woocommerce_tax_display_shop` setting (including or excluding taxes).
*
* @return string
*/
public function get_variation_sale_price( $min_or_max = 'min', $for_display = false ) {
$prices = $this->get_variation_prices( $for_display );
$price = 'min' === $min_or_max ? current( $prices['sale_price'] ) : end( $prices['sale_price'] );
return apply_filters( 'woocommerce_get_variation_sale_price', $price, $this, $min_or_max, $for_display );
}
/**
* Get the min or max variation (active) price.
*
* @param string $min_or_max Min or max price.
* @param string $min_or_max Min or max price.
* @param boolean $for_display If true, prices will be adapted for display based on the `woocommerce_tax_display_shop` setting (including or excluding taxes).
*
* @return string
*/
public function get_variation_price( $min_or_max = 'min', $for_display = false ) {
$prices = $this->get_variation_prices( $for_display );
$price = 'min' === $min_or_max ? current( $prices['price'] ) : end( $prices['price'] );
return apply_filters( 'woocommerce_get_variation_price', $price, $this, $min_or_max, $for_display );
}
@ -140,6 +147,7 @@ class WC_Product_Variable extends WC_Product {
* is shown instead.
*
* @param string $price (default: '')
*
* @return string
*/
public function get_price_html( $price = '' ) {
@ -174,8 +182,9 @@ class WC_Product_Variable extends WC_Product {
* has dynamic values such as {price_excluding_tax} for variable products.
* @see get_price_html for an explanation as to why.
*
* @param string $price to calculate, left blank to just use get_price()
* @param integer $qty passed on to get_price_including_tax() or get_price_excluding_tax()
* @param string $price to calculate, left blank to just use get_price()
* @param integer $qty passed on to get_price_including_tax() or get_price_excluding_tax()
*
* @return string
*/
public function get_price_suffix( $price = '', $qty = 1 ) {
@ -198,8 +207,10 @@ class WC_Product_Variable extends WC_Product {
public function get_children( $visible_only = '' ) {
if ( is_bool( $visible_only ) ) {
wc_deprecated_argument( 'visible_only', '3.0', 'WC_Product_Variable::get_visible_children' );
return $visible_only ? $this->get_visible_children() : $this->get_children();
}
return apply_filters( 'woocommerce_get_children', $this->children, $this, false );
}
@ -226,11 +237,13 @@ class WC_Product_Variable extends WC_Product {
* If set, get the default attributes for a variable product.
*
* @param string $attribute_name
*
* @return string
*/
public function get_variation_default_attribute( $attribute_name ) {
$defaults = $this->get_default_attributes();
$attribute_name = sanitize_title( $attribute_name );
return isset( $defaults[ $attribute_name ] ) ? $defaults[ $attribute_name ] : '';
}
@ -279,6 +292,7 @@ class WC_Product_Variable extends WC_Product {
$available_variations[] = $this->get_available_variation( $variation );
}
$available_variations = array_filter( $available_variations );
return $available_variations;
}
@ -286,14 +300,18 @@ class WC_Product_Variable extends WC_Product {
/**
* Returns an array of data for a variation. Used in the add to cart form.
* @since 2.4.0
*
* @param WC_Product $variation Variation product object or ID
* @return array
*
* @return array|bool
*/
public function get_available_variation( $variation ) {
if ( is_numeric( $variation ) ) {
$variation = wc_get_product( $variation );
}
if ( ! $variation instanceof WC_Product_Variation ) {
return false;
}
// See if prices should be shown for each variation after selection.
$show_variation_price = apply_filters( 'woocommerce_show_variation_price', $variation->get_price() === "" || $this->get_variation_sale_price( 'min' ) !== $this->get_variation_sale_price( 'max' ) || $this->get_variation_regular_price( 'min' ) !== $this->get_variation_regular_price( 'max' ), $this, $variation );
@ -335,6 +353,7 @@ class WC_Product_Variable extends WC_Product {
* Sets an array of variation attributes.
*
* @since 3.0.0
*
* @param array
*/
public function set_variation_attributes( $variation_attributes ) {
@ -345,6 +364,7 @@ class WC_Product_Variable extends WC_Product {
* Sets an array of children for the product.
*
* @since 3.0.0
*
* @param array
*/
public function set_children( $children ) {
@ -355,6 +375,7 @@ class WC_Product_Variable extends WC_Product {
* Sets an array of visible children only.
*
* @since 3.0.0
*
* @param array
*/
public function set_visible_children( $visible_children ) {
@ -434,6 +455,7 @@ class WC_Product_Variable extends WC_Product {
* Returns whether or not the product is on sale.
*
* @param string $context What the value is for. Valid values are view and edit.
*
* @return bool
*/
public function is_on_sale( $context = 'view' ) {
@ -473,6 +495,7 @@ class WC_Product_Variable extends WC_Product {
$has_weight = $this->data_store->child_has_weight( $this );
set_transient( $transient_name, $has_weight, DAY_IN_SECONDS * 30 );
}
return (bool) $has_weight;
}
@ -488,6 +511,7 @@ class WC_Product_Variable extends WC_Product {
$has_dimension = $this->data_store->child_has_dimensions( $this );
set_transient( $transient_name, $has_dimension, DAY_IN_SECONDS * 30 );
}
return (bool) $has_dimension;
}
@ -532,6 +556,7 @@ class WC_Product_Variable extends WC_Product {
*
* @param WC_Product|int $product Product object or ID for which you wish to sync.
* @param bool $save If true, the product object will be saved to the DB before returning it.
*
* @return WC_Product Synced product object.
*/
public static function sync( $product, $save = true ) {
@ -550,8 +575,12 @@ class WC_Product_Variable extends WC_Product {
$product->save();
}
wc_do_deprecated_action( 'woocommerce_variable_product_sync', array( $product->get_id(), $product->get_visible_children() ), '3.0', 'woocommerce_variable_product_sync_data, woocommerce_new_product or woocommerce_update_product' );
wc_do_deprecated_action( 'woocommerce_variable_product_sync', array(
$product->get_id(),
$product->get_visible_children()
), '3.0', 'woocommerce_variable_product_sync_data, woocommerce_new_product or woocommerce_update_product' );
}
return $product;
}
@ -560,6 +589,7 @@ class WC_Product_Variable extends WC_Product {
*
* @param WC_Product|int $product Product object or ID for which you wish to sync.
* @param bool $save If true, the product object will be saved to the DB before returning it.
*
* @return WC_Product Synced product object.
*/
public static function sync_stock_status( $product, $save = true ) {
@ -574,6 +604,7 @@ class WC_Product_Variable extends WC_Product {
$product->save();
}
}
return $product;
}
@ -581,10 +612,12 @@ class WC_Product_Variable extends WC_Product {
* Sort an associativate array of $variation_id => $price pairs in order of min and max prices.
*
* @param array $prices Associativate array of $variation_id => $price pairs
*
* @return array
*/
protected function sort_variation_prices( $prices ) {
asort( $prices );
return $prices;
}
}

View File

@ -43,7 +43,7 @@ class WC_Regenerate_Images {
}
// Not required when Jetpack Photon is in use.
if ( class_exists( 'Jetpack' ) && Jetpack::is_module_active( 'photon' ) ) {
if ( method_exists( 'Jetpack', 'is_module_active' ) && Jetpack::is_module_active( 'photon' ) ) {
return;
}
@ -84,7 +84,7 @@ class WC_Regenerate_Images {
// See if the image size has changed from our settings.
if ( ! self::image_size_matches_settings( $data, $size ) ) {
// If Photon is running we can just return false and let Jetpack handle regeneration.
if ( class_exists( 'Jetpack' ) && Jetpack::is_module_active( 'photon' ) ) {
if ( method_exists( 'Jetpack', 'is_module_active' ) && Jetpack::is_module_active( 'photon' ) ) {
return false;
} else {
// If we get here, Jetpack is not running and we don't have the correct image sized stored. Try to return closest match.

View File

@ -144,6 +144,7 @@ class WC_Shipping_Rate {
/**
* Set rate cost.
*
* @todo 4.0 Prevent negative value being set. #19293
* @since 3.2.0
* @param string $cost
*/

View File

@ -3,7 +3,6 @@
* Handles storage and retrieval of shipping zones
*
* @package WooCommerce/Classes
* @author Automattic
* @version 3.3.0
* @since 2.6.0
*/
@ -29,11 +28,11 @@ class WC_Shipping_Zones {
$zones = array();
foreach ( $raw_zones as $raw_zone ) {
$zone = new WC_Shipping_Zone( $raw_zone );
$zones[ $zone->get_id() ] = $zone->get_data();
$zones[ $zone->get_id() ]['zone_id'] = $zone->get_id();
$zone = new WC_Shipping_Zone( $raw_zone );
$zones[ $zone->get_id() ] = $zone->get_data();
$zones[ $zone->get_id() ]['zone_id'] = $zone->get_id();
$zones[ $zone->get_id() ]['formatted_zone_location'] = $zone->get_formatted_location();
$zones[ $zone->get_id() ]['shipping_methods'] = $zone->get_shipping_methods();
$zones[ $zone->get_id() ]['shipping_methods'] = $zone->get_shipping_methods( false, 'json' );
}
return $zones;

View File

@ -264,7 +264,7 @@ class WC_Structured_Data {
$markup['offers'] = array( apply_filters( 'woocommerce_structured_data_product_offer', $markup_offer, $product ) );
}
if ( $product->get_review_count() ) {
if ( $product->get_review_count() && 'yes' === get_option( 'woocommerce_enable_review_rating' ) ) {
$markup['aggregateRating'] = array(
'@type' => 'AggregateRating',
'ratingValue' => $product->get_average_rating(),

View File

@ -275,7 +275,9 @@ class WC_Template_Loader {
$prefix = '';
}
add_filter( 'woocommerce_shortcode_products_query', array( __CLASS__, 'unsupported_archive_layered_nav_compatibility' ) );
$shortcode = new WC_Shortcode_Products( $shortcode_args );
remove_filter( 'woocommerce_shortcode_products_query', array( __CLASS__, 'unsupported_archive_layered_nav_compatibility' ) );
$shop_page = get_post( self::$shop_page_id );
$dummy_post_properties = array(
@ -318,7 +320,7 @@ class WC_Template_Loader {
$wp_query->is_page = true;
$wp_query->is_single = true;
$wp_query->is_archive = false;
$wp_query->is_tax = false;
$wp_query->is_tax = true;
$wp_query->max_num_pages = 0;
// Prepare everything for rendering.
@ -328,6 +330,26 @@ class WC_Template_Loader {
add_filter( 'template_include', array( __CLASS__, 'force_single_template_filter' ) );
}
/**
* Add layered nav args to WP_Query args generated by the 'products' shortcode.
*
* @since 3.3.4
* @param array $query WP_Query args.
* @return array
*/
public static function unsupported_archive_layered_nav_compatibility( $query ) {
foreach ( WC()->query->get_layered_nav_chosen_attributes() as $taxonomy => $data ) {
$query['tax_query'][] = array(
'taxonomy' => $taxonomy,
'field' => 'slug',
'terms' => $data['terms'],
'operator' => 'and' === $data['query_type'] ? 'AND' : 'IN',
'include_children' => false,
);
}
return $query;
}
/**
* Force the loading of one of the single templates instead of whatever template was about to be loaded.
*

View File

@ -341,7 +341,7 @@ final class WooCommerce {
include_once WC_ABSPATH . 'includes/data-stores/class-wc-order-item-data-store.php';
include_once WC_ABSPATH . 'includes/data-stores/class-wc-order-item-coupon-data-store.php';
include_once WC_ABSPATH . 'includes/data-stores/class-wc-order-item-fee-data-store.php';
include_once WC_ABSPATH . 'includes/data-stores/class-wc-order-item-product-store.php';
include_once WC_ABSPATH . 'includes/data-stores/class-wc-order-item-product-data-store.php';
include_once WC_ABSPATH . 'includes/data-stores/class-wc-order-item-shipping-data-store.php';
include_once WC_ABSPATH . 'includes/data-stores/class-wc-order-item-tax-data-store.php';
include_once WC_ABSPATH . 'includes/data-stores/class-wc-payment-token-data-store.php';

View File

@ -64,13 +64,6 @@ class WC_CLI_REST_Command {
*/
private $schema;
/**
* Nesting level.
*
* @var int
*/
private $output_nesting_level = 0;
/**
* List of supported IDs and their description (name => desc).
*
@ -417,60 +410,6 @@ EOT;
return rtrim( $route );
}
/**
* Output a line to be added
*
* @param string $line Line to add.
*/
private function add_line( $line ) {
$this->nested_line( $line, 'add' );
}
/**
* Output a line to be removed
*
* @param string $line Line to remove.
*/
private function remove_line( $line ) {
$this->nested_line( $line, 'remove' );
}
/**
* Output a line that's appropriately nested
*
* @param string $line Line to nest.
* @param bool|string $change Type of change.
*/
private function nested_line( $line, $change = false ) {
if ( 'add' === $change ) {
$label = '+ ';
} elseif ( 'remove' === $change ) {
$label = '- ';
} else {
$label = false;
}
$spaces = ( $this->output_nesting_level * 2 ) + 2;
if ( $label ) {
$line = $label . $line;
$spaces = $spaces - 2;
}
WP_CLI::line( str_pad( ' ', $spaces ) . $line );
}
/**
* Whether or not this is an associative array
*
* @param array $array Array to check.
* @return bool
*/
private function is_assoc_array( $array ) {
if ( ! is_array( $array ) ) {
return false;
}
return array_keys( $array ) !== range( 0, count( $array ) - 1 );
}
/**
* Reduce an item to specific fields.
*

View File

@ -6,7 +6,6 @@
*
* @version 3.3.0
* @package WooCommerce
* @author WooCommerce
*/
if ( ! defined( 'ABSPATH' ) ) {

View File

@ -13,8 +13,6 @@ if ( ! defined( 'ABSPATH' ) ) {
* Abstract Order Data Store: Stored in CPT.
*
* @version 3.0.0
* @category Class
* @author WooThemes
*/
abstract class Abstract_WC_Order_Data_Store_CPT extends WC_Data_Store_WP implements WC_Object_Data_Store_Interface, WC_Abstract_Order_Data_Store_Interface {
@ -98,7 +96,7 @@ abstract class Abstract_WC_Order_Data_Store_CPT extends WC_Data_Store_WP impleme
$order->set_defaults();
$post_object = get_post( $order->get_id() );
if ( ! $order->get_id() || ! $post_object || ! in_array( $post_object->post_type, wc_get_order_types() ) ) {
if ( ! $order->get_id() || ! $post_object || ! in_array( $post_object->post_type, wc_get_order_types(), true ) ) {
throw new Exception( __( 'Invalid order.', 'woocommerce' ) );
}

View File

@ -1,4 +1,10 @@
<?php
/**
* Class Abstract_WC_Order_Item_Type_Data_Store file.
*
* @package WooCommerce\DataStores
*/
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
@ -7,8 +13,6 @@ if ( ! defined( 'ABSPATH' ) ) {
* WC Order Item Data Store
*
* @version 3.0.0
* @category Class
* @author WooCommerce
*/
abstract class Abstract_WC_Order_Item_Type_Data_Store extends WC_Data_Store_WP implements WC_Object_Data_Store_Interface {
@ -16,6 +20,8 @@ abstract class Abstract_WC_Order_Item_Type_Data_Store extends WC_Data_Store_WP i
* Meta type. This should match up with
* the types available at https://codex.wordpress.org/Function_Reference/add_metadata.
* WP defines 'post', 'user', 'comment', and 'term'.
*
* @var string
*/
protected $meta_type = 'order_item';
@ -23,6 +29,7 @@ abstract class Abstract_WC_Order_Item_Type_Data_Store extends WC_Data_Store_WP i
* This only needs set if you are using a custom metadata type (for example payment tokens.
* This should be the name of the field your table uses for associating meta with objects.
* For example, in payment_tokenmeta, this would be payment_token_id.
*
* @var string
*/
protected $object_id_field_for_meta = 'order_item_id';
@ -31,16 +38,18 @@ abstract class Abstract_WC_Order_Item_Type_Data_Store extends WC_Data_Store_WP i
* Create a new order item in the database.
*
* @since 3.0.0
* @param WC_Order_Item $item
* @param WC_Order_Item $item Order item object.
*/
public function create( &$item ) {
global $wpdb;
$wpdb->insert( $wpdb->prefix . 'woocommerce_order_items', array(
'order_item_name' => $item->get_name(),
'order_item_type' => $item->get_type(),
'order_id' => $item->get_order_id(),
) );
$wpdb->insert(
$wpdb->prefix . 'woocommerce_order_items', array(
'order_item_name' => $item->get_name(),
'order_item_type' => $item->get_type(),
'order_id' => $item->get_order_id(),
)
);
$item->set_id( $wpdb->insert_id );
$this->save_item_data( $item );
$item->save_meta_data();
@ -54,7 +63,7 @@ abstract class Abstract_WC_Order_Item_Type_Data_Store extends WC_Data_Store_WP i
* Update a order item in the database.
*
* @since 3.0.0
* @param WC_Order_Item $item
* @param WC_Order_Item $item Order item object.
*/
public function update( &$item ) {
global $wpdb;
@ -62,11 +71,13 @@ abstract class Abstract_WC_Order_Item_Type_Data_Store extends WC_Data_Store_WP i
$changes = $item->get_changes();
if ( array_intersect( array( 'name', 'order_id' ), array_keys( $changes ) ) ) {
$wpdb->update( $wpdb->prefix . 'woocommerce_order_items', array(
'order_item_name' => $item->get_name(),
'order_item_type' => $item->get_type(),
'order_id' => $item->get_order_id(),
), array( 'order_item_id' => $item->get_id() ) );
$wpdb->update(
$wpdb->prefix . 'woocommerce_order_items', array(
'order_item_name' => $item->get_name(),
'order_item_type' => $item->get_type(),
'order_id' => $item->get_order_id(),
), array( 'order_item_id' => $item->get_id() )
);
}
$this->save_item_data( $item );
@ -81,8 +92,8 @@ abstract class Abstract_WC_Order_Item_Type_Data_Store extends WC_Data_Store_WP i
* Remove an order item from the database.
*
* @since 3.0.0
* @param WC_Order_Item $item
* @param array $args Array of args to pass to the delete method.
* @param WC_Order_Item $item Order item object.
* @param array $args Array of args to pass to the delete method.
*/
public function delete( &$item, $args = array() ) {
if ( $item->get_id() ) {
@ -100,9 +111,9 @@ abstract class Abstract_WC_Order_Item_Type_Data_Store extends WC_Data_Store_WP i
*
* @since 3.0.0
*
* @param WC_Order_Item $item
* @param WC_Order_Item $item Order item object.
*
* @throws Exception
* @throws Exception If invalid order item.
*/
public function read( &$item ) {
global $wpdb;
@ -121,10 +132,12 @@ abstract class Abstract_WC_Order_Item_Type_Data_Store extends WC_Data_Store_WP i
throw new Exception( __( 'Invalid order item.', 'woocommerce' ) );
}
$item->set_props( array(
'order_id' => $data->order_id,
'name' => $data->order_item_name,
) );
$item->set_props(
array(
'order_id' => $data->order_id,
'name' => $data->order_item_name,
)
);
$item->read_meta_data();
}
@ -133,14 +146,14 @@ abstract class Abstract_WC_Order_Item_Type_Data_Store extends WC_Data_Store_WP i
* Ran after both create and update, so $item->get_id() will be set.
*
* @since 3.0.0
* @param WC_Order_Item $item
* @param WC_Order_Item $item Order item object.
*/
public function save_item_data( &$item ) {}
/**
* Clear meta cache.
*
* @param WC_Order_Item $item
* @param WC_Order_Item $item Order item object.
*/
public function clear_cache( &$item ) {
wp_cache_delete( 'item-' . $item->get_id(), 'order-items' );

View File

@ -1,4 +1,10 @@
<?php
/**
* Class WC_Coupon_Data_Store_CPT file.
*
* @package WooCommerce\DataStore
*/
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
@ -7,13 +13,12 @@ if ( ! defined( 'ABSPATH' ) ) {
* WC Coupon Data Store: Custom Post Type.
*
* @version 3.0.0
* @category Class
* @author WooThemes
*/
class WC_Coupon_Data_Store_CPT extends WC_Data_Store_WP implements WC_Coupon_Data_Store_Interface, WC_Object_Data_Store_Interface {
/**
* Internal meta type used to store coupon data.
*
* @since 3.0.0
* @var string
*/
@ -21,6 +26,7 @@ class WC_Coupon_Data_Store_CPT extends WC_Data_Store_WP implements WC_Coupon_Dat
/**
* Data stored in meta keys, but not considered "meta" for a coupon.
*
* @since 3.0.0
* @var array
*/
@ -52,21 +58,26 @@ class WC_Coupon_Data_Store_CPT extends WC_Data_Store_WP implements WC_Coupon_Dat
* Method to create a new coupon in the database.
*
* @since 3.0.0
* @param WC_Coupon $coupon
* @param WC_Coupon $coupon Coupon object.
*/
public function create( &$coupon ) {
$coupon->set_date_created( current_time( 'timestamp', true ) );
$coupon_id = wp_insert_post( apply_filters( 'woocommerce_new_coupon_data', array(
'post_type' => 'shop_coupon',
'post_status' => 'publish',
'post_author' => get_current_user_id(),
'post_title' => $coupon->get_code( 'edit' ),
'post_content' => '',
'post_excerpt' => $coupon->get_description( 'edit' ),
'post_date' => gmdate( 'Y-m-d H:i:s', $coupon->get_date_created()->getOffsetTimestamp() ),
'post_date_gmt' => gmdate( 'Y-m-d H:i:s', $coupon->get_date_created()->getTimestamp() ),
) ), true );
$coupon_id = wp_insert_post(
apply_filters(
'woocommerce_new_coupon_data',
array(
'post_type' => 'shop_coupon',
'post_status' => 'publish',
'post_author' => get_current_user_id(),
'post_title' => $coupon->get_code( 'edit' ),
'post_content' => '',
'post_excerpt' => $coupon->get_description( 'edit' ),
'post_date' => gmdate( 'Y-m-d H:i:s', $coupon->get_date_created()->getOffsetTimestamp() ),
'post_date_gmt' => gmdate( 'Y-m-d H:i:s', $coupon->get_date_created()->getTimestamp() ),
)
), true
);
if ( $coupon_id ) {
$coupon->set_id( $coupon_id );
@ -82,42 +93,46 @@ class WC_Coupon_Data_Store_CPT extends WC_Data_Store_WP implements WC_Coupon_Dat
*
* @since 3.0.0
*
* @param WC_Data $coupon
* @param WC_Coupon $coupon Coupon object.
*
* @throws Exception
* @throws Exception If invalid coupon.
*/
public function read( &$coupon ) {
$coupon->set_defaults();
if ( ! $coupon->get_id() || ! ( $post_object = get_post( $coupon->get_id() ) ) || 'shop_coupon' !== $post_object->post_type ) {
$post_object = get_post( $coupon->get_id() );
if ( ! $coupon->get_id() || ! $post_object || 'shop_coupon' !== $post_object->post_type ) {
throw new Exception( __( 'Invalid coupon.', 'woocommerce' ) );
}
$coupon_id = $coupon->get_id();
$coupon->set_props( array(
'code' => $post_object->post_title,
'description' => $post_object->post_excerpt,
'date_created' => 0 < $post_object->post_date_gmt ? wc_string_to_timestamp( $post_object->post_date_gmt ) : null,
'date_modified' => 0 < $post_object->post_modified_gmt ? wc_string_to_timestamp( $post_object->post_modified_gmt ) : null,
'date_expires' => metadata_exists( 'post', $coupon_id, 'date_expires' ) ? get_post_meta( $coupon_id, 'date_expires', true ) : get_post_meta( $coupon_id, 'expiry_date', true ),
'discount_type' => get_post_meta( $coupon_id, 'discount_type', true ),
'amount' => get_post_meta( $coupon_id, 'coupon_amount', true ),
'usage_count' => get_post_meta( $coupon_id, 'usage_count', true ),
'individual_use' => 'yes' === get_post_meta( $coupon_id, 'individual_use', true ),
'product_ids' => array_filter( (array) explode( ',', get_post_meta( $coupon_id, 'product_ids', true ) ) ),
'excluded_product_ids' => array_filter( (array) explode( ',', get_post_meta( $coupon_id, 'exclude_product_ids', true ) ) ),
'usage_limit' => get_post_meta( $coupon_id, 'usage_limit', true ),
'usage_limit_per_user' => get_post_meta( $coupon_id, 'usage_limit_per_user', true ),
'limit_usage_to_x_items' => 0 < get_post_meta( $coupon_id, 'limit_usage_to_x_items', true ) ? get_post_meta( $coupon_id, 'limit_usage_to_x_items', true ) : null,
'free_shipping' => 'yes' === get_post_meta( $coupon_id, 'free_shipping', true ),
'product_categories' => array_filter( (array) get_post_meta( $coupon_id, 'product_categories', true ) ),
'excluded_product_categories' => array_filter( (array) get_post_meta( $coupon_id, 'exclude_product_categories', true ) ),
'exclude_sale_items' => 'yes' === get_post_meta( $coupon_id, 'exclude_sale_items', true ),
'minimum_amount' => get_post_meta( $coupon_id, 'minimum_amount', true ),
'maximum_amount' => get_post_meta( $coupon_id, 'maximum_amount', true ),
'email_restrictions' => array_filter( (array) get_post_meta( $coupon_id, 'customer_email', true ) ),
'used_by' => array_filter( (array) get_post_meta( $coupon_id, '_used_by' ) ),
) );
$coupon->set_props(
array(
'code' => $post_object->post_title,
'description' => $post_object->post_excerpt,
'date_created' => 0 < $post_object->post_date_gmt ? wc_string_to_timestamp( $post_object->post_date_gmt ) : null,
'date_modified' => 0 < $post_object->post_modified_gmt ? wc_string_to_timestamp( $post_object->post_modified_gmt ) : null,
'date_expires' => metadata_exists( 'post', $coupon_id, 'date_expires' ) ? get_post_meta( $coupon_id, 'date_expires', true ) : get_post_meta( $coupon_id, 'expiry_date', true ),
'discount_type' => get_post_meta( $coupon_id, 'discount_type', true ),
'amount' => get_post_meta( $coupon_id, 'coupon_amount', true ),
'usage_count' => get_post_meta( $coupon_id, 'usage_count', true ),
'individual_use' => 'yes' === get_post_meta( $coupon_id, 'individual_use', true ),
'product_ids' => array_filter( (array) explode( ',', get_post_meta( $coupon_id, 'product_ids', true ) ) ),
'excluded_product_ids' => array_filter( (array) explode( ',', get_post_meta( $coupon_id, 'exclude_product_ids', true ) ) ),
'usage_limit' => get_post_meta( $coupon_id, 'usage_limit', true ),
'usage_limit_per_user' => get_post_meta( $coupon_id, 'usage_limit_per_user', true ),
'limit_usage_to_x_items' => 0 < get_post_meta( $coupon_id, 'limit_usage_to_x_items', true ) ? get_post_meta( $coupon_id, 'limit_usage_to_x_items', true ) : null,
'free_shipping' => 'yes' === get_post_meta( $coupon_id, 'free_shipping', true ),
'product_categories' => array_filter( (array) get_post_meta( $coupon_id, 'product_categories', true ) ),
'excluded_product_categories' => array_filter( (array) get_post_meta( $coupon_id, 'exclude_product_categories', true ) ),
'exclude_sale_items' => 'yes' === get_post_meta( $coupon_id, 'exclude_sale_items', true ),
'minimum_amount' => get_post_meta( $coupon_id, 'minimum_amount', true ),
'maximum_amount' => get_post_meta( $coupon_id, 'maximum_amount', true ),
'email_restrictions' => array_filter( (array) get_post_meta( $coupon_id, 'customer_email', true ) ),
'used_by' => array_filter( (array) get_post_meta( $coupon_id, '_used_by' ) ),
)
);
$coupon->read_meta_data();
$coupon->set_object_read( true );
do_action( 'woocommerce_coupon_loaded', $coupon );
@ -127,7 +142,7 @@ class WC_Coupon_Data_Store_CPT extends WC_Data_Store_WP implements WC_Coupon_Dat
* Updates a coupon in the database.
*
* @since 3.0.0
* @param WC_Coupon $coupon
* @param WC_Coupon $coupon Coupon object.
*/
public function update( &$coupon ) {
$coupon->save_meta_data();
@ -140,7 +155,7 @@ class WC_Coupon_Data_Store_CPT extends WC_Data_Store_WP implements WC_Coupon_Dat
'post_date' => gmdate( 'Y-m-d H:i:s', $coupon->get_date_created( 'edit' )->getOffsetTimestamp() ),
'post_date_gmt' => gmdate( 'Y-m-d H:i:s', $coupon->get_date_created( 'edit' )->getTimestamp() ),
'post_modified' => isset( $changes['date_modified'] ) ? gmdate( 'Y-m-d H:i:s', $coupon->get_date_modified( 'edit' )->getOffsetTimestamp() ) : current_time( 'mysql' ),
'post_modified_gmt' => isset( $changes['date_modified'] ) ? gmdate( 'Y-m-d H:i:s', $coupon->get_date_modified( 'edit' )->getTimestamp() ) : current_time( 'mysql', 1 ),
'post_modified_gmt' => isset( $changes['date_modified'] ) ? gmdate( 'Y-m-d H:i:s', $coupon->get_date_modified( 'edit' )->getTimestamp() ) : current_time( 'mysql', 1 ),
);
/**
@ -169,13 +184,15 @@ class WC_Coupon_Data_Store_CPT extends WC_Data_Store_WP implements WC_Coupon_Dat
*
* @since 3.0.0
*
* @param WC_Coupon $coupon
* @param WC_Coupon $coupon Coupon object.
* @param array $args Array of args to pass to the delete method.
*/
public function delete( &$coupon, $args = array() ) {
$args = wp_parse_args( $args, array(
'force_delete' => false,
) );
$args = wp_parse_args(
$args, array(
'force_delete' => false,
)
);
$id = $coupon->get_id();
@ -199,7 +216,7 @@ class WC_Coupon_Data_Store_CPT extends WC_Data_Store_WP implements WC_Coupon_Dat
/**
* Helper method that updates all the post meta for a coupon based on it's settings in the WC_Coupon class.
*
* @param WC_Coupon
* @param WC_Coupon $coupon Coupon object.
* @since 3.0.0
*/
private function update_post_meta( &$coupon ) {
@ -214,7 +231,7 @@ class WC_Coupon_Data_Store_CPT extends WC_Data_Store_WP implements WC_Coupon_Dat
'usage_limit_per_user' => 'usage_limit_per_user',
'limit_usage_to_x_items' => 'limit_usage_to_x_items',
'usage_count' => 'usage_count',
'date_expires' => 'date_expires',
'date_expires' => 'date_expires',
'free_shipping' => 'free_shipping',
'product_categories' => 'product_categories',
'exclude_product_categories' => 'excluded_product_categories',
@ -228,27 +245,27 @@ class WC_Coupon_Data_Store_CPT extends WC_Data_Store_WP implements WC_Coupon_Dat
foreach ( $props_to_update as $meta_key => $prop ) {
$value = $coupon->{"get_$prop"}( 'edit' );
switch ( $prop ) {
case 'individual_use' :
case 'free_shipping' :
case 'exclude_sale_items' :
case 'individual_use':
case 'free_shipping':
case 'exclude_sale_items':
$updated = update_post_meta( $coupon->get_id(), $meta_key, wc_bool_to_string( $value ) );
break;
case 'product_ids' :
case 'excluded_product_ids' :
case 'product_ids':
case 'excluded_product_ids':
$updated = update_post_meta( $coupon->get_id(), $meta_key, implode( ',', array_filter( array_map( 'intval', $value ) ) ) );
break;
case 'product_categories' :
case 'excluded_product_categories' :
case 'product_categories':
case 'excluded_product_categories':
$updated = update_post_meta( $coupon->get_id(), $meta_key, array_filter( array_map( 'intval', $value ) ) );
break;
case 'email_restrictions' :
case 'email_restrictions':
$updated = update_post_meta( $coupon->get_id(), $meta_key, array_filter( array_map( 'sanitize_email', $value ) ) );
break;
case 'date_expires' :
case 'date_expires':
$updated = update_post_meta( $coupon->get_id(), $meta_key, ( $value ? $value->getTimestamp() : null ) );
update_post_meta( $coupon->get_id(), 'expiry_date', ( $value ? $value->date( 'Y-m-d' ) : '' ) ); // Update the old meta key for backwards compatibility.
break;
default :
default:
$updated = update_post_meta( $coupon->get_id(), $meta_key, $value );
break;
}
@ -264,9 +281,9 @@ class WC_Coupon_Data_Store_CPT extends WC_Data_Store_WP implements WC_Coupon_Dat
* Increase usage count for current coupon.
*
* @since 3.0.0
* @param WC_Coupon
* @param string $used_by Either user ID or billing email
* @return int New usage count
* @param WC_Coupon $coupon Coupon object.
* @param string $used_by Either user ID or billing email.
* @return int New usage count.
*/
public function increase_usage_count( &$coupon, $used_by = '' ) {
$new_count = $this->update_usage_count_meta( $coupon, 'increase' );
@ -281,9 +298,9 @@ class WC_Coupon_Data_Store_CPT extends WC_Data_Store_WP implements WC_Coupon_Dat
* Decrease usage count for current coupon.
*
* @since 3.0.0
* @param WC_Coupon
* @param string $used_by Either user ID or billing email
* @return int New usage count
* @param WC_Coupon $coupon Coupon object.
* @param string $used_by Either user ID or billing email.
* @return int New usage count.
*/
public function decrease_usage_count( &$coupon, $used_by = '' ) {
global $wpdb;
@ -306,17 +323,22 @@ class WC_Coupon_Data_Store_CPT extends WC_Data_Store_WP implements WC_Coupon_Dat
* Increase or decrease the usage count for a coupon by 1.
*
* @since 3.0.0
* @param WC_Coupon
* @param string $operation 'increase' or 'decrease'
* @param WC_Coupon $coupon Coupon object.
* @param string $operation 'increase' or 'decrease'.
* @return int New usage count
*/
private function update_usage_count_meta( &$coupon, $operation = 'increase' ) {
global $wpdb;
$id = $coupon->get_id();
$id = $coupon->get_id();
$operator = ( 'increase' === $operation ) ? '+' : '-';
add_post_meta( $id, 'usage_count', $coupon->get_usage_count( 'edit' ), true );
$wpdb->query( $wpdb->prepare( "UPDATE $wpdb->postmeta SET meta_value = meta_value {$operator} 1 WHERE meta_key = 'usage_count' AND post_id = %d;", $id ) );
$wpdb->query(
$wpdb->prepare(
"UPDATE $wpdb->postmeta SET meta_value = meta_value {$operator} 1 WHERE meta_key = 'usage_count' AND post_id = %d;", // phpcs:ignore WordPress.WP.PreparedSQL.NotPrepared
$id
)
);
// Get the latest value direct from the DB, instead of possibly the WP meta cache.
return (int) $wpdb->get_var( $wpdb->prepare( "SELECT meta_value FROM $wpdb->postmeta WHERE meta_key = 'usage_count' AND post_id = %d;", $id ) );
@ -326,8 +348,8 @@ class WC_Coupon_Data_Store_CPT extends WC_Data_Store_WP implements WC_Coupon_Dat
* Get the number of uses for a coupon by user ID.
*
* @since 3.0.0
* @param WC_Coupon
* @param id $user_id
* @param WC_Coupon $coupon Coupon object.
* @param id $user_id User ID.
* @return int
*/
public function get_usage_by_user_id( &$coupon, $user_id ) {
@ -339,18 +361,21 @@ class WC_Coupon_Data_Store_CPT extends WC_Data_Store_WP implements WC_Coupon_Dat
* Return a coupon code for a specific ID.
*
* @since 3.0.0
* @param int $id
* @param int $id Coupon ID.
* @return string Coupon Code
*/
public function get_code_by_id( $id ) {
global $wpdb;
return $wpdb->get_var( $wpdb->prepare( "
SELECT post_title
FROM $wpdb->posts
WHERE ID = %d
AND post_type = 'shop_coupon'
AND post_status = 'publish';
", $id ) );
return $wpdb->get_var(
$wpdb->prepare(
"SELECT post_title
FROM $wpdb->posts
WHERE ID = %d
AND post_type = 'shop_coupon'
AND post_status = 'publish'",
$id
)
);
}
/**
@ -358,11 +383,16 @@ class WC_Coupon_Data_Store_CPT extends WC_Data_Store_WP implements WC_Coupon_Dat
* Can return multiple to check for existence.
*
* @since 3.0.0
* @param string $code
* @param string $code Coupon code.
* @return array Array of IDs.
*/
public function get_ids_by_code( $code ) {
global $wpdb;
return $wpdb->get_col( $wpdb->prepare( "SELECT ID FROM $wpdb->posts WHERE post_title = %s AND post_type = 'shop_coupon' AND post_status = 'publish' ORDER BY post_date DESC;", $code ) );
return $wpdb->get_col(
$wpdb->prepare(
"SELECT ID FROM $wpdb->posts WHERE post_title = %s AND post_type = 'shop_coupon' AND post_status = 'publish' ORDER BY post_date DESC",
$code
)
);
}
}

View File

@ -1,4 +1,10 @@
<?php
/**
* Class WC_Customer_Data_Store_Session file.
*
* @package WooCommerce\DataStores
*/
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
@ -7,13 +13,12 @@ if ( ! defined( 'ABSPATH' ) ) {
* WC Customer Data Store which stores the data in session.
*
* @version 3.0.0
* @category Class
* @author WooThemes
*/
class WC_Customer_Data_Store_Session extends WC_Data_Store_WP implements WC_Customer_Data_Store_Interface, WC_Object_Data_Store_Interface {
/**
* Keys which are also stored in a session (so we can make sure they get updated...)
*
* @var array
*/
protected $session_keys = array(
@ -48,7 +53,7 @@ class WC_Customer_Data_Store_Session extends WC_Data_Store_WP implements WC_Cust
/**
* Simply update the session.
*
* @param WC_Customer $customer
* @param WC_Customer $customer Customer object.
*/
public function create( &$customer ) {
$this->save_to_session( $customer );
@ -57,7 +62,7 @@ class WC_Customer_Data_Store_Session extends WC_Data_Store_WP implements WC_Cust
/**
* Simply update the session.
*
* @param WC_Customer $customer
* @param WC_Customer $customer Customer object.
*/
public function update( &$customer ) {
$this->save_to_session( $customer );
@ -66,7 +71,7 @@ class WC_Customer_Data_Store_Session extends WC_Data_Store_WP implements WC_Cust
/**
* Saves all customer data to the session.
*
* @param WC_Customer $customer
* @param WC_Customer $customer Customer object.
*/
public function save_to_session( $customer ) {
$data = array();
@ -85,7 +90,7 @@ class WC_Customer_Data_Store_Session extends WC_Data_Store_WP implements WC_Cust
* which case the stored ID will differ from the actual ID.
*
* @since 3.0.0
* @param WC_Customer $customer
* @param WC_Customer $customer Customer object.
*/
public function read( &$customer ) {
$data = (array) WC()->session->get( 'customer' );
@ -116,7 +121,7 @@ class WC_Customer_Data_Store_Session extends WC_Data_Store_WP implements WC_Cust
/**
* Load default values if props are unset.
*
* @param WC_Customer $customer
* @param WC_Customer $customer Customer object.
*/
protected function set_defaults( &$customer ) {
try {
@ -142,15 +147,16 @@ class WC_Customer_Data_Store_Session extends WC_Data_Store_WP implements WC_Cust
$current_user = wp_get_current_user();
$customer->set_billing_email( $current_user->user_email );
}
} catch ( WC_Data_Exception $e ) {}
} catch ( WC_Data_Exception $e ) { // phpcs:ignore Generic.CodeAnalysis.EmptyStatement.DetectedCatch
}
}
/**
* Deletes a customer from the database.
*
* @since 3.0.0
* @param WC_Customer $customer
* @param array $args Array of args to pass to the delete method.
* @param WC_Customer $customer Customer object.
* @param array $args Array of args to pass to the delete method.
*/
public function delete( &$customer, $args = array() ) {
WC()->session->set( 'customer', null );
@ -160,7 +166,7 @@ class WC_Customer_Data_Store_Session extends WC_Data_Store_WP implements WC_Cust
* Gets the customers last order.
*
* @since 3.0.0
* @param WC_Customer
* @param WC_Customer $customer Customer object.
* @return WC_Order|false
*/
public function get_last_order( &$customer ) {
@ -171,7 +177,7 @@ class WC_Customer_Data_Store_Session extends WC_Data_Store_WP implements WC_Cust
* Return the number of orders this customer has.
*
* @since 3.0.0
* @param WC_Customer
* @param WC_Customer $customer Customer object.
* @return integer
*/
public function get_order_count( &$customer ) {
@ -182,7 +188,7 @@ class WC_Customer_Data_Store_Session extends WC_Data_Store_WP implements WC_Cust
* Return how much money this customer has spent.
*
* @since 3.0.0
* @param WC_Customer
* @param WC_Customer $customer Customer object.
* @return float
*/
public function get_total_spent( &$customer ) {

View File

@ -1,4 +1,10 @@
<?php
/**
* Class WC_Customer_Data_Store file.
*
* @package WooCommerce\DataStores
*/
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
@ -7,8 +13,6 @@ if ( ! defined( 'ABSPATH' ) ) {
* WC Customer Data Store.
*
* @version 3.0.0
* @category Class
* @author WooThemes
*/
class WC_Customer_Data_Store extends WC_Data_Store_WP implements WC_Customer_Data_Store_Interface, WC_Object_Data_Store_Interface {
@ -72,7 +76,7 @@ class WC_Customer_Data_Store extends WC_Data_Store_WP implements WC_Customer_Dat
/**
* Callback to remove unwanted meta data.
*
* @param object $meta
* @param object $meta Meta object.
* @return bool
*/
protected function exclude_internal_meta_keys( $meta ) {
@ -80,23 +84,23 @@ class WC_Customer_Data_Store extends WC_Data_Store_WP implements WC_Customer_Dat
$table_prefix = $wpdb->prefix ? $wpdb->prefix : 'wp_';
return ! in_array( $meta->meta_key, $this->internal_meta_keys )
return ! in_array( $meta->meta_key, $this->internal_meta_keys, true )
&& 0 !== strpos( $meta->meta_key, '_woocommerce_persistent_cart' )
&& 0 !== strpos( $meta->meta_key, 'closedpostboxes_' )
&& 0 !== strpos( $meta->meta_key, 'metaboxhidden_' )
&& 0 !== strpos( $meta->meta_key, 'manageedit-' )
&& ! strstr( $meta->meta_key, $table_prefix )
&& 0 !== stripos( $meta->meta_key, 'wp_' );
}
}
/**
* Method to create a new customer in the database.
*
* @since 3.0.0
*
* @param WC_Data $customer
* @param WC_Customer $customer Customer object.
*
* @throws WC_Data_Exception
* @throws WC_Data_Exception If unable to create new customer.
*/
public function create( &$customer ) {
$id = wc_create_new_customer( $customer->get_email(), $customer->get_username(), $customer->get_password() );
@ -108,14 +112,18 @@ class WC_Customer_Data_Store extends WC_Data_Store_WP implements WC_Customer_Dat
$customer->set_id( $id );
$this->update_user_meta( $customer );
// Prevent wp_update_user calls in the same request and customer trigger the 'Notice of Password Changed' email
// Prevent wp_update_user calls in the same request and customer trigger the 'Notice of Password Changed' email.
$customer->set_password( '' );
wp_update_user( apply_filters( 'woocommerce_update_customer_args', array(
'ID' => $customer->get_id(),
'role' => $customer->get_role(),
'display_name' => $customer->get_display_name(),
), $customer ) );
wp_update_user(
apply_filters(
'woocommerce_update_customer_args', array(
'ID' => $customer->get_id(),
'role' => $customer->get_role(),
'display_name' => $customer->get_display_name(),
), $customer
)
);
$wp_user = new WP_User( $customer->get_id() );
$customer->set_date_created( $wp_user->user_registered );
$customer->set_date_modified( get_user_meta( $customer->get_id(), 'last_update', true ) );
@ -128,12 +136,14 @@ class WC_Customer_Data_Store extends WC_Data_Store_WP implements WC_Customer_Dat
* Method to read a customer object.
*
* @since 3.0.0
* @param WC_Customer $customer
* @throws Exception
* @param WC_Customer $customer Customer object.
* @throws Exception If invalid customer.
*/
public function read( &$customer ) {
$user_object = $customer->get_id() ? get_user_by( 'id', $customer->get_id() ) : false;
// User object is required.
if ( ! $customer->get_id() || ! ( $user_object = get_user_by( 'id', $customer->get_id() ) ) || empty( $user_object->ID ) ) {
if ( ! $user_object || empty( $user_object->ID ) ) {
throw new Exception( __( 'Invalid customer.', 'woocommerce' ) );
}
@ -146,15 +156,17 @@ class WC_Customer_Data_Store extends WC_Data_Store_WP implements WC_Customer_Dat
// Load meta but exclude deprecated props.
$user_meta = array_diff_key( array_map( 'wc_flatten_meta_callback', get_user_meta( $customer_id ) ), array_flip( array( 'country', 'state', 'postcode', 'city', 'address', 'address_2', 'default', 'location' ) ) );
$customer->set_props( $user_meta );
$customer->set_props( array(
'is_paying_customer' => get_user_meta( $customer_id, 'paying_customer', true ),
'email' => $user_object->user_email,
'username' => $user_object->user_login,
'display_name' => $user_object->display_name,
'date_created' => $user_object->user_registered, // Mysql string in local format.
'date_modified' => get_user_meta( $customer_id, 'last_update', true ),
'role' => ! empty( $user_object->roles[0] ) ? $user_object->roles[0] : 'customer',
) );
$customer->set_props(
array(
'is_paying_customer' => get_user_meta( $customer_id, 'paying_customer', true ),
'email' => $user_object->user_email,
'username' => $user_object->user_login,
'display_name' => $user_object->display_name,
'date_created' => $user_object->user_registered, // Mysql string in local format.
'date_modified' => get_user_meta( $customer_id, 'last_update', true ),
'role' => ! empty( $user_object->roles[0] ) ? $user_object->roles[0] : 'customer',
)
);
$customer->read_meta_data();
$customer->set_object_read( true );
do_action( 'woocommerce_customer_loaded', $customer );
@ -164,17 +176,26 @@ class WC_Customer_Data_Store extends WC_Data_Store_WP implements WC_Customer_Dat
* Updates a customer in the database.
*
* @since 3.0.0
* @param WC_Customer $customer
* @param WC_Customer $customer Customer object.
*/
public function update( &$customer ) {
wp_update_user( apply_filters( 'woocommerce_update_customer_args', array(
'ID' => $customer->get_id(),
'user_email' => $customer->get_email(),
'display_name' => $customer->get_display_name(),
), $customer ) );
wp_update_user(
apply_filters(
'woocommerce_update_customer_args', array(
'ID' => $customer->get_id(),
'user_email' => $customer->get_email(),
'display_name' => $customer->get_display_name(),
), $customer
)
);
// Only update password if a new one was set with set_password.
if ( $customer->get_password() ) {
wp_update_user( array( 'ID' => $customer->get_id(), 'user_pass' => $customer->get_password() ) );
wp_update_user(
array(
'ID' => $customer->get_id(),
'user_pass' => $customer->get_password(),
)
);
$customer->set_password( '' );
}
$this->update_user_meta( $customer );
@ -188,16 +209,18 @@ class WC_Customer_Data_Store extends WC_Data_Store_WP implements WC_Customer_Dat
* Deletes a customer from the database.
*
* @since 3.0.0
* @param WC_Customer $customer
* @param array $args Array of args to pass to the delete method.
* @param WC_Customer $customer Customer object.
* @param array $args Array of args to pass to the delete method.
*/
public function delete( &$customer, $args = array() ) {
if ( ! $customer->get_id() ) {
return;
}
$args = wp_parse_args( $args, array(
'reassign' => 0,
) );
$args = wp_parse_args(
$args, array(
'reassign' => 0,
)
);
$id = $customer->get_id();
wp_delete_user( $id, $args['reassign'] );
@ -207,8 +230,9 @@ class WC_Customer_Data_Store extends WC_Data_Store_WP implements WC_Customer_Dat
/**
* Helper method that updates all the meta for a customer. Used for update & create.
*
* @since 3.0.0
* @param WC_Customer
* @param WC_Customer $customer Customer object.
*/
private function update_user_meta( $customer ) {
$updated_props = array();
@ -283,21 +307,24 @@ class WC_Customer_Data_Store extends WC_Data_Store_WP implements WC_Customer_Dat
* Gets the customers last order.
*
* @since 3.0.0
* @param WC_Customer
* @param WC_Customer $customer Customer object.
* @return WC_Order|false
*/
public function get_last_order( &$customer ) {
global $wpdb;
$last_order = $wpdb->get_var( "SELECT posts.ID
$last_order = $wpdb->get_var(
// phpcs:disable WordPress.WP.PreparedSQL.NotPrepared
"SELECT posts.ID
FROM $wpdb->posts AS posts
LEFT JOIN {$wpdb->postmeta} AS meta on posts.ID = meta.post_id
WHERE meta.meta_key = '_customer_user'
AND meta.meta_value = '" . esc_sql( $customer->get_id() ) . "'
AND posts.post_type = 'shop_order'
AND posts.post_status IN ( '" . implode( "','", array_map( 'esc_sql', array_keys( wc_get_order_statuses() ) ) ) . "' )
ORDER BY posts.ID DESC
" );
ORDER BY posts.ID DESC"
// phpcs:enable
);
if ( $last_order ) {
return wc_get_order( absint( $last_order ) );
@ -310,7 +337,7 @@ class WC_Customer_Data_Store extends WC_Data_Store_WP implements WC_Customer_Dat
* Return the number of orders this customer has.
*
* @since 3.0.0
* @param WC_Customer
* @param WC_Customer $customer Customer object.
* @return integer
*/
public function get_order_count( &$customer ) {
@ -319,14 +346,17 @@ class WC_Customer_Data_Store extends WC_Data_Store_WP implements WC_Customer_Dat
if ( '' === $count ) {
global $wpdb;
$count = $wpdb->get_var( "SELECT COUNT(*)
$count = $wpdb->get_var(
// phpcs:disable WordPress.WP.PreparedSQL.NotPrepared
"SELECT COUNT(*)
FROM $wpdb->posts as posts
LEFT JOIN {$wpdb->postmeta} AS meta ON posts.ID = meta.post_id
WHERE meta.meta_key = '_customer_user'
AND posts.post_type = 'shop_order'
AND posts.post_status IN ( '" . implode( "','", array_map( 'esc_sql', array_keys( wc_get_order_statuses() ) ) ) . "' )
AND meta_value = '" . esc_sql( $customer->get_id() ) . "'
" );
AND meta_value = '" . esc_sql( $customer->get_id() ) . "'"
// phpcs:enable
);
update_user_meta( $customer->get_id(), '_order_count', $count );
}
@ -337,7 +367,7 @@ class WC_Customer_Data_Store extends WC_Data_Store_WP implements WC_Customer_Dat
* Return how much money this customer has spent.
*
* @since 3.0.0
* @param WC_Customer
* @param WC_Customer $customer Customer object.
* @return float
*/
public function get_total_spent( &$customer ) {
@ -347,16 +377,23 @@ class WC_Customer_Data_Store extends WC_Data_Store_WP implements WC_Customer_Dat
global $wpdb;
$statuses = array_map( 'esc_sql', wc_get_is_paid_statuses() );
$spent = $wpdb->get_var( apply_filters( 'woocommerce_customer_get_total_spent_query', "SELECT SUM(meta2.meta_value)
FROM $wpdb->posts as posts
LEFT JOIN {$wpdb->postmeta} AS meta ON posts.ID = meta.post_id
LEFT JOIN {$wpdb->postmeta} AS meta2 ON posts.ID = meta2.post_id
WHERE meta.meta_key = '_customer_user'
AND meta.meta_value = '" . esc_sql( $customer->get_id() ) . "'
AND posts.post_type = 'shop_order'
AND posts.post_status IN ( 'wc-" . implode( "','wc-", $statuses ) . "' )
AND meta2.meta_key = '_order_total'
", $customer ) );
$spent = $wpdb->get_var(
// phpcs:disable WordPress.WP.PreparedSQL.NotPrepared
apply_filters(
'woocommerce_customer_get_total_spent_query',
"SELECT SUM(meta2.meta_value)
FROM $wpdb->posts as posts
LEFT JOIN {$wpdb->postmeta} AS meta ON posts.ID = meta.post_id
LEFT JOIN {$wpdb->postmeta} AS meta2 ON posts.ID = meta2.post_id
WHERE meta.meta_key = '_customer_user'
AND meta.meta_value = '" . esc_sql( $customer->get_id() ) . "'
AND posts.post_type = 'shop_order'
AND posts.post_status IN ( 'wc-" . implode( "','wc-", $statuses ) . "' )
AND meta2.meta_key = '_order_total'",
$customer
)
// phpcs:enable
);
if ( ! $spent ) {
$spent = 0;
@ -370,8 +407,9 @@ class WC_Customer_Data_Store extends WC_Data_Store_WP implements WC_Customer_Dat
/**
* Search customers and return customer IDs.
*
* @param string $term
* @param int|string $limit @since 3.0.7
* @param string $term Search term.
* @param int|string $limit Limit search results.
* @since 3.0.7
*
* @return array
*/
@ -381,30 +419,38 @@ class WC_Customer_Data_Store extends WC_Data_Store_WP implements WC_Customer_Dat
return $results;
}
$query = new WP_User_Query( apply_filters( 'woocommerce_customer_search_customers', array(
'search' => '*' . esc_attr( $term ) . '*',
'search_columns' => array( 'user_login', 'user_url', 'user_email', 'user_nicename', 'display_name' ),
'fields' => 'ID',
'number' => $limit,
), $term, $limit, 'main_query' ) );
$query = new WP_User_Query(
apply_filters(
'woocommerce_customer_search_customers', array(
'search' => '*' . esc_attr( $term ) . '*',
'search_columns' => array( 'user_login', 'user_url', 'user_email', 'user_nicename', 'display_name' ),
'fields' => 'ID',
'number' => $limit,
), $term, $limit, 'main_query'
)
);
$query2 = new WP_User_Query( apply_filters( 'woocommerce_customer_search_customers', array(
'fields' => 'ID',
'number' => $limit,
'meta_query' => array(
'relation' => 'OR',
array(
'key' => 'first_name',
'value' => $term,
'compare' => 'LIKE',
),
array(
'key' => 'last_name',
'value' => $term,
'compare' => 'LIKE',
),
),
), $term, $limit, 'meta_query' ) );
$query2 = new WP_User_Query(
apply_filters(
'woocommerce_customer_search_customers', array(
'fields' => 'ID',
'number' => $limit,
'meta_query' => array(
'relation' => 'OR',
array(
'key' => 'first_name',
'value' => $term,
'compare' => 'LIKE',
),
array(
'key' => 'last_name',
'value' => $term,
'compare' => 'LIKE',
),
),
), $term, $limit, 'meta_query'
)
);
$results = wp_parse_id_list( array_merge( (array) $query->get_results(), (array) $query2->get_results() ) );

View File

@ -1,4 +1,10 @@
<?php
/**
* Class WC_Customer_Download_Log_Data_Store file.
*
* @package WooCommerce\DataStores
*/
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
@ -7,8 +13,6 @@ if ( ! defined( 'ABSPATH' ) ) {
* WC Customer Download Log Data Store.
*
* @version 3.3.0
* @category Class
* @author WooThemes
*/
class WC_Customer_Download_Log_Data_Store implements WC_Customer_Download_Log_Data_Store_Interface {
@ -27,7 +31,7 @@ class WC_Customer_Download_Log_Data_Store implements WC_Customer_Download_Log_Da
/**
* Create download log entry.
*
* @param WC_Customer_Download_Log $download_log
* @param WC_Customer_Download_Log $download_log Customer download log object.
*/
public function create( WC_Customer_Download_Log &$download_log ) {
global $wpdb;
@ -38,10 +42,10 @@ class WC_Customer_Download_Log_Data_Store implements WC_Customer_Download_Log_Da
}
$data = array(
'timestamp' => date( 'Y-m-d H:i:s', $download_log->get_timestamp( 'edit' )->getTimestamp() ),
'permission_id' => $download_log->get_permission_id( 'edit' ),
'user_id' => $download_log->get_user_id( 'edit' ),
'user_ip_address' => $download_log->get_user_ip_address( 'edit' ),
'timestamp' => date( 'Y-m-d H:i:s', $download_log->get_timestamp( 'edit' )->getTimestamp() ),
'permission_id' => $download_log->get_permission_id( 'edit' ),
'user_id' => $download_log->get_user_id( 'edit' ),
'user_ip_address' => $download_log->get_user_ip_address( 'edit' ),
);
$format = array(
@ -62,18 +66,17 @@ class WC_Customer_Download_Log_Data_Store implements WC_Customer_Download_Log_Da
if ( $result ) {
$download_log->set_id( $wpdb->insert_id );
$download_log->apply_changes();
}
else {
wp_die( __( 'Unable to insert download log entry in database.', 'woocommerce' ) );
} else {
wp_die( esc_html__( 'Unable to insert download log entry in database.', 'woocommerce' ) );
}
}
/**
* Method to read a download log from the database.
*
* @param $download_log
* @param WC_Customer_Download_Log $download_log Customer download log object.
*
* @throws Exception
* @throws Exception If invalid download log.
*/
public function read( &$download_log ) {
global $wpdb;
@ -86,20 +89,24 @@ class WC_Customer_Download_Log_Data_Store implements WC_Customer_Download_Log_Da
}
// Query the DB for the download log.
$raw_download_log_query = $wpdb->prepare(
"SELECT * FROM {$wpdb->prefix}" . self::get_table_name() . " WHERE download_log_id = %d", $download_log->get_id()
$raw_download_log = $wpdb->get_row(
$wpdb->prepare(
"SELECT * FROM {$wpdb->prefix}" . self::get_table_name() . ' WHERE download_log_id = %d', // phpcs:ignore WordPress.WP.PreparedSQL.NotPrepared
$download_log->get_id()
)
);
$raw_download_log = $wpdb->get_row( $raw_download_log_query );
if ( ! $raw_download_log ) {
throw new Exception( __( 'Invalid download log: not found.', 'woocommerce' ) );
}
$download_log->set_props( array(
'timestamp' => strtotime( $raw_download_log->timestamp ),
'permission_id' => $raw_download_log->permission_id,
'user_id' => $raw_download_log->user_id,
'user_ip_address' => $raw_download_log->user_ip_address,
) );
$download_log->set_props(
array(
'timestamp' => strtotime( $raw_download_log->timestamp ),
'permission_id' => $raw_download_log->permission_id,
'user_id' => $raw_download_log->user_id,
'user_ip_address' => $raw_download_log->user_ip_address,
)
);
$download_log->set_object_read( true );
}
@ -107,16 +114,16 @@ class WC_Customer_Download_Log_Data_Store implements WC_Customer_Download_Log_Da
/**
* Method to update a download log in the database.
*
* @param WC_Customer_Download_Log $download_log
* @param WC_Customer_Download_Log $download_log Customer download log object.
*/
public function update( &$download_log ) {
global $wpdb;
$data = array(
'timestamp' => date( 'Y-m-d H:i:s', $download_log->get_timestamp( 'edit' )->getTimestamp() ),
'permission_id' => $download_log->get_permission_id( 'edit' ),
'user_id' => $download_log->get_user_id( 'edit' ),
'user_ip_address' => $download_log->get_user_ip_address( 'edit' ),
'timestamp' => date( 'Y-m-d H:i:s', $download_log->get_timestamp( 'edit' )->getTimestamp() ),
'permission_id' => $download_log->get_permission_id( 'edit' ),
'user_id' => $download_log->get_user_id( 'edit' ),
'user_ip_address' => $download_log->get_user_ip_address( 'edit' ),
);
$format = array(
@ -150,53 +157,55 @@ class WC_Customer_Download_Log_Data_Store implements WC_Customer_Download_Log_Da
/**
* Get array of download log ids by specified args.
*
* @param array $args
* @param array $args Arguments to define download logs to retrieve.
* @return array
*/
public function get_download_logs( $args = array() ) {
global $wpdb;
$args = wp_parse_args( $args, array(
'permission_id' => '',
'user_id' => '',
'user_ip_address' => '',
'orderby' => 'download_log_id',
'order' => 'DESC',
'limit' => -1,
'return' => 'objects',
) );
$args = wp_parse_args(
$args, array(
'permission_id' => '',
'user_id' => '',
'user_ip_address' => '',
'orderby' => 'download_log_id',
'order' => 'DESC',
'limit' => -1,
'return' => 'objects',
)
);
$query = array();
$query[] = "SELECT * FROM {$wpdb->prefix}" . self::get_table_name() . " WHERE 1=1";
$query[] = "SELECT * FROM {$wpdb->prefix}" . self::get_table_name() . ' WHERE 1=1';
if ( $args['permission_id'] ) {
$query[] = $wpdb->prepare( "AND permission_id = %d", $args['permission_id'] );
$query[] = $wpdb->prepare( 'AND permission_id = %d', $args['permission_id'] );
}
if ( $args['user_id'] ) {
$query[] = $wpdb->prepare( "AND user_id = %d", $args['user_id'] );
$query[] = $wpdb->prepare( 'AND user_id = %d', $args['user_id'] );
}
if ( $args['user_ip_address'] ) {
$query[] = $wpdb->prepare( "AND user_ip_address = %s", $args['user_ip_address'] );
$query[] = $wpdb->prepare( 'AND user_ip_address = %s', $args['user_ip_address'] );
}
$allowed_orders = array( 'download_log_id', 'timestamp', 'permission_id', 'user_id' );
$order = in_array( $args['order'], $allowed_orders ) ? $args['order'] : 'download_log_id';
$order = in_array( $args['order'], $allowed_orders, true ) ? $args['order'] : 'download_log_id';
$orderby = 'DESC' === strtoupper( $args['orderby'] ) ? 'DESC' : 'ASC';
$orderby_sql = sanitize_sql_orderby( "{$order} {$orderby}" );
$query[] = "ORDER BY {$orderby_sql}";
if ( 0 < $args['limit'] ) {
$query[] = $wpdb->prepare( "LIMIT %d", $args['limit'] );
$query[] = $wpdb->prepare( 'LIMIT %d', $args['limit'] );
}
$raw_download_logs = $wpdb->get_results( implode( ' ', $query ) );
$raw_download_logs = $wpdb->get_results( implode( ' ', $query ) ); // phpcs:ignore WordPress.WP.PreparedSQL.NotPrepared
switch ( $args['return'] ) {
case 'ids' :
case 'ids':
return wp_list_pluck( $raw_download_logs, 'download_log_id' );
default :
default:
return array_map( array( $this, 'get_download_log' ), $raw_download_logs );
}
}
@ -204,7 +213,7 @@ class WC_Customer_Download_Log_Data_Store implements WC_Customer_Download_Log_Da
/**
* Get download logs for a given download permission.
*
* @param int $permission_id
* @param int $permission_id Permission ID.
* @return array
*/
public function get_download_logs_for_permission( $permission_id ) {
@ -213,9 +222,11 @@ class WC_Customer_Download_Log_Data_Store implements WC_Customer_Download_Log_Da
return array();
}
return $this->get_download_logs( array(
'permission_id' => $permission_id
) );
return $this->get_download_logs(
array(
'permission_id' => $permission_id,
)
);
}
}

View File

@ -1,4 +1,10 @@
<?php
/**
* Class WC_Data_Store_WP file.
*
* @package WooCommerce\DataStores
*/
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
@ -10,8 +16,6 @@ if ( ! defined( 'ABSPATH' ) ) {
* your own meta handling functions.
*
* @version 3.0.0
* @category Class
* @author WooThemes
*/
class WC_Data_Store_WP {
@ -19,6 +23,8 @@ class WC_Data_Store_WP {
* Meta type. This should match up with
* the types available at https://codex.wordpress.org/Function_Reference/add_metadata.
* WP defines 'post', 'user', 'comment', and 'term'.
*
* @var string
*/
protected $meta_type = 'post';
@ -26,12 +32,14 @@ class WC_Data_Store_WP {
* This only needs set if you are using a custom metadata type (for example payment tokens.
* This should be the name of the field your table uses for associating meta with objects.
* For example, in payment_tokenmeta, this would be payment_token_id.
*
* @var string
*/
protected $object_id_field_for_meta = '';
/**
* Data stored in meta keys, but not considered "meta" for an object.
*
* @since 3.0.0
* @var array
*/
@ -41,8 +49,8 @@ class WC_Data_Store_WP {
* Get and store terms from a taxonomy.
*
* @since 3.0.0
* @param WC_Data|integer $object
* @param string $taxonomy Taxonomy name e.g. product_cat
* @param WC_Data|integer $object WC_Data object or object ID.
* @param string $taxonomy Taxonomy name e.g. product_cat.
* @return array of terms
*/
protected function get_term_ids( $object, $taxonomy ) {
@ -62,18 +70,23 @@ class WC_Data_Store_WP {
* Returns an array of meta for an object.
*
* @since 3.0.0
* @param WC_Data
* @param WC_Data $object WC_Data object.
* @return array
*/
public function read_meta( &$object ) {
global $wpdb;
$db_info = $this->get_db_info();
$raw_meta_data = $wpdb->get_results( $wpdb->prepare( "
SELECT {$db_info['meta_id_field']} as meta_id, meta_key, meta_value
FROM {$db_info['table']}
WHERE {$db_info['object_id_field']} = %d
ORDER BY {$db_info['meta_id_field']}
", $object->get_id() ) );
$raw_meta_data = $wpdb->get_results(
$wpdb->prepare(
// phpcs:disable WordPress.WP.PreparedSQL.NotPrepared
"SELECT {$db_info['meta_id_field']} as meta_id, meta_key, meta_value
FROM {$db_info['table']}
WHERE {$db_info['object_id_field']} = %d
ORDER BY {$db_info['meta_id_field']}",
// phpcs:enable
$object->get_id()
)
);
$this->internal_meta_keys = array_merge( array_map( array( $this, 'prefix_key' ), $object->get_data_keys() ), $this->internal_meta_keys );
$meta_data = array_filter( $raw_meta_data, array( $this, 'exclude_internal_meta_keys' ) );
@ -84,8 +97,8 @@ class WC_Data_Store_WP {
* Deletes meta based on meta ID.
*
* @since 3.0.0
* @param WC_Data
* @param stdClass (containing at least ->id)
* @param WC_Data $object WC_Data object.
* @param stdClass $meta (containing at least ->id).
*/
public function delete_meta( &$object, $meta ) {
delete_metadata_by_mid( $this->meta_type, $meta->id );
@ -95,8 +108,8 @@ class WC_Data_Store_WP {
* Add new piece of meta.
*
* @since 3.0.0
* @param WC_Data
* @param stdClass (containing ->key and ->value)
* @param WC_Data $object WC_Data object.
* @param stdClass $meta (containing ->key and ->value).
* @return int meta ID
*/
public function add_meta( &$object, $meta ) {
@ -107,8 +120,8 @@ class WC_Data_Store_WP {
* Update meta.
*
* @since 3.0.0
* @param WC_Data
* @param stdClass (containing ->id, ->key and ->value)
* @param WC_Data $object WC_Data object.
* @param stdClass $meta (containing ->id, ->key and ->value).
*/
public function update_meta( &$object, $meta ) {
update_metadata_by_mid( $this->meta_type, $meta->id, $meta->value, $meta->key );
@ -123,11 +136,11 @@ class WC_Data_Store_WP {
protected function get_db_info() {
global $wpdb;
$meta_id_field = 'meta_id'; // for some reason users calls this umeta_id so we need to track this as well.
$table = $wpdb->prefix;
$meta_id_field = 'meta_id'; // for some reason users calls this umeta_id so we need to track this as well.
$table = $wpdb->prefix;
// If we are dealing with a type of metadata that is not a core type, the table should be prefixed.
if ( ! in_array( $this->meta_type, array( 'post', 'user', 'comment', 'term' ) ) ) {
if ( ! in_array( $this->meta_type, array( 'post', 'user', 'comment', 'term' ), true ) ) {
$table .= 'woocommerce_';
}
@ -154,9 +167,10 @@ class WC_Data_Store_WP {
/**
* Internal meta keys we don't want exposed as part of meta_data. This is in
* addition to all data props with _ prefix.
*
* @since 2.6.0
*
* @param string $key
* @param string $key Prefix to be added to meta keys.
*
* @return string
*/
@ -167,11 +181,11 @@ class WC_Data_Store_WP {
/**
* Callback to remove unwanted meta data.
*
* @param object $meta
* @param object $meta Meta object to check if it should be excluded or not.
* @return bool
*/
protected function exclude_internal_meta_keys( $meta ) {
return ! in_array( $meta->meta_key, $this->internal_meta_keys ) && 0 !== stripos( $meta->meta_key, 'wp_' );
return ! in_array( $meta->meta_key, $this->internal_meta_keys, true ) && 0 !== stripos( $meta->meta_key, 'wp_' );
}
/**
@ -201,15 +215,15 @@ class WC_Data_Store_WP {
* Get valid WP_Query args from a WC_Object_Query's query variables.
*
* @since 3.1.0
* @param array $query_vars query vars from a WC_Object_Query
* @param array $query_vars query vars from a WC_Object_Query.
* @return array
*/
protected function get_wp_query_args( $query_vars ) {
$skipped_values = array( '', array(), null );
$wp_query_args = array(
$wp_query_args = array(
'errors' => array(),
'meta_query' => array(),
'meta_query' => array(), // phpcs:ignore WordPress.VIP.SlowDBQuery.slow_db_query_meta_query
);
foreach ( $query_vars as $key => $value ) {
@ -218,14 +232,13 @@ class WC_Data_Store_WP {
}
// Build meta queries out of vars that are stored in internal meta keys.
if ( in_array( '_' . $key, $this->internal_meta_keys ) ) {
if ( in_array( '_' . $key, $this->internal_meta_keys, true ) ) {
$wp_query_args['meta_query'][] = array(
'key' => '_' . $key,
'value' => $value,
'compare' => '=',
);
// Other vars get mapped to wp_query args or just left alone.
} else {
} else { // Other vars get mapped to wp_query args or just left alone.
$key_mapping = array(
'parent' => 'post_parent',
'parent_exclude' => 'post_parent__not_in',
@ -252,9 +265,9 @@ class WC_Data_Store_WP {
* Also accepts a WC_DateTime object.
*
* @since 3.2.0
* @param mixed $query_var A valid date format
* @param string $key meta or db column key
* @param array $wp_query_args WP_Query args
* @param mixed $query_var A valid date format.
* @param string $key meta or db column key.
* @param array $wp_query_args WP_Query args.
* @return array Modified $wp_query_args
*/
public function parse_date_for_wp_query( $query_var, $key, $wp_query_args = array() ) {
@ -271,27 +284,21 @@ class WC_Data_Store_WP {
// Specific time query with a WC_DateTime.
if ( is_a( $query_var, 'WC_DateTime' ) ) {
$dates[] = $query_var;
// Specific time query with a timestamp.
} elseif ( is_numeric( $query_var ) ) {
} elseif ( is_numeric( $query_var ) ) { // Specific time query with a timestamp.
$dates[] = new WC_DateTime( "@{$query_var}", new DateTimeZone( 'UTC' ) );
// Query with operators and possible range of dates.
} elseif ( preg_match( $query_parse_regex, $query_var, $sections ) ) {
} elseif ( preg_match( $query_parse_regex, $query_var, $sections ) ) { // Query with operators and possible range of dates.
if ( ! empty( $sections[1] ) ) {
$dates[] = is_numeric( $sections[1] ) ? new WC_DateTime( "@{$sections[1]}", new DateTimeZone( 'UTC' ) ) : wc_string_to_datetime( $sections[1] );
}
$operator = in_array( $sections[2], $valid_operators ) ? $sections[2] : '';
$dates[] = is_numeric( $sections[3] ) ? new WC_DateTime( "@{$sections[3]}", new DateTimeZone( 'UTC' ) ) : wc_string_to_datetime( $sections[3] );
$operator = in_array( $sections[2], $valid_operators, true ) ? $sections[2] : '';
$dates[] = is_numeric( $sections[3] ) ? new WC_DateTime( "@{$sections[3]}", new DateTimeZone( 'UTC' ) ) : wc_string_to_datetime( $sections[3] );
if ( ! is_numeric( $sections[1] ) && ! is_numeric( $sections[3] ) ) {
$precision = 'day';
}
// Specific time query with a string.
} else {
$dates[] = wc_string_to_datetime( $query_var );
} else { // Specific time query with a string.
$dates[] = wc_string_to_datetime( $query_var );
$precision = 'day';
}
} catch ( Exception $e ) {
@ -324,20 +331,21 @@ class WC_Data_Store_WP {
}
foreach ( $comparisons as $index => $comparison ) {
/**
* WordPress doesn't generate the correct SQL for inclusive day queries with both a 'before' and
* 'after' string query, so we have to use the array format in 'day' precision.
* @see https://core.trac.wordpress.org/ticket/29908
*/
if ( 'day' === $precision ) {
/**
* WordPress doesn't generate the correct SQL for inclusive day queries with both a 'before' and
* 'after' string query, so we have to use the array format in 'day' precision.
*
* @see https://core.trac.wordpress.org/ticket/29908
*/
$query_arg[ $comparison ]['year'] = $dates[ $index ]->date( 'Y' );
$query_arg[ $comparison ]['month'] = $dates[ $index ]->date( 'n' );
$query_arg[ $comparison ]['day'] = $dates[ $index ]->date( 'j' );
/**
* WordPress doesn't support 'hour'/'second'/'minute' in array format 'before'/'after' queries,
* so we have to use a string query.
*/
} else {
/**
* WordPress doesn't support 'hour'/'second'/'minute' in array format 'before'/'after' queries,
* so we have to use a string query.
*/
$query_arg[ $comparison ] = gmdate( 'm/d/Y H:i:s', $dates[ $index ]->getTimestamp() );
}
}
@ -358,14 +366,14 @@ class WC_Data_Store_WP {
// Build meta query for unrecognized keys.
if ( ! isset( $wp_query_args['meta_query'] ) ) {
$wp_query_args['meta_query'] = array();
$wp_query_args['meta_query'] = array(); // phpcs:ignore WordPress.VIP.SlowDBQuery.slow_db_query_meta_query
}
// Meta dates are stored as timestamps in the db.
// Check against beginning/end-of-day timestamps when using 'day' precision.
if ( 'day' === $precision ) {
$start_timestamp = strtotime( gmdate( 'm/d/Y 00:00:00', $dates[0]->getTimestamp() ) );
$end_timestamp = '...' !== $operator ? ( $start_timestamp + DAY_IN_SECONDS ) : strtotime( gmdate( 'm/d/Y 00:00:00', $dates[1]->getTimestamp() ) );
$end_timestamp = '...' !== $operator ? ( $start_timestamp + DAY_IN_SECONDS ) : strtotime( gmdate( 'm/d/Y 00:00:00', $dates[1]->getTimestamp() ) );
switch ( $operator ) {
case '>':
case '<=':
@ -374,7 +382,7 @@ class WC_Data_Store_WP {
'value' => $end_timestamp,
'compare' => $operator,
);
break;
break;
case '<':
case '>=':
@ -383,7 +391,7 @@ class WC_Data_Store_WP {
'value' => $start_timestamp,
'compare' => $operator,
);
break;
break;
default:
$wp_query_args['meta_query'][] = array(

View File

@ -13,8 +13,6 @@ if ( ! defined( 'ABSPATH' ) ) {
* WC Order Data Store: Stored in CPT.
*
* @version 3.0.0
* @category Class
* @author WooThemes
*/
class WC_Order_Data_Store_CPT extends Abstract_WC_Order_Data_Store_CPT implements WC_Object_Data_Store_Interface, WC_Order_Data_Store_Interface {
@ -253,15 +251,15 @@ class WC_Order_Data_Store_CPT extends Abstract_WC_Order_Data_Store_CPT implement
parent::update_post_meta( $order );
// If address changed, store concatenated version to make searches faster.
if ( in_array( 'billing', $updated_props ) || ! metadata_exists( 'post', $id, '_billing_address_index' ) ) {
if ( in_array( 'billing', $updated_props, true ) || ! metadata_exists( 'post', $id, '_billing_address_index' ) ) {
update_post_meta( $id, '_billing_address_index', implode( ' ', $order->get_address( 'billing' ) ) );
}
if ( in_array( 'shipping', $updated_props ) || ! metadata_exists( 'post', $id, '_shipping_address_index' ) ) {
if ( in_array( 'shipping', $updated_props, true ) || ! metadata_exists( 'post', $id, '_shipping_address_index' ) ) {
update_post_meta( $id, '_shipping_address_index', implode( ' ', $order->get_address( 'shipping' ) ) );
}
// If customer changed, update any downloadable permissions.
if ( in_array( 'customer_user', $updated_props ) || in_array( 'billing_email', $updated_props ) ) {
if ( in_array( 'customer_user', $updated_props, true ) || in_array( 'billing_email', $updated_props, true ) ) {
$data_store = WC_Data_Store::load( 'customer-download' );
$data_store->update_user_by_order_id( $id, $order->get_customer_id(), $order->get_billing_email() );
}
@ -680,7 +678,7 @@ class WC_Order_Data_Store_CPT extends Abstract_WC_Order_Data_Store_CPT implement
// Remove any existing meta queries for the same keys to prevent conflicts.
$existing_queries = wp_list_pluck( $wp_query_args['meta_query'], 'key', true );
$meta_query_index = array_search( $db_key, $existing_queries );
$meta_query_index = array_search( $db_key, $existing_queries, true );
if ( false !== $meta_query_index ) {
unset( $wp_query_args['meta_query'][ $meta_query_index ] );
}

View File

@ -1,4 +1,10 @@
<?php
/**
* Class WC_Order_Item_Coupon_Data_Store file.
*
* @package WooCommerce\DataStores
*/
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
@ -7,13 +13,12 @@ if ( ! defined( 'ABSPATH' ) ) {
* WC Order Item Coupon Data Store
*
* @version 3.0.0
* @category Class
* @author WooCommerce
*/
class WC_Order_Item_Coupon_Data_Store extends Abstract_WC_Order_Item_Type_Data_Store implements WC_Object_Data_Store_Interface, WC_Order_Item_Type_Data_Store_Interface {
/**
* Data stored in meta keys.
*
* @since 3.0.0
* @var array
*/
@ -23,15 +28,17 @@ class WC_Order_Item_Coupon_Data_Store extends Abstract_WC_Order_Item_Type_Data_S
* Read/populate data properties specific to this order item.
*
* @since 3.0.0
* @param WC_Order_Item_Coupon $item
* @param WC_Order_Item_Coupon $item Coupon order item.
*/
public function read( &$item ) {
parent::read( $item );
$id = $item->get_id();
$item->set_props( array(
'discount' => get_metadata( 'order_item', $id, 'discount_amount', true ),
'discount_tax' => get_metadata( 'order_item', $id, 'discount_amount_tax', true ),
) );
$item->set_props(
array(
'discount' => get_metadata( 'order_item', $id, 'discount_amount', true ),
'discount_tax' => get_metadata( 'order_item', $id, 'discount_amount_tax', true ),
)
);
$item->set_object_read( true );
}
@ -40,7 +47,7 @@ class WC_Order_Item_Coupon_Data_Store extends Abstract_WC_Order_Item_Type_Data_S
* Ran after both create and update, so $item->get_id() will be set.
*
* @since 3.0.0
* @param WC_Order_Item_Coupon $item
* @param WC_Order_Item_Coupon $item Coupon order item.
*/
public function save_item_data( &$item ) {
$id = $item->get_id();

View File

@ -1,4 +1,10 @@
<?php
/**
* Class WC_Order_Item_Data_Store file.
*
* @package WooCommerce\DataStores
*/
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
@ -7,8 +13,6 @@ if ( ! defined( 'ABSPATH' ) ) {
* WC Order Item Data Store: Misc Order Item Data functions.
*
* @version 3.0.0
* @category Class
* @author WooCommerce
*/
class WC_Order_Item_Data_Store implements WC_Order_Item_Data_Store_Interface {
@ -16,18 +20,18 @@ class WC_Order_Item_Data_Store implements WC_Order_Item_Data_Store_Interface {
* Add an order item to an order.
*
* @since 3.0.0
* @param int $order_id
* @param int $order_id Order ID.
* @param array $item order_item_name and order_item_type.
* @return int Order Item ID
*/
public function add_order_item( $order_id, $item ) {
global $wpdb;
$wpdb->insert(
$wpdb->prefix . "woocommerce_order_items",
$wpdb->prefix . 'woocommerce_order_items',
array(
'order_item_name' => $item['order_item_name'],
'order_item_type' => $item['order_item_type'],
'order_id' => $order_id,
'order_item_name' => $item['order_item_name'],
'order_item_type' => $item['order_item_type'],
'order_id' => $order_id,
),
array(
'%s',
@ -43,7 +47,7 @@ class WC_Order_Item_Data_Store implements WC_Order_Item_Data_Store_Interface {
* Update an order item.
*
* @since 3.0.0
* @param int $item_id
* @param int $item_id Item ID.
* @param array $item order_item_name or order_item_type.
* @return boolean
*/
@ -56,7 +60,7 @@ class WC_Order_Item_Data_Store implements WC_Order_Item_Data_Store_Interface {
* Delete an order item.
*
* @since 3.0.0
* @param int $item_id
* @param int $item_id Item ID.
*/
public function delete_order_item( $item_id ) {
global $wpdb;
@ -68,10 +72,10 @@ class WC_Order_Item_Data_Store implements WC_Order_Item_Data_Store_Interface {
* Update term meta.
*
* @since 3.0.0
* @param int $item_id
* @param string $meta_key
* @param mixed $meta_value
* @param string $prev_value (default: '')
* @param int $item_id Item ID.
* @param string $meta_key Meta key.
* @param mixed $meta_value Meta value.
* @param string $prev_value (default: '').
* @return bool
*/
public function update_metadata( $item_id, $meta_key, $meta_value, $prev_value = '' ) {
@ -82,10 +86,10 @@ class WC_Order_Item_Data_Store implements WC_Order_Item_Data_Store_Interface {
* Add term meta.
*
* @since 3.0.0
* @param int $item_id
* @param string $meta_key
* @param mixed $meta_value
* @param bool $unique (default: false)
* @param int $item_id Item ID.
* @param string $meta_key Meta key.
* @param mixed $meta_value Meta value.
* @param bool $unique (default: false).
* @return int New row ID or 0
*/
public function add_metadata( $item_id, $meta_key, $meta_value, $unique = false ) {
@ -96,10 +100,10 @@ class WC_Order_Item_Data_Store implements WC_Order_Item_Data_Store_Interface {
* Delete term meta.
*
* @since 3.0.0
* @param int $item_id
* @param string $meta_key
* @param string $meta_value (default: '')
* @param bool $delete_all (default: false)
* @param int $item_id Item ID.
* @param string $meta_key Meta key.
* @param string $meta_value (default: '').
* @param bool $delete_all (default: false).
* @return bool
*/
public function delete_metadata( $item_id, $meta_key, $meta_value = '', $delete_all = false ) {
@ -110,9 +114,9 @@ class WC_Order_Item_Data_Store implements WC_Order_Item_Data_Store_Interface {
* Get term meta.
*
* @since 3.0.0
* @param int $item_id
* @param string $key
* @param bool $single (default: true)
* @param int $item_id Item ID.
* @param string $key Meta key.
* @param bool $single (default: true).
* @return mixed
*/
public function get_metadata( $item_id, $key, $single = true ) {
@ -123,22 +127,24 @@ class WC_Order_Item_Data_Store implements WC_Order_Item_Data_Store_Interface {
* Get order ID by order item ID.
*
* @since 3.0.0
* @param int $item_id
* @param int $item_id Item ID.
* @return int
*/
function get_order_id_by_order_item_id( $item_id ) {
public function get_order_id_by_order_item_id( $item_id ) {
global $wpdb;
return (int) $wpdb->get_var( $wpdb->prepare(
"SELECT order_id FROM {$wpdb->prefix}woocommerce_order_items WHERE order_item_id = %d",
$item_id
) );
return (int) $wpdb->get_var(
$wpdb->prepare(
"SELECT order_id FROM {$wpdb->prefix}woocommerce_order_items WHERE order_item_id = %d",
$item_id
)
);
}
/**
* Get the order item type based on Item ID.
*
* @since 3.0.0
* @param int $item_id
* @param int $item_id Item ID.
* @return string
*/
public function get_order_item_type( $item_id ) {

View File

@ -1,4 +1,10 @@
<?php
/**
* Class WC_Order_Item_Fee_Data_Store file.
*
* @package WooCommerce\DataStores
*/
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
@ -7,8 +13,6 @@ if ( ! defined( 'ABSPATH' ) ) {
* WC Order Item Fee Data Store
*
* @version 3.0.0
* @category Class
* @author WooCommerce
*/
class WC_Order_Item_Fee_Data_Store extends Abstract_WC_Order_Item_Type_Data_Store implements WC_Object_Data_Store_Interface, WC_Order_Item_Type_Data_Store_Interface {
@ -24,18 +28,20 @@ class WC_Order_Item_Fee_Data_Store extends Abstract_WC_Order_Item_Type_Data_Stor
* Read/populate data properties specific to this order item.
*
* @since 3.0.0
* @param WC_Order_Item_Fee $item
* @param WC_Order_Item_Fee $item Fee order item object.
*/
public function read( &$item ) {
parent::read( $item );
$id = $item->get_id();
$item->set_props( array(
'amount' => get_metadata( 'order_item', $id, '_fee_amount', true ),
'tax_class' => get_metadata( 'order_item', $id, '_tax_class', true ),
'tax_status' => get_metadata( 'order_item', $id, '_tax_status', true ),
'total' => get_metadata( 'order_item', $id, '_line_total', true ),
'taxes' => get_metadata( 'order_item', $id, '_line_tax_data', true ),
) );
$item->set_props(
array(
'amount' => get_metadata( 'order_item', $id, '_fee_amount', true ),
'tax_class' => get_metadata( 'order_item', $id, '_tax_class', true ),
'tax_status' => get_metadata( 'order_item', $id, '_tax_status', true ),
'total' => get_metadata( 'order_item', $id, '_line_total', true ),
'taxes' => get_metadata( 'order_item', $id, '_line_tax_data', true ),
)
);
$item->set_object_read( true );
}
@ -44,7 +50,7 @@ class WC_Order_Item_Fee_Data_Store extends Abstract_WC_Order_Item_Type_Data_Stor
* Ran after both create and update, so $id will be set.
*
* @since 3.0.0
* @param WC_Order_Item_Fee $item
* @param WC_Order_Item_Fee $item Fee order item object.
*/
public function save_item_data( &$item ) {
$id = $item->get_id();

View File

@ -1,4 +1,10 @@
<?php
/**
* Class WC_Order_Item_Product_Data_Store file.
*
* @package WooCommerce\DataStores
*/
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
@ -7,13 +13,12 @@ if ( ! defined( 'ABSPATH' ) ) {
* WC Order Item Product Data Store
*
* @version 3.0.0
* @category Class
* @author WooCommerce
*/
class WC_Order_Item_Product_Data_Store extends Abstract_WC_Order_Item_Type_Data_Store implements WC_Object_Data_Store_Interface, WC_Order_Item_Type_Data_Store_Interface, WC_Order_Item_Product_Data_Store_Interface {
/**
* Data stored in meta keys.
*
* @since 3.0.0
* @var array
*/
@ -23,20 +28,22 @@ class WC_Order_Item_Product_Data_Store extends Abstract_WC_Order_Item_Type_Data_
* Read/populate data properties specific to this order item.
*
* @since 3.0.0
* @param WC_Order_Item_Product $item
* @param WC_Order_Item_Product $item Product order item object.
*/
public function read( &$item ) {
parent::read( $item );
$id = $item->get_id();
$item->set_props( array(
'product_id' => get_metadata( 'order_item', $id, '_product_id', true ),
'variation_id' => get_metadata( 'order_item', $id, '_variation_id', true ),
'quantity' => get_metadata( 'order_item', $id, '_qty', true ),
'tax_class' => get_metadata( 'order_item', $id, '_tax_class', true ),
'subtotal' => get_metadata( 'order_item', $id, '_line_subtotal', true ),
'total' => get_metadata( 'order_item', $id, '_line_total', true ),
'taxes' => get_metadata( 'order_item', $id, '_line_tax_data', true ),
) );
$item->set_props(
array(
'product_id' => get_metadata( 'order_item', $id, '_product_id', true ),
'variation_id' => get_metadata( 'order_item', $id, '_variation_id', true ),
'quantity' => get_metadata( 'order_item', $id, '_qty', true ),
'tax_class' => get_metadata( 'order_item', $id, '_tax_class', true ),
'subtotal' => get_metadata( 'order_item', $id, '_line_subtotal', true ),
'total' => get_metadata( 'order_item', $id, '_line_total', true ),
'taxes' => get_metadata( 'order_item', $id, '_line_tax_data', true ),
)
);
$item->set_object_read( true );
}
@ -45,7 +52,7 @@ class WC_Order_Item_Product_Data_Store extends Abstract_WC_Order_Item_Type_Data_
* Ran after both create and update, so $id will be set.
*
* @since 3.0.0
* @param WC_Order_Item_Product $item
* @param WC_Order_Item_Product $item Product order item object.
*/
public function save_item_data( &$item ) {
$id = $item->get_id();
@ -61,7 +68,7 @@ class WC_Order_Item_Product_Data_Store extends Abstract_WC_Order_Item_Type_Data_
'_line_tax' => 'total_tax',
'_line_tax_data' => 'taxes',
);
$props_to_update = $this->get_props_to_update( $item, $meta_key_to_props, 'order_item' );
$props_to_update = $this->get_props_to_update( $item, $meta_key_to_props, 'order_item' );
foreach ( $props_to_update as $meta_key => $prop ) {
update_metadata( 'order_item', $id, $meta_key, $item->{"get_$prop"}( 'edit' ) );
@ -72,8 +79,8 @@ class WC_Order_Item_Product_Data_Store extends Abstract_WC_Order_Item_Type_Data_
* Get a list of download IDs for a specific item from an order.
*
* @since 3.0.0
* @param WC_Order_Item_Product $item
* @param WC_Order $order
* @param WC_Order_Item_Product $item Product order item object.
* @param WC_Order $order Order object.
* @return array
*/
public function get_download_ids( $item, $order ) {

View File

@ -28,16 +28,19 @@ class WC_Order_Item_Shipping_Data_Store extends Abstract_WC_Order_Item_Type_Data
*
* @since 3.0.0
* @param WC_Order_Item_Shipping $item Item to read to.
* @throws Exception If invalid shipping order item.
*/
public function read( &$item ) {
parent::read( $item );
$id = $item->get_id();
$item->set_props( array(
'method_id' => get_metadata( 'order_item', $id, 'method_id', true ),
'instance_id' => get_metadata( 'order_item', $id, 'instance_id', true ),
'total' => get_metadata( 'order_item', $id, 'cost', true ),
'taxes' => get_metadata( 'order_item', $id, 'taxes', true ),
) );
$item->set_props(
array(
'method_id' => get_metadata( 'order_item', $id, 'method_id', true ),
'instance_id' => get_metadata( 'order_item', $id, 'instance_id', true ),
'total' => get_metadata( 'order_item', $id, 'cost', true ),
'taxes' => get_metadata( 'order_item', $id, 'taxes', true ),
)
);
// BW compat.
if ( '' === $item->get_instance_id() && strstr( $item->get_method_id(), ':' ) ) {

View File

@ -1,4 +1,10 @@
<?php
/**
* Class WC_Order_Item_Tax_Data_Store file.
*
* @package WooCommerce\DataStores
*/
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
@ -7,13 +13,12 @@ if ( ! defined( 'ABSPATH' ) ) {
* WC Order Item Tax Data Store
*
* @version 3.0.0
* @category Class
* @author WooCommerce
*/
class WC_Order_Item_Tax_Data_Store extends Abstract_WC_Order_Item_Type_Data_Store implements WC_Object_Data_Store_Interface, WC_Order_Item_Type_Data_Store_Interface {
/**
* Data stored in meta keys.
*
* @since 3.0.0
* @var array
*/
@ -23,18 +28,21 @@ class WC_Order_Item_Tax_Data_Store extends Abstract_WC_Order_Item_Type_Data_Stor
* Read/populate data properties specific to this order item.
*
* @since 3.0.0
* @param WC_Order_Item_Tax $item
* @param WC_Order_Item_Tax $item Tax order item object.
* @throws Exception If invalid order item.
*/
public function read( &$item ) {
parent::read( $item );
$id = $item->get_id();
$item->set_props( array(
'rate_id' => get_metadata( 'order_item', $id, 'rate_id', true ),
'label' => get_metadata( 'order_item', $id, 'label', true ),
'compound' => get_metadata( 'order_item', $id, 'compound', true ),
'tax_total' => get_metadata( 'order_item', $id, 'tax_amount', true ),
'shipping_tax_total' => get_metadata( 'order_item', $id, 'shipping_tax_amount', true ),
) );
$item->set_props(
array(
'rate_id' => get_metadata( 'order_item', $id, 'rate_id', true ),
'label' => get_metadata( 'order_item', $id, 'label', true ),
'compound' => get_metadata( 'order_item', $id, 'compound', true ),
'tax_total' => get_metadata( 'order_item', $id, 'tax_amount', true ),
'shipping_tax_total' => get_metadata( 'order_item', $id, 'shipping_tax_amount', true ),
)
);
$item->set_object_read( true );
}
@ -43,7 +51,7 @@ class WC_Order_Item_Tax_Data_Store extends Abstract_WC_Order_Item_Type_Data_Stor
* Ran after both create and update, so $id will be set.
*
* @since 3.0.0
* @param WC_Order_Item_Tax $item
* @param WC_Order_Item_Tax $item Tax order item object.
*/
public function save_item_data( &$item ) {
$id = $item->get_id();
@ -55,7 +63,7 @@ class WC_Order_Item_Tax_Data_Store extends Abstract_WC_Order_Item_Type_Data_Stor
'tax_amount' => 'tax_total',
'shipping_tax_amount' => 'shipping_tax_total',
);
$props_to_update = $this->get_props_to_update( $item, $meta_key_to_props, 'order_item' );
$props_to_update = $this->get_props_to_update( $item, $meta_key_to_props, 'order_item' );
foreach ( $props_to_update as $meta_key => $prop ) {
update_metadata( 'order_item', $id, $meta_key, $item->{"get_$prop"}( 'edit' ) );

View File

@ -1,4 +1,10 @@
<?php
/**
* Class WC_Order_Refund_Data_Store_CPT file.
*
* @package WooCommerce\DataStores
*/
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
@ -7,13 +13,12 @@ if ( ! defined( 'ABSPATH' ) ) {
* WC Order Refund Data Store: Stored in CPT.
*
* @version 3.0.0
* @category Class
* @author WooThemes
*/
class WC_Order_Refund_Data_Store_CPT extends Abstract_WC_Order_Data_Store_CPT implements WC_Object_Data_Store_Interface, WC_Order_Refund_Data_Store_Interface {
/**
* Data stored in meta keys, but not considered "meta" for an order.
*
* @since 3.0.0
* @var array
*/
@ -35,8 +40,9 @@ class WC_Order_Refund_Data_Store_CPT extends Abstract_WC_Order_Data_Store_CPT im
/**
* Delete a refund - no trash is supported.
* @param WC_Order $order
* @param array $args Array of args to pass to the delete method.
*
* @param WC_Order $order Order object.
* @param array $args Array of args to pass to the delete method.
*/
public function delete( &$order, $args = array() ) {
$id = $order->get_id();
@ -53,25 +59,26 @@ class WC_Order_Refund_Data_Store_CPT extends Abstract_WC_Order_Data_Store_CPT im
/**
* Read refund data. Can be overridden by child classes to load other props.
*
* @param WC_Order $refund
* @param object $post_object
* @param WC_Order $refund Refund object.
* @param object $post_object Post object.
* @since 3.0.0
*/
protected function read_order_data( &$refund, $post_object ) {
parent::read_order_data( $refund, $post_object );
$id = $refund->get_id();
$refund->set_props( array(
'amount' => get_post_meta( $id, '_refund_amount', true ),
'refunded_by' => metadata_exists( 'post', $id, '_refunded_by' ) ? get_post_meta( $id, '_refunded_by', true ) : absint( $post_object->post_author ),
'reason' => metadata_exists( 'post', $id, '_refund_reason' ) ? get_post_meta( $id, '_refund_reason', true ) : $post_object->post_excerpt,
) );
$refund->set_props(
array(
'amount' => get_post_meta( $id, '_refund_amount', true ),
'refunded_by' => metadata_exists( 'post', $id, '_refunded_by' ) ? get_post_meta( $id, '_refunded_by', true ) : absint( $post_object->post_author ),
'reason' => metadata_exists( 'post', $id, '_refund_reason' ) ? get_post_meta( $id, '_refund_reason', true ) : $post_object->post_excerpt,
)
);
}
/**
* Helper method that updates all the post meta for an order based on it's settings in the WC_Order class.
*
* @param WC_Order
* @param WC_Order $refund
* @param WC_Order $refund Refund object.
* @since 3.0.0
*/
protected function update_post_meta( &$refund ) {
@ -100,9 +107,10 @@ class WC_Order_Refund_Data_Store_CPT extends Abstract_WC_Order_Data_Store_CPT im
* @return string
*/
protected function get_post_title() {
// @codingStandardsIgnoreStart
/* translators: %s: Order date */
return sprintf( __( 'Refund &ndash; %s', 'woocommerce' ), strftime( _x( '%b %d, %Y @ %I:%M %p', 'Order date parsed by strftime', 'woocommerce' ) ) );
// @codingStandardsIgnoreEnd
return sprintf(
/* translators: %s: Order date */
__( 'Refund &ndash; %s', 'woocommerce' ),
strftime( _x( '%b %d, %Y @ %I:%M %p', 'Order date parsed by strftime', 'woocommerce' ) ) // phpcs:ignore WordPress.WP.I18n.MissingTranslatorsComment, WordPress.WP.I18n.UnorderedPlaceholdersText
);
}
}

View File

@ -1,4 +1,10 @@
<?php
/**
* Class WC_Payment_Token_Data_Store file.
*
* @package WooCommerce\DataStores
*/
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
@ -7,19 +13,20 @@ if ( ! defined( 'ABSPATH' ) ) {
* WC Payment Token Data Store: Custom Table.
*
* @version 3.0.0
* @category Class
* @author WooThemes
*/
class WC_Payment_Token_Data_Store extends WC_Data_Store_WP implements WC_Payment_Token_Data_Store_Interface, WC_Object_Data_Store_Interface {
/**
* Meta type. Payment tokens are a new object type.
*
* @var string
*/
protected $meta_type = 'payment_token';
/**
* If we have already saved our extra data, don't do automatic / default handling.
*
* @var bool
*/
protected $extra_data_saved = false;
@ -28,9 +35,9 @@ class WC_Payment_Token_Data_Store extends WC_Data_Store_WP implements WC_Payment
*
* @since 3.0.0
*
* @param WC_Payment_Token $token
* @param WC_Payment_Token $token Payment token object.
*
* @throws Exception
* @throws Exception Throw exception if invalid or missing payment token fields.
*/
public function create( &$token ) {
if ( false === $token->validate() ) {
@ -59,7 +66,7 @@ class WC_Payment_Token_Data_Store extends WC_Data_Store_WP implements WC_Payment
$token->save_meta_data();
$token->apply_changes();
// Make sure all other tokens are not set to default
// Make sure all other tokens are not set to default.
if ( $token->is_default() && $token->get_user_id() > 0 ) {
WC_Payment_Tokens::set_users_default( $token->get_user_id(), $token_id );
}
@ -72,9 +79,9 @@ class WC_Payment_Token_Data_Store extends WC_Data_Store_WP implements WC_Payment
*
* @since 3.0.0
*
* @param WC_Payment_Token $token
* @param WC_Payment_Token $token Payment token object.
*
* @throws Exception
* @throws Exception Throw exception if invalid or missing payment token fields.
*/
public function update( &$token ) {
if ( false === $token->validate() ) {
@ -83,16 +90,16 @@ class WC_Payment_Token_Data_Store extends WC_Data_Store_WP implements WC_Payment
global $wpdb;
$updated_props = array();
$core_props = array( 'gateway_id', 'token', 'user_id', 'type' );
$changed_props = array_keys( $token->get_changes() );
$updated_props = array();
$core_props = array( 'gateway_id', 'token', 'user_id', 'type' );
$changed_props = array_keys( $token->get_changes() );
foreach ( $changed_props as $prop ) {
if ( ! in_array( $prop, $core_props ) ) {
if ( ! in_array( $prop, $core_props, true ) ) {
continue;
}
$updated_props[] = $prop;
$payment_token_data[ $prop ] = $token->{"get_" . $prop}( 'edit' );
$payment_token_data[ $prop ] = $token->{'get_' . $prop}( 'edit' );
}
if ( ! empty( $payment_token_data ) ) {
@ -108,7 +115,7 @@ class WC_Payment_Token_Data_Store extends WC_Data_Store_WP implements WC_Payment
$token->save_meta_data();
$token->apply_changes();
// Make sure all other tokens are not set to default
// Make sure all other tokens are not set to default.
if ( $token->is_default() && $token->get_user_id() > 0 ) {
WC_Payment_Tokens::set_users_default( $token->get_user_id(), $token->get_id() );
}
@ -121,8 +128,8 @@ class WC_Payment_Token_Data_Store extends WC_Data_Store_WP implements WC_Payment
* Remove a payment token from the database.
*
* @since 3.0.0
* @param WC_Payment_Token $token
* @param bool $force_delete
* @param WC_Payment_Token $token Payment token object.
* @param bool $force_delete Unused param.
*/
public function delete( &$token, $force_delete = false ) {
global $wpdb;
@ -136,19 +143,29 @@ class WC_Payment_Token_Data_Store extends WC_Data_Store_WP implements WC_Payment
*
* @since 3.0.0
*
* @param WC_Payment_Token $token
* @param WC_Payment_Token $token Payment token object.
*
* @throws Exception
* @throws Exception Throw exception if invalid payment token.
*/
public function read( &$token ) {
global $wpdb;
if ( $data = $wpdb->get_row( $wpdb->prepare( "SELECT token, user_id, gateway_id, is_default FROM {$wpdb->prefix}woocommerce_payment_tokens WHERE token_id = %d LIMIT 1;", $token->get_id() ) ) ) {
$token->set_props( array(
'token' => $data->token,
'user_id' => $data->user_id,
'gateway_id' => $data->gateway_id,
'default' => $data->is_default,
) );
$data = $wpdb->get_row(
$wpdb->prepare(
"SELECT token, user_id, gateway_id, is_default FROM {$wpdb->prefix}woocommerce_payment_tokens WHERE token_id = %d LIMIT 1",
$token->get_id()
)
);
if ( $data ) {
$token->set_props(
array(
'token' => $data->token,
'user_id' => $data->user_id,
'gateway_id' => $data->gateway_id,
'default' => $data->is_default,
)
);
$this->read_extra_data( $token );
$token->read_meta_data();
$token->set_object_read( true );
@ -161,7 +178,7 @@ class WC_Payment_Token_Data_Store extends WC_Data_Store_WP implements WC_Payment
/**
* Read extra data associated with the token (like last4 digits of a card for expiry dates).
*
* @param WC_Payment_Token
* @param WC_Payment_Token $token Payment token object.
* @since 3.0.0
*/
protected function read_extra_data( &$token ) {
@ -177,8 +194,8 @@ class WC_Payment_Token_Data_Store extends WC_Data_Store_WP implements WC_Payment
* Saves extra token data as meta.
*
* @since 3.0.0
* @param $token WC_Token
* @param $force bool
* @param WC_Payment_Token $token Payment token object.
* @param bool $force By default, only changed props are updated. When this param is true all props are updated.
* @return array List of updated props.
*/
protected function save_extra_data( &$token, $force = false ) {
@ -212,17 +229,19 @@ class WC_Payment_Token_Data_Store extends WC_Data_Store_WP implements WC_Payment
* Each object should contain the fields token_id, gateway_id, token, user_id, type, is_default.
*
* @since 3.0.0
* @param array $args
* @param array $args List of accepted args: token_id, gateway_id, user_id, type.
* @return array
*/
public function get_tokens( $args ) {
global $wpdb;
$args = wp_parse_args( $args, array(
'token_id' => '',
'user_id' => '',
'gateway_id' => '',
'type' => '',
) );
$args = wp_parse_args(
$args, array(
'token_id' => '',
'user_id' => '',
'gateway_id' => '',
'type' => '',
)
);
$sql = "SELECT * FROM {$wpdb->prefix}woocommerce_payment_tokens";
$where = array( '1=1' );
@ -250,6 +269,7 @@ class WC_Payment_Token_Data_Store extends WC_Data_Store_WP implements WC_Payment
$where[] = $wpdb->prepare( 'type = %s', $args['type'] );
}
// phpcs:ignore WordPress.WP.PreparedSQL.NotPrepared
$token_results = $wpdb->get_results( $sql . ' WHERE ' . implode( ' AND ', $where ) );
return $token_results;
@ -260,15 +280,17 @@ class WC_Payment_Token_Data_Store extends WC_Data_Store_WP implements WC_Payment
* Should contain the fields token_id, gateway_id, token, user_id, type, is_default.
*
* @since 3.0.0
* @param id $user_id
* @param id $user_id User ID.
* @return object
*/
public function get_users_default_token( $user_id ) {
global $wpdb;
return $wpdb->get_row( $wpdb->prepare(
"SELECT * FROM {$wpdb->prefix}woocommerce_payment_tokens WHERE user_id = %d AND is_default = 1",
$user_id
) );
return $wpdb->get_row(
$wpdb->prepare(
"SELECT * FROM {$wpdb->prefix}woocommerce_payment_tokens WHERE user_id = %d AND is_default = 1",
$user_id
)
);
}
/**
@ -276,22 +298,24 @@ class WC_Payment_Token_Data_Store extends WC_Data_Store_WP implements WC_Payment
* Should contain the fields token_id, gateway_id, token, user_id, type, is_default.
*
* @since 3.0.0
* @param id $token_id
* @param id $token_id Token ID.
* @return object
*/
public function get_token_by_id( $token_id ) {
global $wpdb;
return $wpdb->get_row( $wpdb->prepare(
"SELECT * FROM {$wpdb->prefix}woocommerce_payment_tokens WHERE token_id = %d",
$token_id
) );
return $wpdb->get_row(
$wpdb->prepare(
"SELECT * FROM {$wpdb->prefix}woocommerce_payment_tokens WHERE token_id = %d",
$token_id
)
);
}
/**
* Returns metadata for a specific payment token.
*
* @since 3.0.0
* @param id $token_id
* @param id $token_id Token ID.
* @return array
*/
public function get_metadata( $token_id ) {
@ -302,15 +326,17 @@ class WC_Payment_Token_Data_Store extends WC_Data_Store_WP implements WC_Payment
* Get a token's type by ID.
*
* @since 3.0.0
* @param id $token_id
* @param id $token_id Token ID.
* @return string
*/
public function get_token_type_by_id( $token_id ) {
global $wpdb;
return $wpdb->get_var( $wpdb->prepare(
"SELECT type FROM {$wpdb->prefix}woocommerce_payment_tokens WHERE token_id = %d",
$token_id
) );
return $wpdb->get_var(
$wpdb->prepare(
"SELECT type FROM {$wpdb->prefix}woocommerce_payment_tokens WHERE token_id = %d",
$token_id
)
);
}
/**
@ -320,10 +346,10 @@ class WC_Payment_Token_Data_Store extends WC_Data_Store_WP implements WC_Payment
*
* @since 3.0.0
*
* @param id $token_id
* @param bool $status
* @param id $token_id Token ID.
* @param bool $status Whether given payment token is the default payment token or not.
*
* @return string
* @return void
*/
public function set_default_status( $token_id, $status = true ) {
global $wpdb;

View File

@ -824,8 +824,8 @@ class WC_Product_Data_Store_CPT extends WC_Data_Store_WP implements WC_Object_Da
$outofstock_where = ' AND exclude_join.object_id IS NULL';
}
// @codingStandardsIgnoreStart.
return $wpdb->get_results(
// phpcs:disable WordPress.WP.PreparedSQL.NotPrepared
$wpdb->prepare(
"SELECT post.ID as id, post.post_parent as parent_id FROM `$wpdb->posts` AS post
LEFT JOIN `$wpdb->postmeta` AS meta ON post.ID = meta.post_id
@ -843,8 +843,8 @@ class WC_Product_Data_Store_CPT extends WC_Data_Store_WP implements WC_Object_Da
$decimals,
$decimals
)
// phpcs:enable
);
// @codingStandardsIgnoreEnd.
}
/**

View File

@ -1,4 +1,10 @@
<?php
/**
* Class WC_Product_Grouped_Data_Store_CPT file.
*
* @package WooCommerce\DataStores
*/
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
@ -7,16 +13,14 @@ if ( ! defined( 'ABSPATH' ) ) {
* WC Grouped Product Data Store: Stored in CPT.
*
* @version 3.0.0
* @category Class
* @author WooThemes
*/
class WC_Product_Grouped_Data_Store_CPT extends WC_Product_Data_Store_CPT implements WC_Object_Data_Store_Interface {
/**
* Helper method that updates all the post meta for a grouped product.
*
* @param WC_Product
* @param bool Force update. Used during create.
* @param WC_Product $product Product object.
* @param bool $force Force update. Used during create.
* @since 3.0.0
*/
protected function update_post_meta( &$product, $force = false ) {
@ -41,10 +45,10 @@ class WC_Product_Grouped_Data_Store_CPT extends WC_Product_Data_Store_CPT implem
* Handle updated meta props after updating meta data.
*
* @since 3.0.0
* @param WC_Product $product
* @param WC_Product $product Product object.
*/
protected function handle_updated_props( &$product ) {
if ( in_array( 'children', $this->updated_props ) ) {
if ( in_array( 'children', $this->updated_props, true ) ) {
$this->update_prices_from_children( $product );
}
parent::handle_updated_props( $product );
@ -54,7 +58,7 @@ class WC_Product_Grouped_Data_Store_CPT extends WC_Product_Data_Store_CPT implem
* Sync grouped product prices with children.
*
* @since 3.0.0
* @param WC_Product|int $product
* @param WC_Product|int $product Product object or product ID.
*/
public function sync_price( &$product ) {
$this->update_prices_from_children( $product );

View File

@ -13,8 +13,6 @@ if ( ! defined( 'ABSPATH' ) ) {
* WC Variable Product Data Store: Stored in CPT.
*
* @version 3.0.0
* @category Class
* @author WooThemes
*/
class WC_Product_Variable_Data_Store_CPT extends WC_Product_Data_Store_CPT implements WC_Object_Data_Store_Interface, WC_Product_Variable_Data_Store_Interface {
@ -37,14 +35,16 @@ class WC_Product_Variable_Data_Store_CPT extends WC_Product_Data_Store_CPT imple
$attributes = array();
$force_update = false;
foreach ( $meta_attributes as $meta_attribute_key => $meta_attribute_value ) {
$meta_value = array_merge( array(
'name' => '',
'value' => '',
'position' => 0,
'is_visible' => 0,
'is_variation' => 0,
'is_taxonomy' => 0,
), (array) $meta_attribute_value );
$meta_value = array_merge(
array(
'name' => '',
'value' => '',
'position' => 0,
'is_visible' => 0,
'is_variation' => 0,
'is_taxonomy' => 0,
), (array) $meta_attribute_value
);
// Maintain data integrity. 4.9 changed sanitization functions - update the values here so variations function correctly.
if ( $meta_value['is_variation'] && strstr( $meta_value['name'], '/' ) && sanitize_title( $meta_value['name'] ) !== $meta_attribute_key ) {
@ -134,7 +134,7 @@ class WC_Product_Variable_Data_Store_CPT extends WC_Product_Data_Store_CPT imple
),
'fields' => 'ids',
'post_status' => array( 'publish', 'private' ),
'numberposts' => -1,
'numberposts' => -1, // phpcs:ignore WordPress.VIP.PostsPerPage.posts_per_page_numberposts
);
$visible_only_args = $all_args;
@ -187,13 +187,17 @@ class WC_Product_Variable_Data_Store_CPT extends WC_Product_Data_Store_CPT imple
}
// Get possible values for this attribute, for only visible variations.
$values = array_unique( $wpdb->get_col( $wpdb->prepare(
"SELECT meta_value FROM {$wpdb->postmeta} WHERE meta_key = %s AND post_id IN (" . implode( ',', array_map( 'absint', $child_ids ) ) . ')',
wc_variation_attribute_name( $attribute['name'] )
) ) );
$values = array_unique(
$wpdb->get_col(
$wpdb->prepare(
"SELECT meta_value FROM {$wpdb->postmeta} WHERE meta_key = %s AND post_id IN (" . implode( ',', array_map( 'absint', $child_ids ) ) . ')', // phpcs:ignore WordPress.WP.PreparedSQL.NotPrepared
wc_variation_attribute_name( $attribute['name'] )
)
)
);
// Empty value indicates that all options for given attribute are available.
if ( in_array( '', $values ) || empty( $values ) ) {
if ( in_array( null, $values, true ) || in_array( '', $values, true ) || empty( $values ) ) {
$values = $attribute['is_taxonomy'] ? wc_get_object_terms( $product->get_id(), $attribute['name'], 'slug' ) : wc_get_text_attributes( $attribute['value'] );
// Get custom attributes (non taxonomy) as defined.
} elseif ( ! $attribute['is_taxonomy'] ) {
@ -205,13 +209,13 @@ class WC_Product_Variable_Data_Store_CPT extends WC_Product_Data_Store_CPT imple
if ( version_compare( get_post_meta( $product->get_id(), '_product_version', true ), '2.4.0', '<' ) ) {
$assigned_text_attributes = array_map( 'sanitize_title', $assigned_text_attributes );
foreach ( $text_attributes as $text_attribute ) {
if ( in_array( sanitize_title( $text_attribute ), $assigned_text_attributes ) ) {
if ( in_array( sanitize_title( $text_attribute ), $assigned_text_attributes, true ) ) {
$values[] = $text_attribute;
}
}
} else {
foreach ( $text_attributes as $text_attribute ) {
if ( in_array( $text_attribute, $assigned_text_attributes ) ) {
if ( in_array( $text_attribute, $assigned_text_attributes, true ) ) {
$values[] = $text_attribute;
}
}
@ -267,7 +271,9 @@ class WC_Product_Variable_Data_Store_CPT extends WC_Product_Data_Store_CPT imple
$sale_prices = array();
$variation_ids = $product->get_visible_children();
foreach ( $variation_ids as $variation_id ) {
if ( $variation = wc_get_product( $variation_id ) ) {
$variation = wc_get_product( $variation_id );
if ( $variation ) {
$price = apply_filters( 'woocommerce_variation_prices_price', $variation->get_price( 'edit' ), $variation, $product );
$regular_price = apply_filters( 'woocommerce_variation_prices_regular_price', $variation->get_regular_price( 'edit' ), $variation, $product );
$sale_price = apply_filters( 'woocommerce_variation_prices_sale_price', $variation->get_sale_price( 'edit' ), $variation, $product );
@ -285,13 +291,43 @@ class WC_Product_Variable_Data_Store_CPT extends WC_Product_Data_Store_CPT imple
// If we are getting prices for display, we need to account for taxes.
if ( $for_display ) {
if ( 'incl' === get_option( 'woocommerce_tax_display_shop' ) ) {
$price = '' === $price ? '' : wc_get_price_including_tax( $variation, array( 'qty' => 1, 'price' => $price ) );
$regular_price = '' === $regular_price ? '' : wc_get_price_including_tax( $variation, array( 'qty' => 1, 'price' => $regular_price ) );
$sale_price = '' === $sale_price ? '' : wc_get_price_including_tax( $variation, array( 'qty' => 1, 'price' => $sale_price ) );
$price = '' === $price ? '' : wc_get_price_including_tax(
$variation, array(
'qty' => 1,
'price' => $price,
)
);
$regular_price = '' === $regular_price ? '' : wc_get_price_including_tax(
$variation, array(
'qty' => 1,
'price' => $regular_price,
)
);
$sale_price = '' === $sale_price ? '' : wc_get_price_including_tax(
$variation, array(
'qty' => 1,
'price' => $sale_price,
)
);
} else {
$price = '' === $price ? '' : wc_get_price_excluding_tax( $variation, array( 'qty' => 1, 'price' => $price ) );
$regular_price = '' === $regular_price ? '' : wc_get_price_excluding_tax( $variation, array( 'qty' => 1, 'price' => $regular_price ) );
$sale_price = '' === $sale_price ? '' : wc_get_price_excluding_tax( $variation, array( 'qty' => 1, 'price' => $sale_price ) );
$price = '' === $price ? '' : wc_get_price_excluding_tax(
$variation, array(
'qty' => 1,
'price' => $price,
)
);
$regular_price = '' === $regular_price ? '' : wc_get_price_excluding_tax(
$variation, array(
'qty' => 1,
'price' => $regular_price,
)
);
$sale_price = '' === $sale_price ? '' : wc_get_price_excluding_tax(
$variation, array(
'qty' => 1,
'price' => $sale_price,
)
);
}
}
@ -345,7 +381,11 @@ class WC_Product_Variable_Data_Store_CPT extends WC_Product_Data_Store_CPT imple
}
$price_hash[] = WC_Cache_Helper::get_transient_version( 'product' );
$price_hash = md5( json_encode( apply_filters( 'woocommerce_get_variation_prices_hash', $price_hash, $product, $for_display ) ) );
$price_hash = md5(
wp_json_encode(
apply_filters( 'woocommerce_get_variation_prices_hash', $price_hash, $product, $for_display )
)
);
return $price_hash;
}
@ -360,7 +400,7 @@ class WC_Product_Variable_Data_Store_CPT extends WC_Product_Data_Store_CPT imple
public function child_has_weight( $product ) {
global $wpdb;
$children = $product->get_visible_children();
return $children ? null !== $wpdb->get_var( "SELECT post_id FROM $wpdb->postmeta WHERE meta_key = '_weight' AND meta_value > 0 AND post_id IN ( " . implode( ',', array_map( 'absint', $children ) ) . ' )' ) : false;
return $children ? null !== $wpdb->get_var( "SELECT post_id FROM $wpdb->postmeta WHERE meta_key = '_weight' AND meta_value > 0 AND post_id IN ( " . implode( ',', array_map( 'absint', $children ) ) . ' )' ) : false; // phpcs:ignore WordPress.WP.PreparedSQL.NotPrepared
}
/**
@ -373,7 +413,7 @@ class WC_Product_Variable_Data_Store_CPT extends WC_Product_Data_Store_CPT imple
public function child_has_dimensions( $product ) {
global $wpdb;
$children = $product->get_visible_children();
return $children ? null !== $wpdb->get_var( "SELECT post_id FROM $wpdb->postmeta WHERE meta_key IN ( '_length', '_width', '_height' ) AND meta_value > 0 AND post_id IN ( " . implode( ',', array_map( 'absint', $children ) ) . ' )' ) : false;
return $children ? null !== $wpdb->get_var( "SELECT post_id FROM $wpdb->postmeta WHERE meta_key IN ( '_length', '_width', '_height' ) AND meta_value > 0 AND post_id IN ( " . implode( ',', array_map( 'absint', $children ) ) . ' )' ) : false; // phpcs:ignore WordPress.WP.PreparedSQL.NotPrepared
}
/**
@ -392,14 +432,24 @@ class WC_Product_Variable_Data_Store_CPT extends WC_Product_Data_Store_CPT imple
*
* @since 3.3.0
* @param WC_Product $product Product object.
* @param string $status 'instock', 'outofstock', or 'onbackorder'.
* @param string $status 'instock', 'outofstock', or 'onbackorder'.
* @return boolean
*/
public function child_has_stock_status( $product, $status ) {
global $wpdb;
$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;
$children = $product->get_children();
if ( $children ) {
$children_with_status = $wpdb->get_var(
$wpdb->prepare(
"SELECT COUNT( post_id ) FROM $wpdb->postmeta WHERE meta_key = '_stock_status' AND meta_value = %s AND post_id IN ( " . implode( ',', array_map( 'absint', $children ) ) . ' )', // phpcs:ignore WordPress.WP.PreparedSQL.NotPrepared
$status
)
);
} else {
$children_with_status = 0;
}
return (bool) $children_with_status;
}
@ -416,17 +466,17 @@ class WC_Product_Variable_Data_Store_CPT extends WC_Product_Data_Store_CPT imple
if ( $new_name !== $previous_name ) {
global $wpdb;
$wpdb->query( $wpdb->prepare(
"
UPDATE {$wpdb->posts}
$wpdb->query(
$wpdb->prepare(
"UPDATE {$wpdb->posts}
SET post_title = REPLACE( post_title, %s, %s )
WHERE post_type = 'product_variation'
AND post_parent = %d
",
$previous_name ? $previous_name : 'AUTO-DRAFT',
$new_name,
$product->get_id()
) );
AND post_parent = %d",
$previous_name ? $previous_name : 'AUTO-DRAFT',
$new_name,
$product->get_id()
)
);
}
}
@ -443,7 +493,7 @@ class WC_Product_Variable_Data_Store_CPT extends WC_Product_Data_Store_CPT imple
if ( $product->get_manage_stock() ) {
$status = $product->get_stock_status();
$children = $product->get_children();
$managed_children = $children ? array_unique( $wpdb->get_col( "SELECT post_id FROM $wpdb->postmeta WHERE meta_key = '_manage_stock' AND meta_value != 'yes' AND post_id IN ( " . implode( ',', array_map( 'absint', $children ) ) . ' )' ) ) : array();
$managed_children = $children ? array_unique( $wpdb->get_col( "SELECT post_id FROM $wpdb->postmeta WHERE meta_key = '_manage_stock' AND meta_value != 'yes' AND post_id IN ( " . implode( ',', array_map( 'absint', $children ) ) . ' )' ) ) : array(); // phpcs:ignore WordPress.WP.PreparedSQL.NotPrepared
$changed = false;
foreach ( $managed_children as $managed_child ) {
if ( update_post_meta( $managed_child, '_stock_status', $status ) ) {
@ -468,7 +518,7 @@ class WC_Product_Variable_Data_Store_CPT extends WC_Product_Data_Store_CPT imple
global $wpdb;
$children = $product->get_visible_children();
$prices = $children ? array_unique( $wpdb->get_col( "SELECT meta_value FROM $wpdb->postmeta WHERE meta_key = '_price' AND post_id IN ( " . implode( ',', array_map( 'absint', $children ) ) . ' )' ) ) : array();
$prices = $children ? array_unique( $wpdb->get_col( "SELECT meta_value FROM $wpdb->postmeta WHERE meta_key = '_price' AND post_id IN ( " . implode( ',', array_map( 'absint', $children ) ) . ' )' ) ) : array(); // phpcs:ignore WordPress.WP.PreparedSQL.NotPrepared
delete_post_meta( $product->get_id(), '_price' );
@ -513,13 +563,17 @@ class WC_Product_Variable_Data_Store_CPT extends WC_Product_Data_Store_CPT imple
return;
}
$variation_ids = wp_parse_id_list( get_posts( array(
'post_parent' => $product_id,
'post_type' => 'product_variation',
'fields' => 'ids',
'post_status' => array( 'any', 'trash', 'auto-draft' ),
'numberposts' => -1,
) ) );
$variation_ids = wp_parse_id_list(
get_posts(
array(
'post_parent' => $product_id,
'post_type' => 'product_variation',
'fields' => 'ids',
'post_status' => array( 'any', 'trash', 'auto-draft' ),
'numberposts' => -1, // phpcs:ignore WordPress.VIP.PostsPerPage.posts_per_page_numberposts
)
)
);
if ( ! empty( $variation_ids ) ) {
foreach ( $variation_ids as $variation_id ) {
@ -540,13 +594,17 @@ class WC_Product_Variable_Data_Store_CPT extends WC_Product_Data_Store_CPT imple
* @param int $product_id Product ID.
*/
public function untrash_variations( $product_id ) {
$variation_ids = wp_parse_id_list( get_posts( array(
'post_parent' => $product_id,
'post_type' => 'product_variation',
'fields' => 'ids',
'post_status' => 'trash',
'numberposts' => -1,
) ) );
$variation_ids = wp_parse_id_list(
get_posts(
array(
'post_parent' => $product_id,
'post_type' => 'product_variation',
'fields' => 'ids',
'post_status' => 'trash',
'numberposts' => -1, // phpcs:ignore WordPress.VIP.PostsPerPage.posts_per_page_numberposts
)
)
);
if ( ! empty( $variation_ids ) ) {
foreach ( $variation_ids as $variation_id ) {

View File

@ -1,4 +1,10 @@
<?php
/**
* Class WC_Product_Variation_Data_Store_CPT file.
*
* @package WooCommerce\DataStores
*/
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
@ -7,19 +13,17 @@ if ( ! defined( 'ABSPATH' ) ) {
* WC Variation Product Data Store: Stored in CPT.
*
* @version 3.0.0
* @category Class
* @author WooThemes
*/
class WC_Product_Variation_Data_Store_CPT extends WC_Product_Data_Store_CPT implements WC_Object_Data_Store_Interface {
/**
* Callback to remove unwanted meta data.
*
* @param object $meta
* @param object $meta Meta object.
* @return bool false if excluded.
*/
protected function exclude_internal_meta_keys( $meta ) {
return ! in_array( $meta->meta_key, $this->internal_meta_keys ) && 0 !== stripos( $meta->meta_key, 'attribute_' ) && 0 !== stripos( $meta->meta_key, 'wp_' );
return ! in_array( $meta->meta_key, $this->internal_meta_keys, true ) && 0 !== stripos( $meta->meta_key, 'attribute_' ) && 0 !== stripos( $meta->meta_key, 'wp_' );
}
/*
@ -32,26 +36,33 @@ class WC_Product_Variation_Data_Store_CPT extends WC_Product_Data_Store_CPT impl
* Reads a product from the database and sets its data to the class.
*
* @since 3.0.0
* @param WC_Product $product
* @throws Exception
* @param WC_Product $product Product object. $product Product object.
*/
public function read( &$product ) {
$product->set_defaults();
if ( ! $product->get_id() || ! ( $post_object = get_post( $product->get_id() ) ) || ! in_array( $post_object->post_type, array( 'product', 'product_variation' ) ) ) {
if ( ! $product->get_id() ) {
return;
}
$product->set_props( array(
'name' => $post_object->post_title,
'slug' => $post_object->post_name,
'date_created' => 0 < $post_object->post_date_gmt ? wc_string_to_timestamp( $post_object->post_date_gmt ) : null,
'date_modified' => 0 < $post_object->post_modified_gmt ? wc_string_to_timestamp( $post_object->post_modified_gmt ) : null,
'status' => $post_object->post_status,
'menu_order' => $post_object->menu_order,
'reviews_allowed' => 'open' === $post_object->comment_status,
'parent_id' => $post_object->post_parent,
) );
$post_object = get_post( $product->get_id() );
if ( ! $post_object || ! in_array( $post_object->post_type, array( 'product', 'product_variation' ), true ) ) {
return;
}
$product->set_props(
array(
'name' => $post_object->post_title,
'slug' => $post_object->post_name,
'date_created' => 0 < $post_object->post_date_gmt ? wc_string_to_timestamp( $post_object->post_date_gmt ) : null,
'date_modified' => 0 < $post_object->post_modified_gmt ? wc_string_to_timestamp( $post_object->post_modified_gmt ) : null,
'status' => $post_object->post_status,
'menu_order' => $post_object->menu_order,
'reviews_allowed' => 'open' === $post_object->comment_status,
'parent_id' => $post_object->post_parent,
)
);
// The post parent is not a valid variable product so we should prevent this.
if ( $product->get_parent_id( 'edit' ) && 'product' !== get_post_type( $product->get_parent_id( 'edit' ) ) ) {
@ -82,7 +93,7 @@ class WC_Product_Variation_Data_Store_CPT extends WC_Product_Data_Store_CPT impl
* Create a new product.
*
* @since 3.0.0
* @param WC_Product $product
* @param WC_Product $product Product object.
*/
public function create( &$product ) {
if ( ! $product->get_date_created() ) {
@ -100,20 +111,24 @@ class WC_Product_Variation_Data_Store_CPT extends WC_Product_Data_Store_CPT impl
$product->set_parent_id( 0 );
}
$id = wp_insert_post( apply_filters( 'woocommerce_new_product_variation_data', array(
'post_type' => 'product_variation',
'post_status' => $product->get_status() ? $product->get_status() : 'publish',
'post_author' => get_current_user_id(),
'post_title' => $product->get_name( 'edit' ),
'post_content' => '',
'post_parent' => $product->get_parent_id(),
'comment_status' => 'closed',
'ping_status' => 'closed',
'menu_order' => $product->get_menu_order(),
'post_date' => gmdate( 'Y-m-d H:i:s', $product->get_date_created( 'edit' )->getOffsetTimestamp() ),
'post_date_gmt' => gmdate( 'Y-m-d H:i:s', $product->get_date_created( 'edit' )->getTimestamp() ),
'post_name' => $product->get_slug( 'edit' ),
) ), true );
$id = wp_insert_post(
apply_filters(
'woocommerce_new_product_variation_data', array(
'post_type' => 'product_variation',
'post_status' => $product->get_status() ? $product->get_status() : 'publish',
'post_author' => get_current_user_id(),
'post_title' => $product->get_name( 'edit' ),
'post_content' => '',
'post_parent' => $product->get_parent_id(),
'comment_status' => 'closed',
'ping_status' => 'closed',
'menu_order' => $product->get_menu_order(),
'post_date' => gmdate( 'Y-m-d H:i:s', $product->get_date_created( 'edit' )->getOffsetTimestamp() ),
'post_date_gmt' => gmdate( 'Y-m-d H:i:s', $product->get_date_created( 'edit' )->getTimestamp() ),
'post_name' => $product->get_slug( 'edit' ),
)
), true
);
if ( $id && ! is_wp_error( $id ) ) {
$product->set_id( $id );
@ -139,7 +154,7 @@ class WC_Product_Variation_Data_Store_CPT extends WC_Product_Data_Store_CPT impl
* Updates an existing product.
*
* @since 3.0.0
* @param WC_Product $product
* @param WC_Product $product Product object.
*/
public function update( &$product ) {
$product->save_meta_data();
@ -220,7 +235,7 @@ class WC_Product_Variation_Data_Store_CPT extends WC_Product_Data_Store_CPT impl
* Products will get a title of the form "Name - Value, Value" or just "Name".
*
* @since 3.0.0
* @param WC_Product
* @param WC_Product $product Product object.
* @return string
*/
protected function generate_product_title( $product ) {
@ -251,7 +266,7 @@ class WC_Product_Variation_Data_Store_CPT extends WC_Product_Data_Store_CPT impl
/**
* Make sure we store the product version (to track data changes).
*
* @param WC_Product
* @param WC_Product $product Product object.
* @since 3.0.0
*/
protected function update_version_and_type( &$product ) {
@ -263,35 +278,38 @@ class WC_Product_Variation_Data_Store_CPT extends WC_Product_Data_Store_CPT impl
* Read post data.
*
* @since 3.0.0
* @param WC_Product
* @param WC_Product $product Product object.
* @throws WC_Data_Exception If WC_Product::set_tax_status() is called with an invalid tax status.
*/
protected function read_product_data( &$product ) {
$id = $product->get_id();
$product->set_props( array(
'description' => get_post_meta( $id, '_variation_description', true ),
'regular_price' => get_post_meta( $id, '_regular_price', true ),
'sale_price' => get_post_meta( $id, '_sale_price', true ),
'date_on_sale_from' => get_post_meta( $id, '_sale_price_dates_from', true ),
'date_on_sale_to' => get_post_meta( $id, '_sale_price_dates_to', true ),
'manage_stock' => get_post_meta( $id, '_manage_stock', true ),
'stock_status' => get_post_meta( $id, '_stock_status', true ),
'shipping_class_id' => current( $this->get_term_ids( $id, 'product_shipping_class' ) ),
'virtual' => get_post_meta( $id, '_virtual', true ),
'downloadable' => get_post_meta( $id, '_downloadable', true ),
'gallery_image_ids' => array_filter( explode( ',', get_post_meta( $id, '_product_image_gallery', true ) ) ),
'download_limit' => get_post_meta( $id, '_download_limit', true ),
'download_expiry' => get_post_meta( $id, '_download_expiry', true ),
'image_id' => get_post_thumbnail_id( $id ),
'backorders' => get_post_meta( $id, '_backorders', true ),
'sku' => get_post_meta( $id, '_sku', true ),
'stock_quantity' => get_post_meta( $id, '_stock', true ),
'weight' => get_post_meta( $id, '_weight', true ),
'length' => get_post_meta( $id, '_length', true ),
'width' => get_post_meta( $id, '_width', true ),
'height' => get_post_meta( $id, '_height', true ),
'tax_class' => ! metadata_exists( 'post', $id, '_tax_class' ) ? 'parent' : get_post_meta( $id, '_tax_class', true ),
) );
$product->set_props(
array(
'description' => get_post_meta( $id, '_variation_description', true ),
'regular_price' => get_post_meta( $id, '_regular_price', true ),
'sale_price' => get_post_meta( $id, '_sale_price', true ),
'date_on_sale_from' => get_post_meta( $id, '_sale_price_dates_from', true ),
'date_on_sale_to' => get_post_meta( $id, '_sale_price_dates_to', true ),
'manage_stock' => get_post_meta( $id, '_manage_stock', true ),
'stock_status' => get_post_meta( $id, '_stock_status', true ),
'shipping_class_id' => current( $this->get_term_ids( $id, 'product_shipping_class' ) ),
'virtual' => get_post_meta( $id, '_virtual', true ),
'downloadable' => get_post_meta( $id, '_downloadable', true ),
'gallery_image_ids' => array_filter( explode( ',', get_post_meta( $id, '_product_image_gallery', true ) ) ),
'download_limit' => get_post_meta( $id, '_download_limit', true ),
'download_expiry' => get_post_meta( $id, '_download_expiry', true ),
'image_id' => get_post_thumbnail_id( $id ),
'backorders' => get_post_meta( $id, '_backorders', true ),
'sku' => get_post_meta( $id, '_sku', true ),
'stock_quantity' => get_post_meta( $id, '_stock', true ),
'weight' => get_post_meta( $id, '_weight', true ),
'length' => get_post_meta( $id, '_length', true ),
'width' => get_post_meta( $id, '_width', true ),
'height' => get_post_meta( $id, '_height', true ),
'tax_class' => ! metadata_exists( 'post', $id, '_tax_class' ) ? 'parent' : get_post_meta( $id, '_tax_class', true ),
)
);
if ( $product->is_on_sale( 'edit' ) ) {
$product->set_price( $product->get_sale_price( 'edit' ) );
@ -302,8 +320,8 @@ class WC_Product_Variation_Data_Store_CPT extends WC_Product_Data_Store_CPT impl
$parent_object = get_post( $product->get_parent_id() );
$terms = get_the_terms( $product->get_parent_id(), 'product_visibility' );
$term_names = is_array( $terms ) ? wp_list_pluck( $terms, 'name' ) : array();
$exclude_search = in_array( 'exclude-from-search', $term_names );
$exclude_catalog = in_array( 'exclude-from-catalog', $term_names );
$exclude_search = in_array( 'exclude-from-search', $term_names, true );
$exclude_catalog = in_array( 'exclude-from-catalog', $term_names, true );
if ( $exclude_search && $exclude_catalog ) {
$catalog_visibility = 'hidden';
@ -315,23 +333,25 @@ class WC_Product_Variation_Data_Store_CPT extends WC_Product_Data_Store_CPT impl
$catalog_visibility = 'visible';
}
$product->set_parent_data( array(
'title' => $parent_object ? $parent_object->post_title : '',
'status' => $parent_object ? $parent_object->post_status : '',
'sku' => get_post_meta( $product->get_parent_id(), '_sku', true ),
'manage_stock' => get_post_meta( $product->get_parent_id(), '_manage_stock', true ),
'backorders' => get_post_meta( $product->get_parent_id(), '_backorders', true ),
'stock_quantity' => wc_stock_amount( get_post_meta( $product->get_parent_id(), '_stock', true ) ),
'weight' => get_post_meta( $product->get_parent_id(), '_weight', true ),
'length' => get_post_meta( $product->get_parent_id(), '_length', true ),
'width' => get_post_meta( $product->get_parent_id(), '_width', true ),
'height' => get_post_meta( $product->get_parent_id(), '_height', true ),
'tax_class' => get_post_meta( $product->get_parent_id(), '_tax_class', true ),
'shipping_class_id' => absint( current( $this->get_term_ids( $product->get_parent_id(), 'product_shipping_class' ) ) ),
'image_id' => get_post_thumbnail_id( $product->get_parent_id() ),
'purchase_note' => get_post_meta( $product->get_parent_id(), '_purchase_note', true ),
'catalog_visibility' => $catalog_visibility,
) );
$product->set_parent_data(
array(
'title' => $parent_object ? $parent_object->post_title : '',
'status' => $parent_object ? $parent_object->post_status : '',
'sku' => get_post_meta( $product->get_parent_id(), '_sku', true ),
'manage_stock' => get_post_meta( $product->get_parent_id(), '_manage_stock', true ),
'backorders' => get_post_meta( $product->get_parent_id(), '_backorders', true ),
'stock_quantity' => wc_stock_amount( get_post_meta( $product->get_parent_id(), '_stock', true ) ),
'weight' => get_post_meta( $product->get_parent_id(), '_weight', true ),
'length' => get_post_meta( $product->get_parent_id(), '_length', true ),
'width' => get_post_meta( $product->get_parent_id(), '_width', true ),
'height' => get_post_meta( $product->get_parent_id(), '_height', true ),
'tax_class' => get_post_meta( $product->get_parent_id(), '_tax_class', true ),
'shipping_class_id' => absint( current( $this->get_term_ids( $product->get_parent_id(), 'product_shipping_class' ) ) ),
'image_id' => get_post_thumbnail_id( $product->get_parent_id() ),
'purchase_note' => get_post_meta( $product->get_parent_id(), '_purchase_note', true ),
'catalog_visibility' => $catalog_visibility,
)
);
// Pull data from the parent when there is no user-facing way to set props.
$product->set_sold_individually( get_post_meta( $product->get_parent_id(), '_sold_individually', true ) );
@ -343,8 +363,8 @@ class WC_Product_Variation_Data_Store_CPT extends WC_Product_Data_Store_CPT impl
* For all stored terms in all taxonomies, save them to the DB.
*
* @since 3.0.0
* @param WC_Product
* @param bool Force update. Used during create.
* @param WC_Product $product Product object.
* @param bool $force Force update. Used during create.
*/
protected function update_terms( &$product, $force = false ) {
$changes = $product->get_changes();
@ -359,8 +379,8 @@ class WC_Product_Variation_Data_Store_CPT extends WC_Product_Data_Store_CPT impl
*
* @since 3.0.0
*
* @param WC_Product $product
* @param bool $force Force update. Used during create.
* @param WC_Product $product Product object.
* @param bool $force Force update. Used during create.
*/
protected function update_visibility( &$product, $force = false ) {
$changes = $product->get_changes();
@ -380,8 +400,8 @@ class WC_Product_Variation_Data_Store_CPT extends WC_Product_Data_Store_CPT impl
* Update attribute meta values.
*
* @since 3.0.0
* @param WC_Product
* @param bool Force update. Used during create.
* @param WC_Product $product Product object.
* @param bool $force Force update. Used during create.
*/
protected function update_attributes( &$product, $force = false ) {
$changes = $product->get_changes();
@ -396,7 +416,13 @@ class WC_Product_Variation_Data_Store_CPT extends WC_Product_Data_Store_CPT impl
}
// Remove old taxonomies attributes so data is kept up to date - first get attribute key names.
$delete_attribute_keys = $wpdb->get_col( $wpdb->prepare( "SELECT meta_key FROM {$wpdb->postmeta} WHERE meta_key LIKE 'attribute_%%' AND meta_key NOT IN ( '" . implode( "','", array_map( 'esc_sql', $updated_attribute_keys ) ) . "' ) AND post_id = %d;", $product->get_id() ) );
$delete_attribute_keys = $wpdb->get_col(
$wpdb->prepare(
"SELECT meta_key FROM {$wpdb->postmeta} WHERE meta_key LIKE %s AND meta_key NOT IN ( '" . implode( "','", array_map( 'esc_sql', $updated_attribute_keys ) ) . "' ) AND post_id = %d", // phpcs:ignore WordPress.WP.PreparedSQL.NotPrepared, WordPress.DB.PreparedSQLPlaceholders.QuotedDynamicPlaceholderGeneration
$wpdb->esc_like( 'attribute_' ) . '%',
$product->get_id()
)
);
foreach ( $delete_attribute_keys as $key ) {
delete_post_meta( $product->get_id(), $key );
@ -408,8 +434,8 @@ class WC_Product_Variation_Data_Store_CPT extends WC_Product_Data_Store_CPT impl
* Helper method that updates all the post meta for a product based on it's settings in the WC_Product class.
*
* @since 3.0.0
* @param WC_Product
* @param bool Force update. Used during create.
* @param WC_Product $product Product object.
* @param bool $force Force update. Used during create.
*/
public function update_post_meta( &$product, $force = false ) {
$meta_key_to_props = array(

View File

@ -1,4 +1,10 @@
<?php
/**
* Class WC_Shipping_Zone_Data_Store file.
*
* @package WooCommerce\DataStores
*/
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
@ -7,8 +13,6 @@ if ( ! defined( 'ABSPATH' ) ) {
* WC Shipping Zone Data Store.
*
* @version 3.0.0
* @category Class
* @author WooCommerce
*/
class WC_Shipping_Zone_Data_Store extends WC_Data_Store_WP implements WC_Shipping_Zone_Data_Store_Interface, WC_Object_Data_Store_Interface {
@ -16,14 +20,16 @@ class WC_Shipping_Zone_Data_Store extends WC_Data_Store_WP implements WC_Shippin
* Method to create a new shipping zone.
*
* @since 3.0.0
* @param WC_Shipping_Zone $zone
* @param WC_Shipping_Zone $zone Shipping zone object.
*/
public function create( &$zone ) {
global $wpdb;
$wpdb->insert( $wpdb->prefix . 'woocommerce_shipping_zones', array(
'zone_name' => $zone->get_zone_name(),
'zone_order' => $zone->get_zone_order(),
) );
$wpdb->insert(
$wpdb->prefix . 'woocommerce_shipping_zones', array(
'zone_name' => $zone->get_zone_name(),
'zone_order' => $zone->get_zone_order(),
)
);
$zone->set_id( $wpdb->insert_id );
$zone->save_meta_data();
$this->save_locations( $zone );
@ -36,15 +42,17 @@ class WC_Shipping_Zone_Data_Store extends WC_Data_Store_WP implements WC_Shippin
* Update zone in the database.
*
* @since 3.0.0
* @param WC_Shipping_Zone $zone
* @param WC_Shipping_Zone $zone Shipping zone object.
*/
public function update( &$zone ) {
global $wpdb;
if ( $zone->get_id() ) {
$wpdb->update( $wpdb->prefix . 'woocommerce_shipping_zones', array(
'zone_name' => $zone->get_zone_name(),
'zone_order' => $zone->get_zone_order(),
), array( 'zone_id' => $zone->get_id() ) );
$wpdb->update(
$wpdb->prefix . 'woocommerce_shipping_zones', array(
'zone_name' => $zone->get_zone_name(),
'zone_order' => $zone->get_zone_order(),
), array( 'zone_id' => $zone->get_id() )
);
}
$zone->save_meta_data();
$this->save_locations( $zone );
@ -57,18 +65,30 @@ class WC_Shipping_Zone_Data_Store extends WC_Data_Store_WP implements WC_Shippin
* Method to read a shipping zone from the database.
*
* @since 3.0.0
* @param WC_Shipping_Zone $zone
* @throws Exception
* @param WC_Shipping_Zone $zone Shipping zone object.
* @throws Exception If invalid data store.
*/
public function read( &$zone ) {
global $wpdb;
if ( 0 === $zone->get_id() || "0" === $zone->get_id() ) {
$zone_data = false;
if ( 0 !== $zone->get_id() || '0' !== $zone->get_id() ) {
$zone_data = $wpdb->get_row(
$wpdb->prepare(
"SELECT zone_name, zone_order FROM {$wpdb->prefix}woocommerce_shipping_zones WHERE zone_id = %d LIMIT 1",
$zone->get_id()
)
);
}
if ( 0 === $zone->get_id() || '0' === $zone->get_id() ) {
$this->read_zone_locations( $zone );
$zone->set_zone_name( __( 'Locations not covered by your other zones', 'woocommerce' ) );
$zone->read_meta_data();
$zone->set_object_read( true );
do_action( 'woocommerce_shipping_zone_loaded', $zone );
} elseif ( $zone_data = $wpdb->get_row( $wpdb->prepare( "SELECT zone_name, zone_order FROM {$wpdb->prefix}woocommerce_shipping_zones WHERE zone_id = %d LIMIT 1;", $zone->get_id() ) ) ) {
} elseif ( $zone_data ) {
$zone->set_zone_name( $zone_data->zone_name );
$zone->set_zone_order( $zone_data->zone_order );
$this->read_zone_locations( $zone );
@ -84,9 +104,9 @@ class WC_Shipping_Zone_Data_Store extends WC_Data_Store_WP implements WC_Shippin
* Deletes a shipping zone from the database.
*
* @since 3.0.0
* @param WC_Shipping_Zone $zone
* @param array $args Array of args to pass to the delete method.
* @return bool result
* @param WC_Shipping_Zone $zone Shipping zone object.
* @param array $args Array of args to pass to the delete method.
* @return void
*/
public function delete( &$zone, $args = array() ) {
if ( $zone->get_id() ) {
@ -107,21 +127,27 @@ class WC_Shipping_Zone_Data_Store extends WC_Data_Store_WP implements WC_Shippin
* Get a list of shipping methods for a specific zone.
*
* @since 3.0.0
* @param int $zone_id Zone ID
* @param bool $enabled_only True to request enabled methods only.
* @param int $zone_id Zone ID.
* @param bool $enabled_only True to request enabled methods only.
* @return array Array of objects containing method_id, method_order, instance_id, is_enabled
*/
public function get_methods( $zone_id, $enabled_only ) {
global $wpdb;
$raw_methods_sql = $enabled_only ? "SELECT method_id, method_order, instance_id, is_enabled FROM {$wpdb->prefix}woocommerce_shipping_zone_methods WHERE zone_id = %d AND is_enabled = 1;" : "SELECT method_id, method_order, instance_id, is_enabled FROM {$wpdb->prefix}woocommerce_shipping_zone_methods WHERE zone_id = %d;";
return $wpdb->get_results( $wpdb->prepare( $raw_methods_sql, $zone_id ) );
if ( $enabled_only ) {
$raw_methods_sql = "SELECT method_id, method_order, instance_id, is_enabled FROM {$wpdb->prefix}woocommerce_shipping_zone_methods WHERE zone_id = %d AND is_enabled = 1";
} else {
$raw_methods_sql = "SELECT method_id, method_order, instance_id, is_enabled FROM {$wpdb->prefix}woocommerce_shipping_zone_methods WHERE zone_id = %d";
}
return $wpdb->get_results( $wpdb->prepare( $raw_methods_sql, $zone_id ) ); // phpcs:ignore WordPress.WP.PreparedSQL.NotPrepared
}
/**
* Get count of methods for a zone.
*
* @since 3.0.0
* @param int Zone ID
* @param int $zone_id Zone ID.
* @return int Method Count
*/
public function get_method_count( $zone_id ) {
@ -133,9 +159,9 @@ class WC_Shipping_Zone_Data_Store extends WC_Data_Store_WP implements WC_Shippin
* Add a shipping method to a zone.
*
* @since 3.0.0
* @param int $zone_id Zone ID
* @param string $type Method Type/ID
* @param int $order Method Order
* @param int $zone_id Zone ID.
* @param string $type Method Type/ID.
* @param int $order Method Order.
* @return int Instance ID
*/
public function add_method( $zone_id, $type, $order ) {
@ -160,7 +186,7 @@ class WC_Shipping_Zone_Data_Store extends WC_Data_Store_WP implements WC_Shippin
* Delete a method instance.
*
* @since 3.0.0
* @param int $instance_id
* @param int $instance_id Instance ID.
*/
public function delete_method( $instance_id ) {
global $wpdb;
@ -172,7 +198,7 @@ class WC_Shipping_Zone_Data_Store extends WC_Data_Store_WP implements WC_Shippin
* Get a shipping zone method instance.
*
* @since 3.0.0
* @param int
* @param int $instance_id Instance ID.
* @return object
*/
public function get_method( $instance_id ) {
@ -184,25 +210,25 @@ class WC_Shipping_Zone_Data_Store extends WC_Data_Store_WP implements WC_Shippin
* Find a matching zone ID for a given package.
*
* @since 3.0.0
* @param object $package
* @param object $package Package information.
* @return int
*/
public function get_zone_id_from_package( $package ) {
global $wpdb;
$country = strtoupper( wc_clean( $package['destination']['country'] ) );
$state = strtoupper( wc_clean( $package['destination']['state'] ) );
$continent = strtoupper( wc_clean( WC()->countries->get_continent_code_for_country( $country ) ) );
$postcode = wc_normalize_postcode( wc_clean( $package['destination']['postcode'] ) );
$country = strtoupper( wc_clean( $package['destination']['country'] ) );
$state = strtoupper( wc_clean( $package['destination']['state'] ) );
$continent = strtoupper( wc_clean( WC()->countries->get_continent_code_for_country( $country ) ) );
$postcode = wc_normalize_postcode( wc_clean( $package['destination']['postcode'] ) );
// Work out criteria for our zone search
// Work out criteria for our zone search.
$criteria = array();
$criteria[] = $wpdb->prepare( "( ( location_type = 'country' AND location_code = %s )", $country );
$criteria[] = $wpdb->prepare( "OR ( location_type = 'state' AND location_code = %s )", $country . ':' . $state );
$criteria[] = $wpdb->prepare( "OR ( location_type = 'continent' AND location_code = %s )", $continent );
$criteria[] = "OR ( location_type IS NULL ) )";
$criteria[] = 'OR ( location_type IS NULL ) )';
// Postcode range and wildcard matching
// Postcode range and wildcard matching.
$postcode_locations = $wpdb->get_results( "SELECT zone_id, location_code FROM {$wpdb->prefix}woocommerce_shipping_zone_locations WHERE location_type = 'postcode';" );
if ( $postcode_locations ) {
@ -211,17 +237,17 @@ class WC_Shipping_Zone_Data_Store extends WC_Data_Store_WP implements WC_Shippin
$do_not_match = array_unique( array_diff( $zone_ids_with_postcode_rules, array_keys( $matches ) ) );
if ( ! empty( $do_not_match ) ) {
$criteria[] = "AND zones.zone_id NOT IN (" . implode( ',', $do_not_match ) . ")";
$criteria[] = 'AND zones.zone_id NOT IN (' . implode( ',', $do_not_match ) . ')';
}
}
// Get matching zones
return $wpdb->get_var( "
SELECT zones.zone_id FROM {$wpdb->prefix}woocommerce_shipping_zones as zones
// Get matching zones.
return $wpdb->get_var(
"SELECT zones.zone_id FROM {$wpdb->prefix}woocommerce_shipping_zones as zones
LEFT OUTER JOIN {$wpdb->prefix}woocommerce_shipping_zone_locations as locations ON zones.zone_id = locations.zone_id AND location_type != 'postcode'
WHERE " . implode( ' ', $criteria ) . "
ORDER BY zone_order ASC, zone_id ASC LIMIT 1
" );
WHERE " . implode( ' ', $criteria ) // phpcs:ignore WordPress.WP.PreparedSQL.NotPrepared
. ' ORDER BY zone_order ASC, zone_id ASC LIMIT 1'
);
}
/**
@ -240,7 +266,7 @@ class WC_Shipping_Zone_Data_Store extends WC_Data_Store_WP implements WC_Shippin
* Return a zone ID from an instance ID.
*
* @since 3.0.0
* @param int
* @param int $id Instnace ID.
* @return int
*/
public function get_zone_id_by_instance_id( $id ) {
@ -251,11 +277,19 @@ class WC_Shipping_Zone_Data_Store extends WC_Data_Store_WP implements WC_Shippin
/**
* Read location data from the database.
*
* @param WC_Shipping_Zone
* @param WC_Shipping_Zone $zone Shipping zone object.
*/
private function read_zone_locations( &$zone ) {
global $wpdb;
if ( $locations = $wpdb->get_results( $wpdb->prepare( "SELECT location_code, location_type FROM {$wpdb->prefix}woocommerce_shipping_zone_locations WHERE zone_id = %d;", $zone->get_id() ) ) ) {
$locations = $wpdb->get_results(
$wpdb->prepare(
"SELECT location_code, location_type FROM {$wpdb->prefix}woocommerce_shipping_zone_locations WHERE zone_id = %d",
$zone->get_id()
)
);
if ( $locations ) {
foreach ( $locations as $location ) {
$zone->add_location( $location->location_code, $location->location_type );
}
@ -268,13 +302,13 @@ class WC_Shipping_Zone_Data_Store extends WC_Data_Store_WP implements WC_Shippin
*
* @since 3.0.0
*
* @param WC_Shipping_Zone
* @param WC_Shipping_Zone $zone Shipping zone object.
*
* @return bool|void
*/
private function save_locations( &$zone ) {
$changed_props = array_keys( $zone->get_changes() );
if ( ! in_array( 'zone_locations', $changed_props ) ) {
if ( ! in_array( 'zone_locations', $changed_props, true ) ) {
return false;
}
@ -282,11 +316,13 @@ class WC_Shipping_Zone_Data_Store extends WC_Data_Store_WP implements WC_Shippin
$wpdb->delete( $wpdb->prefix . 'woocommerce_shipping_zone_locations', array( 'zone_id' => $zone->get_id() ) );
foreach ( $zone->get_zone_locations( 'edit' ) as $location ) {
$wpdb->insert( $wpdb->prefix . 'woocommerce_shipping_zone_locations', array(
'zone_id' => $zone->get_id(),
'location_code' => $location->code,
'location_type' => $location->type,
) );
$wpdb->insert(
$wpdb->prefix . 'woocommerce_shipping_zone_locations', array(
'zone_id' => $zone->get_id(),
'location_code' => $location->code,
'location_type' => $location->type,
)
);
}
}
}

View File

@ -4,8 +4,6 @@
*
* @version 3.3.0
* @package WooCommerce/Classes/Data_Store
* @category Class
* @author Automattic
*/
if ( ! defined( 'ABSPATH' ) ) {
@ -85,20 +83,22 @@ class WC_Webhook_Data_Store implements WC_Webhook_Data_Store_Interface {
}
if ( is_array( $data ) ) {
$webhook->set_props( array(
'id' => $data['webhook_id'],
'status' => $data['status'],
'name' => $data['name'],
'user_id' => $data['user_id'],
'delivery_url' => $data['delivery_url'],
'secret' => $data['secret'],
'topic' => $data['topic'],
'date_created' => '0000-00-00 00:00:00' === $data['date_created'] ? null : $data['date_created'],
'date_modified' => '0000-00-00 00:00:00' === $data['date_modified'] ? null : $data['date_modified'],
'api_version' => $data['api_version'],
'failure_count' => $data['failure_count'],
'pending_delivery' => $data['pending_delivery'],
) );
$webhook->set_props(
array(
'id' => $data['webhook_id'],
'status' => $data['status'],
'name' => $data['name'],
'user_id' => $data['user_id'],
'delivery_url' => $data['delivery_url'],
'secret' => $data['secret'],
'topic' => $data['topic'],
'date_created' => '0000-00-00 00:00:00' === $data['date_created'] ? null : $data['date_created'],
'date_modified' => '0000-00-00 00:00:00' === $data['date_modified'] ? null : $data['date_modified'],
'api_version' => $data['api_version'],
'failure_count' => $data['failure_count'],
'pending_delivery' => $data['pending_delivery'],
)
);
$webhook->set_object_read( true );
do_action( 'woocommerce_webhook_loaded', $webhook );
@ -226,12 +226,14 @@ class WC_Webhook_Data_Store implements WC_Webhook_Data_Store_Interface {
public function search_webhooks( $args ) {
global $wpdb;
$args = wp_parse_args( $args, array(
'limit' => 10,
'offset' => 0,
'order' => 'DESC',
'orderby' => 'id',
) );
$args = wp_parse_args(
$args, array(
'limit' => 10,
'offset' => 0,
'order' => 'DESC',
'orderby' => 'id',
)
);
// Map post statuses.
$statuses = array(
@ -300,8 +302,8 @@ class WC_Webhook_Data_Store implements WC_Webhook_Data_Store_Interface {
return $ids;
}
$query = trim( "
SELECT webhook_id
$query = trim(
"SELECT webhook_id
FROM {$wpdb->prefix}wc_webhooks
WHERE 1=1
{$status}
@ -312,8 +314,8 @@ class WC_Webhook_Data_Store implements WC_Webhook_Data_Store_Interface {
{$date_modified}
{$order}
{$limit}
{$offset}
" );
{$offset}"
);
$results = $wpdb->get_results( $query ); // WPCS: cache ok, DB call ok, unprepared SQL ok.
@ -333,10 +335,14 @@ class WC_Webhook_Data_Store implements WC_Webhook_Data_Store_Interface {
$counts = array();
foreach ( $statuses as $status ) {
$count = count( $this->search_webhooks( array(
'limit' => -1,
'status' => $status,
) ) );
$count = count(
$this->search_webhooks(
array(
'limit' => -1,
'status' => $status,
)
)
);
$counts[ $status ] = $count;
}

View File

@ -1,4 +1,9 @@
<?php
/**
* Class WC_Email_Cancelled_Order file.
*
* @package WooCommerce\Emails
*/
if ( ! defined( 'ABSPATH' ) ) {
exit;
@ -6,172 +11,175 @@ if ( ! defined( 'ABSPATH' ) ) {
if ( ! class_exists( 'WC_Email_Cancelled_Order', false ) ) :
/**
* Cancelled Order Email.
*
* An email sent to the admin when an order is cancelled.
*
* @class WC_Email_Cancelled_Order
* @version 2.2.7
* @package WooCommerce/Classes/Emails
* @author WooThemes
* @extends WC_Email
*/
class WC_Email_Cancelled_Order extends WC_Email {
/**
* Constructor.
*/
public function __construct() {
$this->id = 'cancelled_order';
$this->title = __( 'Cancelled order', 'woocommerce' );
$this->description = __( 'Cancelled order emails are sent to chosen recipient(s) when orders have been marked cancelled (if they were previously processing or on-hold).', 'woocommerce' );
$this->template_html = 'emails/admin-cancelled-order.php';
$this->template_plain = 'emails/plain/admin-cancelled-order.php';
$this->placeholders = array(
'{site_title}' => $this->get_blogname(),
'{order_date}' => '',
'{order_number}' => '',
);
// Triggers for this email
add_action( 'woocommerce_order_status_processing_to_cancelled_notification', array( $this, 'trigger' ), 10, 2 );
add_action( 'woocommerce_order_status_on-hold_to_cancelled_notification', array( $this, 'trigger' ), 10, 2 );
// Call parent constructor
parent::__construct();
// Other settings
$this->recipient = $this->get_option( 'recipient', get_option( 'admin_email' ) );
}
/**
* Get email subject.
* Cancelled Order Email.
*
* @since 3.1.0
* @return string
*/
public function get_default_subject() {
return __( '[{site_title}] Cancelled order ({order_number})', 'woocommerce' );
}
/**
* Get email heading.
* An email sent to the admin when an order is cancelled.
*
* @since 3.1.0
* @return string
* @class WC_Email_Cancelled_Order
* @version 2.2.7
* @package WooCommerce/Classes/Emails
* @extends WC_Email
*/
public function get_default_heading() {
return __( 'Cancelled order', 'woocommerce' );
}
class WC_Email_Cancelled_Order extends WC_Email {
/**
* Trigger the sending of this email.
*
* @param int $order_id The order ID.
* @param WC_Order $order Order object.
*/
public function trigger( $order_id, $order = false ) {
$this->setup_locale();
/**
* Constructor.
*/
public function __construct() {
$this->id = 'cancelled_order';
$this->title = __( 'Cancelled order', 'woocommerce' );
$this->description = __( 'Cancelled order emails are sent to chosen recipient(s) when orders have been marked cancelled (if they were previously processing or on-hold).', 'woocommerce' );
$this->template_html = 'emails/admin-cancelled-order.php';
$this->template_plain = 'emails/plain/admin-cancelled-order.php';
$this->placeholders = array(
'{site_title}' => $this->get_blogname(),
'{order_date}' => '',
'{order_number}' => '',
);
if ( $order_id && ! is_a( $order, 'WC_Order' ) ) {
$order = wc_get_order( $order_id );
// Triggers for this email.
add_action( 'woocommerce_order_status_processing_to_cancelled_notification', array( $this, 'trigger' ), 10, 2 );
add_action( 'woocommerce_order_status_on-hold_to_cancelled_notification', array( $this, 'trigger' ), 10, 2 );
// Call parent constructor.
parent::__construct();
// Other settings.
$this->recipient = $this->get_option( 'recipient', get_option( 'admin_email' ) );
}
if ( is_a( $order, 'WC_Order' ) ) {
$this->object = $order;
$this->placeholders['{order_date}'] = wc_format_datetime( $this->object->get_date_created() );
$this->placeholders['{order_number}'] = $this->object->get_order_number();
/**
* Get email subject.
*
* @since 3.1.0
* @return string
*/
public function get_default_subject() {
return __( '[{site_title}] Cancelled order ({order_number})', 'woocommerce' );
}
if ( $this->is_enabled() && $this->get_recipient() ) {
$this->send( $this->get_recipient(), $this->get_subject(), $this->get_content(), $this->get_headers(), $this->get_attachments() );
/**
* Get email heading.
*
* @since 3.1.0
* @return string
*/
public function get_default_heading() {
return __( 'Cancelled order', 'woocommerce' );
}
$this->restore_locale();
}
/**
* Trigger the sending of this email.
*
* @param int $order_id The order ID.
* @param WC_Order|false $order Order object.
*/
public function trigger( $order_id, $order = false ) {
$this->setup_locale();
/**
* Get content html.
*
* @access public
* @return string
*/
public function get_content_html() {
return wc_get_template_html( $this->template_html, array(
'order' => $this->object,
'email_heading' => $this->get_heading(),
'sent_to_admin' => true,
'plain_text' => false,
'email' => $this,
) );
}
if ( $order_id && ! is_a( $order, 'WC_Order' ) ) {
$order = wc_get_order( $order_id );
}
/**
* Get content plain.
*
* @return string
*/
public function get_content_plain() {
return wc_get_template_html( $this->template_plain, array(
'order' => $this->object,
'email_heading' => $this->get_heading(),
'sent_to_admin' => true,
'plain_text' => true,
'email' => $this,
) );
}
if ( is_a( $order, 'WC_Order' ) ) {
$this->object = $order;
$this->placeholders['{order_date}'] = wc_format_datetime( $this->object->get_date_created() );
$this->placeholders['{order_number}'] = $this->object->get_order_number();
}
/**
* Initialise settings form fields.
*/
public function init_form_fields() {
$this->form_fields = array(
'enabled' => array(
'title' => __( 'Enable/Disable', 'woocommerce' ),
'type' => 'checkbox',
'label' => __( 'Enable this email notification', 'woocommerce' ),
'default' => 'yes',
),
'recipient' => array(
'title' => __( 'Recipient(s)', 'woocommerce' ),
'type' => 'text',
/* translators: %s: admin email */
'description' => sprintf( __( 'Enter recipients (comma separated) for this email. Defaults to %s.', 'woocommerce' ), '<code>' . esc_attr( get_option( 'admin_email' ) ) . '</code>' ),
'placeholder' => '',
'default' => '',
'desc_tip' => true,
),
'subject' => array(
'title' => __( 'Subject', 'woocommerce' ),
'type' => 'text',
'desc_tip' => true,
/* translators: %s: list of placeholders */
'description' => sprintf( __( 'Available placeholders: %s', 'woocommerce' ), '<code>{site_title}, {order_date}, {order_number}</code>' ),
'placeholder' => $this->get_default_subject(),
'default' => '',
),
'heading' => array(
'title' => __( 'Email heading', 'woocommerce' ),
'type' => 'text',
'desc_tip' => true,
/* translators: %s: list of placeholders */
'description' => sprintf( __( 'Available placeholders: %s', 'woocommerce' ), '<code>{site_title}, {order_date}, {order_number}</code>' ),
'placeholder' => $this->get_default_heading(),
'default' => '',
),
'email_type' => array(
'title' => __( 'Email type', 'woocommerce' ),
'type' => 'select',
'description' => __( 'Choose which format of email to send.', 'woocommerce' ),
'default' => 'html',
'class' => 'email_type wc-enhanced-select',
'options' => $this->get_email_type_options(),
'desc_tip' => true,
),
);
if ( $this->is_enabled() && $this->get_recipient() ) {
$this->send( $this->get_recipient(), $this->get_subject(), $this->get_content(), $this->get_headers(), $this->get_attachments() );
}
$this->restore_locale();
}
/**
* Get content html.
*
* @access public
* @return string
*/
public function get_content_html() {
return wc_get_template_html(
$this->template_html, array(
'order' => $this->object,
'email_heading' => $this->get_heading(),
'sent_to_admin' => true,
'plain_text' => false,
'email' => $this,
)
);
}
/**
* Get content plain.
*
* @return string
*/
public function get_content_plain() {
return wc_get_template_html(
$this->template_plain, array(
'order' => $this->object,
'email_heading' => $this->get_heading(),
'sent_to_admin' => true,
'plain_text' => true,
'email' => $this,
)
);
}
/**
* Initialise settings form fields.
*/
public function init_form_fields() {
$this->form_fields = array(
'enabled' => array(
'title' => __( 'Enable/Disable', 'woocommerce' ),
'type' => 'checkbox',
'label' => __( 'Enable this email notification', 'woocommerce' ),
'default' => 'yes',
),
'recipient' => array(
'title' => __( 'Recipient(s)', 'woocommerce' ),
'type' => 'text',
/* translators: %s: admin email */
'description' => sprintf( __( 'Enter recipients (comma separated) for this email. Defaults to %s.', 'woocommerce' ), '<code>' . esc_attr( get_option( 'admin_email' ) ) . '</code>' ),
'placeholder' => '',
'default' => '',
'desc_tip' => true,
),
'subject' => array(
'title' => __( 'Subject', 'woocommerce' ),
'type' => 'text',
'desc_tip' => true,
/* translators: %s: list of placeholders */
'description' => sprintf( __( 'Available placeholders: %s', 'woocommerce' ), '<code>{site_title}, {order_date}, {order_number}</code>' ),
'placeholder' => $this->get_default_subject(),
'default' => '',
),
'heading' => array(
'title' => __( 'Email heading', 'woocommerce' ),
'type' => 'text',
'desc_tip' => true,
/* translators: %s: list of placeholders */
'description' => sprintf( __( 'Available placeholders: %s', 'woocommerce' ), '<code>{site_title}, {order_date}, {order_number}</code>' ),
'placeholder' => $this->get_default_heading(),
'default' => '',
),
'email_type' => array(
'title' => __( 'Email type', 'woocommerce' ),
'type' => 'select',
'description' => __( 'Choose which format of email to send.', 'woocommerce' ),
'default' => 'html',
'class' => 'email_type wc-enhanced-select',
'options' => $this->get_email_type_options(),
'desc_tip' => true,
),
);
}
}
}
endif;

View File

@ -1,167 +1,175 @@
<?php
/**
* Class WC_Email_Customer_Completed_Order file.
*
* @package WooCommerce\Emails
*/
if ( ! defined( 'ABSPATH' ) ) {
exit; // Exit if accessed directly
exit; // Exit if accessed directly.
}
if ( ! class_exists( 'WC_Email_Customer_Completed_Order', false ) ) :
/**
* Customer Completed Order Email.
*
* Order complete emails are sent to the customer when the order is marked complete and usual indicates that the order has been shipped.
*
* @class WC_Email_Customer_Completed_Order
* @version 2.0.0
* @package WooCommerce/Classes/Emails
* @author WooThemes
* @extends WC_Email
*/
class WC_Email_Customer_Completed_Order extends WC_Email {
/**
* Constructor.
*/
public function __construct() {
$this->id = 'customer_completed_order';
$this->customer_email = true;
$this->title = __( 'Completed order', 'woocommerce' );
$this->description = __( 'Order complete emails are sent to customers when their orders are marked completed and usually indicate that their orders have been shipped.', 'woocommerce' );
$this->template_html = 'emails/customer-completed-order.php';
$this->template_plain = 'emails/plain/customer-completed-order.php';
$this->placeholders = array(
'{site_title}' => $this->get_blogname(),
'{order_date}' => '',
'{order_number}' => '',
);
// Triggers for this email
add_action( 'woocommerce_order_status_completed_notification', array( $this, 'trigger' ), 10, 2 );
// Call parent constructor
parent::__construct();
}
/**
* Trigger the sending of this email.
* Customer Completed Order Email.
*
* @param int $order_id The order ID.
* @param WC_Order $order Order object.
* Order complete emails are sent to the customer when the order is marked complete and usual indicates that the order has been shipped.
*
* @class WC_Email_Customer_Completed_Order
* @version 2.0.0
* @package WooCommerce/Classes/Emails
* @extends WC_Email
*/
public function trigger( $order_id, $order = false ) {
$this->setup_locale();
class WC_Email_Customer_Completed_Order extends WC_Email {
if ( $order_id && ! is_a( $order, 'WC_Order' ) ) {
$order = wc_get_order( $order_id );
/**
* Constructor.
*/
public function __construct() {
$this->id = 'customer_completed_order';
$this->customer_email = true;
$this->title = __( 'Completed order', 'woocommerce' );
$this->description = __( 'Order complete emails are sent to customers when their orders are marked completed and usually indicate that their orders have been shipped.', 'woocommerce' );
$this->template_html = 'emails/customer-completed-order.php';
$this->template_plain = 'emails/plain/customer-completed-order.php';
$this->placeholders = array(
'{site_title}' => $this->get_blogname(),
'{order_date}' => '',
'{order_number}' => '',
);
// Triggers for this email.
add_action( 'woocommerce_order_status_completed_notification', array( $this, 'trigger' ), 10, 2 );
// Call parent constructor.
parent::__construct();
}
if ( is_a( $order, 'WC_Order' ) ) {
$this->object = $order;
$this->recipient = $this->object->get_billing_email();
$this->placeholders['{order_date}'] = wc_format_datetime( $this->object->get_date_created() );
$this->placeholders['{order_number}'] = $this->object->get_order_number();
/**
* Trigger the sending of this email.
*
* @param int $order_id The order ID.
* @param WC_Order|false $order Order object.
*/
public function trigger( $order_id, $order = false ) {
$this->setup_locale();
if ( $order_id && ! is_a( $order, 'WC_Order' ) ) {
$order = wc_get_order( $order_id );
}
if ( is_a( $order, 'WC_Order' ) ) {
$this->object = $order;
$this->recipient = $this->object->get_billing_email();
$this->placeholders['{order_date}'] = wc_format_datetime( $this->object->get_date_created() );
$this->placeholders['{order_number}'] = $this->object->get_order_number();
}
if ( $this->is_enabled() && $this->get_recipient() ) {
$this->send( $this->get_recipient(), $this->get_subject(), $this->get_content(), $this->get_headers(), $this->get_attachments() );
}
$this->restore_locale();
}
if ( $this->is_enabled() && $this->get_recipient() ) {
$this->send( $this->get_recipient(), $this->get_subject(), $this->get_content(), $this->get_headers(), $this->get_attachments() );
/**
* Get email subject.
*
* @since 3.1.0
* @return string
*/
public function get_default_subject() {
return __( 'Your {site_title} order from {order_date} is complete', 'woocommerce' );
}
$this->restore_locale();
}
/**
* Get email heading.
*
* @since 3.1.0
* @return string
*/
public function get_default_heading() {
return __( 'Your order is complete', 'woocommerce' );
}
/**
* Get email subject.
*
* @since 3.1.0
* @return string
*/
public function get_default_subject() {
return __( 'Your {site_title} order from {order_date} is complete', 'woocommerce' );
}
/**
* Get content html.
*
* @access public
* @return string
*/
public function get_content_html() {
return wc_get_template_html(
$this->template_html, array(
'order' => $this->object,
'email_heading' => $this->get_heading(),
'sent_to_admin' => false,
'plain_text' => false,
'email' => $this,
)
);
}
/**
* Get email heading.
*
* @since 3.1.0
* @return string
*/
public function get_default_heading() {
return __( 'Your order is complete', 'woocommerce' );
}
/**
* Get content plain.
*
* @return string
*/
public function get_content_plain() {
return wc_get_template_html(
$this->template_plain, array(
'order' => $this->object,
'email_heading' => $this->get_heading(),
'sent_to_admin' => false,
'plain_text' => true,
'email' => $this,
)
);
}
/**
* Get content html.
*
* @access public
* @return string
*/
public function get_content_html() {
return wc_get_template_html( $this->template_html, array(
'order' => $this->object,
'email_heading' => $this->get_heading(),
'sent_to_admin' => false,
'plain_text' => false,
'email' => $this,
) );
/**
* Initialise settings form fields.
*/
public function init_form_fields() {
$this->form_fields = array(
'enabled' => array(
'title' => __( 'Enable/Disable', 'woocommerce' ),
'type' => 'checkbox',
'label' => __( 'Enable this email notification', 'woocommerce' ),
'default' => 'yes',
),
'subject' => array(
'title' => __( 'Subject', 'woocommerce' ),
'type' => 'text',
'desc_tip' => true,
/* translators: %s: list of placeholders */
'description' => sprintf( __( 'Available placeholders: %s', 'woocommerce' ), '<code>{site_title}, {order_date}, {order_number}</code>' ),
'placeholder' => $this->get_default_subject(),
'default' => '',
),
'heading' => array(
'title' => __( 'Email heading', 'woocommerce' ),
'type' => 'text',
'desc_tip' => true,
/* translators: %s: list of placeholders */
'description' => sprintf( __( 'Available placeholders: %s', 'woocommerce' ), '<code>{site_title}, {order_date}, {order_number}</code>' ),
'placeholder' => $this->get_default_heading(),
'default' => '',
),
'email_type' => array(
'title' => __( 'Email type', 'woocommerce' ),
'type' => 'select',
'description' => __( 'Choose which format of email to send.', 'woocommerce' ),
'default' => 'html',
'class' => 'email_type wc-enhanced-select',
'options' => $this->get_email_type_options(),
'desc_tip' => true,
),
);
}
}
/**
* Get content plain.
*
* @return string
*/
public function get_content_plain() {
return wc_get_template_html( $this->template_plain, array(
'order' => $this->object,
'email_heading' => $this->get_heading(),
'sent_to_admin' => false,
'plain_text' => true,
'email' => $this,
) );
}
/**
* Initialise settings form fields.
*/
public function init_form_fields() {
$this->form_fields = array(
'enabled' => array(
'title' => __( 'Enable/Disable', 'woocommerce' ),
'type' => 'checkbox',
'label' => __( 'Enable this email notification', 'woocommerce' ),
'default' => 'yes',
),
'subject' => array(
'title' => __( 'Subject', 'woocommerce' ),
'type' => 'text',
'desc_tip' => true,
/* translators: %s: list of placeholders */
'description' => sprintf( __( 'Available placeholders: %s', 'woocommerce' ), '<code>{site_title}, {order_date}, {order_number}</code>' ),
'placeholder' => $this->get_default_subject(),
'default' => '',
),
'heading' => array(
'title' => __( 'Email heading', 'woocommerce' ),
'type' => 'text',
'desc_tip' => true,
/* translators: %s: list of placeholders */
'description' => sprintf( __( 'Available placeholders: %s', 'woocommerce' ), '<code>{site_title}, {order_date}, {order_number}</code>' ),
'placeholder' => $this->get_default_heading(),
'default' => '',
),
'email_type' => array(
'title' => __( 'Email type', 'woocommerce' ),
'type' => 'select',
'description' => __( 'Choose which format of email to send.', 'woocommerce' ),
'default' => 'html',
'class' => 'email_type wc-enhanced-select',
'options' => $this->get_email_type_options(),
'desc_tip' => true,
),
);
}
}
endif;
return new WC_Email_Customer_Completed_Order();

View File

@ -1,220 +1,230 @@
<?php
/**
* Class WC_Email_Customer_Invoice file.
*
* @package WooCommerce\Emails
*/
if ( ! defined( 'ABSPATH' ) ) {
exit; // Exit if accessed directly
exit; // Exit if accessed directly.
}
if ( ! class_exists( 'WC_Email_Customer_Invoice', false ) ) :
/**
* Customer Invoice.
*
* An email sent to the customer via admin.
*
* @class WC_Email_Customer_Invoice
* @version 2.3.0
* @package WooCommerce/Classes/Emails
* @author WooThemes
* @extends WC_Email
*/
class WC_Email_Customer_Invoice extends WC_Email {
/**
* Constructor.
*/
public function __construct() {
$this->id = 'customer_invoice';
$this->customer_email = true;
$this->title = __( 'Customer invoice / Order details', 'woocommerce' );
$this->description = __( 'Customer invoice emails can be sent to customers containing their order information and payment links.', 'woocommerce' );
$this->template_html = 'emails/customer-invoice.php';
$this->template_plain = 'emails/plain/customer-invoice.php';
$this->placeholders = array(
'{site_title}' => $this->get_blogname(),
'{order_date}' => '',
'{order_number}' => '',
);
// Call parent constructor
parent::__construct();
$this->manual = true;
}
/**
* Get email subject.
* Customer Invoice.
*
* @since 3.1.0
* @return string
*/
public function get_default_subject( $paid = false ) {
if ( $paid ) {
return __( 'Your {site_title} order from {order_date}', 'woocommerce' );
} else {
return __( 'Invoice for order {order_number}', 'woocommerce' );
}
}
/**
* Get email heading.
* An email sent to the customer via admin.
*
* @since 3.1.0
* @return string
* @class WC_Email_Customer_Invoice
* @version 2.3.0
* @package WooCommerce/Classes/Emails
* @extends WC_Email
*/
public function get_default_heading( $paid = false ) {
if ( $paid ) {
return __( 'Your order details', 'woocommerce' );
} else {
return __( 'Invoice for order {order_number}', 'woocommerce' );
}
}
class WC_Email_Customer_Invoice extends WC_Email {
/**
* Get email subject.
*
* @access public
* @return string
*/
public function get_subject() {
if ( $this->object->has_status( array( 'completed', 'processing' ) ) ) {
$subject = $this->get_option( 'subject_paid', $this->get_default_subject( true ) );
$action = 'woocommerce_email_subject_customer_invoice_paid';
} else {
$subject = $this->get_option( 'subject', $this->get_default_subject() );
$action = 'woocommerce_email_subject_customer_invoice';
}
return apply_filters( $action, $this->format_string( $subject ), $this->object );
}
/**
* Constructor.
*/
public function __construct() {
$this->id = 'customer_invoice';
$this->customer_email = true;
$this->title = __( 'Customer invoice / Order details', 'woocommerce' );
$this->description = __( 'Customer invoice emails can be sent to customers containing their order information and payment links.', 'woocommerce' );
$this->template_html = 'emails/customer-invoice.php';
$this->template_plain = 'emails/plain/customer-invoice.php';
$this->placeholders = array(
'{site_title}' => $this->get_blogname(),
'{order_date}' => '',
'{order_number}' => '',
);
/**
* Get email heading.
*
* @access public
* @return string
*/
public function get_heading() {
if ( $this->object->has_status( wc_get_is_paid_statuses() ) ) {
$heading = $this->get_option( 'heading_paid', $this->get_default_heading( true ) );
$action = 'woocommerce_email_heading_customer_invoice_paid';
} else {
$heading = $this->get_option( 'heading', $this->get_default_heading() );
$action = 'woocommerce_email_heading_customer_invoice';
}
return apply_filters( $action, $this->format_string( $heading ), $this->object );
}
// Call parent constructor.
parent::__construct();
/**
* Trigger the sending of this email.
*
* @param int $order_id The order ID.
* @param WC_Order $order Order object.
*/
public function trigger( $order_id, $order = false ) {
$this->setup_locale();
if ( $order_id && ! is_a( $order, 'WC_Order' ) ) {
$order = wc_get_order( $order_id );
$this->manual = true;
}
if ( is_a( $order, 'WC_Order' ) ) {
$this->object = $order;
$this->recipient = $this->object->get_billing_email();
$this->placeholders['{order_date}'] = wc_format_datetime( $this->object->get_date_created() );
$this->placeholders['{order_number}'] = $this->object->get_order_number();
/**
* Get email subject.
*
* @param bool $paid Whether the order has been paid or not.
* @since 3.1.0
* @return string
*/
public function get_default_subject( $paid = false ) {
if ( $paid ) {
return __( 'Your {site_title} order from {order_date}', 'woocommerce' );
} else {
return __( 'Invoice for order {order_number}', 'woocommerce' );
}
}
if ( $this->get_recipient() ) {
$this->send( $this->get_recipient(), $this->get_subject(), $this->get_content(), $this->get_headers(), $this->get_attachments() );
/**
* Get email heading.
*
* @param bool $paid Whether the order has been paid or not.
* @since 3.1.0
* @return string
*/
public function get_default_heading( $paid = false ) {
if ( $paid ) {
return __( 'Your order details', 'woocommerce' );
} else {
return __( 'Invoice for order {order_number}', 'woocommerce' );
}
}
$this->restore_locale();
}
/**
* Get email subject.
*
* @access public
* @return string
*/
public function get_subject() {
if ( $this->object->has_status( array( 'completed', 'processing' ) ) ) {
$subject = $this->get_option( 'subject_paid', $this->get_default_subject( true ) );
$action = 'woocommerce_email_subject_customer_invoice_paid';
} else {
$subject = $this->get_option( 'subject', $this->get_default_subject() );
$action = 'woocommerce_email_subject_customer_invoice';
}
return apply_filters( $action, $this->format_string( $subject ), $this->object );
}
/**
* Get content html.
*
* @access public
* @return string
*/
public function get_content_html() {
return wc_get_template_html( $this->template_html, array(
'order' => $this->object,
'email_heading' => $this->get_heading(),
'sent_to_admin' => false,
'plain_text' => false,
'email' => $this,
) );
}
/**
* Get email heading.
*
* @access public
* @return string
*/
public function get_heading() {
if ( $this->object->has_status( wc_get_is_paid_statuses() ) ) {
$heading = $this->get_option( 'heading_paid', $this->get_default_heading( true ) );
$action = 'woocommerce_email_heading_customer_invoice_paid';
} else {
$heading = $this->get_option( 'heading', $this->get_default_heading() );
$action = 'woocommerce_email_heading_customer_invoice';
}
return apply_filters( $action, $this->format_string( $heading ), $this->object );
}
/**
* Get content plain.
*
* @access public
* @return string
*/
public function get_content_plain() {
return wc_get_template_html( $this->template_plain, array(
'order' => $this->object,
'email_heading' => $this->get_heading(),
'sent_to_admin' => false,
'plain_text' => true,
'email' => $this,
) );
}
/**
* Trigger the sending of this email.
*
* @param int $order_id The order ID.
* @param WC_Order $order Order object.
*/
public function trigger( $order_id, $order = false ) {
$this->setup_locale();
/**
* Initialise settings form fields.
*/
public function init_form_fields() {
$this->form_fields = array(
'subject' => array(
'title' => __( 'Subject', 'woocommerce' ),
'type' => 'text',
'desc_tip' => true,
/* translators: %s: list of placeholders */
'description' => sprintf( __( 'Available placeholders: %s', 'woocommerce' ), '<code>{site_title}, {order_date}, {order_number}</code>' ),
'placeholder' => $this->get_default_subject(),
'default' => '',
),
'heading' => array(
'title' => __( 'Email heading', 'woocommerce' ),
'type' => 'text',
'desc_tip' => true,
/* translators: %s: list of placeholders */
'description' => sprintf( __( 'Available placeholders: %s', 'woocommerce' ), '<code>{site_title}, {order_date}, {order_number}</code>' ),
'placeholder' => $this->get_default_heading(),
'default' => '',
),
'subject_paid' => array(
'title' => __( 'Subject (paid)', 'woocommerce' ),
'type' => 'text',
'desc_tip' => true,
/* translators: %s: list of placeholders */
'description' => sprintf( __( 'Available placeholders: %s', 'woocommerce' ), '<code>{site_title}, {order_date}, {order_number}</code>' ),
'placeholder' => $this->get_default_subject( true ),
'default' => '',
),
'heading_paid' => array(
'title' => __( 'Email heading (paid)', 'woocommerce' ),
'type' => 'text',
'desc_tip' => true,
/* translators: %s: list of placeholders */
'description' => sprintf( __( 'Available placeholders: %s', 'woocommerce' ), '<code>{site_title}, {order_date}, {order_number}</code>' ),
'placeholder' => $this->get_default_heading( true ),
'default' => '',
),
'email_type' => array(
'title' => __( 'Email type', 'woocommerce' ),
'type' => 'select',
'description' => __( 'Choose which format of email to send.', 'woocommerce' ),
'default' => 'html',
'class' => 'email_type wc-enhanced-select',
'options' => $this->get_email_type_options(),
'desc_tip' => true,
),
);
if ( $order_id && ! is_a( $order, 'WC_Order' ) ) {
$order = wc_get_order( $order_id );
}
if ( is_a( $order, 'WC_Order' ) ) {
$this->object = $order;
$this->recipient = $this->object->get_billing_email();
$this->placeholders['{order_date}'] = wc_format_datetime( $this->object->get_date_created() );
$this->placeholders['{order_number}'] = $this->object->get_order_number();
}
if ( $this->get_recipient() ) {
$this->send( $this->get_recipient(), $this->get_subject(), $this->get_content(), $this->get_headers(), $this->get_attachments() );
}
$this->restore_locale();
}
/**
* Get content html.
*
* @access public
* @return string
*/
public function get_content_html() {
return wc_get_template_html(
$this->template_html, array(
'order' => $this->object,
'email_heading' => $this->get_heading(),
'sent_to_admin' => false,
'plain_text' => false,
'email' => $this,
)
);
}
/**
* Get content plain.
*
* @access public
* @return string
*/
public function get_content_plain() {
return wc_get_template_html(
$this->template_plain, array(
'order' => $this->object,
'email_heading' => $this->get_heading(),
'sent_to_admin' => false,
'plain_text' => true,
'email' => $this,
)
);
}
/**
* Initialise settings form fields.
*/
public function init_form_fields() {
$this->form_fields = array(
'subject' => array(
'title' => __( 'Subject', 'woocommerce' ),
'type' => 'text',
'desc_tip' => true,
/* translators: %s: list of placeholders */
'description' => sprintf( __( 'Available placeholders: %s', 'woocommerce' ), '<code>{site_title}, {order_date}, {order_number}</code>' ),
'placeholder' => $this->get_default_subject(),
'default' => '',
),
'heading' => array(
'title' => __( 'Email heading', 'woocommerce' ),
'type' => 'text',
'desc_tip' => true,
/* translators: %s: list of placeholders */
'description' => sprintf( __( 'Available placeholders: %s', 'woocommerce' ), '<code>{site_title}, {order_date}, {order_number}</code>' ),
'placeholder' => $this->get_default_heading(),
'default' => '',
),
'subject_paid' => array(
'title' => __( 'Subject (paid)', 'woocommerce' ),
'type' => 'text',
'desc_tip' => true,
/* translators: %s: list of placeholders */
'description' => sprintf( __( 'Available placeholders: %s', 'woocommerce' ), '<code>{site_title}, {order_date}, {order_number}</code>' ),
'placeholder' => $this->get_default_subject( true ),
'default' => '',
),
'heading_paid' => array(
'title' => __( 'Email heading (paid)', 'woocommerce' ),
'type' => 'text',
'desc_tip' => true,
/* translators: %s: list of placeholders */
'description' => sprintf( __( 'Available placeholders: %s', 'woocommerce' ), '<code>{site_title}, {order_date}, {order_number}</code>' ),
'placeholder' => $this->get_default_heading( true ),
'default' => '',
),
'email_type' => array(
'title' => __( 'Email type', 'woocommerce' ),
'type' => 'select',
'description' => __( 'Choose which format of email to send.', 'woocommerce' ),
'default' => 'html',
'class' => 'email_type wc-enhanced-select',
'options' => $this->get_email_type_options(),
'desc_tip' => true,
),
);
}
}
}
endif;

View File

@ -1,152 +1,160 @@
<?php
/**
* Class WC_Email_Customer_New_Account file.
*
* @package WooCommerce\Emails
*/
if ( ! defined( 'ABSPATH' ) ) {
exit; // Exit if accessed directly
exit; // Exit if accessed directly.
}
if ( ! class_exists( 'WC_Email_Customer_New_Account', false ) ) :
/**
* Customer New Account.
*
* An email sent to the customer when they create an account.
*
* @class WC_Email_Customer_New_Account
* @version 2.3.0
* @package WooCommerce/Classes/Emails
* @author WooThemes
* @extends WC_Email
*/
class WC_Email_Customer_New_Account extends WC_Email {
/**
* User login name.
* Customer New Account.
*
* @var string
*/
public $user_login;
/**
* User email.
* An email sent to the customer when they create an account.
*
* @var string
* @class WC_Email_Customer_New_Account
* @version 2.3.0
* @package WooCommerce/Classes/Emails
* @extends WC_Email
*/
public $user_email;
class WC_Email_Customer_New_Account extends WC_Email {
/**
* User password.
*
* @var string
*/
public $user_pass;
/**
* User login name.
*
* @var string
*/
public $user_login;
/**
* Is the password generated?
*
* @var bool
*/
public $password_generated;
/**
* User email.
*
* @var string
*/
public $user_email;
/**
* Constructor.
*/
public function __construct() {
$this->id = 'customer_new_account';
$this->customer_email = true;
$this->title = __( 'New account', 'woocommerce' );
$this->description = __( 'Customer "new account" emails are sent to the customer when a customer signs up via checkout or account pages.', 'woocommerce' );
$this->template_html = 'emails/customer-new-account.php';
$this->template_plain = 'emails/plain/customer-new-account.php';
/**
* User password.
*
* @var string
*/
public $user_pass;
// Call parent constructor
parent::__construct();
}
/**
* Is the password generated?
*
* @var bool
*/
public $password_generated;
/**
* Get email subject.
*
* @since 3.1.0
* @return string
*/
public function get_default_subject() {
return __( 'Your account on {site_title}', 'woocommerce' );
}
/**
* Constructor.
*/
public function __construct() {
$this->id = 'customer_new_account';
$this->customer_email = true;
$this->title = __( 'New account', 'woocommerce' );
$this->description = __( 'Customer "new account" emails are sent to the customer when a customer signs up via checkout or account pages.', 'woocommerce' );
$this->template_html = 'emails/customer-new-account.php';
$this->template_plain = 'emails/plain/customer-new-account.php';
/**
* Get email heading.
*
* @since 3.1.0
* @return string
*/
public function get_default_heading() {
return __( 'Welcome to {site_title}', 'woocommerce' );
}
/**
* Trigger.
*
* @param int $user_id
* @param string $user_pass
* @param bool $password_generated
*/
public function trigger( $user_id, $user_pass = '', $password_generated = false ) {
$this->setup_locale();
if ( $user_id ) {
$this->object = new WP_User( $user_id );
$this->user_pass = $user_pass;
$this->user_login = stripslashes( $this->object->user_login );
$this->user_email = stripslashes( $this->object->user_email );
$this->recipient = $this->user_email;
$this->password_generated = $password_generated;
// Call parent constructor.
parent::__construct();
}
if ( $this->is_enabled() && $this->get_recipient() ) {
$this->send( $this->get_recipient(), $this->get_subject(), $this->get_content(), $this->get_headers(), $this->get_attachments() );
/**
* Get email subject.
*
* @since 3.1.0
* @return string
*/
public function get_default_subject() {
return __( 'Your account on {site_title}', 'woocommerce' );
}
$this->restore_locale();
}
/**
* Get email heading.
*
* @since 3.1.0
* @return string
*/
public function get_default_heading() {
return __( 'Welcome to {site_title}', 'woocommerce' );
}
/**
* Get content html.
*
* @access public
* @return string
*/
public function get_content_html() {
return wc_get_template_html( $this->template_html, array(
'email_heading' => $this->get_heading(),
'user_login' => $this->user_login,
'user_pass' => $this->user_pass,
'blogname' => $this->get_blogname(),
'password_generated' => $this->password_generated,
'sent_to_admin' => false,
'plain_text' => false,
'email' => $this,
) );
}
/**
* Trigger.
*
* @param int $user_id User ID.
* @param string $user_pass User password.
* @param bool $password_generated Whether the password was generated automatically or not.
*/
public function trigger( $user_id, $user_pass = '', $password_generated = false ) {
$this->setup_locale();
/**
* Get content plain.
*
* @access public
* @return string
*/
public function get_content_plain() {
return wc_get_template_html( $this->template_plain, array(
'email_heading' => $this->get_heading(),
'user_login' => $this->user_login,
'user_pass' => $this->user_pass,
'blogname' => $this->get_blogname(),
'password_generated' => $this->password_generated,
'sent_to_admin' => false,
'plain_text' => true,
'email' => $this,
) );
if ( $user_id ) {
$this->object = new WP_User( $user_id );
$this->user_pass = $user_pass;
$this->user_login = stripslashes( $this->object->user_login );
$this->user_email = stripslashes( $this->object->user_email );
$this->recipient = $this->user_email;
$this->password_generated = $password_generated;
}
if ( $this->is_enabled() && $this->get_recipient() ) {
$this->send( $this->get_recipient(), $this->get_subject(), $this->get_content(), $this->get_headers(), $this->get_attachments() );
}
$this->restore_locale();
}
/**
* Get content html.
*
* @access public
* @return string
*/
public function get_content_html() {
return wc_get_template_html(
$this->template_html, array(
'email_heading' => $this->get_heading(),
'user_login' => $this->user_login,
'user_pass' => $this->user_pass,
'blogname' => $this->get_blogname(),
'password_generated' => $this->password_generated,
'sent_to_admin' => false,
'plain_text' => false,
'email' => $this,
)
);
}
/**
* Get content plain.
*
* @access public
* @return string
*/
public function get_content_plain() {
return wc_get_template_html(
$this->template_plain, array(
'email_heading' => $this->get_heading(),
'user_login' => $this->user_login,
'user_pass' => $this->user_pass,
'blogname' => $this->get_blogname(),
'password_generated' => $this->password_generated,
'sent_to_admin' => false,
'plain_text' => true,
'email' => $this,
)
);
}
}
}
endif;

View File

@ -1,142 +1,155 @@
<?php
/**
* Class WC_Email_Customer_Note file.
*
* @package WooCommerce\Emails
*/
if ( ! defined( 'ABSPATH' ) ) {
exit; // Exit if accessed directly
exit; // Exit if accessed directly.
}
if ( ! class_exists( 'WC_Email_Customer_Note', false ) ) :
/**
* Customer Note Order Email.
*
* Customer note emails are sent when you add a note to an order.
*
* @class WC_Email_Customer_Note
* @version 2.3.0
* @package WooCommerce/Classes/Emails
* @author WooThemes
* @extends WC_Email
*/
class WC_Email_Customer_Note extends WC_Email {
/**
* Customer note.
* Customer Note Order Email.
*
* @var string
*/
public $customer_note;
/**
* Constructor.
*/
public function __construct() {
$this->id = 'customer_note';
$this->customer_email = true;
$this->title = __( 'Customer note', 'woocommerce' );
$this->description = __( 'Customer note emails are sent when you add a note to an order.', 'woocommerce' );
$this->template_html = 'emails/customer-note.php';
$this->template_plain = 'emails/plain/customer-note.php';
$this->placeholders = array(
'{site_title}' => $this->get_blogname(),
'{order_date}' => '',
'{order_number}' => '',
);
// Triggers
add_action( 'woocommerce_new_customer_note_notification', array( $this, 'trigger' ) );
// Call parent constructor
parent::__construct();
}
/**
* Get email subject.
* Customer note emails are sent when you add a note to an order.
*
* @since 3.1.0
* @return string
* @class WC_Email_Customer_Note
* @version 2.3.0
* @package WooCommerce/Classes/Emails
* @extends WC_Email
*/
public function get_default_subject() {
return __( 'Note added to your {site_title} order from {order_date}', 'woocommerce' );
}
class WC_Email_Customer_Note extends WC_Email {
/**
* Get email heading.
*
* @since 3.1.0
* @return string
*/
public function get_default_heading() {
return __( 'A note has been added to your order', 'woocommerce' );
}
/**
* Customer note.
*
* @var string
*/
public $customer_note;
/**
* Trigger.
*
* @param array $args
*/
public function trigger( $args ) {
$this->setup_locale();
if ( ! empty( $args ) ) {
$defaults = array(
'order_id' => '',
'customer_note' => '',
/**
* Constructor.
*/
public function __construct() {
$this->id = 'customer_note';
$this->customer_email = true;
$this->title = __( 'Customer note', 'woocommerce' );
$this->description = __( 'Customer note emails are sent when you add a note to an order.', 'woocommerce' );
$this->template_html = 'emails/customer-note.php';
$this->template_plain = 'emails/plain/customer-note.php';
$this->placeholders = array(
'{site_title}' => $this->get_blogname(),
'{order_date}' => '',
'{order_number}' => '',
);
$args = wp_parse_args( $args, $defaults );
// Triggers.
add_action( 'woocommerce_new_customer_note_notification', array( $this, 'trigger' ) );
extract( $args );
// Call parent constructor.
parent::__construct();
}
if ( $order_id && ( $this->object = wc_get_order( $order_id ) ) ) {
$this->recipient = $this->object->get_billing_email();
$this->customer_note = $customer_note;
$this->placeholders['{order_date}'] = wc_format_datetime( $this->object->get_date_created() );
$this->placeholders['{order_number}'] = $this->object->get_order_number();
/**
* Get email subject.
*
* @since 3.1.0
* @return string
*/
public function get_default_subject() {
return __( 'Note added to your {site_title} order from {order_date}', 'woocommerce' );
}
/**
* Get email heading.
*
* @since 3.1.0
* @return string
*/
public function get_default_heading() {
return __( 'A note has been added to your order', 'woocommerce' );
}
/**
* Trigger.
*
* @param array $args Email arguments.
*/
public function trigger( $args ) {
$this->setup_locale();
if ( ! empty( $args ) ) {
$defaults = array(
'order_id' => '',
'customer_note' => '',
);
$args = wp_parse_args( $args, $defaults );
$order_id = $args['order_id'];
$customer_note = $args['customer_note'];
if ( $order_id ) {
$this->object = wc_get_order( $order_id );
if ( $this->object ) {
$this->recipient = $this->object->get_billing_email();
$this->customer_note = $customer_note;
$this->placeholders['{order_date}'] = wc_format_datetime( $this->object->get_date_created() );
$this->placeholders['{order_number}'] = $this->object->get_order_number();
}
}
}
if ( $this->is_enabled() && $this->get_recipient() ) {
$this->send( $this->get_recipient(), $this->get_subject(), $this->get_content(), $this->get_headers(), $this->get_attachments() );
}
$this->restore_locale();
}
if ( $this->is_enabled() && $this->get_recipient() ) {
$this->send( $this->get_recipient(), $this->get_subject(), $this->get_content(), $this->get_headers(), $this->get_attachments() );
/**
* Get content html.
*
* @access public
* @return string
*/
public function get_content_html() {
return wc_get_template_html(
$this->template_html, array(
'order' => $this->object,
'email_heading' => $this->get_heading(),
'customer_note' => $this->customer_note,
'sent_to_admin' => false,
'plain_text' => false,
'email' => $this,
)
);
}
$this->restore_locale();
/**
* Get content plain.
*
* @access public
* @return string
*/
public function get_content_plain() {
return wc_get_template_html(
$this->template_plain, array(
'order' => $this->object,
'email_heading' => $this->get_heading(),
'customer_note' => $this->customer_note,
'sent_to_admin' => false,
'plain_text' => true,
'email' => $this,
)
);
}
}
/**
* Get content html.
*
* @access public
* @return string
*/
public function get_content_html() {
return wc_get_template_html( $this->template_html, array(
'order' => $this->object,
'email_heading' => $this->get_heading(),
'customer_note' => $this->customer_note,
'sent_to_admin' => false,
'plain_text' => false,
'email' => $this,
) );
}
/**
* Get content plain.
*
* @access public
* @return string
*/
public function get_content_plain() {
return wc_get_template_html( $this->template_plain, array(
'order' => $this->object,
'email_heading' => $this->get_heading(),
'customer_note' => $this->customer_note,
'sent_to_admin' => false,
'plain_text' => true,
'email' => $this,
) );
}
}
endif;
return new WC_Email_Customer_Note();

View File

@ -1,127 +1,135 @@
<?php
/**
* Class WC_Email_Customer_On_Hold_Order file.
*
* @package WooCommerce\Emails
*/
if ( ! defined( 'ABSPATH' ) ) {
exit; // Exit if accessed directly
exit; // Exit if accessed directly.
}
if ( ! class_exists( 'WC_Email_Customer_On_Hold_Order', false ) ) :
/**
* Customer On-hold Order Email.
*
* An email sent to the customer when a new order is on-hold for.
*
* @class WC_Email_Customer_On_Hold_Order
* @version 2.6.0
* @package WooCommerce/Classes/Emails
* @author WooThemes
* @extends WC_Email
*/
class WC_Email_Customer_On_Hold_Order extends WC_Email {
/**
* Constructor.
*/
public function __construct() {
$this->id = 'customer_on_hold_order';
$this->customer_email = true;
$this->title = __( 'Order on-hold', 'woocommerce' );
$this->description = __( 'This is an order notification sent to customers containing order details after an order is placed on-hold.', 'woocommerce' );
$this->template_html = 'emails/customer-on-hold-order.php';
$this->template_plain = 'emails/plain/customer-on-hold-order.php';
$this->placeholders = array(
'{site_title}' => $this->get_blogname(),
'{order_date}' => '',
'{order_number}' => '',
);
// Triggers for this email
add_action( 'woocommerce_order_status_pending_to_on-hold_notification', array( $this, 'trigger' ), 10, 2 );
add_action( 'woocommerce_order_status_failed_to_on-hold_notification', array( $this, 'trigger' ), 10, 2 );
// Call parent constructor
parent::__construct();
}
/**
* Get email subject.
* Customer On-hold Order Email.
*
* @since 3.1.0
* @return string
*/
public function get_default_subject() {
return __( 'Your {site_title} order receipt from {order_date}', 'woocommerce' );
}
/**
* Get email heading.
* An email sent to the customer when a new order is on-hold for.
*
* @since 3.1.0
* @return string
* @class WC_Email_Customer_On_Hold_Order
* @version 2.6.0
* @package WooCommerce/Classes/Emails
* @extends WC_Email
*/
public function get_default_heading() {
return __( 'Thank you for your order', 'woocommerce' );
}
class WC_Email_Customer_On_Hold_Order extends WC_Email {
/**
* Trigger the sending of this email.
*
* @param int $order_id The order ID.
* @param WC_Order $order Order object.
*/
public function trigger( $order_id, $order = false ) {
$this->setup_locale();
/**
* Constructor.
*/
public function __construct() {
$this->id = 'customer_on_hold_order';
$this->customer_email = true;
$this->title = __( 'Order on-hold', 'woocommerce' );
$this->description = __( 'This is an order notification sent to customers containing order details after an order is placed on-hold.', 'woocommerce' );
$this->template_html = 'emails/customer-on-hold-order.php';
$this->template_plain = 'emails/plain/customer-on-hold-order.php';
$this->placeholders = array(
'{site_title}' => $this->get_blogname(),
'{order_date}' => '',
'{order_number}' => '',
);
if ( $order_id && ! is_a( $order, 'WC_Order' ) ) {
$order = wc_get_order( $order_id );
// Triggers for this email.
add_action( 'woocommerce_order_status_pending_to_on-hold_notification', array( $this, 'trigger' ), 10, 2 );
add_action( 'woocommerce_order_status_failed_to_on-hold_notification', array( $this, 'trigger' ), 10, 2 );
// Call parent constructor.
parent::__construct();
}
if ( is_a( $order, 'WC_Order' ) ) {
$this->object = $order;
$this->recipient = $this->object->get_billing_email();
$this->placeholders['{order_date}'] = wc_format_datetime( $this->object->get_date_created() );
$this->placeholders['{order_number}'] = $this->object->get_order_number();
/**
* Get email subject.
*
* @since 3.1.0
* @return string
*/
public function get_default_subject() {
return __( 'Your {site_title} order receipt from {order_date}', 'woocommerce' );
}
if ( $this->is_enabled() && $this->get_recipient() ) {
$this->send( $this->get_recipient(), $this->get_subject(), $this->get_content(), $this->get_headers(), $this->get_attachments() );
/**
* Get email heading.
*
* @since 3.1.0
* @return string
*/
public function get_default_heading() {
return __( 'Thank you for your order', 'woocommerce' );
}
$this->restore_locale();
}
/**
* Trigger the sending of this email.
*
* @param int $order_id The order ID.
* @param WC_Order|false $order Order object.
*/
public function trigger( $order_id, $order = false ) {
$this->setup_locale();
/**
* Get content html.
*
* @access public
* @return string
*/
public function get_content_html() {
return wc_get_template_html( $this->template_html, array(
'order' => $this->object,
'email_heading' => $this->get_heading(),
'sent_to_admin' => false,
'plain_text' => false,
'email' => $this,
) );
}
if ( $order_id && ! is_a( $order, 'WC_Order' ) ) {
$order = wc_get_order( $order_id );
}
/**
* Get content plain.
*
* @access public
* @return string
*/
public function get_content_plain() {
return wc_get_template_html( $this->template_plain, array(
'order' => $this->object,
'email_heading' => $this->get_heading(),
'sent_to_admin' => false,
'plain_text' => true,
'email' => $this,
) );
if ( is_a( $order, 'WC_Order' ) ) {
$this->object = $order;
$this->recipient = $this->object->get_billing_email();
$this->placeholders['{order_date}'] = wc_format_datetime( $this->object->get_date_created() );
$this->placeholders['{order_number}'] = $this->object->get_order_number();
}
if ( $this->is_enabled() && $this->get_recipient() ) {
$this->send( $this->get_recipient(), $this->get_subject(), $this->get_content(), $this->get_headers(), $this->get_attachments() );
}
$this->restore_locale();
}
/**
* Get content html.
*
* @access public
* @return string
*/
public function get_content_html() {
return wc_get_template_html(
$this->template_html, array(
'order' => $this->object,
'email_heading' => $this->get_heading(),
'sent_to_admin' => false,
'plain_text' => false,
'email' => $this,
)
);
}
/**
* Get content plain.
*
* @access public
* @return string
*/
public function get_content_plain() {
return wc_get_template_html(
$this->template_plain, array(
'order' => $this->object,
'email_heading' => $this->get_heading(),
'sent_to_admin' => false,
'plain_text' => true,
'email' => $this,
)
);
}
}
}
endif;

View File

@ -1,129 +1,137 @@
<?php
/**
* Class WC_Email_Customer_Processing_Order file.
*
* @package WooCommerce\Emails
*/
if ( ! defined( 'ABSPATH' ) ) {
exit; // Exit if accessed directly
exit; // Exit if accessed directly.
}
if ( ! class_exists( 'WC_Email_Customer_Processing_Order', false ) ) :
/**
* Customer Processing Order Email.
*
* An email sent to the customer when a new order is paid for.
*
* @class WC_Email_Customer_Processing_Order
* @version 2.0.0
* @package WooCommerce/Classes/Emails
* @author WooThemes
* @extends WC_Email
*/
class WC_Email_Customer_Processing_Order extends WC_Email {
/**
* Constructor.
*/
public function __construct() {
$this->id = 'customer_processing_order';
$this->customer_email = true;
$this->title = __( 'Processing order', 'woocommerce' );
$this->description = __( 'This is an order notification sent to customers containing order details after payment.', 'woocommerce' );
$this->template_html = 'emails/customer-processing-order.php';
$this->template_plain = 'emails/plain/customer-processing-order.php';
$this->placeholders = array(
'{site_title}' => $this->get_blogname(),
'{order_date}' => '',
'{order_number}' => '',
);
// Triggers for this email
add_action( 'woocommerce_order_status_failed_to_processing_notification', array( $this, 'trigger' ), 10, 2 );
add_action( 'woocommerce_order_status_on-hold_to_processing_notification', array( $this, 'trigger' ), 10, 2 );
add_action( 'woocommerce_order_status_pending_to_processing_notification', array( $this, 'trigger' ), 10, 2 );
// Call parent constructor
parent::__construct();
}
/**
* Get email subject.
* Customer Processing Order Email.
*
* @since 3.1.0
* @return string
*/
public function get_default_subject() {
return __( 'Your {site_title} order receipt from {order_date}', 'woocommerce' );
}
/**
* Get email heading.
* An email sent to the customer when a new order is paid for.
*
* @since 3.1.0
* @return string
* @class WC_Email_Customer_Processing_Order
* @version 2.0.0
* @package WooCommerce/Classes/Emails
* @extends WC_Email
*/
public function get_default_heading() {
return __( 'Thank you for your order', 'woocommerce' );
}
class WC_Email_Customer_Processing_Order extends WC_Email {
/**
* Trigger the sending of this email.
*
* @param int $order_id The order ID.
* @param WC_Order $order Order object.
*/
public function trigger( $order_id, $order = false ) {
$this->setup_locale();
/**
* Constructor.
*/
public function __construct() {
$this->id = 'customer_processing_order';
$this->customer_email = true;
if ( $order_id && ! is_a( $order, 'WC_Order' ) ) {
$order = wc_get_order( $order_id );
$this->title = __( 'Processing order', 'woocommerce' );
$this->description = __( 'This is an order notification sent to customers containing order details after payment.', 'woocommerce' );
$this->template_html = 'emails/customer-processing-order.php';
$this->template_plain = 'emails/plain/customer-processing-order.php';
$this->placeholders = array(
'{site_title}' => $this->get_blogname(),
'{order_date}' => '',
'{order_number}' => '',
);
// Triggers for this email.
add_action( 'woocommerce_order_status_failed_to_processing_notification', array( $this, 'trigger' ), 10, 2 );
add_action( 'woocommerce_order_status_on-hold_to_processing_notification', array( $this, 'trigger' ), 10, 2 );
add_action( 'woocommerce_order_status_pending_to_processing_notification', array( $this, 'trigger' ), 10, 2 );
// Call parent constructor.
parent::__construct();
}
if ( is_a( $order, 'WC_Order' ) ) {
$this->object = $order;
$this->recipient = $this->object->get_billing_email();
$this->placeholders['{order_date}'] = wc_format_datetime( $this->object->get_date_created() );
$this->placeholders['{order_number}'] = $this->object->get_order_number();
/**
* Get email subject.
*
* @since 3.1.0
* @return string
*/
public function get_default_subject() {
return __( 'Your {site_title} order receipt from {order_date}', 'woocommerce' );
}
if ( $this->is_enabled() && $this->get_recipient() ) {
$this->send( $this->get_recipient(), $this->get_subject(), $this->get_content(), $this->get_headers(), $this->get_attachments() );
/**
* Get email heading.
*
* @since 3.1.0
* @return string
*/
public function get_default_heading() {
return __( 'Thank you for your order', 'woocommerce' );
}
$this->restore_locale();
}
/**
* Trigger the sending of this email.
*
* @param int $order_id The order ID.
* @param WC_Order|false $order Order object.
*/
public function trigger( $order_id, $order = false ) {
$this->setup_locale();
/**
* Get content html.
*
* @access public
* @return string
*/
public function get_content_html() {
return wc_get_template_html( $this->template_html, array(
'order' => $this->object,
'email_heading' => $this->get_heading(),
'sent_to_admin' => false,
'plain_text' => false,
'email' => $this,
) );
}
if ( $order_id && ! is_a( $order, 'WC_Order' ) ) {
$order = wc_get_order( $order_id );
}
/**
* Get content plain.
*
* @access public
* @return string
*/
public function get_content_plain() {
return wc_get_template_html( $this->template_plain, array(
'order' => $this->object,
'email_heading' => $this->get_heading(),
'sent_to_admin' => false,
'plain_text' => true,
'email' => $this,
) );
if ( is_a( $order, 'WC_Order' ) ) {
$this->object = $order;
$this->recipient = $this->object->get_billing_email();
$this->placeholders['{order_date}'] = wc_format_datetime( $this->object->get_date_created() );
$this->placeholders['{order_number}'] = $this->object->get_order_number();
}
if ( $this->is_enabled() && $this->get_recipient() ) {
$this->send( $this->get_recipient(), $this->get_subject(), $this->get_content(), $this->get_headers(), $this->get_attachments() );
}
$this->restore_locale();
}
/**
* Get content html.
*
* @access public
* @return string
*/
public function get_content_html() {
return wc_get_template_html(
$this->template_html, array(
'order' => $this->object,
'email_heading' => $this->get_heading(),
'sent_to_admin' => false,
'plain_text' => false,
'email' => $this,
)
);
}
/**
* Get content plain.
*
* @access public
* @return string
*/
public function get_content_plain() {
return wc_get_template_html(
$this->template_plain, array(
'order' => $this->object,
'email_heading' => $this->get_heading(),
'sent_to_admin' => false,
'plain_text' => true,
'email' => $this,
)
);
}
}
}
endif;

View File

@ -1,272 +1,284 @@
<?php
/**
* Class WC_Email_Customer_Refunded_Order file.
*
* @package WooCommerce\Emails
*/
if ( ! defined( 'ABSPATH' ) ) {
exit; // Exit if accessed directly
exit; // Exit if accessed directly.
}
if ( ! class_exists( 'WC_Email_Customer_Refunded_Order', false ) ) :
/**
* Customer Refunded Order Email.
*
* Order refunded emails are sent to the customer when the order is marked refunded.
*
* @class WC_Email_Customer_Refunded_Order
* @version 2.4.0
* @package WooCommerce/Classes/Emails
* @author WooThemes
* @extends WC_Email
*/
class WC_Email_Customer_Refunded_Order extends WC_Email {
/**
* Refund order.
* Customer Refunded Order Email.
*
* @var WC_Order|bool
*/
public $refund;
/**
* Is the order partial refunded?
* Order refunded emails are sent to the customer when the order is marked refunded.
*
* @var bool
* @class WC_Email_Customer_Refunded_Order
* @version 2.4.0
* @package WooCommerce/Classes/Emails
* @extends WC_Email
*/
public $partial_refund;
class WC_Email_Customer_Refunded_Order extends WC_Email {
/**
* Constructor.
*/
public function __construct() {
$this->customer_email = true;
$this->id = 'customer_refunded_order';
$this->title = __( 'Refunded order', 'woocommerce' );
$this->description = __( 'Order refunded emails are sent to customers when their orders are refunded.', 'woocommerce' );
$this->template_html = 'emails/customer-refunded-order.php';
$this->template_plain = 'emails/plain/customer-refunded-order.php';
$this->placeholders = array(
'{site_title}' => $this->get_blogname(),
'{order_date}' => '',
'{order_number}' => '',
);
/**
* Refund order.
*
* @var WC_Order|bool
*/
public $refund;
// Triggers for this email
add_action( 'woocommerce_order_fully_refunded_notification', array( $this, 'trigger_full' ), 10, 2 );
add_action( 'woocommerce_order_partially_refunded_notification', array( $this, 'trigger_partial' ), 10, 2 );
/**
* Is the order partial refunded?
*
* @var bool
*/
public $partial_refund;
// Call parent constructor.
parent::__construct();
}
/**
* Constructor.
*/
public function __construct() {
$this->customer_email = true;
$this->id = 'customer_refunded_order';
$this->title = __( 'Refunded order', 'woocommerce' );
$this->description = __( 'Order refunded emails are sent to customers when their orders are refunded.', 'woocommerce' );
$this->template_html = 'emails/customer-refunded-order.php';
$this->template_plain = 'emails/plain/customer-refunded-order.php';
$this->placeholders = array(
'{site_title}' => $this->get_blogname(),
'{order_date}' => '',
'{order_number}' => '',
);
/**
* Get email subject.
*
* @since 3.1.0
* @return string
*/
public function get_default_subject( $partial = false ) {
if ( $partial ) {
return __( 'Your {site_title} order from {order_date} has been partially refunded', 'woocommerce' );
} else {
return __( 'Your {site_title} order from {order_date} has been refunded', 'woocommerce' );
}
}
// Triggers for this email.
add_action( 'woocommerce_order_fully_refunded_notification', array( $this, 'trigger_full' ), 10, 2 );
add_action( 'woocommerce_order_partially_refunded_notification', array( $this, 'trigger_partial' ), 10, 2 );
/**
* Get email heading.
*
* @since 3.1.0
* @return string
*/
public function get_default_heading( $partial = false ) {
if ( $partial ) {
return __( 'Your order has been partially refunded', 'woocommerce' );
} else {
return __( 'Order {order_number} details', 'woocommerce' );
}
}
/**
* Get email subject.
*
* @access public
* @return string
*/
public function get_subject() {
if ( $this->partial_refund ) {
$subject = $this->get_option( 'subject_partial', $this->get_default_subject( true ) );
} else {
$subject = $this->get_option( 'subject_full', $this->get_default_subject() );
}
return apply_filters( 'woocommerce_email_subject_customer_refunded_order', $this->format_string( $subject ), $this->object );
}
/**
* Get email heading.
*
* @access public
* @return string
*/
public function get_heading() {
if ( $this->partial_refund ) {
$heading = $this->get_option( 'heading_partial', $this->get_default_heading( true ) );
} else {
$heading = $this->get_option( 'heading_full', $this->get_default_heading() );
}
return apply_filters( 'woocommerce_email_heading_customer_refunded_order', $this->format_string( $heading ), $this->object );
}
/**
* Set email strings.
* @deprecated 3.1.0 Unused.
*/
public function set_email_strings( $partial_refund = false ) {}
/**
* Full refund notification.
*
* @param int $order_id
* @param int $refund_id
*/
public function trigger_full( $order_id, $refund_id = null ) {
$this->trigger( $order_id, false, $refund_id );
}
/**
* Partial refund notification.
*
* @param int $order_id
* @param int $refund_id
*/
public function trigger_partial( $order_id, $refund_id = null ) {
$this->trigger( $order_id, true, $refund_id );
}
/**
* Trigger.
*
* @param int $order_id
* @param bool $partial_refund
* @param int $refund_id
*/
public function trigger( $order_id, $partial_refund = false, $refund_id = null ) {
$this->setup_locale();
$this->partial_refund = $partial_refund;
$this->id = $this->partial_refund ? 'customer_partially_refunded_order' : 'customer_refunded_order';
if ( $order_id ) {
$this->object = wc_get_order( $order_id );
$this->recipient = $this->object->get_billing_email();
$this->placeholders['{order_date}'] = wc_format_datetime( $this->object->get_date_created() );
$this->placeholders['{order_number}'] = $this->object->get_order_number();
// Call parent constructor.
parent::__construct();
}
if ( ! empty( $refund_id ) ) {
$this->refund = wc_get_order( $refund_id );
} else {
$this->refund = false;
/**
* Get email subject.
*
* @param bool $partial Whether it is a partial refund or a full refund.
* @since 3.1.0
* @return string
*/
public function get_default_subject( $partial = false ) {
if ( $partial ) {
return __( 'Your {site_title} order from {order_date} has been partially refunded', 'woocommerce' );
} else {
return __( 'Your {site_title} order from {order_date} has been refunded', 'woocommerce' );
}
}
if ( $this->is_enabled() && $this->get_recipient() ) {
$this->send( $this->get_recipient(), $this->get_subject(), $this->get_content(), $this->get_headers(), $this->get_attachments() );
/**
* Get email heading.
*
* @param bool $partial Whether it is a partial refund or a full refund.
* @since 3.1.0
* @return string
*/
public function get_default_heading( $partial = false ) {
if ( $partial ) {
return __( 'Your order has been partially refunded', 'woocommerce' );
} else {
return __( 'Order {order_number} details', 'woocommerce' );
}
}
$this->restore_locale();
}
/**
* Get email subject.
*
* @access public
* @return string
*/
public function get_subject() {
if ( $this->partial_refund ) {
$subject = $this->get_option( 'subject_partial', $this->get_default_subject( true ) );
} else {
$subject = $this->get_option( 'subject_full', $this->get_default_subject() );
}
return apply_filters( 'woocommerce_email_subject_customer_refunded_order', $this->format_string( $subject ), $this->object );
}
/**
* Get content html.
*
* @access public
* @return string
*/
public function get_content_html() {
return wc_get_template_html( $this->template_html, array(
'order' => $this->object,
'refund' => $this->refund,
'partial_refund' => $this->partial_refund,
'email_heading' => $this->get_heading(),
'sent_to_admin' => false,
'plain_text' => false,
'email' => $this,
) );
}
/**
* Get email heading.
*
* @access public
* @return string
*/
public function get_heading() {
if ( $this->partial_refund ) {
$heading = $this->get_option( 'heading_partial', $this->get_default_heading( true ) );
} else {
$heading = $this->get_option( 'heading_full', $this->get_default_heading() );
}
return apply_filters( 'woocommerce_email_heading_customer_refunded_order', $this->format_string( $heading ), $this->object );
}
/**
* Get content plain.
*
* @return string
*/
public function get_content_plain() {
return wc_get_template_html( $this->template_plain, array(
'order' => $this->object,
'refund' => $this->refund,
'partial_refund' => $this->partial_refund,
'email_heading' => $this->get_heading(),
'sent_to_admin' => false,
'plain_text' => true,
'email' => $this,
) );
}
/**
* Set email strings.
*
* @param bool $partial_refund Whether it is a partial refund or a full refund.
* @deprecated 3.1.0 Unused.
*/
public function set_email_strings( $partial_refund = false ) {}
/**
* Initialise settings form fields.
*/
public function init_form_fields() {
$this->form_fields = array(
'enabled' => array(
'title' => __( 'Enable/Disable', 'woocommerce' ),
'type' => 'checkbox',
'label' => __( 'Enable this email notification', 'woocommerce' ),
'default' => 'yes',
),
'subject_full' => array(
'title' => __( 'Full refund subject', 'woocommerce' ),
'type' => 'text',
'desc_tip' => true,
/* translators: %s: list of placeholders */
'description' => sprintf( __( 'Available placeholders: %s', 'woocommerce' ), '<code>{site_title}, {order_date}, {order_number}</code>' ),
'placeholder' => $this->get_default_subject(),
'default' => '',
),
'subject_partial' => array(
'title' => __( 'Partial refund subject', 'woocommerce' ),
'type' => 'text',
'desc_tip' => true,
/* translators: %s: list of placeholders */
'description' => sprintf( __( 'Available placeholders: %s', 'woocommerce' ), '<code>{site_title}, {order_date}, {order_number}</code>' ),
'placeholder' => $this->get_default_subject( true ),
'default' => '',
),
'heading_full' => array(
'title' => __( 'Full refund email heading', 'woocommerce' ),
'type' => 'text',
'desc_tip' => true,
/* translators: %s: list of placeholders */
'description' => sprintf( __( 'Available placeholders: %s', 'woocommerce' ), '<code>{site_title}, {order_date}, {order_number}</code>' ),
'placeholder' => $this->get_default_heading(),
'default' => '',
),
'heading_partial' => array(
'title' => __( 'Partial refund email heading', 'woocommerce' ),
'type' => 'text',
'desc_tip' => true,
/* translators: %s: list of placeholders */
'description' => sprintf( __( 'Available placeholders: %s', 'woocommerce' ), '<code>{site_title}, {order_date}, {order_number}</code>' ),
'placeholder' => $this->get_default_heading( true ),
'default' => '',
),
'email_type' => array(
'title' => __( 'Email type', 'woocommerce' ),
'type' => 'select',
'description' => __( 'Choose which format of email to send.', 'woocommerce' ),
'default' => 'html',
'class' => 'email_type wc-enhanced-select',
'options' => $this->get_email_type_options(),
'desc_tip' => true,
),
);
/**
* Full refund notification.
*
* @param int $order_id Order ID.
* @param int $refund_id Refund ID.
*/
public function trigger_full( $order_id, $refund_id = null ) {
$this->trigger( $order_id, false, $refund_id );
}
/**
* Partial refund notification.
*
* @param int $order_id Order ID.
* @param int $refund_id Refund ID.
*/
public function trigger_partial( $order_id, $refund_id = null ) {
$this->trigger( $order_id, true, $refund_id );
}
/**
* Trigger.
*
* @param int $order_id Order ID.
* @param bool $partial_refund Whether it is a partial refund or a full refund.
* @param int $refund_id Refund ID.
*/
public function trigger( $order_id, $partial_refund = false, $refund_id = null ) {
$this->setup_locale();
$this->partial_refund = $partial_refund;
$this->id = $this->partial_refund ? 'customer_partially_refunded_order' : 'customer_refunded_order';
if ( $order_id ) {
$this->object = wc_get_order( $order_id );
$this->recipient = $this->object->get_billing_email();
$this->placeholders['{order_date}'] = wc_format_datetime( $this->object->get_date_created() );
$this->placeholders['{order_number}'] = $this->object->get_order_number();
}
if ( ! empty( $refund_id ) ) {
$this->refund = wc_get_order( $refund_id );
} else {
$this->refund = false;
}
if ( $this->is_enabled() && $this->get_recipient() ) {
$this->send( $this->get_recipient(), $this->get_subject(), $this->get_content(), $this->get_headers(), $this->get_attachments() );
}
$this->restore_locale();
}
/**
* Get content html.
*
* @access public
* @return string
*/
public function get_content_html() {
return wc_get_template_html(
$this->template_html, array(
'order' => $this->object,
'refund' => $this->refund,
'partial_refund' => $this->partial_refund,
'email_heading' => $this->get_heading(),
'sent_to_admin' => false,
'plain_text' => false,
'email' => $this,
)
);
}
/**
* Get content plain.
*
* @return string
*/
public function get_content_plain() {
return wc_get_template_html(
$this->template_plain, array(
'order' => $this->object,
'refund' => $this->refund,
'partial_refund' => $this->partial_refund,
'email_heading' => $this->get_heading(),
'sent_to_admin' => false,
'plain_text' => true,
'email' => $this,
)
);
}
/**
* Initialise settings form fields.
*/
public function init_form_fields() {
$this->form_fields = array(
'enabled' => array(
'title' => __( 'Enable/Disable', 'woocommerce' ),
'type' => 'checkbox',
'label' => __( 'Enable this email notification', 'woocommerce' ),
'default' => 'yes',
),
'subject_full' => array(
'title' => __( 'Full refund subject', 'woocommerce' ),
'type' => 'text',
'desc_tip' => true,
/* translators: %s: list of placeholders */
'description' => sprintf( __( 'Available placeholders: %s', 'woocommerce' ), '<code>{site_title}, {order_date}, {order_number}</code>' ),
'placeholder' => $this->get_default_subject(),
'default' => '',
),
'subject_partial' => array(
'title' => __( 'Partial refund subject', 'woocommerce' ),
'type' => 'text',
'desc_tip' => true,
/* translators: %s: list of placeholders */
'description' => sprintf( __( 'Available placeholders: %s', 'woocommerce' ), '<code>{site_title}, {order_date}, {order_number}</code>' ),
'placeholder' => $this->get_default_subject( true ),
'default' => '',
),
'heading_full' => array(
'title' => __( 'Full refund email heading', 'woocommerce' ),
'type' => 'text',
'desc_tip' => true,
/* translators: %s: list of placeholders */
'description' => sprintf( __( 'Available placeholders: %s', 'woocommerce' ), '<code>{site_title}, {order_date}, {order_number}</code>' ),
'placeholder' => $this->get_default_heading(),
'default' => '',
),
'heading_partial' => array(
'title' => __( 'Partial refund email heading', 'woocommerce' ),
'type' => 'text',
'desc_tip' => true,
/* translators: %s: list of placeholders */
'description' => sprintf( __( 'Available placeholders: %s', 'woocommerce' ), '<code>{site_title}, {order_date}, {order_number}</code>' ),
'placeholder' => $this->get_default_heading( true ),
'default' => '',
),
'email_type' => array(
'title' => __( 'Email type', 'woocommerce' ),
'type' => 'select',
'description' => __( 'Choose which format of email to send.', 'woocommerce' ),
'default' => 'html',
'class' => 'email_type wc-enhanced-select',
'options' => $this->get_email_type_options(),
'desc_tip' => true,
),
);
}
}
}
endif;

View File

@ -1,156 +1,164 @@
<?php
/**
* Class WC_Email_Customer_Reset_Password file.
*
* @package WooCommerce\Emails
*/
if ( ! defined( 'ABSPATH' ) ) {
exit; // Exit if accessed directly
exit; // Exit if accessed directly.
}
if ( ! class_exists( 'WC_Email_Customer_Reset_Password', false ) ) :
/**
* Customer Reset Password.
*
* An email sent to the customer when they reset their password.
*
* @class WC_Email_Customer_Reset_Password
* @version 2.3.0
* @package WooCommerce/Classes/Emails
* @author WooThemes
* @extends WC_Email
*/
class WC_Email_Customer_Reset_Password extends WC_Email {
/**
* User ID.
* Customer Reset Password.
*
* @var integer
*/
public $user_id;
/**
* User login name.
* An email sent to the customer when they reset their password.
*
* @var string
* @class WC_Email_Customer_Reset_Password
* @version 2.3.0
* @package WooCommerce/Classes/Emails
* @extends WC_Email
*/
public $user_login;
class WC_Email_Customer_Reset_Password extends WC_Email {
/**
* User email.
*
* @var string
*/
public $user_email;
/**
* User ID.
*
* @var integer
*/
public $user_id;
/**
* Reset key.
*
* @var string
*/
public $reset_key;
/**
* User login name.
*
* @var string
*/
public $user_login;
/**
* Constructor.
*/
public function __construct() {
/**
* User email.
*
* @var string
*/
public $user_email;
$this->id = 'customer_reset_password';
$this->customer_email = true;
/**
* Reset key.
*
* @var string
*/
public $reset_key;
$this->title = __( 'Reset password', 'woocommerce' );
$this->description = __( 'Customer "reset password" emails are sent when customers reset their passwords.', 'woocommerce' );
/**
* Constructor.
*/
public function __construct() {
$this->template_html = 'emails/customer-reset-password.php';
$this->template_plain = 'emails/plain/customer-reset-password.php';
$this->id = 'customer_reset_password';
$this->customer_email = true;
// Trigger
add_action( 'woocommerce_reset_password_notification', array( $this, 'trigger' ), 10, 2 );
$this->title = __( 'Reset password', 'woocommerce' );
$this->description = __( 'Customer "reset password" emails are sent when customers reset their passwords.', 'woocommerce' );
// Call parent constructor
parent::__construct();
}
$this->template_html = 'emails/customer-reset-password.php';
$this->template_plain = 'emails/plain/customer-reset-password.php';
/**
* Get email subject.
*
* @since 3.1.0
* @return string
*/
public function get_default_subject() {
return __( 'Password reset for {site_title}', 'woocommerce' );
}
// Trigger.
add_action( 'woocommerce_reset_password_notification', array( $this, 'trigger' ), 10, 2 );
/**
* Get email heading.
*
* @since 3.1.0
* @return string
*/
public function get_default_heading() {
return __( 'Password reset instructions', 'woocommerce' );
}
/**
* Trigger.
*
* @param string $user_login
* @param string $reset_key
*/
public function trigger( $user_login = '', $reset_key = '' ) {
$this->setup_locale();
if ( $user_login && $reset_key ) {
$this->object = get_user_by( 'login', $user_login );
$this->user_id = $this->object->ID;
$this->user_login = $user_login;
$this->reset_key = $reset_key;
$this->user_email = stripslashes( $this->object->user_email );
$this->recipient = $this->user_email;
// Call parent constructor.
parent::__construct();
}
if ( $this->is_enabled() && $this->get_recipient() ) {
$this->send( $this->get_recipient(), $this->get_subject(), $this->get_content(), $this->get_headers(), $this->get_attachments() );
/**
* Get email subject.
*
* @since 3.1.0
* @return string
*/
public function get_default_subject() {
return __( 'Password reset for {site_title}', 'woocommerce' );
}
$this->restore_locale();
}
/**
* Get email heading.
*
* @since 3.1.0
* @return string
*/
public function get_default_heading() {
return __( 'Password reset instructions', 'woocommerce' );
}
/**
* Get content html.
*
* @access public
* @return string
*/
public function get_content_html() {
return wc_get_template_html( $this->template_html, array(
'email_heading' => $this->get_heading(),
'user_id' => $this->user_id,
'user_login' => $this->user_login,
'reset_key' => $this->reset_key,
'blogname' => $this->get_blogname(),
'sent_to_admin' => false,
'plain_text' => false,
'email' => $this,
) );
}
/**
* Trigger.
*
* @param string $user_login User login.
* @param string $reset_key Password reset key.
*/
public function trigger( $user_login = '', $reset_key = '' ) {
$this->setup_locale();
/**
* Get content plain.
*
* @access public
* @return string
*/
public function get_content_plain() {
return wc_get_template_html( $this->template_plain, array(
'email_heading' => $this->get_heading(),
'user_id' => $this->user_id,
'user_login' => $this->user_login,
'reset_key' => $this->reset_key,
'blogname' => $this->get_blogname(),
'sent_to_admin' => false,
'plain_text' => true,
'email' => $this,
) );
if ( $user_login && $reset_key ) {
$this->object = get_user_by( 'login', $user_login );
$this->user_id = $this->object->ID;
$this->user_login = $user_login;
$this->reset_key = $reset_key;
$this->user_email = stripslashes( $this->object->user_email );
$this->recipient = $this->user_email;
}
if ( $this->is_enabled() && $this->get_recipient() ) {
$this->send( $this->get_recipient(), $this->get_subject(), $this->get_content(), $this->get_headers(), $this->get_attachments() );
}
$this->restore_locale();
}
/**
* Get content html.
*
* @access public
* @return string
*/
public function get_content_html() {
return wc_get_template_html(
$this->template_html, array(
'email_heading' => $this->get_heading(),
'user_id' => $this->user_id,
'user_login' => $this->user_login,
'reset_key' => $this->reset_key,
'blogname' => $this->get_blogname(),
'sent_to_admin' => false,
'plain_text' => false,
'email' => $this,
)
);
}
/**
* Get content plain.
*
* @access public
* @return string
*/
public function get_content_plain() {
return wc_get_template_html(
$this->template_plain, array(
'email_heading' => $this->get_heading(),
'user_id' => $this->user_id,
'user_login' => $this->user_login,
'reset_key' => $this->reset_key,
'blogname' => $this->get_blogname(),
'sent_to_admin' => false,
'plain_text' => true,
'email' => $this,
)
);
}
}
}
endif;

View File

@ -1,4 +1,9 @@
<?php
/**
* Class WC_Email_Failed_Order file.
*
* @package WooCommerce\Emails
*/
if ( ! defined( 'ABSPATH' ) ) {
exit;
@ -6,171 +11,175 @@ if ( ! defined( 'ABSPATH' ) ) {
if ( ! class_exists( 'WC_Email_Failed_Order', false ) ) :
/**
* Failed Order Email.
*
* An email sent to the admin when payment fails to go through.
*
* @class WC_Email_Failed_Order
* @version 2.5.0
* @package WooCommerce/Classes/Emails
* @author WooThemes
* @extends WC_Email
*/
class WC_Email_Failed_Order extends WC_Email {
/**
* Constructor.
*/
public function __construct() {
$this->id = 'failed_order';
$this->title = __( 'Failed order', 'woocommerce' );
$this->description = __( 'Failed order emails are sent to chosen recipient(s) when orders have been marked failed (if they were previously processing or on-hold).', 'woocommerce' );
$this->template_html = 'emails/admin-failed-order.php';
$this->template_plain = 'emails/plain/admin-failed-order.php';
$this->placeholders = array(
'{site_title}' => $this->get_blogname(),
'{order_date}' => '',
'{order_number}' => '',
);
// Triggers for this email
add_action( 'woocommerce_order_status_pending_to_failed_notification', array( $this, 'trigger' ), 10, 2 );
add_action( 'woocommerce_order_status_on-hold_to_failed_notification', array( $this, 'trigger' ), 10, 2 );
// Call parent constructor
parent::__construct();
// Other settings
$this->recipient = $this->get_option( 'recipient', get_option( 'admin_email' ) );
}
/**
* Get email subject.
* Failed Order Email.
*
* @since 3.1.0
* @return string
*/
public function get_default_subject() {
return __( '[{site_title}] Failed order ({order_number})', 'woocommerce' );
}
/**
* Get email heading.
* An email sent to the admin when payment fails to go through.
*
* @since 3.1.0
* @return string
* @class WC_Email_Failed_Order
* @version 2.5.0
* @package WooCommerce/Classes/Emails
* @extends WC_Email
*/
public function get_default_heading() {
return __( 'Failed order', 'woocommerce' );
}
class WC_Email_Failed_Order extends WC_Email {
/**
* Trigger the sending of this email.
*
* @param int $order_id The order ID.
* @param WC_Order $order Order object.
*/
public function trigger( $order_id, $order = false ) {
$this->setup_locale();
/**
* Constructor.
*/
public function __construct() {
$this->id = 'failed_order';
$this->title = __( 'Failed order', 'woocommerce' );
$this->description = __( 'Failed order emails are sent to chosen recipient(s) when orders have been marked failed (if they were previously processing or on-hold).', 'woocommerce' );
$this->template_html = 'emails/admin-failed-order.php';
$this->template_plain = 'emails/plain/admin-failed-order.php';
$this->placeholders = array(
'{site_title}' => $this->get_blogname(),
'{order_date}' => '',
'{order_number}' => '',
);
if ( $order_id && ! is_a( $order, 'WC_Order' ) ) {
$order = wc_get_order( $order_id );
// Triggers for this email.
add_action( 'woocommerce_order_status_pending_to_failed_notification', array( $this, 'trigger' ), 10, 2 );
add_action( 'woocommerce_order_status_on-hold_to_failed_notification', array( $this, 'trigger' ), 10, 2 );
// Call parent constructor.
parent::__construct();
// Other settings.
$this->recipient = $this->get_option( 'recipient', get_option( 'admin_email' ) );
}
if ( is_a( $order, 'WC_Order' ) ) {
$this->object = $order;
$this->placeholders['{order_date}'] = wc_format_datetime( $this->object->get_date_created() );
$this->placeholders['{order_number}'] = $this->object->get_order_number();
/**
* Get email subject.
*
* @since 3.1.0
* @return string
*/
public function get_default_subject() {
return __( '[{site_title}] Failed order ({order_number})', 'woocommerce' );
}
if ( $this->is_enabled() && $this->get_recipient() ) {
$this->send( $this->get_recipient(), $this->get_subject(), $this->get_content(), $this->get_headers(), $this->get_attachments() );
/**
* Get email heading.
*
* @since 3.1.0
* @return string
*/
public function get_default_heading() {
return __( 'Failed order', 'woocommerce' );
}
$this->restore_locale();
}
/**
* Trigger the sending of this email.
*
* @param int $order_id The order ID.
* @param WC_Order|false $order Order object.
*/
public function trigger( $order_id, $order = false ) {
$this->setup_locale();
/**
* Get content html.
*
* @access public
* @return string
*/
public function get_content_html() {
return wc_get_template_html( $this->template_html, array(
'order' => $this->object,
'email_heading' => $this->get_heading(),
'sent_to_admin' => true,
'plain_text' => false,
'email' => $this,
) );
}
if ( $order_id && ! is_a( $order, 'WC_Order' ) ) {
$order = wc_get_order( $order_id );
}
/**
* Get content plain.
*
* @return string
*/
public function get_content_plain() {
return wc_get_template_html( $this->template_plain, array(
'order' => $this->object,
'email_heading' => $this->get_heading(),
'sent_to_admin' => true,
'plain_text' => true,
'email' => $this,
) );
}
if ( is_a( $order, 'WC_Order' ) ) {
$this->object = $order;
$this->placeholders['{order_date}'] = wc_format_datetime( $this->object->get_date_created() );
$this->placeholders['{order_number}'] = $this->object->get_order_number();
}
/**
* Initialise settings form fields.
*/
public function init_form_fields() {
$this->form_fields = array(
'enabled' => array(
'title' => __( 'Enable/Disable', 'woocommerce' ),
'type' => 'checkbox',
'label' => __( 'Enable this email notification', 'woocommerce' ),
'default' => 'yes',
),
'recipient' => array(
'title' => __( 'Recipient(s)', 'woocommerce' ),
'type' => 'text',
'description' => sprintf( __( 'Enter recipients (comma separated) for this email. Defaults to %s.', 'woocommerce' ), '<code>' . esc_attr( get_option( 'admin_email' ) ) . '</code>' ),
'placeholder' => '',
'default' => '',
'desc_tip' => true,
),
'subject' => array(
'title' => __( 'Subject', 'woocommerce' ),
'type' => 'text',
'desc_tip' => true,
/* translators: %s: list of placeholders */
'description' => sprintf( __( 'Available placeholders: %s', 'woocommerce' ), '<code>{site_title}, {order_date}, {order_number}</code>' ),
'placeholder' => $this->get_default_subject(),
'default' => '',
),
'heading' => array(
'title' => __( 'Email heading', 'woocommerce' ),
'type' => 'text',
'desc_tip' => true,
/* translators: %s: list of placeholders */
'description' => sprintf( __( 'Available placeholders: %s', 'woocommerce' ), '<code>{site_title}, {order_date}, {order_number}</code>' ),
'placeholder' => $this->get_default_heading(),
'default' => '',
),
'email_type' => array(
'title' => __( 'Email type', 'woocommerce' ),
'type' => 'select',
'description' => __( 'Choose which format of email to send.', 'woocommerce' ),
'default' => 'html',
'class' => 'email_type wc-enhanced-select',
'options' => $this->get_email_type_options(),
'desc_tip' => true,
),
);
if ( $this->is_enabled() && $this->get_recipient() ) {
$this->send( $this->get_recipient(), $this->get_subject(), $this->get_content(), $this->get_headers(), $this->get_attachments() );
}
$this->restore_locale();
}
/**
* Get content html.
*
* @access public
* @return string
*/
public function get_content_html() {
return wc_get_template_html(
$this->template_html, array(
'order' => $this->object,
'email_heading' => $this->get_heading(),
'sent_to_admin' => true,
'plain_text' => false,
'email' => $this,
)
);
}
/**
* Get content plain.
*
* @return string
*/
public function get_content_plain() {
return wc_get_template_html(
$this->template_plain, array(
'order' => $this->object,
'email_heading' => $this->get_heading(),
'sent_to_admin' => true,
'plain_text' => true,
'email' => $this,
)
);
}
/**
* Initialise settings form fields.
*/
public function init_form_fields() {
$this->form_fields = array(
'enabled' => array(
'title' => __( 'Enable/Disable', 'woocommerce' ),
'type' => 'checkbox',
'label' => __( 'Enable this email notification', 'woocommerce' ),
'default' => 'yes',
),
'recipient' => array(
'title' => __( 'Recipient(s)', 'woocommerce' ),
'type' => 'text',
/* translators: %s: WP admin email */
'description' => sprintf( __( 'Enter recipients (comma separated) for this email. Defaults to %s.', 'woocommerce' ), '<code>' . esc_attr( get_option( 'admin_email' ) ) . '</code>' ),
'placeholder' => '',
'default' => '',
'desc_tip' => true,
),
'subject' => array(
'title' => __( 'Subject', 'woocommerce' ),
'type' => 'text',
'desc_tip' => true,
/* translators: %s: list of placeholders */
'description' => sprintf( __( 'Available placeholders: %s', 'woocommerce' ), '<code>{site_title}, {order_date}, {order_number}</code>' ),
'placeholder' => $this->get_default_subject(),
'default' => '',
),
'heading' => array(
'title' => __( 'Email heading', 'woocommerce' ),
'type' => 'text',
'desc_tip' => true,
/* translators: %s: list of placeholders */
'description' => sprintf( __( 'Available placeholders: %s', 'woocommerce' ), '<code>{site_title}, {order_date}, {order_number}</code>' ),
'placeholder' => $this->get_default_heading(),
'default' => '',
),
'email_type' => array(
'title' => __( 'Email type', 'woocommerce' ),
'type' => 'select',
'description' => __( 'Choose which format of email to send.', 'woocommerce' ),
'default' => 'html',
'class' => 'email_type wc-enhanced-select',
'options' => $this->get_email_type_options(),
'desc_tip' => true,
),
);
}
}
}
endif;

View File

@ -1,4 +1,9 @@
<?php
/**
* Class WC_Email_New_Order file
*
* @package WooCommerce\Emails
*/
if ( ! defined( 'ABSPATH' ) ) {
exit;
@ -6,176 +11,180 @@ if ( ! defined( 'ABSPATH' ) ) {
if ( ! class_exists( 'WC_Email_New_Order' ) ) :
/**
* New Order Email.
*
* An email sent to the admin when a new order is received/paid for.
*
* @class WC_Email_New_Order
* @version 2.0.0
* @package WooCommerce/Classes/Emails
* @author WooThemes
* @extends WC_Email
*/
class WC_Email_New_Order extends WC_Email {
/**
* Constructor.
*/
public function __construct() {
$this->id = 'new_order';
$this->title = __( 'New order', 'woocommerce' );
$this->description = __( 'New order emails are sent to chosen recipient(s) when a new order is received.', 'woocommerce' );
$this->template_html = 'emails/admin-new-order.php';
$this->template_plain = 'emails/plain/admin-new-order.php';
$this->placeholders = array(
'{site_title}' => $this->get_blogname(),
'{order_date}' => '',
'{order_number}' => '',
);
// Triggers for this email
add_action( 'woocommerce_order_status_pending_to_processing_notification', array( $this, 'trigger' ), 10, 2 );
add_action( 'woocommerce_order_status_pending_to_completed_notification', array( $this, 'trigger' ), 10, 2 );
add_action( 'woocommerce_order_status_pending_to_on-hold_notification', array( $this, 'trigger' ), 10, 2 );
add_action( 'woocommerce_order_status_failed_to_processing_notification', array( $this, 'trigger' ), 10, 2 );
add_action( 'woocommerce_order_status_failed_to_completed_notification', array( $this, 'trigger' ), 10, 2 );
add_action( 'woocommerce_order_status_failed_to_on-hold_notification', array( $this, 'trigger' ), 10, 2 );
// Call parent constructor
parent::__construct();
// Other settings
$this->recipient = $this->get_option( 'recipient', get_option( 'admin_email' ) );
}
/**
* Get email subject.
* New Order Email.
*
* @since 3.1.0
* @return string
*/
public function get_default_subject() {
return __( '[{site_title}] New customer order ({order_number}) - {order_date}', 'woocommerce' );
}
/**
* Get email heading.
* An email sent to the admin when a new order is received/paid for.
*
* @since 3.1.0
* @return string
* @class WC_Email_New_Order
* @version 2.0.0
* @package WooCommerce/Classes/Emails
* @extends WC_Email
*/
public function get_default_heading() {
return __( 'New customer order', 'woocommerce' );
}
class WC_Email_New_Order extends WC_Email {
/**
* Trigger the sending of this email.
*
* @param int $order_id The order ID.
* @param WC_Order $order Order object.
*/
public function trigger( $order_id, $order = false ) {
$this->setup_locale();
/**
* Constructor.
*/
public function __construct() {
$this->id = 'new_order';
$this->title = __( 'New order', 'woocommerce' );
$this->description = __( 'New order emails are sent to chosen recipient(s) when a new order is received.', 'woocommerce' );
$this->template_html = 'emails/admin-new-order.php';
$this->template_plain = 'emails/plain/admin-new-order.php';
$this->placeholders = array(
'{site_title}' => $this->get_blogname(),
'{order_date}' => '',
'{order_number}' => '',
);
if ( $order_id && ! is_a( $order, 'WC_Order' ) ) {
$order = wc_get_order( $order_id );
// Triggers for this email.
add_action( 'woocommerce_order_status_pending_to_processing_notification', array( $this, 'trigger' ), 10, 2 );
add_action( 'woocommerce_order_status_pending_to_completed_notification', array( $this, 'trigger' ), 10, 2 );
add_action( 'woocommerce_order_status_pending_to_on-hold_notification', array( $this, 'trigger' ), 10, 2 );
add_action( 'woocommerce_order_status_failed_to_processing_notification', array( $this, 'trigger' ), 10, 2 );
add_action( 'woocommerce_order_status_failed_to_completed_notification', array( $this, 'trigger' ), 10, 2 );
add_action( 'woocommerce_order_status_failed_to_on-hold_notification', array( $this, 'trigger' ), 10, 2 );
// Call parent constructor.
parent::__construct();
// Other settings.
$this->recipient = $this->get_option( 'recipient', get_option( 'admin_email' ) );
}
if ( is_a( $order, 'WC_Order' ) ) {
$this->object = $order;
$this->placeholders['{order_date}'] = wc_format_datetime( $this->object->get_date_created() );
$this->placeholders['{order_number}'] = $this->object->get_order_number();
/**
* Get email subject.
*
* @since 3.1.0
* @return string
*/
public function get_default_subject() {
return __( '[{site_title}] New customer order ({order_number}) - {order_date}', 'woocommerce' );
}
if ( $this->is_enabled() && $this->get_recipient() ) {
$this->send( $this->get_recipient(), $this->get_subject(), $this->get_content(), $this->get_headers(), $this->get_attachments() );
/**
* Get email heading.
*
* @since 3.1.0
* @return string
*/
public function get_default_heading() {
return __( 'New customer order', 'woocommerce' );
}
$this->restore_locale();
}
/**
* Trigger the sending of this email.
*
* @param int $order_id The order ID.
* @param WC_Order|false $order Order object.
*/
public function trigger( $order_id, $order = false ) {
$this->setup_locale();
/**
* Get content html.
*
* @access public
* @return string
*/
public function get_content_html() {
return wc_get_template_html( $this->template_html, array(
'order' => $this->object,
'email_heading' => $this->get_heading(),
'sent_to_admin' => true,
'plain_text' => false,
'email' => $this,
) );
}
if ( $order_id && ! is_a( $order, 'WC_Order' ) ) {
$order = wc_get_order( $order_id );
}
/**
* Get content plain.
*
* @access public
* @return string
*/
public function get_content_plain() {
return wc_get_template_html( $this->template_plain, array(
'order' => $this->object,
'email_heading' => $this->get_heading(),
'sent_to_admin' => true,
'plain_text' => true,
'email' => $this,
) );
}
if ( is_a( $order, 'WC_Order' ) ) {
$this->object = $order;
$this->placeholders['{order_date}'] = wc_format_datetime( $this->object->get_date_created() );
$this->placeholders['{order_number}'] = $this->object->get_order_number();
}
/**
* Initialise settings form fields.
*/
public function init_form_fields() {
$this->form_fields = array(
'enabled' => array(
'title' => __( 'Enable/Disable', 'woocommerce' ),
'type' => 'checkbox',
'label' => __( 'Enable this email notification', 'woocommerce' ),
'default' => 'yes',
),
'recipient' => array(
'title' => __( 'Recipient(s)', 'woocommerce' ),
'type' => 'text',
'description' => sprintf( __( 'Enter recipients (comma separated) for this email. Defaults to %s.', 'woocommerce' ), '<code>' . esc_attr( get_option( 'admin_email' ) ) . '</code>' ),
'placeholder' => '',
'default' => '',
'desc_tip' => true,
),
'subject' => array(
'title' => __( 'Subject', 'woocommerce' ),
'type' => 'text',
'desc_tip' => true,
/* translators: %s: list of placeholders */
'description' => sprintf( __( 'Available placeholders: %s', 'woocommerce' ), '<code>{site_title}, {order_date}, {order_number}</code>' ),
'placeholder' => $this->get_default_subject(),
'default' => '',
),
'heading' => array(
'title' => __( 'Email heading', 'woocommerce' ),
'type' => 'text',
'desc_tip' => true,
/* translators: %s: list of placeholders */
'description' => sprintf( __( 'Available placeholders: %s', 'woocommerce' ), '<code>{site_title}, {order_date}, {order_number}</code>' ),
'placeholder' => $this->get_default_heading(),
'default' => '',
),
'email_type' => array(
'title' => __( 'Email type', 'woocommerce' ),
'type' => 'select',
'description' => __( 'Choose which format of email to send.', 'woocommerce' ),
'default' => 'html',
'class' => 'email_type wc-enhanced-select',
'options' => $this->get_email_type_options(),
'desc_tip' => true,
),
);
if ( $this->is_enabled() && $this->get_recipient() ) {
$this->send( $this->get_recipient(), $this->get_subject(), $this->get_content(), $this->get_headers(), $this->get_attachments() );
}
$this->restore_locale();
}
/**
* Get content html.
*
* @access public
* @return string
*/
public function get_content_html() {
return wc_get_template_html(
$this->template_html, array(
'order' => $this->object,
'email_heading' => $this->get_heading(),
'sent_to_admin' => true,
'plain_text' => false,
'email' => $this,
)
);
}
/**
* Get content plain.
*
* @access public
* @return string
*/
public function get_content_plain() {
return wc_get_template_html(
$this->template_plain, array(
'order' => $this->object,
'email_heading' => $this->get_heading(),
'sent_to_admin' => true,
'plain_text' => true,
'email' => $this,
)
);
}
/**
* Initialise settings form fields.
*/
public function init_form_fields() {
$this->form_fields = array(
'enabled' => array(
'title' => __( 'Enable/Disable', 'woocommerce' ),
'type' => 'checkbox',
'label' => __( 'Enable this email notification', 'woocommerce' ),
'default' => 'yes',
),
'recipient' => array(
'title' => __( 'Recipient(s)', 'woocommerce' ),
'type' => 'text',
/* translators: %s: WP admin email */
'description' => sprintf( __( 'Enter recipients (comma separated) for this email. Defaults to %s.', 'woocommerce' ), '<code>' . esc_attr( get_option( 'admin_email' ) ) . '</code>' ),
'placeholder' => '',
'default' => '',
'desc_tip' => true,
),
'subject' => array(
'title' => __( 'Subject', 'woocommerce' ),
'type' => 'text',
'desc_tip' => true,
/* translators: %s: list of placeholders */
'description' => sprintf( __( 'Available placeholders: %s', 'woocommerce' ), '<code>{site_title}, {order_date}, {order_number}</code>' ),
'placeholder' => $this->get_default_subject(),
'default' => '',
),
'heading' => array(
'title' => __( 'Email heading', 'woocommerce' ),
'type' => 'text',
'desc_tip' => true,
/* translators: %s: list of placeholders */
'description' => sprintf( __( 'Available placeholders: %s', 'woocommerce' ), '<code>{site_title}, {order_date}, {order_number}</code>' ),
'placeholder' => $this->get_default_heading(),
'default' => '',
),
'email_type' => array(
'title' => __( 'Email type', 'woocommerce' ),
'type' => 'select',
'description' => __( 'Choose which format of email to send.', 'woocommerce' ),
'default' => 'html',
'class' => 'email_type wc-enhanced-select',
'options' => $this->get_email_type_options(),
'desc_tip' => true,
),
);
}
}
}
endif;

View File

@ -1,4 +1,9 @@
<?php
/**
* Class WC_Email file.
*
* @package WooCommerce\Emails
*/
if ( ! defined( 'ABSPATH' ) ) {
exit;
@ -16,31 +21,34 @@ if ( class_exists( 'WC_Email', false ) ) {
* @class WC_Email
* @version 2.5.0
* @package WooCommerce/Classes/Emails
* @author WooThemes
* @extends WC_Settings_API
*/
class WC_Email extends WC_Settings_API {
/**
* Email method ID.
*
* @var String
*/
public $id;
/**
* Email method title.
*
* @var string
*/
public $title;
/**
* 'yes' if the method is enabled.
*
* @var string yes, no
*/
public $enabled;
/**
* Description for the email.
*
* @var string
*/
public $description;
@ -67,60 +75,70 @@ class WC_Email extends WC_Settings_API {
/**
* Plain text template path.
*
* @var string
*/
public $template_plain;
/**
* HTML template path.
*
* @var string
*/
public $template_html;
/**
* Template path.
*
* @var string
*/
public $template_base;
/**
* Recipients for the email.
*
* @var string
*/
public $recipient;
/**
* Object this email is for, for example a customer, product, or email.
*
* @var object|bool
*/
public $object;
/**
* Mime boundary (for multipart emails).
*
* @var string
*/
public $mime_boundary;
/**
* Mime boundary header (for multipart emails).
*
* @var string
*/
public $mime_boundary_header;
/**
* True when email is being sent.
*
* @var bool
*/
public $sending;
/**
* True when the email notification is sent manually only.
*
* @var bool
*/
protected $manual = false;
/**
* True when the email notification is sent to customers.
*
* @var bool
*/
protected $customer_email = false;
@ -129,56 +147,58 @@ class WC_Email extends WC_Settings_API {
* List of preg* regular expression patterns to search for,
* used in conjunction with $plain_replace.
* https://raw.github.com/ushahidi/wp-silcc/master/class.html2text.inc
*
* @var array $plain_search
* @see $plain_replace
*/
public $plain_search = array(
"/\r/", // Non-legal carriage return
'/&(nbsp|#0*160);/i', // Non-breaking space
'/&(quot|rdquo|ldquo|#0*8220|#0*8221|#0*147|#0*148);/i', // Double quotes
'/&(apos|rsquo|lsquo|#0*8216|#0*8217);/i', // Single quotes
'/&gt;/i', // Greater-than
'/&lt;/i', // Less-than
'/&#0*38;/i', // Ampersand
'/&amp;/i', // Ampersand
'/&(copy|#0*169);/i', // Copyright
'/&(trade|#0*8482|#0*153);/i', // Trademark
'/&(reg|#0*174);/i', // Registered
'/&(mdash|#0*151|#0*8212);/i', // mdash
'/&(ndash|minus|#0*8211|#0*8722);/i', // ndash
'/&(bull|#0*149|#0*8226);/i', // Bullet
'/&(pound|#0*163);/i', // Pound sign
'/&(euro|#0*8364);/i', // Euro sign
'/&(dollar|#0*36);/i', // Dollar sign
'/&[^&\s;]+;/i', // Unknown/unhandled entities
'/[ ]{2,}/', // Runs of spaces, post-handling
"/\r/", // Non-legal carriage return.
'/&(nbsp|#0*160);/i', // Non-breaking space.
'/&(quot|rdquo|ldquo|#0*8220|#0*8221|#0*147|#0*148);/i', // Double quotes.
'/&(apos|rsquo|lsquo|#0*8216|#0*8217);/i', // Single quotes.
'/&gt;/i', // Greater-than.
'/&lt;/i', // Less-than.
'/&#0*38;/i', // Ampersand.
'/&amp;/i', // Ampersand.
'/&(copy|#0*169);/i', // Copyright.
'/&(trade|#0*8482|#0*153);/i', // Trademark.
'/&(reg|#0*174);/i', // Registered.
'/&(mdash|#0*151|#0*8212);/i', // mdash.
'/&(ndash|minus|#0*8211|#0*8722);/i', // ndash.
'/&(bull|#0*149|#0*8226);/i', // Bullet.
'/&(pound|#0*163);/i', // Pound sign.
'/&(euro|#0*8364);/i', // Euro sign.
'/&(dollar|#0*36);/i', // Dollar sign.
'/&[^&\s;]+;/i', // Unknown/unhandled entities.
'/[ ]{2,}/', // Runs of spaces, post-handling.
);
/**
* List of pattern replacements corresponding to patterns searched.
*
* @var array $plain_replace
* @see $plain_search
*/
public $plain_replace = array(
'', // Non-legal carriage return
' ', // Non-breaking space
'"', // Double quotes
"'", // Single quotes
'>', // Greater-than
'<', // Less-than
'&', // Ampersand
'&', // Ampersand
'(c)', // Copyright
'(tm)', // Trademark
'(R)', // Registered
'--', // mdash
'-', // ndash
'*', // Bullet
'£', // Pound sign
'EUR', // Euro sign. € ?
'$', // Dollar sign
'', // Unknown/unhandled entities
' ', // Runs of spaces, post-handling
'', // Non-legal carriage return.
' ', // Non-breaking space.
'"', // Double quotes.
"'", // Single quotes.
'>', // Greater-than.
'<', // Less-than.
'&', // Ampersand.
'&', // Ampersand.
'(c)', // Copyright.
'(tm)', // Trademark.
'(R)', // Registered.
'--', // mdash.
'-', // ndash.
'*', // Bullet.
'£', // Pound sign.
'EUR', // Euro sign. € ?.
'$', // Dollar sign.
'', // Unknown/unhandled entities.
' ', // Runs of spaces, post-handling.
);
/**
@ -188,7 +208,7 @@ class WC_Email extends WC_Settings_API {
*/
protected $placeholders = array();
/**
/**
* Strings to find in subjects/headings.
*
* @deprecated 3.2.0 in favour of placeholders
@ -208,18 +228,18 @@ class WC_Email extends WC_Settings_API {
* Constructor.
*/
public function __construct() {
// Find/replace
// Find/replace.
if ( empty( $this->placeholders ) ) {
$this->placeholders = array(
'{site_title}' => $this->get_blogname(),
);
}
// Init settings
// Init settings.
$this->init_form_fields();
$this->init_settings();
// Default template base if not declared in child constructor
// Default template base if not declared in child constructor.
if ( is_null( $this->template_base ) ) {
$this->template_base = WC()->plugin_path() . '/templates/';
}
@ -234,12 +254,14 @@ class WC_Email extends WC_Settings_API {
/**
* Handle multipart mail.
*
* @param PHPMailer $mailer
* @param PHPMailer $mailer PHPMailer object.
* @return PHPMailer
*/
public function handle_multipart( $mailer ) {
if ( $this->sending && 'multipart' === $this->get_email_type() ) {
$mailer->AltBody = wordwrap( preg_replace( $this->plain_search, $this->plain_replace, strip_tags( $this->get_content_plain() ) ) );
$mailer->AltBody = wordwrap( // phpcs:ignore WordPress.NamingConventions.ValidVariableName.NotSnakeCaseMemberVar
preg_replace( $this->plain_search, $this->plain_replace, strip_tags( $this->get_content_plain() ) )
);
$this->sending = false;
}
return $mailer;
@ -278,7 +300,7 @@ class WC_Email extends WC_Settings_API {
}
/**
* woocommerce_email_format_string filter for main find/replace code.
* Filter for main find/replace.
*
* @since 3.2.0
*/
@ -343,6 +365,7 @@ class WC_Email extends WC_Settings_API {
/**
* Get valid recipients.
*
* @return string
*/
public function get_recipient() {
@ -358,7 +381,7 @@ class WC_Email extends WC_Settings_API {
* @return string
*/
public function get_headers() {
$header = "Content-Type: " . $this->get_content_type() . "\r\n";
$header = 'Content-Type: ' . $this->get_content_type() . "\r\n";
if ( 'new_order' === $this->id && $this->object && $this->object->get_billing_email() && ( $this->object->get_billing_first_name() || $this->object->get_billing_last_name() ) ) {
$header .= 'Reply-to: ' . $this->object->get_billing_first_name() . ' ' . $this->object->get_billing_last_name() . ' <' . $this->object->get_billing_email() . ">\r\n";
@ -377,7 +400,7 @@ class WC_Email extends WC_Settings_API {
}
/**
* get_type function.
* Return email type.
*
* @return string
*/
@ -392,17 +415,18 @@ class WC_Email extends WC_Settings_API {
*/
public function get_content_type() {
switch ( $this->get_email_type() ) {
case 'html' :
case 'html':
return 'text/html';
case 'multipart' :
case 'multipart':
return 'multipart/alternative';
default :
default:
return 'text/plain';
}
}
/**
* Return the email's title
*
* @return string
*/
public function get_title() {
@ -411,6 +435,7 @@ class WC_Email extends WC_Settings_API {
/**
* Return the email's description
*
* @return string
*/
public function get_description() {
@ -420,8 +445,8 @@ class WC_Email extends WC_Settings_API {
/**
* Proxy to parent's get_option and attempt to localize the result using gettext.
*
* @param string $key
* @param mixed $empty_value
* @param string $key Option key.
* @param mixed $empty_value Value to use when option is empty.
* @return string
*/
public function get_option( $key, $empty_value = null ) {
@ -431,6 +456,7 @@ class WC_Email extends WC_Settings_API {
/**
* Checks if this email is enabled and will be sent.
*
* @return bool
*/
public function is_enabled() {
@ -439,6 +465,7 @@ class WC_Email extends WC_Settings_API {
/**
* Checks if this email is manually sent
*
* @return bool
*/
public function is_manual() {
@ -447,6 +474,7 @@ class WC_Email extends WC_Settings_API {
/**
* Checks if this email is customer focussed.
*
* @return bool
*/
public function is_customer_email() {
@ -482,17 +510,17 @@ class WC_Email extends WC_Settings_API {
/**
* Apply inline styles to dynamic content.
*
* @param string|null $content
* @param string|null $content Content that will receive inline styles.
* @return string
*/
public function style_inline( $content ) {
// make sure we only inline CSS for html emails
if ( in_array( $this->get_content_type(), array( 'text/html', 'multipart/alternative' ) ) && class_exists( 'DOMDocument' ) ) {
// make sure we only inline CSS for html emails.
if ( in_array( $this->get_content_type(), array( 'text/html', 'multipart/alternative' ), true ) && class_exists( 'DOMDocument' ) ) {
ob_start();
wc_get_template( 'emails/email-styles.php' );
$css = apply_filters( 'woocommerce_email_styles', ob_get_clean() );
// apply CSS styles inline for picky email clients
// apply CSS styles inline for picky email clients.
try {
$emogrifier = new Emogrifier( $content, $css );
$content = $emogrifier->emogrify();
@ -506,18 +534,23 @@ class WC_Email extends WC_Settings_API {
/**
* Get the email content in plain text format.
*
* @return string
*/
public function get_content_plain() { return ''; }
public function get_content_plain() {
return ''; }
/**
* Get the email content in HTML format.
*
* @return string
*/
public function get_content_html() { return ''; }
public function get_content_html() {
return ''; }
/**
* Get the from name for outgoing emails.
*
* @return string
*/
public function get_from_name() {
@ -527,6 +560,7 @@ class WC_Email extends WC_Settings_API {
/**
* Get the from address for outgoing emails.
*
* @return string
*/
public function get_from_address() {
@ -536,11 +570,12 @@ class WC_Email extends WC_Settings_API {
/**
* Send an email.
* @param string $to
* @param string $subject
* @param string $message
* @param string $headers
* @param string $attachments
*
* @param string $to Email to.
* @param string $subject Email subject.
* @param string $message Email message.
* @param string $headers Email headers.
* @param array $attachments Email attachments.
* @return bool success
*/
public function send( $to, $subject, $message, $headers, $attachments ) {
@ -562,32 +597,32 @@ class WC_Email extends WC_Settings_API {
* Initialise Settings Form Fields - these are generic email options most will use.
*/
public function init_form_fields() {
$this->form_fields = array(
'enabled' => array(
'title' => __( 'Enable/Disable', 'woocommerce' ),
'type' => 'checkbox',
'label' => __( 'Enable this email notification', 'woocommerce' ),
'default' => 'yes',
$this->form_fields = array(
'enabled' => array(
'title' => __( 'Enable/Disable', 'woocommerce' ),
'type' => 'checkbox',
'label' => __( 'Enable this email notification', 'woocommerce' ),
'default' => 'yes',
),
'subject' => array(
'subject' => array(
'title' => __( 'Subject', 'woocommerce' ),
'type' => 'text',
'desc_tip' => true,
'desc_tip' => true,
/* translators: %s: list of placeholders */
'description' => sprintf( __( 'Available placeholders: %s', 'woocommerce' ), '<code>' . implode( '</code>, <code>', array_keys( $this->placeholders ) ) . '</code>' ),
'description' => sprintf( __( 'Available placeholders: %s', 'woocommerce' ), '<code>' . implode( '</code>, <code>', array_keys( $this->placeholders ) ) . '</code>' ),
'placeholder' => $this->get_default_subject(),
'default' => '',
),
'heading' => array(
'heading' => array(
'title' => __( 'Email heading', 'woocommerce' ),
'type' => 'text',
'desc_tip' => true,
'desc_tip' => true,
/* translators: %s: list of placeholders */
'description' => sprintf( __( 'Available placeholders: %s', 'woocommerce' ), '<code>' . implode( '</code>, <code>', array_keys( $this->placeholders ) ) . '</code>' ),
'description' => sprintf( __( 'Available placeholders: %s', 'woocommerce' ), '<code>' . implode( '</code>, <code>', array_keys( $this->placeholders ) ) . '</code>' ),
'placeholder' => $this->get_default_heading(),
'default' => '',
),
'email_type' => array(
'email_type' => array(
'title' => __( 'Email type', 'woocommerce' ),
'type' => 'select',
'description' => __( 'Choose which format of email to send.', 'woocommerce' ),
@ -601,6 +636,7 @@ class WC_Email extends WC_Settings_API {
/**
* Email type options.
*
* @return array
*/
public function get_email_type_options() {
@ -618,12 +654,12 @@ class WC_Email extends WC_Settings_API {
* Admin Panel Options Processing.
*/
public function process_admin_options() {
// Save regular options
// Save regular options.
parent::process_admin_options();
$post_data = $this->get_post_data();
// Save templates
// Save templates.
if ( isset( $post_data['template_html_code'] ) ) {
$this->save_template( $post_data['template_html_code'], $this->template_html );
}
@ -635,7 +671,7 @@ class WC_Email extends WC_Settings_API {
/**
* Get template.
*
* @param string $type
* @param string $type Template type. Can be either 'template_html' or 'template_plain'.
* @return string
*/
public function get_template( $type ) {
@ -653,16 +689,16 @@ class WC_Email extends WC_Settings_API {
* Save the email templates.
*
* @since 2.4.0
* @param string $template_code
* @param string $template_path
* @param string $template_code Template code.
* @param string $template_path Template path.
*/
protected function save_template( $template_code, $template_path ) {
if ( current_user_can( 'edit_themes' ) && ! empty( $template_code ) && ! empty( $template_path ) ) {
$saved = false;
$file = get_stylesheet_directory() . '/' . WC()->template_path() . $template_path;
$code = wp_unslash( $template_code );
$saved = false;
$file = get_stylesheet_directory() . '/' . WC()->template_path() . $template_path;
$code = wp_unslash( $template_code );
if ( is_writeable( $file ) ) {
if ( is_writeable( $file ) ) { // phpcs:ignore WordPress.VIP.FileSystemWritesDisallow.file_ops_is_writeable
$f = fopen( $file, 'w+' );
if ( false !== $f ) {
@ -683,7 +719,7 @@ class WC_Email extends WC_Settings_API {
/**
* Get the template file in the current theme.
*
* @param string $template
* @param string $template Template name.
*
* @return string
*/
@ -694,33 +730,35 @@ class WC_Email extends WC_Settings_API {
/**
* Move template action.
*
* @param string $template_type
* @param string $template_type Template type.
*/
protected function move_template_action( $template_type ) {
if ( $template = $this->get_template( $template_type ) ) {
if ( ! empty( $template ) ) {
$template = $this->get_template( $template_type );
if ( ! empty( $template ) ) {
$theme_file = $this->get_theme_template_file( $template );
$theme_file = $this->get_theme_template_file( $template );
if ( wp_mkdir_p( dirname( $theme_file ) ) && ! file_exists( $theme_file ) ) {
if ( wp_mkdir_p( dirname( $theme_file ) ) && ! file_exists( $theme_file ) ) {
// Locate template file.
$core_file = $this->template_base . $template;
$template_file = apply_filters( 'woocommerce_locate_core_template', $core_file, $template, $this->template_base, $this->id );
// Locate template file
$core_file = $this->template_base . $template;
$template_file = apply_filters( 'woocommerce_locate_core_template', $core_file, $template, $this->template_base, $this->id );
// Copy template file.
copy( $template_file, $theme_file );
// Copy template file
copy( $template_file, $theme_file );
/**
* Action hook fired after copying email template file.
*
* @param string $template_type The copied template type
* @param string $email The email object
*/
do_action( 'woocommerce_copy_email_template', $template_type, $this );
/**
* woocommerce_copy_email_template action hook.
*
* @param string $template_type The copied template type
* @param string $email The email object
*/
do_action( 'woocommerce_copy_email_template', $template_type, $this );
echo '<div class="updated"><p>' . __( 'Template file copied to theme.', 'woocommerce' ) . '</p></div>';
}
?>
<div class="updated">
<p><?php echo esc_html__( 'Template file copied to theme.', 'woocommerce' ); ?></p>
</div>
<?php
}
}
}
@ -728,27 +766,30 @@ class WC_Email extends WC_Settings_API {
/**
* Delete template action.
*
* @param string $template_type
* @param string $template_type Template type.
*/
protected function delete_template_action( $template_type ) {
if ( $template = $this->get_template( $template_type ) ) {
$template = $this->get_template( $template_type );
if ( $template ) {
if ( ! empty( $template ) ) {
$theme_file = $this->get_theme_template_file( $template );
if ( file_exists( $theme_file ) ) {
unlink( $theme_file );
unlink( $theme_file ); // phpcs:ignore WordPress.VIP.FileSystemWritesDisallow.file_ops_unlink
/**
* woocommerce_delete_email_template action hook.
* Action hook fired after deleting template file.
*
* @param string $template The deleted template type
* @param string $email The email object
*/
do_action( 'woocommerce_delete_email_template', $template_type, $this );
echo '<div class="updated"><p>' . __( 'Template file deleted from theme.', 'woocommerce' ) . '</p></div>';
?>
<div class="updated">
<p><?php echo esc_html__( 'Template file deleted from theme.', 'woocommerce' ); ?></p>
</div>
<?php
}
}
}
@ -758,26 +799,26 @@ class WC_Email extends WC_Settings_API {
* Admin actions.
*/
protected function admin_actions() {
// Handle any actions
// Handle any actions.
if (
( ! empty( $this->template_html ) || ! empty( $this->template_plain ) )
&& ( ! empty( $_GET['move_template'] ) || ! empty( $_GET['delete_template'] ) )
&& 'GET' === $_SERVER['REQUEST_METHOD']
&& 'GET' === $_SERVER['REQUEST_METHOD'] // phpcs:ignore WordPress.VIP.ValidatedSanitizedInput.InputNotValidated
) {
if ( empty( $_GET['_wc_email_nonce'] ) || ! wp_verify_nonce( $_GET['_wc_email_nonce'], 'woocommerce_email_template_nonce' ) ) {
wp_die( __( 'Action failed. Please refresh the page and retry.', 'woocommerce' ) );
if ( empty( $_GET['_wc_email_nonce'] ) || ! wp_verify_nonce( wc_clean( wp_unslash( $_GET['_wc_email_nonce'] ) ), 'woocommerce_email_template_nonce' ) ) {
wp_die( esc_html__( 'Action failed. Please refresh the page and retry.', 'woocommerce' ) );
}
if ( ! current_user_can( 'edit_themes' ) ) {
wp_die( __( 'You don&#8217;t have permission to do this.', 'woocommerce' ) );
wp_die( esc_html__( 'You don&#8217;t have permission to do this.', 'woocommerce' ) );
}
if ( ! empty( $_GET['move_template'] ) ) {
$this->move_template_action( $_GET['move_template'] );
$this->move_template_action( wc_clean( wp_unslash( $_GET['move_template'] ) ) );
}
if ( ! empty( $_GET['delete_template'] ) ) {
$this->delete_template_action( $_GET['delete_template'] );
$this->delete_template_action( wc_clean( wp_unslash( $_GET['delete_template'] ) ) );
}
}
}
@ -796,14 +837,15 @@ class WC_Email extends WC_Settings_API {
?>
<h2><?php echo esc_html( $this->get_title() ); ?> <?php wc_back_link( __( 'Return to emails', 'woocommerce' ), admin_url( 'admin.php?page=wc-settings&tab=email' ) ); ?></h2>
<?php echo wpautop( wp_kses_post( $this->get_description() ) ); ?>
<?php echo wpautop( wp_kses_post( $this->get_description() ) ); // phpcs:ignore WordPress.XSS.EscapeOutput.OutputNotEscaped ?>
<?php
/**
* woocommerce_email_settings_before action hook.
* @param string $email The email object
*/
do_action( 'woocommerce_email_settings_before', $this );
/**
* Action hook fired before displaying email settings.
*
* @param string $email The email object
*/
do_action( 'woocommerce_email_settings_before', $this );
?>
<table class="form-table">
@ -811,16 +853,20 @@ class WC_Email extends WC_Settings_API {
</table>
<?php
/**
* woocommerce_email_settings_after action hook.
* @param string $email The email object
*/
do_action( 'woocommerce_email_settings_after', $this );
/**
* Action hook fired after displaying email settings.
*
* @param string $email The email object
*/
do_action( 'woocommerce_email_settings_after', $this );
?>
<?php if ( current_user_can( 'edit_themes' ) && ( ! empty( $this->template_html ) || ! empty( $this->template_plain ) ) ) { ?>
<?php
if ( current_user_can( 'edit_themes' ) && ( ! empty( $this->template_html ) || ! empty( $this->template_plain ) ) ) {
?>
<div id="template">
<?php
<?php
$templates = array(
'template_html' => __( 'HTML template', 'woocommerce' ),
'template_plain' => __( 'Plain text template', 'woocommerce' ),
@ -838,72 +884,77 @@ class WC_Email extends WC_Settings_API {
$template_file = apply_filters( 'woocommerce_locate_core_template', $core_file, $template, $this->template_base, $this->id );
$template_dir = apply_filters( 'woocommerce_template_directory', 'woocommerce', $template );
?>
<div class="template <?php echo $template_type; ?>">
<div class="template <?php echo esc_attr( $template_type ); ?>">
<h4><?php echo wp_kses_post( $title ); ?></h4>
<?php if ( file_exists( $local_file ) ) { ?>
<?php if ( file_exists( $local_file ) ) : ?>
<p>
<a href="#" class="button toggle_editor"></a>
<?php if ( is_writable( $local_file ) ) : ?>
<a href="<?php echo esc_url( wp_nonce_url( remove_query_arg( array( 'move_template', 'saved' ), add_query_arg( 'delete_template', $template_type ) ), 'woocommerce_email_template_nonce', '_wc_email_nonce' ) ); ?>" class="delete_template button"><?php _e( 'Delete template file', 'woocommerce' ); ?></a>
<?php if ( is_writable( $local_file ) ) : // phpcs:ignore WordPress.VIP.FileSystemWritesDisallow.file_ops_is_writable ?>
<a href="<?php echo esc_url( wp_nonce_url( remove_query_arg( array( 'move_template', 'saved' ), add_query_arg( 'delete_template', $template_type ) ), 'woocommerce_email_template_nonce', '_wc_email_nonce' ) ); ?>" class="delete_template button">
<?php esc_html_e( 'Delete template file', 'woocommerce' ); ?>
</a>
<?php endif; ?>
<?php printf( __( 'This template has been overridden by your theme and can be found in: %s.', 'woocommerce' ), '<code>' . trailingslashit( basename( get_stylesheet_directory() ) ) . $template_dir . '/' . $template . '</code>' ); ?>
<?php
/* translators: %s: Path to template file */
printf( esc_html__( 'This template has been overridden by your theme and can be found in: %s.', 'woocommerce' ), '<code>' . esc_html( trailingslashit( basename( get_stylesheet_directory() ) ) . $template_dir . '/' . $template ) . '</code>' );
?>
</p>
<div class="editor" style="display:none">
<textarea class="code" cols="25" rows="20" <?php if ( ! is_writable( $local_file ) ) : ?>readonly="readonly" disabled="disabled"<?php else : ?>data-name="<?php echo $template_type . '_code'; ?>"<?php endif; ?>><?php echo file_get_contents( $local_file ); ?></textarea>
<textarea class="code" cols="25" rows="20"
<?php
if ( ! is_writable( $local_file ) ) : // phpcs:ignore WordPress.VIP.FileSystemWritesDisallow.file_ops_is_writable
?>
readonly="readonly" disabled="disabled"
<?php else : ?>
data-name="<?php echo esc_attr( $template_type ) . '_code'; ?>"<?php endif; ?>><?php echo esc_html( file_get_contents( $local_file ) ); ?></textarea>
</div>
<?php } elseif ( file_exists( $template_file ) ) { ?>
<?php elseif ( file_exists( $template_file ) ) : ?>
<p>
<a href="#" class="button toggle_editor"></a>
<?php
$emails_dir = get_stylesheet_directory() . '/' . $template_dir . '/emails';
$templates_dir = get_stylesheet_directory() . '/' . $template_dir;
$theme_dir = get_stylesheet_directory();
$emails_dir = get_stylesheet_directory() . '/' . $template_dir . '/emails';
$templates_dir = get_stylesheet_directory() . '/' . $template_dir;
$theme_dir = get_stylesheet_directory();
if ( is_dir( $emails_dir ) ) {
$target_dir = $emails_dir;
} elseif ( is_dir( $templates_dir ) ) {
$target_dir = $templates_dir;
} else {
$target_dir = $theme_dir;
}
if ( is_dir( $emails_dir ) ) {
$target_dir = $emails_dir;
} elseif ( is_dir( $templates_dir ) ) {
$target_dir = $templates_dir;
} else {
$target_dir = $theme_dir;
}
if ( is_writable( $target_dir ) ) {
?>
<a href="<?php echo esc_url( wp_nonce_url( remove_query_arg( array( 'delete_template', 'saved' ), add_query_arg( 'move_template', $template_type ) ), 'woocommerce_email_template_nonce', '_wc_email_nonce' ) ); ?>" class="button"><?php _e( 'Copy file to theme', 'woocommerce' ); ?></a>
<?php
}
if ( is_writable( $target_dir ) ) : // phpcs:ignore WordPress.VIP.FileSystemWritesDisallow.file_ops_is_writable
?>
<a href="<?php echo esc_url( wp_nonce_url( remove_query_arg( array( 'delete_template', 'saved' ), add_query_arg( 'move_template', $template_type ) ), 'woocommerce_email_template_nonce', '_wc_email_nonce' ) ); ?>" class="button">
<?php esc_html_e( 'Copy file to theme', 'woocommerce' ); ?>
</a>
<?php endif; ?>
<?php
/* translators: 1: Path to template file 2: Path to theme folder */
printf( esc_html__( 'To override and edit this email template copy %1$s to your theme folder: %2$s.', 'woocommerce' ), '<code>' . esc_html( plugin_basename( $template_file ) ) . '</code>', '<code>' . esc_html( trailingslashit( basename( get_stylesheet_directory() ) ) . $template_dir . '/' . $template ) . '</code>' );
?>
<?php printf( __( 'To override and edit this email template copy %1$s to your theme folder: %2$s.', 'woocommerce' ), '<code>' . plugin_basename( $template_file ) . '</code>', '<code>' . trailingslashit( basename( get_stylesheet_directory() ) ) . $template_dir . '/' . $template . '</code>' ); ?>
</p>
<div class="editor" style="display:none">
<textarea class="code" readonly="readonly" disabled="disabled" cols="25" rows="20"><?php echo file_get_contents( $template_file ); ?></textarea>
<textarea class="code" readonly="readonly" disabled="disabled" cols="25" rows="20"><?php echo esc_html( file_get_contents( $template_file ) ); ?></textarea>
</div>
<?php } else { ?>
<p><?php _e( 'File was not found.', 'woocommerce' ); ?></p>
<?php } ?>
<?php else : ?>
<p><?php esc_html_e( 'File was not found.', 'woocommerce' ); ?></p>
<?php endif; ?>
</div>
<?php
endforeach;
?>
<?php endforeach; ?>
</div>
<?php
wc_enqueue_js( "
jQuery( 'select.email_type' ).change( function() {
wc_enqueue_js(
"jQuery( 'select.email_type' ).change( function() {
var val = jQuery( this ).val();
@ -944,8 +995,8 @@ class WC_Email extends WC_Settings_API {
if ( name ) {
jQuery( this ).attr( 'name', name );
}
});
" );
});"
);
}
}
}

View File

@ -7,6 +7,7 @@
* @package WooCommerce/Export
* @version 3.1.0
*/
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
@ -15,7 +16,7 @@ if ( ! defined( 'ABSPATH' ) ) {
* Include dependencies.
*/
if ( ! class_exists( 'WC_CSV_Exporter', false ) ) {
include_once( WC_ABSPATH . 'includes/export/abstract-wc-csv-exporter.php' );
require_once WC_ABSPATH . 'includes/export/abstract-wc-csv-exporter.php';
}
/**
@ -55,11 +56,11 @@ abstract class WC_CSV_Batch_Exporter extends WC_CSV_Exporter {
*/
public function get_file() {
$file = '';
if ( @file_exists( $this->get_file_path() ) ) {
$file = @file_get_contents( $this->get_file_path() );
if ( @file_exists( $this->get_file_path() ) ) { // phpcs:ignore Generic.PHP.NoSilencedErrors.Discouraged
$file = @file_get_contents( $this->get_file_path() ); // phpcs:ignore Generic.PHP.NoSilencedErrors.Discouraged, WordPress.WP.AlternativeFunctions.file_get_contents_file_get_contents, WordPress.WP.AlternativeFunctions.file_system_read_file_get_contents
} else {
@file_put_contents( $this->get_file_path(), '' );
@chmod( $this->get_file_path(), 0664 );
@file_put_contents( $this->get_file_path(), '' ); // phpcs:ignore WordPress.VIP.FileSystemWritesDisallow.file_ops_file_put_contents, Generic.PHP.NoSilencedErrors.Discouraged, WordPress.WP.AlternativeFunctions.file_system_read_file_put_contents
@chmod( $this->get_file_path(), 0664 ); // phpcs:ignore WordPress.VIP.FileSystemWritesDisallow.chmod_chmod, WordPress.WP.AlternativeFunctions.file_system_read_file_put_contents, Generic.PHP.NoSilencedErrors.Discouraged
}
return $file;
}
@ -72,7 +73,7 @@ abstract class WC_CSV_Batch_Exporter extends WC_CSV_Exporter {
public function export() {
$this->send_headers();
$this->send_content( $this->get_file() );
@unlink( $this->get_file_path() );
@unlink( $this->get_file_path() ); // phpcs:ignore WordPress.VIP.FileSystemWritesDisallow.file_ops_unlink, Generic.PHP.NoSilencedErrors.Discouraged
die();
}
@ -83,7 +84,7 @@ abstract class WC_CSV_Batch_Exporter extends WC_CSV_Exporter {
*/
public function generate_file() {
if ( 1 === $this->get_page() ) {
@unlink( $this->get_file_path() );
@unlink( $this->get_file_path() ); // phpcs:ignore WordPress.VIP.FileSystemWritesDisallow.file_ops_unlink, Generic.PHP.NoSilencedErrors.Discouraged,
}
$this->prepare_data_to_export();
$this->write_csv_data( $this->get_csv_data() );
@ -93,7 +94,7 @@ abstract class WC_CSV_Batch_Exporter extends WC_CSV_Exporter {
* Write data to the file.
*
* @since 3.1.0
* @param string $data
* @param string $data Data.
*/
protected function write_csv_data( $data ) {
$file = $this->get_file();
@ -104,7 +105,7 @@ abstract class WC_CSV_Batch_Exporter extends WC_CSV_Exporter {
}
$file .= $data;
@file_put_contents( $this->get_file_path(), $file );
@file_put_contents( $this->get_file_path(), $file ); // phpcs:ignore WordPress.VIP.FileSystemWritesDisallow.file_ops_file_put_contents, Generic.PHP.NoSilencedErrors.Discouraged, WordPress.WP.AlternativeFunctions.file_system_read_file_put_contents
}
/**
@ -121,7 +122,7 @@ abstract class WC_CSV_Batch_Exporter extends WC_CSV_Exporter {
* Set page.
*
* @since 3.1.0
* @param int $page
* @param int $page Page Nr.
*/
public function set_page( $page ) {
$this->page = absint( $page );

View File

@ -74,7 +74,7 @@ abstract class WC_CSV_Exporter {
/**
* Prepare data that will be exported.
*/
abstract function prepare_data_to_export();
abstract public function prepare_data_to_export();
/**
* Return an array of supported column names and ids.
@ -171,7 +171,7 @@ abstract class WC_CSV_Exporter {
*/
public function send_headers() {
if ( function_exists( 'gc_enable' ) ) {
gc_enable();
gc_enable(); // phpcs:ignore PHPCompatibility.PHP.NewFunctions.gc_enableFound
}
if ( function_exists( 'apache_setenv' ) ) {
@apache_setenv( 'no-gzip', 1 ); // @codingStandardsIgnoreLine
@ -192,7 +192,6 @@ abstract class WC_CSV_Exporter {
* Set filename to export to.
*
* @param string $filename Filename to export to.
* @return string
*/
public function set_filename( $filename ) {
$this->filename = sanitize_file_name( str_replace( '.csv', '', $filename ) . '.csv' );
@ -236,7 +235,7 @@ abstract class WC_CSV_Exporter {
protected function export_column_headers() {
$columns = $this->get_column_names();
$export_row = array();
$buffer = fopen( 'php://output', 'w' );
$buffer = fopen( 'php://output', 'w' ); // phpcs:ignore WordPress.WP.AlternativeFunctions.file_system_read_fopen
ob_start();
foreach ( $columns as $column_id => $column_name ) {
@ -269,7 +268,7 @@ abstract class WC_CSV_Exporter {
*/
protected function export_rows() {
$data = $this->get_data_to_export();
$buffer = fopen( 'php://output', 'w' );
$buffer = fopen( 'php://output', 'w' ); // phpcs:ignore WordPress.WP.AlternativeFunctions.file_system_read_fopen
ob_start();
array_walk( $data, array( $this, 'export_row' ), $buffer );
@ -378,8 +377,8 @@ abstract class WC_CSV_Exporter {
$data = $data ? 1 : 0;
}
$use_mb = function_exists( 'mb_convert_encoding' );
$data = (string) urldecode( $data );
$use_mb = function_exists( 'mb_convert_encoding' );
$data = (string) urldecode( $data );
if ( $use_mb ) {
$encoding = mb_detect_encoding( $data, 'UTF-8, ISO-8859-1', true );
@ -448,7 +447,7 @@ abstract class WC_CSV_Exporter {
* @return string
*/
protected function implode_values( $values ) {
$values_to_implode = array();
$values_to_implode = array();
foreach ( $values as $value ) {
$value = (string) is_scalar( $value ) ? $value : '';

View File

@ -1,7 +1,12 @@
<?php
/**
* Class WC_Gateway_BACS file.
*
* @package WooCommerce\Gateways
*/
if ( ! defined( 'ABSPATH' ) ) {
exit; // Exit if accessed directly
exit; // Exit if accessed directly.
}
/**
@ -13,11 +18,14 @@ if ( ! defined( 'ABSPATH' ) ) {
* @extends WC_Payment_Gateway
* @version 2.1.0
* @package WooCommerce/Classes/Payment
* @author WooThemes
*/
class WC_Gateway_BACS extends WC_Payment_Gateway {
/** @var array Array of locales */
/**
* Array of locales
*
* @var array
*/
public $locale;
/**
@ -35,13 +43,14 @@ class WC_Gateway_BACS extends WC_Payment_Gateway {
$this->init_form_fields();
$this->init_settings();
// Define user set variables
// Define user set variables.
$this->title = $this->get_option( 'title' );
$this->description = $this->get_option( 'description' );
$this->instructions = $this->get_option( 'instructions' );
// BACS account fields shown on the thanks page and in emails
$this->account_details = get_option( 'woocommerce_bacs_accounts',
// BACS account fields shown on the thanks page and in emails.
$this->account_details = get_option(
'woocommerce_bacs_accounts',
array(
array(
'account_name' => $this->get_option( 'account_name' ),
@ -54,12 +63,12 @@ class WC_Gateway_BACS extends WC_Payment_Gateway {
)
);
// Actions
// Actions.
add_action( 'woocommerce_update_options_payment_gateways_' . $this->id, array( $this, 'process_admin_options' ) );
add_action( 'woocommerce_update_options_payment_gateways_' . $this->id, array( $this, 'save_account_details' ) );
add_action( 'woocommerce_thankyou_bacs', array( $this, 'thankyou_page' ) );
// Customer Emails
// Customer Emails.
add_action( 'woocommerce_email_before_order_table', array( $this, 'email_instructions' ), 10, 3 );
}
@ -69,27 +78,27 @@ class WC_Gateway_BACS extends WC_Payment_Gateway {
public function init_form_fields() {
$this->form_fields = array(
'enabled' => array(
'enabled' => array(
'title' => __( 'Enable/Disable', 'woocommerce' ),
'type' => 'checkbox',
'label' => __( 'Enable bank transfer', 'woocommerce' ),
'default' => 'no',
),
'title' => array(
'title' => array(
'title' => __( 'Title', 'woocommerce' ),
'type' => 'text',
'description' => __( 'This controls the title which the user sees during checkout.', 'woocommerce' ),
'default' => __( 'Direct bank transfer', 'woocommerce' ),
'desc_tip' => true,
),
'description' => array(
'description' => array(
'title' => __( 'Description', 'woocommerce' ),
'type' => 'textarea',
'description' => __( 'Payment method description that the customer will see on your checkout.', 'woocommerce' ),
'default' => __( 'Make your payment directly into our bank account. Please use your Order ID as the payment reference. Your order will not be shipped until the funds have cleared in our account.', 'woocommerce' ),
'desc_tip' => true,
),
'instructions' => array(
'instructions' => array(
'title' => __( 'Instructions', 'woocommerce' ),
'type' => 'textarea',
'description' => __( 'Instructions that will be added to the thank you page and emails.', 'woocommerce' ),
@ -97,7 +106,7 @@ class WC_Gateway_BACS extends WC_Payment_Gateway {
'desc_tip' => true,
),
'account_details' => array(
'type' => 'account_details',
'type' => 'account_details',
),
);
@ -112,27 +121,27 @@ class WC_Gateway_BACS extends WC_Payment_Gateway {
ob_start();
$country = WC()->countries->get_base_country();
$locale = $this->get_country_locale();
$country = WC()->countries->get_base_country();
$locale = $this->get_country_locale();
// Get sortcode label in the $locale array and use appropriate one
// Get sortcode label in the $locale array and use appropriate one.
$sortcode = isset( $locale[ $country ]['sortcode']['label'] ) ? $locale[ $country ]['sortcode']['label'] : __( 'Sort code', 'woocommerce' );
?>
<tr valign="top">
<th scope="row" class="titledesc"><?php _e( 'Account details', 'woocommerce' ); ?>:</th>
<th scope="row" class="titledesc"><?php esc_html_e( 'Account details:', 'woocommerce' ); ?></th>
<td class="forminp" id="bacs_accounts">
<div class="wc_input_table_wrapper">
<table class="widefat wc_input_table sortable" cellspacing="0">
<thead>
<tr>
<th class="sort">&nbsp;</th>
<th><?php _e( 'Account name', 'woocommerce' ); ?></th>
<th><?php _e( 'Account number', 'woocommerce' ); ?></th>
<th><?php _e( 'Bank name', 'woocommerce' ); ?></th>
<th><?php echo $sortcode; ?></th>
<th><?php _e( 'IBAN', 'woocommerce' ); ?></th>
<th><?php _e( 'BIC / Swift', 'woocommerce' ); ?></th>
<th><?php esc_html_e( 'Account name', 'woocommerce' ); ?></th>
<th><?php esc_html_e( 'Account number', 'woocommerce' ); ?></th>
<th><?php esc_html_e( 'Bank name', 'woocommerce' ); ?></th>
<th><?php echo esc_html( $sortcode ); ?></th>
<th><?php esc_html_e( 'IBAN', 'woocommerce' ); ?></th>
<th><?php esc_html_e( 'BIC / Swift', 'woocommerce' ); ?></th>
</tr>
</thead>
<tbody class="accounts">
@ -144,12 +153,12 @@ class WC_Gateway_BACS extends WC_Payment_Gateway {
echo '<tr class="account">
<td class="sort"></td>
<td><input type="text" value="' . esc_attr( wp_unslash( $account['account_name'] ) ) . '" name="bacs_account_name[' . $i . ']" /></td>
<td><input type="text" value="' . esc_attr( $account['account_number'] ) . '" name="bacs_account_number[' . $i . ']" /></td>
<td><input type="text" value="' . esc_attr( wp_unslash( $account['bank_name'] ) ) . '" name="bacs_bank_name[' . $i . ']" /></td>
<td><input type="text" value="' . esc_attr( $account['sort_code'] ) . '" name="bacs_sort_code[' . $i . ']" /></td>
<td><input type="text" value="' . esc_attr( $account['iban'] ) . '" name="bacs_iban[' . $i . ']" /></td>
<td><input type="text" value="' . esc_attr( $account['bic'] ) . '" name="bacs_bic[' . $i . ']" /></td>
<td><input type="text" value="' . esc_attr( wp_unslash( $account['account_name'] ) ) . '" name="bacs_account_name[' . esc_attr( $i ) . ']" /></td>
<td><input type="text" value="' . esc_attr( $account['account_number'] ) . '" name="bacs_account_number[' . esc_attr( $i ) . ']" /></td>
<td><input type="text" value="' . esc_attr( wp_unslash( $account['bank_name'] ) ) . '" name="bacs_bank_name[' . esc_attr( $i ) . ']" /></td>
<td><input type="text" value="' . esc_attr( $account['sort_code'] ) . '" name="bacs_sort_code[' . esc_attr( $i ) . ']" /></td>
<td><input type="text" value="' . esc_attr( $account['iban'] ) . '" name="bacs_iban[' . esc_attr( $i ) . ']" /></td>
<td><input type="text" value="' . esc_attr( $account['bic'] ) . '" name="bacs_bic[' . esc_attr( $i ) . ']" /></td>
</tr>';
}
}
@ -157,7 +166,7 @@ class WC_Gateway_BACS extends WC_Payment_Gateway {
</tbody>
<tfoot>
<tr>
<th colspan="7"><a href="#" class="add button"><?php _e( '+ Add account', 'woocommerce' ); ?></a> <a href="#" class="remove_rows button"><?php _e( 'Remove selected account(s)', 'woocommerce' ); ?></a></th>
<th colspan="7"><a href="#" class="add button"><?php esc_html_e( '+ Add account', 'woocommerce' ); ?></a> <a href="#" class="remove_rows button"><?php esc_html_e( 'Remove selected account(s)', 'woocommerce' ); ?></a></th>
</tr>
</tfoot>
</table>
@ -196,14 +205,16 @@ class WC_Gateway_BACS extends WC_Payment_Gateway {
$accounts = array();
if ( isset( $_POST['bacs_account_name'] ) ) {
// phpcs:disable WordPress.CSRF.NonceVerification.NoNonceVerification -- Nonce verification already handled in WC_Admin_Settings::save()
if ( isset( $_POST['bacs_account_name'] ) && isset( $_POST['bacs_account_number'] ) && isset( $_POST['bacs_bank_name'] )
&& isset( $_POST['bacs_sort_code'] ) && isset( $_POST['bacs_iban'] ) && isset( $_POST['bacs_bic'] ) ) {
$account_names = array_map( 'wc_clean', $_POST['bacs_account_name'] );
$account_numbers = array_map( 'wc_clean', $_POST['bacs_account_number'] );
$bank_names = array_map( 'wc_clean', $_POST['bacs_bank_name'] );
$sort_codes = array_map( 'wc_clean', $_POST['bacs_sort_code'] );
$ibans = array_map( 'wc_clean', $_POST['bacs_iban'] );
$bics = array_map( 'wc_clean', $_POST['bacs_bic'] );
$account_names = wc_clean( wp_unslash( $_POST['bacs_account_name'] ) );
$account_numbers = wc_clean( wp_unslash( $_POST['bacs_account_number'] ) );
$bank_names = wc_clean( wp_unslash( $_POST['bacs_bank_name'] ) );
$sort_codes = wc_clean( wp_unslash( $_POST['bacs_sort_code'] ) );
$ibans = wc_clean( wp_unslash( $_POST['bacs_iban'] ) );
$bics = wc_clean( wp_unslash( $_POST['bacs_bic'] ) );
foreach ( $account_names as $i => $name ) {
if ( ! isset( $account_names[ $i ] ) ) {
@ -220,20 +231,20 @@ class WC_Gateway_BACS extends WC_Payment_Gateway {
);
}
}
// phpcs:enable
update_option( 'woocommerce_bacs_accounts', $accounts );
}
/**
* Output for the order received page.
*
* @param int $order_id
* @param int $order_id Order ID.
*/
public function thankyou_page( $order_id ) {
if ( $this->instructions ) {
echo wpautop( wptexturize( wp_kses_post( $this->instructions ) ) );
echo wp_kses_post( wpautop( wptexturize( wp_kses_post( $this->instructions ) ) ) );
}
$this->bank_details( $order_id );
@ -242,15 +253,15 @@ class WC_Gateway_BACS extends WC_Payment_Gateway {
/**
* Add content to the WC emails.
*
* @param WC_Order $order
* @param bool $sent_to_admin
* @param bool $plain_text
* @param WC_Order $order Order object.
* @param bool $sent_to_admin Sent to admin.
* @param bool $plain_text Email format: plain text or HTML.
*/
public function email_instructions( $order, $sent_to_admin, $plain_text = false ) {
if ( ! $sent_to_admin && 'bacs' === $order->get_payment_method() && $order->has_status( 'on-hold' ) ) {
if ( $this->instructions ) {
echo wpautop( wptexturize( $this->instructions ) ) . PHP_EOL;
echo wp_kses_post( wpautop( wptexturize( $this->instructions ) ) . PHP_EOL );
}
$this->bank_details( $order->get_id() );
}
@ -260,7 +271,7 @@ class WC_Gateway_BACS extends WC_Payment_Gateway {
/**
* Get bank details and place into a list format.
*
* @param int $order_id
* @param int $order_id Order ID.
*/
private function bank_details( $order_id = '' ) {
@ -268,14 +279,14 @@ class WC_Gateway_BACS extends WC_Payment_Gateway {
return;
}
// Get order and store in $order
$order = wc_get_order( $order_id );
// Get order and store in $order.
$order = wc_get_order( $order_id );
// Get the order country and country $locale
$country = $order->get_billing_country();
$locale = $this->get_country_locale();
// Get the order country and country $locale.
$country = $order->get_billing_country();
$locale = $this->get_country_locale();
// Get sortcode label in the $locale array and use appropriate one
// Get sortcode label in the $locale array and use appropriate one.
$sortcode = isset( $locale[ $country ]['sortcode']['label'] ) ? $locale[ $country ]['sortcode']['label'] : __( 'Sort code', 'woocommerce' );
$bacs_accounts = apply_filters( 'woocommerce_bacs_accounts', $this->account_details );
@ -293,29 +304,31 @@ class WC_Gateway_BACS extends WC_Payment_Gateway {
$account_html .= '<ul class="wc-bacs-bank-details order_details bacs_details">' . PHP_EOL;
// BACS account fields shown on the thanks page and in emails
$account_fields = apply_filters( 'woocommerce_bacs_account_fields', array(
'bank_name' => array(
'label' => __( 'Bank', 'woocommerce' ),
'value' => $bacs_account->bank_name,
),
'account_number' => array(
'label' => __( 'Account number', 'woocommerce' ),
'value' => $bacs_account->account_number,
),
'sort_code' => array(
'label' => $sortcode,
'value' => $bacs_account->sort_code,
),
'iban' => array(
'label' => __( 'IBAN', 'woocommerce' ),
'value' => $bacs_account->iban,
),
'bic' => array(
'label' => __( 'BIC', 'woocommerce' ),
'value' => $bacs_account->bic,
),
), $order_id );
// BACS account fields shown on the thanks page and in emails.
$account_fields = apply_filters(
'woocommerce_bacs_account_fields', array(
'bank_name' => array(
'label' => __( 'Bank', 'woocommerce' ),
'value' => $bacs_account->bank_name,
),
'account_number' => array(
'label' => __( 'Account number', 'woocommerce' ),
'value' => $bacs_account->account_number,
),
'sort_code' => array(
'label' => $sortcode,
'value' => $bacs_account->sort_code,
),
'iban' => array(
'label' => __( 'IBAN', 'woocommerce' ),
'value' => $bacs_account->iban,
),
'bic' => array(
'label' => __( 'BIC', 'woocommerce' ),
'value' => $bacs_account->bic,
),
), $order_id
);
foreach ( $account_fields as $field_key => $field ) {
if ( ! empty( $field['value'] ) ) {
@ -328,7 +341,7 @@ class WC_Gateway_BACS extends WC_Payment_Gateway {
}
if ( $has_details ) {
echo '<section class="woocommerce-bacs-bank-details"><h2 class="wc-bacs-bank-details-heading">' . __( 'Our bank details', 'woocommerce' ) . '</h2>' . PHP_EOL . $account_html . '</section>';
echo '<section class="woocommerce-bacs-bank-details"><h2 class="wc-bacs-bank-details-heading">' . esc_html__( 'Our bank details', 'woocommerce' ) . '</h2>' . wp_kses_post( PHP_EOL . $account_html ) . '</section>';
}
}
@ -337,7 +350,7 @@ class WC_Gateway_BACS extends WC_Payment_Gateway {
/**
* Process the payment and return the result.
*
* @param int $order_id
* @param int $order_id Order ID.
* @return array
*/
public function process_payment( $order_id ) {
@ -345,22 +358,22 @@ class WC_Gateway_BACS extends WC_Payment_Gateway {
$order = wc_get_order( $order_id );
if ( $order->get_total() > 0 ) {
// Mark as on-hold (we're awaiting the payment)
$order->update_status( 'on-hold', __( 'Awaiting BACS payment', 'woocommerce' ) );
// Mark as on-hold (we're awaiting the payment).
$order->update_status( apply_filters( 'woocommerce_bacs_process_payment_order_status', 'on-hold', $order ), __( 'Awaiting BACS payment', 'woocommerce' ) );
} else {
$order->payment_complete();
}
// Reduce stock levels
// Reduce stock levels.
wc_reduce_stock_levels( $order_id );
// Remove cart
// Remove cart.
WC()->cart->empty_cart();
// Return thankyou redirect
// Return thankyou redirect.
return array(
'result' => 'success',
'redirect' => $this->get_return_url( $order ),
'result' => 'success',
'redirect' => $this->get_return_url( $order ),
);
}
@ -374,49 +387,51 @@ class WC_Gateway_BACS extends WC_Payment_Gateway {
if ( empty( $this->locale ) ) {
// Locale information to be used - only those that are not 'Sort Code'
$this->locale = apply_filters( 'woocommerce_get_bacs_locale', array(
'AU' => array(
'sortcode' => array(
'label' => __( 'BSB', 'woocommerce' ),
// Locale information to be used - only those that are not 'Sort Code'.
$this->locale = apply_filters(
'woocommerce_get_bacs_locale', array(
'AU' => array(
'sortcode' => array(
'label' => __( 'BSB', 'woocommerce' ),
),
),
),
'CA' => array(
'sortcode' => array(
'label' => __( 'Bank transit number', 'woocommerce' ),
'CA' => array(
'sortcode' => array(
'label' => __( 'Bank transit number', 'woocommerce' ),
),
),
),
'IN' => array(
'sortcode' => array(
'label' => __( 'IFSC', 'woocommerce' ),
'IN' => array(
'sortcode' => array(
'label' => __( 'IFSC', 'woocommerce' ),
),
),
),
'IT' => array(
'sortcode' => array(
'label' => __( 'Branch sort', 'woocommerce' ),
'IT' => array(
'sortcode' => array(
'label' => __( 'Branch sort', 'woocommerce' ),
),
),
),
'NZ' => array(
'sortcode' => array(
'label' => __( 'Bank code', 'woocommerce' ),
'NZ' => array(
'sortcode' => array(
'label' => __( 'Bank code', 'woocommerce' ),
),
),
),
'SE' => array(
'sortcode' => array(
'label' => __( 'Bank code', 'woocommerce' ),
'SE' => array(
'sortcode' => array(
'label' => __( 'Bank code', 'woocommerce' ),
),
),
),
'US' => array(
'sortcode' => array(
'label' => __( 'Routing number', 'woocommerce' ),
'US' => array(
'sortcode' => array(
'label' => __( 'Routing number', 'woocommerce' ),
),
),
),
'ZA' => array(
'sortcode' => array(
'label' => __( 'Branch code', 'woocommerce' ),
'ZA' => array(
'sortcode' => array(
'label' => __( 'Branch code', 'woocommerce' ),
),
),
),
) );
)
);
}

View File

@ -1,7 +1,12 @@
<?php
/**
* Class WC_Gateway_Cheque file.
*
* @package WooCommerce\Gateways
*/
if ( ! defined( 'ABSPATH' ) ) {
exit; // Exit if accessed directly
exit; // Exit if accessed directly.
}
/**
@ -9,11 +14,10 @@ if ( ! defined( 'ABSPATH' ) ) {
*
* Provides a Cheque Payment Gateway, mainly for testing purposes.
*
* @class WC_Gateway_Cheque
* @extends WC_Payment_Gateway
* @version 2.1.0
* @package WooCommerce/Classes/Payment
* @author WooThemes
* @class WC_Gateway_Cheque
* @extends WC_Payment_Gateway
* @version 2.1.0
* @package WooCommerce/Classes/Payment
*/
class WC_Gateway_Cheque extends WC_Payment_Gateway {
@ -31,16 +35,16 @@ class WC_Gateway_Cheque extends WC_Payment_Gateway {
$this->init_form_fields();
$this->init_settings();
// Define user set variables
// Define user set variables.
$this->title = $this->get_option( 'title' );
$this->description = $this->get_option( 'description' );
$this->instructions = $this->get_option( 'instructions' );
// Actions
// Actions.
add_action( 'woocommerce_update_options_payment_gateways_' . $this->id, array( $this, 'process_admin_options' ) );
add_action( 'woocommerce_thankyou_cheque', array( $this, 'thankyou_page' ) );
// Customer Emails
// Customer Emails.
add_action( 'woocommerce_email_before_order_table', array( $this, 'email_instructions' ), 10, 3 );
}
@ -50,20 +54,20 @@ class WC_Gateway_Cheque extends WC_Payment_Gateway {
public function init_form_fields() {
$this->form_fields = array(
'enabled' => array(
'enabled' => array(
'title' => __( 'Enable/Disable', 'woocommerce' ),
'type' => 'checkbox',
'label' => __( 'Enable check payments', 'woocommerce' ),
'default' => 'no',
),
'title' => array(
'title' => array(
'title' => __( 'Title', 'woocommerce' ),
'type' => 'text',
'description' => __( 'This controls the title which the user sees during checkout.', 'woocommerce' ),
'default' => _x( 'Check payments', 'Check payment method', 'woocommerce' ),
'desc_tip' => true,
),
'description' => array(
'description' => array(
'title' => __( 'Description', 'woocommerce' ),
'type' => 'textarea',
'description' => __( 'Payment method description that the customer will see on your checkout.', 'woocommerce' ),
@ -85,7 +89,7 @@ class WC_Gateway_Cheque extends WC_Payment_Gateway {
*/
public function thankyou_page() {
if ( $this->instructions ) {
echo wpautop( wptexturize( $this->instructions ) );
echo wp_kses_post( wpautop( wptexturize( $this->instructions ) ) );
}
}
@ -93,20 +97,20 @@ class WC_Gateway_Cheque extends WC_Payment_Gateway {
* Add content to the WC emails.
*
* @access public
* @param WC_Order $order
* @param bool $sent_to_admin
* @param bool $plain_text
* @param WC_Order $order Order object.
* @param bool $sent_to_admin Sent to admin.
* @param bool $plain_text Email format: plain text or HTML.
*/
public function email_instructions( $order, $sent_to_admin, $plain_text = false ) {
if ( $this->instructions && ! $sent_to_admin && 'cheque' === $order->get_payment_method() && $order->has_status( 'on-hold' ) ) {
echo wpautop( wptexturize( $this->instructions ) ) . PHP_EOL;
echo wp_kses_post( wpautop( wptexturize( $this->instructions ) ) . PHP_EOL );
}
}
/**
* Process the payment and return the result.
*
* @param int $order_id
* @param int $order_id Order ID.
* @return array
*/
public function process_payment( $order_id ) {
@ -114,22 +118,22 @@ class WC_Gateway_Cheque extends WC_Payment_Gateway {
$order = wc_get_order( $order_id );
if ( $order->get_total() > 0 ) {
// Mark as on-hold (we're awaiting the cheque)
// 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
// Reduce stock levels.
wc_reduce_stock_levels( $order_id );
// Remove cart
// Remove cart.
WC()->cart->empty_cart();
// Return thankyou redirect
// Return thankyou redirect.
return array(
'result' => 'success',
'redirect' => $this->get_return_url( $order ),
'result' => 'success',
'redirect' => $this->get_return_url( $order ),
);
}
}

View File

@ -1,4 +1,10 @@
<?php
/**
* Class WC_Payment_Gateway_CC file.
*
* @package WooCommerce\Gateways
*/
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
@ -7,14 +13,14 @@ if ( ! defined( 'ABSPATH' ) ) {
* Credit Card Payment Gateway
*
* @since 2.6.0
* @package WooCommerce/Classes
* @author WooThemes
* @package WooCommerce/Classes
*/
class WC_Payment_Gateway_CC extends WC_Payment_Gateway {
/**
* Builds our payment fields area - including tokenization fields for logged
* in users, and the actual payment fields.
*
* @since 2.6.0
*/
public function payment_fields() {
@ -34,7 +40,7 @@ class WC_Payment_Gateway_CC extends WC_Payment_Gateway {
* Gateways which support tokenization do not require names - we don't want the data to post to the server.
*
* @since 2.6.0
* @param string $name
* @param string $name Field name.
* @return string
*/
public function field_name( $name ) {
@ -43,6 +49,7 @@ class WC_Payment_Gateway_CC extends WC_Payment_Gateway {
/**
* Outputs fields for entering credit card information.
*
* @since 2.6.0
*/
public function form() {
@ -76,9 +83,9 @@ class WC_Payment_Gateway_CC extends WC_Payment_Gateway {
<fieldset id="wc-<?php echo esc_attr( $this->id ); ?>-cc-form" class='wc-credit-card-form wc-payment-form'>
<?php do_action( 'woocommerce_credit_card_form_start', $this->id ); ?>
<?php
foreach ( $fields as $field ) {
echo $field;
}
foreach ( $fields as $field ) {
echo $field; // phpcs:ignore WordPress.XSS.EscapeOutput.OutputNotEscaped
}
?>
<?php do_action( 'woocommerce_credit_card_form_end', $this->id ); ?>
<div class="clear"></div>
@ -86,7 +93,7 @@ class WC_Payment_Gateway_CC extends WC_Payment_Gateway {
<?php
if ( $this->supports( 'credit_card_form_cvc_on_saved_method' ) ) {
echo '<fieldset>' . $cvc_field . '</fieldset>';
echo '<fieldset>' . $cvc_field . '</fieldset>'; // phpcs:ignore WordPress.XSS.EscapeOutput.OutputNotEscaped
}
}
}

View File

@ -1,20 +1,26 @@
<?php
/**
* Class WC_Payment_Gateway_eCheck file.
*
* @package WooCommerce\Gateways
*/
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
/**
* eCheck Payment Gateway
* Class for eCheck Payment Gateway
*
* @since 2.6.0
* @package WooCommerce/Classes
* @author WooThemes
* @package WooCommerce/Classes
*/
class WC_Payment_Gateway_eCheck extends WC_Payment_Gateway {
class WC_Payment_Gateway_ECheck extends WC_Payment_Gateway {
/**
* Builds our payment fields area - including tokenization fields for logged
* in users, and the actual payment fields.
*
* @since 2.6.0
*/
public function payment_fields() {
@ -30,6 +36,7 @@ class WC_Payment_Gateway_eCheck extends WC_Payment_Gateway {
/**
* Outputs fields for entering eCheck information.
*
* @since 2.6.0
*/
public function form() {
@ -52,12 +59,13 @@ class WC_Payment_Gateway_eCheck extends WC_Payment_Gateway {
<fieldset id="<?php echo esc_attr( $this->id ); ?>-cc-form" class='wc-echeck-form wc-payment-form'>
<?php do_action( 'woocommerce_echeck_form_start', $this->id ); ?>
<?php
foreach ( $fields as $field ) {
echo $field;
}
foreach ( $fields as $field ) {
echo $field; // phpcs:ignore WordPress.XSS.EscapeOutput.OutputNotEscaped
}
?>
<?php do_action( 'woocommerce_echeck_form_end', $this->id ); ?>
<div class="clear"></div>
</fieldset><?php
</fieldset>
<?php
}
}

View File

@ -1,7 +1,12 @@
<?php
/**
* Class WC_Gateway_COD file.
*
* @package WooCommerce\Gateways
*/
if ( ! defined( 'ABSPATH' ) ) {
exit; // Exit if accessed directly
exit; // Exit if accessed directly.
}
/**
@ -9,11 +14,10 @@ if ( ! defined( 'ABSPATH' ) ) {
*
* Provides a Cash on Delivery Payment Gateway.
*
* @class WC_Gateway_COD
* @extends WC_Payment_Gateway
* @version 2.1.0
* @package WooCommerce/Classes/Payment
* @author WooThemes
* @class WC_Gateway_COD
* @extends WC_Payment_Gateway
* @version 2.1.0
* @package WooCommerce/Classes/Payment
*/
class WC_Gateway_COD extends WC_Payment_Gateway {
@ -21,14 +25,14 @@ class WC_Gateway_COD extends WC_Payment_Gateway {
* Constructor for the gateway.
*/
public function __construct() {
// Setup general properties
// Setup general properties.
$this->setup_properties();
// Load the settings
// Load the settings.
$this->init_form_fields();
$this->init_settings();
// Get settings
// Get settings.
$this->title = $this->get_option( 'title' );
$this->description = $this->get_option( 'description' );
$this->instructions = $this->get_option( 'instructions' );
@ -39,7 +43,7 @@ class WC_Gateway_COD extends WC_Payment_Gateway {
add_action( 'woocommerce_thankyou_' . $this->id, array( $this, 'thankyou_page' ) );
add_filter( 'woocommerce_payment_complete_order_status', array( $this, 'change_payment_complete_order_status' ), 10, 3 );
// Customer Emails
// Customer Emails.
add_action( 'woocommerce_email_before_order_table', array( $this, 'email_instructions' ), 10, 3 );
}
@ -65,28 +69,28 @@ class WC_Gateway_COD extends WC_Payment_Gateway {
}
$this->form_fields = array(
'enabled' => array(
'enabled' => array(
'title' => __( 'Enable/Disable', 'woocommerce' ),
'label' => __( 'Enable cash on delivery', 'woocommerce' ),
'type' => 'checkbox',
'description' => '',
'default' => 'no',
),
'title' => array(
'title' => array(
'title' => __( 'Title', 'woocommerce' ),
'type' => 'text',
'description' => __( 'Payment method description that the customer will see on your checkout.', 'woocommerce' ),
'default' => __( 'Cash on delivery', 'woocommerce' ),
'desc_tip' => true,
),
'description' => array(
'description' => array(
'title' => __( 'Description', 'woocommerce' ),
'type' => 'textarea',
'description' => __( 'Payment method description that the customer will see on your website.', 'woocommerce' ),
'default' => __( 'Pay with cash upon delivery.', 'woocommerce' ),
'desc_tip' => true,
),
'instructions' => array(
'instructions' => array(
'title' => __( 'Instructions', 'woocommerce' ),
'type' => 'textarea',
'description' => __( 'Instructions that will be added to the thank you page.', 'woocommerce' ),
@ -107,12 +111,12 @@ class WC_Gateway_COD extends WC_Payment_Gateway {
),
),
'enable_for_virtual' => array(
'title' => __( 'Accept for virtual orders', 'woocommerce' ),
'label' => __( 'Accept COD if the order is virtual', 'woocommerce' ),
'type' => 'checkbox',
'default' => 'yes',
'title' => __( 'Accept for virtual orders', 'woocommerce' ),
'label' => __( 'Accept COD if the order is virtual', 'woocommerce' ),
'type' => 'checkbox',
'default' => 'yes',
),
);
);
}
/**
@ -124,7 +128,7 @@ class WC_Gateway_COD extends WC_Payment_Gateway {
$order = null;
$needs_shipping = false;
// Test if shipping is needed first
// Test if shipping is needed first.
if ( WC()->cart && WC()->cart->needs_shipping() ) {
$needs_shipping = true;
} elseif ( is_page( wc_get_page_id( 'checkout' ) ) && 0 < get_query_var( 'order-pay' ) ) {
@ -132,7 +136,7 @@ class WC_Gateway_COD extends WC_Payment_Gateway {
$order = wc_get_order( $order_id );
// Test if order needs shipping.
if ( 0 < sizeof( $order->get_items() ) ) {
if ( 0 < count( $order->get_items() ) ) {
foreach ( $order->get_items() as $item ) {
$_product = $item->get_product();
if ( $_product && $_product->needs_shipping() ) {
@ -145,18 +149,19 @@ class WC_Gateway_COD extends WC_Payment_Gateway {
$needs_shipping = apply_filters( 'woocommerce_cart_needs_shipping', $needs_shipping );
// Virtual order, with virtual disabled
// Virtual order, with virtual disabled.
if ( ! $this->enable_for_virtual && ! $needs_shipping ) {
return false;
}
// Only apply if all packages are being shipped via chosen method, or order is virtual.
if ( ! empty( $this->enable_for_methods ) && $needs_shipping ) {
$chosen_shipping_methods = array();
$chosen_shipping_methods = array();
$chosen_shipping_methods_session = WC()->session->get( 'chosen_shipping_methods' );
if ( is_object( $order ) ) {
$chosen_shipping_methods = array_unique( array_map( 'wc_get_string_before_colon', $order->get_shipping_methods() ) );
} elseif ( $chosen_shipping_methods_session = WC()->session->get( 'chosen_shipping_methods' ) ) {
} elseif ( $chosen_shipping_methods_session ) {
$chosen_shipping_methods = array_unique( array_map( 'wc_get_string_before_colon', $chosen_shipping_methods_session ) );
}
@ -172,29 +177,29 @@ class WC_Gateway_COD extends WC_Payment_Gateway {
/**
* Process the payment and return the result.
*
* @param int $order_id
* @param int $order_id Order ID.
* @return array
*/
public function process_payment( $order_id ) {
$order = wc_get_order( $order_id );
if ( $order->get_total() > 0 ) {
// Mark as processing or on-hold (payment won't be taken until delivery)
// 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
// Reduce stock levels.
wc_reduce_stock_levels( $order_id );
// Remove cart
// Remove cart.
WC()->cart->empty_cart();
// Return thankyou redirect
// Return thankyou redirect.
return array(
'result' => 'success',
'redirect' => $this->get_return_url( $order ),
'result' => 'success',
'redirect' => $this->get_return_url( $order ),
);
}
@ -203,7 +208,7 @@ class WC_Gateway_COD extends WC_Payment_Gateway {
*/
public function thankyou_page() {
if ( $this->instructions ) {
echo wpautop( wptexturize( $this->instructions ) );
echo wp_kses_post( wpautop( wptexturize( $this->instructions ) ) );
}
}
@ -211,9 +216,9 @@ class WC_Gateway_COD extends WC_Payment_Gateway {
* Change payment complete order status to completed for COD orders.
*
* @since 3.1.0
* @param string $status
* @param int $order_id
* @param WC_Order $order
* @param string $status Current order status.
* @param int $order_id Order ID.
* @param WC_Order|false $order Order object.
* @return string
*/
public function change_payment_complete_order_status( $status, $order_id = 0, $order = false ) {
@ -227,13 +232,13 @@ class WC_Gateway_COD extends WC_Payment_Gateway {
* Add content to the WC emails.
*
* @access public
* @param WC_Order $order
* @param bool $sent_to_admin
* @param bool $plain_text
* @param WC_Order $order Order object.
* @param bool $sent_to_admin Sent to admin.
* @param bool $plain_text Email format: plain text or HTML.
*/
public function email_instructions( $order, $sent_to_admin, $plain_text = false ) {
if ( $this->instructions && ! $sent_to_admin && $this->id === $order->get_payment_method() ) {
echo wpautop( wptexturize( $this->instructions ) ) . PHP_EOL;
echo wp_kses_post( wpautop( wptexturize( $this->instructions ) ) . PHP_EOL );
}
}
}

View File

@ -4,11 +4,10 @@
*
* Provides a PayPal Standard Payment Gateway.
*
* @class WC_Gateway_Paypal
* @extends WC_Payment_Gateway
* @version 2.3.0
* @package WooCommerce/Classes/Payment
* @author WooThemes
* @class WC_Gateway_Paypal
* @extends WC_Payment_Gateway
* @version 2.3.0
* @package WooCommerce/Classes/Payment
*/
if ( ! defined( 'ABSPATH' ) ) {
@ -20,20 +19,29 @@ if ( ! defined( 'ABSPATH' ) ) {
*/
class WC_Gateway_Paypal extends WC_Payment_Gateway {
/** @var bool Whether or not logging is enabled */
/**
* Whether or not logging is enabled
*
* @var bool
*/
public static $log_enabled = false;
/** @var WC_Logger Logger instance */
/**
* Logger instance
*
* @var WC_Logger
*/
public static $log = false;
/**
* Constructor for the gateway.
*/
public function __construct() {
$this->id = 'paypal';
$this->has_fields = false;
$this->order_button_text = __( 'Proceed to PayPal', 'woocommerce' );
$this->method_title = __( 'PayPal', 'woocommerce' );
$this->id = 'paypal';
$this->has_fields = false;
$this->order_button_text = __( 'Proceed to PayPal', 'woocommerce' );
$this->method_title = __( 'PayPal', 'woocommerce' );
/* translators: %s: Link to WC system status page */
$this->method_description = sprintf( __( 'PayPal Standard sends customers to PayPal to enter their payment information. PayPal IPN requires fsockopen/cURL support to update order statuses after payment. Check the <a href="%s">system status</a> page for more details.', 'woocommerce' ), admin_url( 'admin.php?page=wc-status' ) );
$this->supports = array(
'products',
@ -53,9 +61,10 @@ class WC_Gateway_Paypal extends WC_Payment_Gateway {
$this->receiver_email = $this->get_option( 'receiver_email', $this->email );
$this->identity_token = $this->get_option( 'identity_token' );
self::$log_enabled = $this->debug;
self::$log_enabled = $this->debug;
if ( $this->testmode ) {
/* translators: %s: Link to PayPal sandbox testing guide page */
$this->description .= ' ' . sprintf( __( 'SANDBOX ENABLED. You can use sandbox testing accounts only. See the <a href="%s">PayPal Sandbox Testing Guide</a> for more details.', 'woocommerce' ), 'https://developer.paypal.com/docs/classic/lifecycle/ug_sandbox/' );
$this->description = trim( $this->description );
}
@ -68,11 +77,11 @@ class WC_Gateway_Paypal extends WC_Payment_Gateway {
if ( ! $this->is_valid_for_use() ) {
$this->enabled = 'no';
} else {
include_once( dirname( __FILE__ ) . '/includes/class-wc-gateway-paypal-ipn-handler.php' );
include_once dirname( __FILE__ ) . '/includes/class-wc-gateway-paypal-ipn-handler.php';
new WC_Gateway_Paypal_IPN_Handler( $this->testmode, $this->receiver_email );
if ( $this->identity_token ) {
include_once( dirname( __FILE__ ) . '/includes/class-wc-gateway-paypal-pdt-handler.php' );
include_once dirname( __FILE__ ) . '/includes/class-wc-gateway-paypal-pdt-handler.php';
new WC_Gateway_Paypal_PDT_Handler( $this->testmode, $this->identity_token );
}
}
@ -82,8 +91,8 @@ class WC_Gateway_Paypal extends WC_Payment_Gateway {
* Logging method.
*
* @param string $message Log message.
* @param string $level Optional. Default 'info'.
* emergency|alert|critical|error|warning|notice|info|debug
* @param string $level Optional. Default 'info'. Possible values:
* emergency|alert|critical|error|warning|notice|info|debug.
*/
public static function log( $message, $level = 'info' ) {
if ( self::$log_enabled ) {
@ -96,6 +105,7 @@ class WC_Gateway_Paypal extends WC_Payment_Gateway {
/**
* Get gateway icon.
*
* @return string
*/
public function get_icon() {
@ -113,7 +123,8 @@ class WC_Gateway_Paypal extends WC_Payment_Gateway {
/**
* Get the link for an icon based on country.
* @param string $country
*
* @param string $country Country two letter code.
* @return string
*/
protected function get_icon_url( $country ) {
@ -121,9 +132,9 @@ class WC_Gateway_Paypal extends WC_Payment_Gateway {
$home_counties = array( 'BE', 'CZ', 'DK', 'HU', 'IT', 'JP', 'NL', 'NO', 'ES', 'SE', 'TR', 'IN' );
$countries = array( 'DZ', 'AU', 'BH', 'BQ', 'BW', 'CA', 'CN', 'CW', 'FI', 'FR', 'DE', 'GR', 'HK', 'ID', 'JO', 'KE', 'KW', 'LU', 'MY', 'MA', 'OM', 'PH', 'PL', 'PT', 'QA', 'IE', 'RU', 'BL', 'SX', 'MF', 'SA', 'SG', 'SK', 'KR', 'SS', 'TW', 'TH', 'AE', 'GB', 'US', 'VN' );
if ( in_array( $country, $home_counties ) ) {
return $url . '/webapps/mpp/home';
} elseif ( in_array( $country, $countries ) ) {
if ( in_array( $country, $home_counties, true ) ) {
return $url . '/webapps/mpp/home';
} elseif ( in_array( $country, $countries, true ) ) {
return $url . '/webapps/mpp/paypal-popup';
} else {
return $url . '/cgi-bin/webscr?cmd=xpt/Marketing/general/WIPaypal-outside';
@ -138,74 +149,82 @@ class WC_Gateway_Paypal extends WC_Payment_Gateway {
*/
protected function get_icon_image( $country ) {
switch ( $country ) {
case 'US' :
case 'NZ' :
case 'CZ' :
case 'HU' :
case 'MY' :
case 'US':
case 'NZ':
case 'CZ':
case 'HU':
case 'MY':
$icon = 'https://www.paypalobjects.com/webstatic/mktg/logo/AM_mc_vs_dc_ae.jpg';
break;
case 'TR' :
break;
case 'TR':
$icon = 'https://www.paypalobjects.com/webstatic/mktg/logo-center/logo_paypal_odeme_secenekleri.jpg';
break;
case 'GB' :
break;
case 'GB':
$icon = 'https://www.paypalobjects.com/webstatic/mktg/Logo/AM_mc_vs_ms_ae_UK.png';
break;
case 'MX' :
break;
case 'MX':
$icon = array(
'https://www.paypal.com/es_XC/Marketing/i/banner/paypal_visa_mastercard_amex.png',
'https://www.paypal.com/es_XC/Marketing/i/banner/paypal_debit_card_275x60.gif',
);
break;
case 'FR' :
break;
case 'FR':
$icon = 'https://www.paypalobjects.com/webstatic/mktg/logo-center/logo_paypal_moyens_paiement_fr.jpg';
break;
case 'AU' :
break;
case 'AU':
$icon = 'https://www.paypalobjects.com/webstatic/en_AU/mktg/logo/Solutions-graphics-1-184x80.jpg';
break;
case 'DK' :
break;
case 'DK':
$icon = 'https://www.paypalobjects.com/webstatic/mktg/logo-center/logo_PayPal_betalingsmuligheder_dk.jpg';
break;
case 'RU' :
break;
case 'RU':
$icon = 'https://www.paypalobjects.com/webstatic/ru_RU/mktg/business/pages/logo-center/AM_mc_vs_dc_ae.jpg';
break;
case 'NO' :
break;
case 'NO':
$icon = 'https://www.paypalobjects.com/webstatic/mktg/logo-center/banner_pl_just_pp_319x110.jpg';
break;
case 'CA' :
break;
case 'CA':
$icon = 'https://www.paypalobjects.com/webstatic/en_CA/mktg/logo-image/AM_mc_vs_dc_ae.jpg';
break;
case 'HK' :
break;
case 'HK':
$icon = 'https://www.paypalobjects.com/webstatic/en_HK/mktg/logo/AM_mc_vs_dc_ae.jpg';
break;
case 'SG' :
break;
case 'SG':
$icon = 'https://www.paypalobjects.com/webstatic/en_SG/mktg/Logos/AM_mc_vs_dc_ae.jpg';
break;
case 'TW' :
break;
case 'TW':
$icon = 'https://www.paypalobjects.com/webstatic/en_TW/mktg/logos/AM_mc_vs_dc_ae.jpg';
break;
case 'TH' :
break;
case 'TH':
$icon = 'https://www.paypalobjects.com/webstatic/en_TH/mktg/Logos/AM_mc_vs_dc_ae.jpg';
break;
case 'JP' :
break;
case 'JP':
$icon = 'https://www.paypal.com/ja_JP/JP/i/bnr/horizontal_solution_4_jcb.gif';
break;
case 'IN' :
case 'IN':
$icon = 'https://www.paypalobjects.com/webstatic/mktg/logo/AM_mc_vs_dc_ae.jpg';
break;
default :
default:
$icon = WC_HTTPS::force_https_url( WC()->plugin_url() . '/includes/gateways/paypal/assets/images/paypal.png' );
break;
break;
}
return apply_filters( 'woocommerce_paypal_icon', $icon );
}
/**
* Check if this gateway is enabled and available in the user's country.
*
* @return bool
*/
public function is_valid_for_use() {
return in_array( get_woocommerce_currency(), apply_filters( 'woocommerce_paypal_supported_currencies', array( 'AUD', 'BRL', 'CAD', 'MXN', 'NZD', 'HKD', 'SGD', 'USD', 'EUR', 'JPY', 'TRY', 'NOK', 'CZK', 'DKK', 'HUF', 'ILS', 'MYR', 'PHP', 'PLN', 'SEK', 'CHF', 'TWD', 'THB', 'GBP', 'RMB', 'RUB', 'INR' ) ) );
return in_array(
get_woocommerce_currency(),
apply_filters(
'woocommerce_paypal_supported_currencies',
array( 'AUD', 'BRL', 'CAD', 'MXN', 'NZD', 'HKD', 'SGD', 'USD', 'EUR', 'JPY', 'TRY', 'NOK', 'CZK', 'DKK', 'HUF', 'ILS', 'MYR', 'PHP', 'PLN', 'SEK', 'CHF', 'TWD', 'THB', 'GBP', 'RMB', 'RUB', 'INR' )
),
true
);
}
/**
@ -219,7 +238,11 @@ class WC_Gateway_Paypal extends WC_Payment_Gateway {
parent::admin_options();
} else {
?>
<div class="inline error"><p><strong><?php _e( 'Gateway disabled', 'woocommerce' ); ?></strong>: <?php _e( 'PayPal does not support your store currency.', 'woocommerce' ); ?></p></div>
<div class="inline error">
<p>
<strong><?php esc_html_e( 'Gateway disabled', 'woocommerce' ); ?></strong>: <?php esc_html_e( 'PayPal does not support your store currency.', 'woocommerce' ); ?>
</p>
</div>
<?php
}
}
@ -228,12 +251,13 @@ class WC_Gateway_Paypal extends WC_Payment_Gateway {
* Initialise Gateway Settings Form Fields.
*/
public function init_form_fields() {
$this->form_fields = include( 'includes/settings-paypal.php' );
$this->form_fields = include 'includes/settings-paypal.php';
}
/**
* Get the transaction URL.
* @param WC_Order $order
*
* @param WC_Order $order Order object.
* @return string
*/
public function get_transaction_url( $order ) {
@ -247,11 +271,12 @@ class WC_Gateway_Paypal extends WC_Payment_Gateway {
/**
* Process the payment and return the result.
* @param int $order_id
*
* @param int $order_id Order ID.
* @return array
*/
public function process_payment( $order_id ) {
include_once( dirname( __FILE__ ) . '/includes/class-wc-gateway-paypal-request.php' );
include_once dirname( __FILE__ ) . '/includes/class-wc-gateway-paypal-request.php';
$order = wc_get_order( $order_id );
$paypal_request = new WC_Gateway_Paypal_Request( $this );
@ -264,7 +289,8 @@ class WC_Gateway_Paypal extends WC_Payment_Gateway {
/**
* Can the order be refunded via PayPal?
* @param WC_Order $order
*
* @param WC_Order $order Order object.
* @return bool
*/
public function can_refund_order( $order ) {
@ -275,7 +301,7 @@ class WC_Gateway_Paypal extends WC_Payment_Gateway {
* Init the API class and set the username/password etc.
*/
protected function init_api() {
include_once( dirname( __FILE__ ) . '/includes/class-wc-gateway-paypal-api-handler.php' );
include_once dirname( __FILE__ ) . '/includes/class-wc-gateway-paypal-api-handler.php';
WC_Gateway_Paypal_API_Handler::$api_username = $this->testmode ? $this->get_option( 'sandbox_api_username' ) : $this->get_option( 'api_username' );
WC_Gateway_Paypal_API_Handler::$api_password = $this->testmode ? $this->get_option( 'sandbox_api_password' ) : $this->get_option( 'api_password' );
@ -285,9 +311,10 @@ class WC_Gateway_Paypal extends WC_Payment_Gateway {
/**
* Process a refund if supported.
* @param int $order_id
* @param float $amount
* @param string $reason
*
* @param int $order_id Order ID.
* @param float $amount Refund amount.
* @param string $reason Refund reason.
* @return bool|WP_Error
*/
public function process_refund( $order_id, $amount = null, $reason = '' ) {
@ -309,21 +336,23 @@ class WC_Gateway_Paypal extends WC_Payment_Gateway {
$this->log( 'Refund Result: ' . wc_print_r( $result, true ) );
switch ( strtolower( $result->ACK ) ) {
switch ( strtolower( $result->ACK ) ) { // phpcs:ignore WordPress.NamingConventions.ValidVariableName.NotSnakeCaseMemberVar
case 'success':
case 'successwithwarning':
$order->add_order_note( sprintf( __( 'Refunded %1$s - Refund ID: %2$s', 'woocommerce' ), $result->GROSSREFUNDAMT, $result->REFUNDTRANSACTIONID ) );
$order->add_order_note(
/* translators: 1: Refund amount, 2: Refund ID */
sprintf( __( 'Refunded %1$s - Refund ID: %2$s', 'woocommerce' ), $result->GROSSREFUNDAMT, $result->REFUNDTRANSACTIONID ) // phpcs:ignore WordPress.NamingConventions.ValidVariableName.NotSnakeCaseMemberVar
);
return true;
break;
}
return isset( $result->L_LONGMESSAGE0 ) ? new WP_Error( 'error', $result->L_LONGMESSAGE0 ) : false;
return isset( $result->L_LONGMESSAGE0 ) ? new WP_Error( 'error', $result->L_LONGMESSAGE0 ) : false; // phpcs:ignore WordPress.NamingConventions.ValidVariableName.NotSnakeCaseMemberVar
}
/**
* Capture payment when the order is changed from on-hold to complete or processing
*
* @param int $order_id
* @param int $order_id Order ID.
*/
public function capture_payment( $order_id ) {
$order = wc_get_order( $order_id );
@ -334,24 +363,29 @@ class WC_Gateway_Paypal extends WC_Payment_Gateway {
if ( is_wp_error( $result ) ) {
$this->log( 'Capture Failed: ' . $result->get_error_message(), 'error' );
/* translators: %s: Paypal gateway error message */
$order->add_order_note( sprintf( __( 'Payment could not captured: %s', 'woocommerce' ), $result->get_error_message() ) );
return;
}
$this->log( 'Capture Result: ' . wc_print_r( $result, true ) );
// phpcs:disable WordPress.NamingConventions.ValidVariableName.NotSnakeCaseMemberVar
if ( ! empty( $result->PAYMENTSTATUS ) ) {
switch ( $result->PAYMENTSTATUS ) {
case 'Completed' :
case 'Completed':
/* translators: 1: Amount, 2: Authorization ID, 3: Transaction ID */
$order->add_order_note( sprintf( __( 'Payment of %1$s was captured - Auth ID: %2$s, Transaction ID: %3$s', 'woocommerce' ), $result->AMT, $result->AUTHORIZATIONID, $result->TRANSACTIONID ) );
update_post_meta( $order->get_id(), '_paypal_status', $result->PAYMENTSTATUS );
update_post_meta( $order->get_id(), '_transaction_id', $result->TRANSACTIONID );
break;
default :
break;
default:
/* translators: 1: Authorization ID, 2: Payment status */
$order->add_order_note( sprintf( __( 'Payment could not captured - Auth ID: %1$s, Status: %2$s', 'woocommerce' ), $result->AUTHORIZATIONID, $result->PAYMENTSTATUS ) );
break;
break;
}
}
// phpcs:enable
}
}
@ -362,7 +396,7 @@ class WC_Gateway_Paypal extends WC_Payment_Gateway {
*/
public function admin_scripts() {
$screen = get_current_screen();
$screen_id = $screen ? $screen->id: '';
$screen_id = $screen ? $screen->id : '';
if ( 'woocommerce_page_wc-settings' !== $screen_id ) {
return;

View File

@ -1,4 +1,9 @@
<?php
/**
* Class WC_Gateway_Paypal_API_Handler file.
*
* @package WooCommerce\Gateways
*/
if ( ! defined( 'ABSPATH' ) ) {
exit;
@ -6,27 +11,45 @@ if ( ! defined( 'ABSPATH' ) ) {
/**
* Handles Refunds and other API requests such as capture.
*
* @since 3.0.0
*/
class WC_Gateway_Paypal_API_Handler {
/** @var string API Username */
/**
* API Username
*
* @var string
*/
public static $api_username;
/** @var string API Password */
/**
* API Password
*
* @var string
*/
public static $api_password;
/** @var string API Signature */
/**
* API Signature
*
* @var string
*/
public static $api_signature;
/** @var bool Sandbox */
/**
* Sandbox
*
* @var bool
*/
public static $sandbox = false;
/**
* Get capture request args.
* See https://developer.paypal.com/docs/classic/api/merchant/DoCapture_API_Operation_NVP/.
* @param WC_Order $order
* @param float $amount
*
* @param WC_Order $order Order object.
* @param float $amount Amount.
* @return array
*/
public static function get_capture_request( $order, $amount = null ) {
@ -46,9 +69,10 @@ class WC_Gateway_Paypal_API_Handler {
/**
* Get refund request args.
* @param WC_Order $order
* @param float $amount
* @param string $reason
*
* @param WC_Order $order Order object.
* @param float $amount Refund amount.
* @param string $reason Refund reason.
* @return array
*/
public static function get_refund_request( $order, $amount = null, $reason = '' ) {
@ -72,8 +96,9 @@ class WC_Gateway_Paypal_API_Handler {
/**
* Capture an authorization.
* @param WC_Order $order
* @param float $amount
*
* @param WC_Order $order Order object.
* @param float $amount Amount.
* @return object Either an object of name value pairs for a success, or a WP_ERROR object.
*/
public static function do_capture( $order, $amount = null ) {
@ -103,9 +128,10 @@ class WC_Gateway_Paypal_API_Handler {
/**
* Refund an order via PayPal.
* @param WC_Order $order
* @param float $amount
* @param string $reason
*
* @param WC_Order $order Order object.
* @param float $amount Refund amount.
* @param string $reason Refund reason.
* @return object Either an object of name value pairs for a success, or a WP_ERROR object.
*/
public static function refund_transaction( $order, $amount = null, $reason = '' ) {
@ -136,12 +162,32 @@ class WC_Gateway_Paypal_API_Handler {
/**
* Here for backwards compatibility.
*
* @since 3.0.0
*/
class WC_Gateway_Paypal_Refund extends WC_Gateway_Paypal_API_Handler {
/**
* Get refund request args. Proxy to WC_Gateway_Paypal_API_Handler::get_refund_request().
*
* @param WC_Order $order Order object.
* @param float $amount Refund amount.
* @param string $reason Refund reason.
*
* @return array
*/
public static function get_request( $order, $amount = null, $reason = '' ) {
return self::get_refund_request( $order, $amount, $reason );
}
/**
* Process an order refund.
*
* @param WC_Order $order Order object.
* @param float $amount Refund amount.
* @param string $reason Refund reason.
* @param bool $sandbox Whether to use sandbox mode or not.
* @return object Either an object of name value pairs for a success, or a WP_ERROR object.
*/
public static function refund_order( $order, $amount = null, $reason = '', $sandbox = false ) {
if ( $sandbox ) {
self::$sandbox = $sandbox;

View File

@ -1,24 +1,33 @@
<?php
/**
* Class WC_Gateway_Paypal_PDT_Handler file.
*
* @package WooCommerce\Gateways
*/
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
include_once( dirname( __FILE__ ) . '/class-wc-gateway-paypal-response.php' );
require_once dirname( __FILE__ ) . '/class-wc-gateway-paypal-response.php';
/**
* Handle PDT Responses from PayPal.
*/
class WC_Gateway_Paypal_PDT_Handler extends WC_Gateway_Paypal_Response {
/** @var string identity_token for PDT support */
/**
* Identity token for PDT support
*
* @var string
*/
protected $identity_token;
/**
* Constructor.
*
* @param bool $sandbox
* @param string $identity_token
* @param bool $sandbox Whether to use sandbox mode or not.
* @param string $identity_token Identity token for PDT support.
*/
public function __construct( $sandbox = false, $identity_token = '' ) {
add_action( 'woocommerce_thankyou_paypal', array( $this, 'check_response' ) );
@ -35,20 +44,20 @@ class WC_Gateway_Paypal_PDT_Handler extends WC_Gateway_Paypal_Response {
*/
protected function validate_transaction( $transaction ) {
$pdt = array(
'body' => array(
'body' => array(
'cmd' => '_notify-synch',
'tx' => $transaction,
'at' => $this->identity_token,
),
'timeout' => 60,
'httpversion' => '1.1',
'user-agent' => 'WooCommerce/' . WC_VERSION,
'timeout' => 60,
'httpversion' => '1.1',
'user-agent' => 'WooCommerce/' . WC_VERSION,
);
// Post back to get a response.
$response = wp_safe_remote_post( $this->sandbox ? 'https://www.sandbox.paypal.com/cgi-bin/webscr' : 'https://www.paypal.com/cgi-bin/webscr', $pdt );
if ( is_wp_error( $response ) || strpos( $response['body'], "SUCCESS" ) !== 0 ) {
if ( is_wp_error( $response ) || strpos( $response['body'], 'SUCCESS' ) !== 0 ) {
return false;
}
@ -57,7 +66,7 @@ class WC_Gateway_Paypal_PDT_Handler extends WC_Gateway_Paypal_Response {
$transaction_results = array();
foreach ( $transaction_result as $line ) {
$line = explode( "=", $line );
$line = explode( '=', $line );
$transaction_results[ $line[0] ] = isset( $line[1] ) ? $line[1] : '';
}
@ -78,12 +87,14 @@ class WC_Gateway_Paypal_PDT_Handler extends WC_Gateway_Paypal_Response {
return;
}
$order_id = wc_clean( stripslashes( $_REQUEST['cm'] ) );
$status = wc_clean( strtolower( stripslashes( $_REQUEST['st'] ) ) );
$amount = wc_clean( stripslashes( $_REQUEST['amt'] ) );
$transaction = wc_clean( stripslashes( $_REQUEST['tx'] ) );
$order_id = wc_clean( wp_unslash( $_REQUEST['cm'] ) );
$status = wc_clean( strtolower( wp_unslash( $_REQUEST['st'] ) ) ); // phpcs:ignore WordPress.VIP.ValidatedSanitizedInput.InputNotSanitized
$amount = wc_clean( wp_unslash( $_REQUEST['amt'] ) ); // phpcs:ignore WordPress.VIP.ValidatedSanitizedInput.InputNotValidated
$transaction = wc_clean( wp_unslash( $_REQUEST['tx'] ) );
if ( ! ( $order = $this->get_paypal_order( $order_id ) ) || ! $order->has_status( 'pending' ) ) {
$order = $this->get_paypal_order( $order_id );
if ( ! $order || ! $order->has_status( 'pending' ) ) {
return false;
}
@ -95,12 +106,13 @@ class WC_Gateway_Paypal_PDT_Handler extends WC_Gateway_Paypal_Response {
update_post_meta( $order->get_id(), '_paypal_status', $status );
update_post_meta( $order->get_id(), '_transaction_id', $transaction );
if ( 'completed' === $status ) {
if ( $order->get_total() != $amount ) {
if ( 'completed' === $status ) {
if ( $order->get_total() !== $amount ) {
WC_Gateway_Paypal::log( 'Payment error: Amounts do not match (amt ' . $amount . ')', 'error' );
/* translators: 1: Payment amount */
$this->payment_on_hold( $order, sprintf( __( 'Validation error: PayPal amounts do not match (amt %s).', 'woocommerce' ), $amount ) );
} else {
$this->payment_complete( $order, $transaction, __( 'PDT payment completed', 'woocommerce' ) );
$this->payment_complete( $order, $transaction, __( 'PDT payment completed', 'woocommerce' ) );
// Log paypal transaction fee and other meta data.
if ( ! empty( $transaction_result['mc_fee'] ) ) {
@ -123,6 +135,7 @@ class WC_Gateway_Paypal_PDT_Handler extends WC_Gateway_Paypal_Response {
if ( 'authorization' === $transaction_result['pending_reason'] ) {
$this->payment_on_hold( $order, __( 'Payment authorized. Change payment status to processing or complete to capture funds.', 'woocommerce' ) );
} else {
/* translators: 1: Pending reason */
$this->payment_on_hold( $order, sprintf( __( 'Payment pending (%s).', 'woocommerce' ), $transaction_result['pending_reason'] ) );
}
}

View File

@ -1,4 +1,9 @@
<?php
/**
* Class WC_Gateway_Paypal_Request file.
*
* @package WooCommerce\Gateways
*/
if ( ! defined( 'ABSPATH' ) ) {
exit;
@ -11,25 +16,29 @@ class WC_Gateway_Paypal_Request {
/**
* Stores line items to send to PayPal.
*
* @var array
*/
protected $line_items = array();
/**
* Pointer to gateway making the request.
*
* @var WC_Gateway_Paypal
*/
protected $gateway;
/**
* Endpoint for requests from PayPal.
*
* @var string
*/
protected $notify_url;
/**
* Constructor.
* @param WC_Gateway_Paypal $gateway
*
* @param WC_Gateway_Paypal $gateway Paypal gateway object.
*/
public function __construct( $gateway ) {
$this->gateway = $gateway;
@ -38,8 +47,9 @@ class WC_Gateway_Paypal_Request {
/**
* Get the PayPal request URL for an order.
* @param WC_Order $order
* @param bool $sandbox
*
* @param WC_Order $order Order object.
* @param bool $sandbox Whether to use sandbox mode or not.
* @return string
*/
public function get_request_url( $order, $sandbox = false ) {
@ -57,8 +67,8 @@ class WC_Gateway_Paypal_Request {
/**
* Limit length of an arg.
*
* @param string $string
* @param integer $limit
* @param string $string Argument to limit.
* @param integer $limit Limit size in characters.
* @return string
*/
protected function limit_length( $string, $limit = 127 ) {
@ -70,53 +80,62 @@ class WC_Gateway_Paypal_Request {
/**
* Get PayPal Args for passing to PP.
* @param WC_Order $order
*
* @param WC_Order $order Order object.
* @return array
*/
protected function get_paypal_args( $order ) {
WC_Gateway_Paypal::log( 'Generating payment form for order ' . $order->get_order_number() . '. Notify URL: ' . $this->notify_url );
return apply_filters( 'woocommerce_paypal_args', array_merge(
array(
'cmd' => '_cart',
'business' => $this->gateway->get_option( 'email' ),
'no_note' => 1,
'currency_code' => get_woocommerce_currency(),
'charset' => 'utf-8',
'rm' => is_ssl() ? 2 : 1,
'upload' => 1,
'return' => esc_url_raw( add_query_arg( 'utm_nooverride', '1', $this->gateway->get_return_url( $order ) ) ),
'cancel_return' => esc_url_raw( $order->get_cancel_order_url_raw() ),
'page_style' => $this->gateway->get_option( 'page_style' ),
'image_url' => esc_url_raw( $this->gateway->get_option( 'image_url' ) ),
'paymentaction' => $this->gateway->get_option( 'paymentaction' ),
'bn' => 'WooThemes_Cart',
'invoice' => $this->limit_length( $this->gateway->get_option( 'invoice_prefix' ) . $order->get_order_number(), 127 ),
'custom' => json_encode( array( 'order_id' => $order->get_id(), 'order_key' => $order->get_order_key() ) ),
'notify_url' => $this->limit_length( $this->notify_url, 255 ),
'first_name' => $this->limit_length( $order->get_billing_first_name(), 32 ),
'last_name' => $this->limit_length( $order->get_billing_last_name(), 64 ),
'address1' => $this->limit_length( $order->get_billing_address_1(), 100 ),
'address2' => $this->limit_length( $order->get_billing_address_2(), 100 ),
'city' => $this->limit_length( $order->get_billing_city(), 40 ),
'state' => $this->get_paypal_state( $order->get_billing_country(), $order->get_billing_state() ),
'zip' => $this->limit_length( wc_format_postcode( $order->get_billing_postcode(), $order->get_billing_country() ), 32 ),
'country' => $this->limit_length( $order->get_billing_country(), 2 ),
'email' => $this->limit_length( $order->get_billing_email() ),
),
$this->get_phone_number_args( $order ),
$this->get_shipping_args( $order ),
$this->get_line_item_args( $order )
), $order );
return apply_filters(
'woocommerce_paypal_args', array_merge(
array(
'cmd' => '_cart',
'business' => $this->gateway->get_option( 'email' ),
'no_note' => 1,
'currency_code' => get_woocommerce_currency(),
'charset' => 'utf-8',
'rm' => is_ssl() ? 2 : 1,
'upload' => 1,
'return' => esc_url_raw( add_query_arg( 'utm_nooverride', '1', $this->gateway->get_return_url( $order ) ) ),
'cancel_return' => esc_url_raw( $order->get_cancel_order_url_raw() ),
'page_style' => $this->gateway->get_option( 'page_style' ),
'image_url' => esc_url_raw( $this->gateway->get_option( 'image_url' ) ),
'paymentaction' => $this->gateway->get_option( 'paymentaction' ),
'bn' => 'WooThemes_Cart',
'invoice' => $this->limit_length( $this->gateway->get_option( 'invoice_prefix' ) . $order->get_order_number(), 127 ),
'custom' => wp_json_encode(
array(
'order_id' => $order->get_id(),
'order_key' => $order->get_order_key(),
)
),
'notify_url' => $this->limit_length( $this->notify_url, 255 ),
'first_name' => $this->limit_length( $order->get_billing_first_name(), 32 ),
'last_name' => $this->limit_length( $order->get_billing_last_name(), 64 ),
'address1' => $this->limit_length( $order->get_billing_address_1(), 100 ),
'address2' => $this->limit_length( $order->get_billing_address_2(), 100 ),
'city' => $this->limit_length( $order->get_billing_city(), 40 ),
'state' => $this->get_paypal_state( $order->get_billing_country(), $order->get_billing_state() ),
'zip' => $this->limit_length( wc_format_postcode( $order->get_billing_postcode(), $order->get_billing_country() ), 32 ),
'country' => $this->limit_length( $order->get_billing_country(), 2 ),
'email' => $this->limit_length( $order->get_billing_email() ),
),
$this->get_phone_number_args( $order ),
$this->get_shipping_args( $order ),
$this->get_line_item_args( $order )
), $order
);
}
/**
* Get phone number args for paypal request.
* @param WC_Order $order
*
* @param WC_Order $order Order object.
* @return array
*/
protected function get_phone_number_args( $order ) {
if ( in_array( $order->get_billing_country(), array( 'US', 'CA' ) ) ) {
if ( in_array( $order->get_billing_country(), array( 'US', 'CA' ), true ) ) {
$phone_number = str_replace( array( '(', '-', ' ', ')', '.' ), '', $order->get_billing_phone() );
$phone_number = ltrim( $phone_number, '+1' );
$phone_args = array(
@ -134,17 +153,18 @@ class WC_Gateway_Paypal_Request {
/**
* Get shipping args for paypal request.
* @param WC_Order $order
*
* @param WC_Order $order Order object.
* @return array
*/
protected function get_shipping_args( $order ) {
$shipping_args = array();
if ( 'yes' == $this->gateway->get_option( 'send_shipping' ) ) {
if ( 'yes' === $this->gateway->get_option( 'send_shipping' ) ) {
$shipping_args['address_override'] = $this->gateway->get_option( 'address_override' ) === 'yes' ? 1 : 0;
$shipping_args['no_shipping'] = 0;
// If we are sending shipping, send shipping address instead of billing
// If we are sending shipping, send shipping address instead of billing.
$shipping_args['first_name'] = $this->limit_length( $order->get_shipping_first_name(), 32 );
$shipping_args['last_name'] = $this->limit_length( $order->get_shipping_last_name(), 64 );
$shipping_args['address1'] = $this->limit_length( $order->get_shipping_address_1(), 100 );
@ -154,7 +174,7 @@ class WC_Gateway_Paypal_Request {
$shipping_args['country'] = $this->limit_length( $order->get_shipping_country(), 2 );
$shipping_args['zip'] = $this->limit_length( wc_format_postcode( $order->get_shipping_postcode(), $order->get_shipping_country() ), 32 );
} else {
$shipping_args['no_shipping'] = 1;
$shipping_args['no_shipping'] = 1;
}
return $shipping_args;
@ -162,7 +182,8 @@ class WC_Gateway_Paypal_Request {
/**
* Get line item args for paypal request.
* @param WC_Order $order
*
* @param WC_Order $order Order object.
* @return array
*/
protected function get_line_item_args( $order ) {
@ -185,17 +206,17 @@ class WC_Gateway_Paypal_Request {
if ( $order->get_shipping_total() > 0 && $order->get_shipping_total() < 999.99 && $this->number_format( $order->get_shipping_total() + $order->get_shipping_tax(), $order ) !== $this->number_format( $order->get_total(), $order ) ) {
$line_item_args['shipping_1'] = $this->number_format( $order->get_shipping_total(), $order );
} elseif ( $order->get_shipping_total() > 0 ) {
/* translators: %s: Order shipping method */
$this->add_line_item( sprintf( __( 'Shipping via %s', 'woocommerce' ), $order->get_shipping_method() ), 1, $this->number_format( $order->get_shipping_total(), $order ) );
}
$line_item_args = array_merge( $line_item_args, $this->get_line_items() );
/**
* Send order as a single item.
*
* For shipping, we longer use shipping_1 because paypal ignores it if *any* shipping rules are within paypal, and paypal ignores anything over 5 digits (999.99 is the max).
*/
} else {
/**
* Send order as a single item.
*
* For shipping, we longer use shipping_1 because paypal ignores it if *any* shipping rules are within paypal, and paypal ignores anything over 5 digits (999.99 is the max).
*/
$this->delete_line_items();
@ -209,6 +230,7 @@ class WC_Gateway_Paypal_Request {
if ( $order->get_shipping_total() > 0 && $order->get_shipping_total() < 999.99 && $this->number_format( $order->get_shipping_total() + $order->get_shipping_tax(), $order ) !== $this->number_format( $order->get_total(), $order ) ) {
$line_item_args['shipping_1'] = $this->number_format( $order->get_shipping_total() + $order->get_shipping_tax(), $order );
} elseif ( $order->get_shipping_total() > 0 ) {
/* translators: %s: Order shipping method */
$this->add_line_item( sprintf( __( 'Shipping via %s', 'woocommerce' ), $order->get_shipping_method() ), 1, $this->number_format( $order->get_shipping_total() + $order->get_shipping_tax(), $order ) );
}
@ -220,7 +242,8 @@ class WC_Gateway_Paypal_Request {
/**
* Get order item names as a string.
* @param WC_Order $order
*
* @param WC_Order $order Order object.
* @return string
*/
protected function get_order_item_names( $order ) {
@ -228,13 +251,17 @@ class WC_Gateway_Paypal_Request {
foreach ( $order->get_items() as $item ) {
$item_name = $item->get_name();
$item_meta = strip_tags( wc_display_item_meta( $item, array(
'before' => "",
'separator' => ", ",
'after' => "",
'echo' => false,
'autop' => false,
) ) );
$item_meta = strip_tags(
wc_display_item_meta(
$item, array(
'before' => '',
'separator' => ', ',
'after' => '',
'echo' => false,
'autop' => false,
)
)
);
if ( $item_meta ) {
$item_name .= ' (' . $item_meta . ')';
@ -248,19 +275,24 @@ class WC_Gateway_Paypal_Request {
/**
* Get order item names as a string.
* @param WC_Order $order
* @param array $item
*
* @param WC_Order $order Order object.
* @param WC_Order_Item $item Order item object.
* @return string
*/
protected function get_order_item_name( $order, $item ) {
$item_name = $item->get_name();
$item_meta = strip_tags( wc_display_item_meta( $item, array(
'before' => "",
'separator' => ", ",
'after' => "",
'echo' => false,
'autop' => false,
) ) );
$item_meta = strip_tags(
wc_display_item_meta(
$item, array(
'before' => '',
'separator' => ', ',
'after' => '',
'echo' => false,
'autop' => false,
)
)
);
if ( $item_meta ) {
$item_name .= ' (' . $item_meta . ')';
@ -285,24 +317,25 @@ class WC_Gateway_Paypal_Request {
/**
* Get line items to send to paypal.
* @param WC_Order $order
*
* @param WC_Order $order Order object.
* @return bool
*/
protected function prepare_line_items( $order ) {
$this->delete_line_items();
$calculated_total = 0;
// Products
// Products.
foreach ( $order->get_items( array( 'line_item', 'fee' ) ) as $item ) {
if ( 'fee' === $item['type'] ) {
$item_line_total = $this->number_format( $item['line_total'], $order );
$line_item = $this->add_line_item( $item->get_name(), 1, $item_line_total );
$item_line_total = $this->number_format( $item['line_total'], $order );
$line_item = $this->add_line_item( $item->get_name(), 1, $item_line_total );
$calculated_total += $item_line_total;
} else {
$product = $item->get_product();
$sku = $product ? $product->get_sku() : '';
$item_line_total = $this->number_format( $order->get_item_subtotal( $item, false ), $order );
$line_item = $this->add_line_item( $this->get_order_item_name( $order, $item ), $item->get_quantity(), $item_line_total, $sku );
$product = $item->get_product();
$sku = $product ? $product->get_sku() : '';
$item_line_total = $this->number_format( $order->get_item_subtotal( $item, false ), $order );
$line_item = $this->add_line_item( $this->get_order_item_name( $order, $item ), $item->get_quantity(), $item_line_total, $sku );
$calculated_total += $item_line_total * $item->get_quantity();
}
@ -312,7 +345,7 @@ class WC_Gateway_Paypal_Request {
}
// Check for mismatched totals.
if ( $this->number_format( $calculated_total + $order->get_total_tax() + $this->round( $order->get_shipping_total(), $order ) - $this->round( $order->get_total_discount(), $order ), $order ) != $this->number_format( $order->get_total(), $order ) ) {
if ( $this->number_format( $calculated_total + $order->get_total_tax() + $this->round( $order->get_shipping_total(), $order ) - $this->round( $order->get_total_discount(), $order ), $order ) !== $this->number_format( $order->get_total(), $order ) ) {
return false;
}
@ -321,25 +354,28 @@ class WC_Gateway_Paypal_Request {
/**
* Add PayPal Line Item.
* @param string $item_name
* @param int $quantity
* @param float $amount
* @param string $item_number
*
* @param string $item_name Item name.
* @param int $quantity Item quantity.
* @param float $amount Amount.
* @param string $item_number Item number.
* @return bool successfully added or not
*/
protected function add_line_item( $item_name, $quantity = 1, $amount = 0.0, $item_number = '' ) {
$index = ( sizeof( $this->line_items ) / 4 ) + 1;
$index = ( count( $this->line_items ) / 4 ) + 1;
if ( $amount < 0 || $index > 9 ) {
return false;
}
$item = apply_filters( 'woocommerce_paypal_line_item', array(
'item_name' => html_entity_decode( wc_trim_string( $item_name ? $item_name : __( 'Item', 'woocommerce' ), 127 ), ENT_NOQUOTES, 'UTF-8' ),
'quantity' => (int) $quantity,
'amount' => wc_float_to_string( (float) $amount ),
'item_number' => $item_number,
), $item_name, $quantity, $amount, $item_number );
$item = apply_filters(
'woocommerce_paypal_line_item', array(
'item_name' => html_entity_decode( wc_trim_string( $item_name ? $item_name : __( 'Item', 'woocommerce' ), 127 ), ENT_NOQUOTES, 'UTF-8' ),
'quantity' => (int) $quantity,
'amount' => wc_float_to_string( (float) $amount ),
'item_number' => $item_number,
), $item_name, $quantity, $amount, $item_number
);
$this->line_items[ 'item_name_' . $index ] = $this->limit_length( $item['item_name'], 127 );
$this->line_items[ 'quantity_' . $index ] = $item['quantity'];
@ -351,8 +387,9 @@ class WC_Gateway_Paypal_Request {
/**
* Get the state to send to paypal.
* @param string $cc
* @param string $state
*
* @param string $cc Country two letter code.
* @param string $state State code.
* @return string
*/
protected function get_paypal_state( $cc, $state ) {
@ -371,11 +408,12 @@ class WC_Gateway_Paypal_Request {
/**
* Check if currency has decimals.
* @param string $currency
*
* @param string $currency Currency to check.
* @return bool
*/
protected function currency_has_decimals( $currency ) {
if ( in_array( $currency, array( 'HUF', 'JPY', 'TWD' ) ) ) {
if ( in_array( $currency, array( 'HUF', 'JPY', 'TWD' ), true ) ) {
return false;
}
@ -384,8 +422,9 @@ class WC_Gateway_Paypal_Request {
/**
* Round prices.
* @param double $price
* @param WC_Order $order
*
* @param double $price Price to round.
* @param WC_Order $order Order object.
* @return double
*/
protected function round( $price, $order ) {
@ -400,8 +439,9 @@ class WC_Gateway_Paypal_Request {
/**
* Format prices.
* @param float|int $price
* @param WC_Order $order
*
* @param float|int $price Price to format.
* @param WC_Order $order Order object.
* @return string
*/
protected function number_format( $price, $order ) {

View File

@ -1,4 +1,9 @@
<?php
/**
* Class WC_Gateway_Paypal_Response file.
*
* @package WooCommerce\Gateways
*/
if ( ! defined( 'ABSPATH' ) ) {
exit;
@ -9,27 +14,34 @@ if ( ! defined( 'ABSPATH' ) ) {
*/
abstract class WC_Gateway_Paypal_Response {
/** @var bool Sandbox mode */
/**
* Sandbox mode
*
* @var bool
*/
protected $sandbox = false;
/**
* Get the order from the PayPal 'Custom' variable.
* @param string $raw_custom JSON Data passed back by PayPal
*
* @param string $raw_custom JSON Data passed back by PayPal.
* @return bool|WC_Order object
*/
protected function get_paypal_order( $raw_custom ) {
// We have the data in the correct format, so get the order.
if ( ( $custom = json_decode( $raw_custom ) ) && is_object( $custom ) ) {
$custom = wp_json_decode( $raw_custom );
if ( $custom && is_object( $custom ) ) {
$order_id = $custom->order_id;
$order_key = $custom->order_key;
// Nothing was found.
} else {
// Nothing was found.
WC_Gateway_Paypal::log( 'Order ID and key were not found in "custom".', 'error' );
return false;
}
if ( ! $order = wc_get_order( $order_id ) ) {
$order = wc_get_order( $order_id );
if ( ! $order ) {
// We have an invalid $order_id, probably because invoice_prefix has changed.
$order_id = wc_get_order_id_by_order_key( $order_key );
$order = wc_get_order( $order_id );
@ -45,9 +57,10 @@ abstract class WC_Gateway_Paypal_Response {
/**
* Complete order, add transaction ID and note.
* @param WC_Order $order
* @param string $txn_id
* @param string $note
*
* @param WC_Order $order Order object.
* @param string $txn_id Transaction ID.
* @param string $note Payment note.
*/
protected function payment_complete( $order, $txn_id = '', $note = '' ) {
$order->add_order_note( $note );
@ -56,8 +69,9 @@ abstract class WC_Gateway_Paypal_Response {
/**
* Hold order and add note.
* @param WC_Order $order
* @param string $reason
*
* @param WC_Order $order Order object.
* @param string $reason Reason why the payment is on hold.
*/
protected function payment_on_hold( $order, $reason = '' ) {
$order->update_status( 'on-hold', $reason );

View File

@ -7,12 +7,12 @@ if ( ! defined( 'ABSPATH' ) ) {
/**
* Simplify Commerce Gateway for subscriptions.
*
* @class WC_Addons_Gateway_Simplify_Commerce
* @extends WC_Gateway_Simplify_Commerce
* @class WC_Addons_Gateway_Simplify_Commerce
* @extends WC_Gateway_Simplify_Commerce
* @since 2.2.0
* @version 1.0.0
* @package WooCommerce/Classes/Payment
* @author WooThemes
* @version 1.0.0
* @package WooCommerce/Classes/Payment
* @author WooThemes
*/
class WC_Addons_Gateway_Simplify_Commerce extends WC_Gateway_Simplify_Commerce {
@ -101,12 +101,14 @@ class WC_Addons_Gateway_Simplify_Commerce extends WC_Gateway_Simplify_Commerce {
}
// Create customer
$customer = Simplify_Customer::createCustomer( array(
'token' => $cart_token,
'email' => $order->get_billing_email(),
'name' => trim( $order->get_formatted_billing_full_name() ),
'reference' => $order->get_id(),
) );
$customer = Simplify_Customer::createCustomer(
array(
'token' => $cart_token,
'email' => $order->get_billing_email(),
'name' => trim( $order->get_formatted_billing_full_name() ),
'reference' => $order->get_id(),
)
);
if ( is_object( $customer ) && '' != $customer->id ) {
$this->save_subscription_meta( $order->get_id(), $customer->id );
@ -149,7 +151,7 @@ class WC_Addons_Gateway_Simplify_Commerce extends WC_Gateway_Simplify_Commerce {
/**
* Store the customer and card IDs on the order and subscriptions in the order.
*
* @param int $order_id
* @param int $order_id
* @param string $customer_id
*/
protected function save_subscription_meta( $order_id, $customer_id ) {
@ -194,12 +196,14 @@ class WC_Addons_Gateway_Simplify_Commerce extends WC_Gateway_Simplify_Commerce {
}
// Create customer
$customer = Simplify_Customer::createCustomer( array(
'token' => $cart_token,
'email' => $order->get_billing_email(),
'name' => trim( $order->get_formatted_billing_full_name() ),
'reference' => $order->get_id(),
) );
$customer = Simplify_Customer::createCustomer(
array(
'token' => $cart_token,
'email' => $order->get_billing_email(),
'name' => trim( $order->get_formatted_billing_full_name() ),
'reference' => $order->get_id(),
)
);
if ( is_object( $customer ) && '' != $customer->id ) {
$customer_id = wc_clean( $customer->id );
@ -241,7 +245,6 @@ class WC_Addons_Gateway_Simplify_Commerce extends WC_Gateway_Simplify_Commerce {
'redirect' => '',
);
}
} else {
return parent::process_standard_payments( $order, $cart_token );
}
@ -261,12 +264,11 @@ class WC_Addons_Gateway_Simplify_Commerce extends WC_Gateway_Simplify_Commerce {
if ( 'standard' == $this->mode && ( $this->order_contains_subscription( $order->get_id() ) || ( function_exists( 'wcs_is_subscription' ) && wcs_is_subscription( $order_id ) ) ) ) {
return $this->process_subscription( $order, $cart_token );
// Processing pre-order
} elseif ( 'standard' == $this->mode && $this->order_contains_pre_order( $order->get_id() ) ) {
// Processing pre-order.
return $this->process_pre_order( $order, $cart_token );
// Processing regular product
} else {
// Processing regular product.
return parent::process_payment( $order_id );
}
}
@ -275,7 +277,7 @@ class WC_Addons_Gateway_Simplify_Commerce extends WC_Gateway_Simplify_Commerce {
* process_subscription_payment function.
*
* @param WC_order $order
* @param int $amount (default: 0)
* @param int $amount (default: 0)
* @uses Simplify_BadRequestException
* @return bool|WP_Error
*/
@ -299,13 +301,15 @@ class WC_Addons_Gateway_Simplify_Commerce extends WC_Gateway_Simplify_Commerce {
try {
// Charge the customer
$payment = Simplify_Payment::createPayment( array(
'amount' => $amount * 100, // In cents.
'customer' => $customer_id,
'description' => sprintf( __( '%1$s - Order #%2$s', 'woocommerce' ), esc_html( get_bloginfo( 'name', 'display' ) ), $order->get_order_number() ),
'currency' => strtoupper( get_woocommerce_currency() ),
'reference' => $order->get_id(),
) );
$payment = Simplify_Payment::createPayment(
array(
'amount' => $amount * 100, // In cents.
'customer' => $customer_id,
'description' => sprintf( __( '%1$s - Order #%2$s', 'woocommerce' ), esc_html( get_bloginfo( 'name', 'display' ) ), $order->get_order_number() ),
'currency' => strtoupper( get_woocommerce_currency() ),
'reference' => $order->get_id(),
)
);
} catch ( Exception $e ) {
@ -341,7 +345,7 @@ class WC_Addons_Gateway_Simplify_Commerce extends WC_Gateway_Simplify_Commerce {
/**
* scheduled_subscription_payment function.
*
* @param float $amount_to_charge The amount to charge.
* @param float $amount_to_charge The amount to charge.
* @param WC_Order $renewal_order A WC_Order object created to record the renewal payment.
*/
public function scheduled_subscription_payment( $amount_to_charge, $renewal_order ) {
@ -357,7 +361,7 @@ class WC_Addons_Gateway_Simplify_Commerce extends WC_Gateway_Simplify_Commerce {
* an automatic renewal payment which previously failed.
*
* @param WC_Subscription $subscription The subscription for which the failing payment method relates.
* @param WC_Order $renewal_order The order which recorded the successful payment (to make up for the failed automatic payment).
* @param WC_Order $renewal_order The order which recorded the successful payment (to make up for the failed automatic payment).
*/
public function update_failing_payment_method( $subscription, $renewal_order ) {
update_post_meta( $subscription->id, '_simplify_customer_id', get_post_meta( $renewal_order->get_id(), '_simplify_customer_id', true ) );
@ -368,7 +372,7 @@ class WC_Addons_Gateway_Simplify_Commerce extends WC_Gateway_Simplify_Commerce {
* manually set up automatic recurring payments for a customer via the Edit Subscription screen in Subscriptions v2.0+.
*
* @since 2.4
* @param array $payment_meta associative array of meta data required for automatic payments
* @param array $payment_meta associative array of meta data required for automatic payments
* @param WC_Subscription $subscription An instance of a subscription object
* @return array
*/
@ -392,7 +396,7 @@ class WC_Addons_Gateway_Simplify_Commerce extends WC_Gateway_Simplify_Commerce {
*
* @since 2.4
* @param string $payment_method_id The ID of the payment method to validate
* @param array $payment_meta associative array of meta data required for automatic payments
* @param array $payment_meta associative array of meta data required for automatic payments
* @throws Exception
*/
public function validate_subscription_payment_meta( $payment_method_id, $payment_meta ) {
@ -423,8 +427,8 @@ class WC_Addons_Gateway_Simplify_Commerce extends WC_Gateway_Simplify_Commerce {
public function process_pre_order_release_payment( $order ) {
try {
$order_items = $order->get_items();
$order_item = array_shift( $order_items );
$order_items = $order->get_items();
$order_item = array_shift( $order_items );
/* translators: 1: site name 2: product name 3: order number */
$pre_order_name = sprintf(
__( '%1$s - Pre-order for "%2$s" (Order #%3$s)', 'woocommerce' ),
@ -440,13 +444,15 @@ class WC_Addons_Gateway_Simplify_Commerce extends WC_Gateway_Simplify_Commerce {
}
// Charge the customer
$payment = Simplify_Payment::createPayment( array(
'amount' => $order->get_total() * 100, // In cents.
'customer' => $customer_id,
'description' => trim( substr( $pre_order_name, 0, 1024 ) ),
'currency' => strtoupper( get_woocommerce_currency() ),
'reference' => $order->get_id(),
) );
$payment = Simplify_Payment::createPayment(
array(
'amount' => $order->get_total() * 100, // In cents.
'customer' => $customer_id,
'description' => trim( substr( $pre_order_name, 0, 1024 ) ),
'currency' => strtoupper( get_woocommerce_currency() ),
'reference' => $order->get_id(),
)
);
if ( 'APPROVED' == $payment->paymentStatus ) {
// Payment complete

View File

@ -7,12 +7,12 @@ if ( ! defined( 'ABSPATH' ) ) {
/**
* Simplify Commerce Gateway.
*
* @class WC_Gateway_Simplify_Commerce
* @extends WC_Payment_Gateway_CC
* @class WC_Gateway_Simplify_Commerce
* @extends WC_Payment_Gateway_CC
* @since 2.2.0
* @version 1.0.0
* @package WooCommerce/Classes/Payment
* @author WooThemes
* @version 1.0.0
* @package WooCommerce/Classes/Payment
* @author WooThemes
*/
class WC_Gateway_Simplify_Commerce extends WC_Payment_Gateway_CC {
@ -20,12 +20,12 @@ class WC_Gateway_Simplify_Commerce extends WC_Payment_Gateway_CC {
* Constructor.
*/
public function __construct() {
$this->id = 'simplify_commerce';
$this->method_title = __( 'Simplify Commerce', 'woocommerce' );
$this->method_description = __( 'Take payments via Simplify Commerce - uses simplify.js to create card tokens and the Simplify Commerce SDK. Requires SSL when sandbox is disabled.', 'woocommerce' );
$this->new_method_label = __( 'Use a new card', 'woocommerce' );
$this->has_fields = true;
$this->supports = array(
$this->id = 'simplify_commerce';
$this->method_title = __( 'Simplify Commerce', 'woocommerce' );
$this->method_description = __( 'Take payments via Simplify Commerce - uses simplify.js to create card tokens and the Simplify Commerce SDK. Requires SSL when sandbox is disabled.', 'woocommerce' );
$this->new_method_label = __( 'Use a new card', 'woocommerce' );
$this->has_fields = true;
$this->supports = array(
'subscriptions',
'products',
'subscription_cancellation',
@ -51,14 +51,14 @@ class WC_Gateway_Simplify_Commerce extends WC_Payment_Gateway_CC {
$this->init_settings();
// Get setting values
$this->title = $this->get_option( 'title' );
$this->description = $this->get_option( 'description' );
$this->enabled = $this->get_option( 'enabled' );
$this->mode = $this->get_option( 'mode', 'standard' );
$this->modal_color = $this->get_option( 'modal_color', '#a46497' );
$this->sandbox = $this->get_option( 'sandbox' );
$this->public_key = ( 'no' === $this->sandbox ) ? $this->get_option( 'public_key' ) : $this->get_option( 'sandbox_public_key' );
$this->private_key = ( 'no' === $this->sandbox ) ? $this->get_option( 'private_key' ) : $this->get_option( 'sandbox_private_key' );
$this->title = $this->get_option( 'title' );
$this->description = $this->get_option( 'description' );
$this->enabled = $this->get_option( 'enabled' );
$this->mode = $this->get_option( 'mode', 'standard' );
$this->modal_color = $this->get_option( 'modal_color', '#a46497' );
$this->sandbox = $this->get_option( 'sandbox' );
$this->public_key = ( 'no' === $this->sandbox ) ? $this->get_option( 'public_key' ) : $this->get_option( 'sandbox_public_key' );
$this->private_key = ( 'no' === $this->sandbox ) ? $this->get_option( 'private_key' ) : $this->get_option( 'sandbox_private_key' );
$this->init_simplify_sdk();
@ -74,7 +74,7 @@ class WC_Gateway_Simplify_Commerce extends WC_Payment_Gateway_CC {
*/
protected function init_simplify_sdk() {
// Include lib
require_once( dirname( __FILE__ ) . '/includes/Simplify.php' );
require_once dirname( __FILE__ ) . '/includes/Simplify.php';
Simplify::$publicKey = $this->public_key;
Simplify::$privateKey = $this->private_key;
@ -186,28 +186,28 @@ class WC_Gateway_Simplify_Commerce extends WC_Payment_Gateway_CC {
*/
public function init_form_fields() {
$this->form_fields = array(
'enabled' => array(
'enabled' => array(
'title' => __( 'Enable/Disable', 'woocommerce' ),
'label' => __( 'Enable Simplify Commerce', 'woocommerce' ),
'type' => 'checkbox',
'description' => '',
'default' => 'no',
),
'title' => array(
'title' => array(
'title' => __( 'Title', 'woocommerce' ),
'type' => 'text',
'description' => __( 'This controls the title which the user sees during checkout.', 'woocommerce' ),
'default' => __( 'Credit card', 'woocommerce' ),
'desc_tip' => true,
),
'description' => array(
'description' => array(
'title' => __( 'Description', 'woocommerce' ),
'type' => 'text',
'description' => __( 'This controls the description which the user sees during checkout.', 'woocommerce' ),
'default' => 'Pay with your credit card via Simplify Commerce by MasterCard.',
'desc_tip' => true,
),
'mode' => array(
'mode' => array(
'title' => __( 'Payment mode', 'woocommerce' ),
'label' => __( 'Enable Hosted Payments', 'woocommerce' ),
'type' => 'select',
@ -218,21 +218,21 @@ class WC_Gateway_Simplify_Commerce extends WC_Payment_Gateway_CC {
'hosted' => __( 'Hosted Payments', 'woocommerce' ),
),
),
'modal_color' => array(
'modal_color' => array(
'title' => __( 'Modal color', 'woocommerce' ),
'type' => 'color',
'description' => __( 'Set the color of the buttons and titles on the modal dialog.', 'woocommerce' ),
'default' => '#a46497',
'desc_tip' => true,
),
'sandbox' => array(
'sandbox' => array(
'title' => __( 'Sandbox', 'woocommerce' ),
'label' => __( 'Enable sandbox mode', 'woocommerce' ),
'type' => 'checkbox',
'description' => __( 'Place the payment gateway in sandbox mode using sandbox API keys (real payments will not be taken).', 'woocommerce' ),
'default' => 'yes',
),
'sandbox_public_key' => array(
'sandbox_public_key' => array(
'title' => __( 'Sandbox public key', 'woocommerce' ),
'type' => 'text',
'description' => __( 'Get your API keys from your Simplify account: Settings > API Keys.', 'woocommerce' ),
@ -246,14 +246,14 @@ class WC_Gateway_Simplify_Commerce extends WC_Payment_Gateway_CC {
'default' => '',
'desc_tip' => true,
),
'public_key' => array(
'public_key' => array(
'title' => __( 'Public key', 'woocommerce' ),
'type' => 'text',
'description' => __( 'Get your API keys from your Simplify account: Settings > API Keys.', 'woocommerce' ),
'default' => '',
'desc_tip' => true,
),
'private_key' => array(
'private_key' => array(
'title' => __( 'Private key', 'woocommerce' ),
'type' => 'text',
'description' => __( 'Get your API keys from your Simplify account: Settings > API Keys.', 'woocommerce' ),
@ -301,15 +301,17 @@ class WC_Gateway_Simplify_Commerce extends WC_Payment_Gateway_CC {
wp_enqueue_script( 'simplify-commerce', 'https://www.simplify.com/commerce/v1/simplify.js', array( 'jquery' ), WC_VERSION, true );
wp_enqueue_script( 'wc-simplify-commerce', WC()->plugin_url() . '/includes/gateways/simplify-commerce/assets/js/simplify-commerce.js', array( 'simplify-commerce', 'wc-credit-card-form' ), WC_VERSION, true );
wp_localize_script( 'wc-simplify-commerce', 'Simplify_commerce_params', array(
'key' => $this->public_key,
'card.number' => __( 'Card number', 'woocommerce' ),
'card.expMonth' => __( 'Expiry month', 'woocommerce' ),
'card.expYear' => __( 'Expiry year', 'woocommerce' ),
'is_invalid' => __( 'is invalid', 'woocommerce' ),
'mode' => $this->mode,
'is_ssl' => is_ssl(),
) );
wp_localize_script(
'wc-simplify-commerce', 'Simplify_commerce_params', array(
'key' => $this->public_key,
'card.number' => __( 'Card number', 'woocommerce' ),
'card.expMonth' => __( 'Expiry month', 'woocommerce' ),
'card.expYear' => __( 'Expiry year', 'woocommerce' ),
'is_invalid' => __( 'is invalid', 'woocommerce' ),
'mode' => $this->mode,
'is_ssl' => is_ssl(),
)
);
}
public function add_payment_method() {
@ -342,33 +344,35 @@ class WC_Gateway_Simplify_Commerce extends WC_Payment_Gateway_CC {
* Actually saves a customer token to the database.
*
* @param WC_Payment_Token $customer_token Payment Token
* @param string $cart_token CC Token
* @param array $customer_info 'email', 'name'
* @param string $cart_token CC Token
* @param array $customer_info 'email', 'name'
*
* @return null|WC_Payment_Token|WC_Payment_Token_CC
*/
public function save_token( $customer_token, $cart_token, $customer_info ) {
if ( ! is_null( $customer_token ) ) {
$customer = Simplify_Customer::findCustomer( $customer_token->get_token() );
$updates = array( 'token' => $cart_token );
$updates = array( 'token' => $cart_token );
$customer->setAll( $updates );
$customer->updateCustomer();
$customer = Simplify_Customer::findCustomer( $customer_token->get_token() ); // get updated customer with new set card
$token = $customer_token;
$token = $customer_token;
} else {
$customer = Simplify_Customer::createCustomer( array(
'token' => $cart_token,
'email' => $customer_info['email'],
'name' => $customer_info['name'],
) );
$token = new WC_Payment_Token_CC();
$customer = Simplify_Customer::createCustomer(
array(
'token' => $cart_token,
'email' => $customer_info['email'],
'name' => $customer_info['name'],
)
);
$token = new WC_Payment_Token_CC();
$token->set_token( $customer->id );
}
// If we were able to create an save our card, save the data on our side too
if ( is_object( $customer ) && '' != $customer->id ) {
$customer_properties = $customer->getProperties();
$card = $customer_properties['card'];
$card = $customer_properties['card'];
$token->set_gateway_id( $this->id );
$token->set_card_type( strtolower( $card->type ) );
$token->set_last4( $card->last4 );
@ -388,9 +392,9 @@ class WC_Gateway_Simplify_Commerce extends WC_Payment_Gateway_CC {
/**
* Process customer: updating or creating a new customer/saved CC
*
* @param WC_Order $order Order object
* @param WC_Payment_Token $customer_token Payment Token
* @param string $cart_token CC Token
* @param WC_Order $order Order object
* @param WC_Payment_Token $customer_token Payment Token
* @param string $cart_token CC Token
*/
protected function process_customer( $order, $customer_token = null, $cart_token = '' ) {
// Are we saving a new payment method?
@ -399,7 +403,7 @@ class WC_Gateway_Simplify_Commerce extends WC_Payment_Gateway_CC {
'email' => $order->get_billing_email(),
'name' => trim( $order->get_formatted_billing_full_name() ),
);
$token = $this->save_token( $customer_token, $cart_token, $customer_info );
$token = $this->save_token( $customer_token, $cart_token, $customer_info );
if ( ! is_null( $token ) ) {
$order->add_payment_token( $token );
}
@ -410,8 +414,8 @@ class WC_Gateway_Simplify_Commerce extends WC_Payment_Gateway_CC {
* Process standard payments.
*
* @param WC_Order $order
* @param string $cart_token
* @param string $customer_token
* @param string $cart_token
* @param string $customer_token
*
* @return array
* @uses Simplify_ApiException
@ -489,8 +493,8 @@ class WC_Gateway_Simplify_Commerce extends WC_Payment_Gateway_CC {
* do payment function.
*
* @param WC_order $order
* @param int $amount (default: 0)
* @param array $token
* @param int $amount (default: 0)
* @param array $token
*
* @return bool|WP_Error
* @uses Simplify_BadRequestException
@ -503,13 +507,13 @@ class WC_Gateway_Simplify_Commerce extends WC_Payment_Gateway_CC {
try {
// Charge the customer
$data = array(
'amount' => $amount * 100, // In cents.
'description' => sprintf( __( '%1$s - Order #%2$s', 'woocommerce' ), esc_html( get_bloginfo( 'name', 'display' ) ), $order->get_order_number() ),
'currency' => strtoupper( get_woocommerce_currency() ),
'reference' => $order->get_id(),
'amount' => $amount * 100, // In cents.
'description' => sprintf( __( '%1$s - Order #%2$s', 'woocommerce' ), esc_html( get_bloginfo( 'name', 'display' ) ), $order->get_order_number() ),
'currency' => strtoupper( get_woocommerce_currency() ),
'reference' => $order->get_id(),
);
$data = array_merge( $data, $token );
$data = array_merge( $data, $token );
$payment = Simplify_Payment::createPayment( $data );
} catch ( Exception $e ) {
@ -557,7 +561,7 @@ class WC_Gateway_Simplify_Commerce extends WC_Payment_Gateway_CC {
}
protected function get_users_token() {
$customer_token = null;
$customer_token = null;
if ( is_user_logged_in() ) {
$tokens = WC_Payment_Tokens::get_customer_tokens( get_current_user_id() );
foreach ( $tokens as $token ) {
@ -615,22 +619,24 @@ class WC_Gateway_Simplify_Commerce extends WC_Payment_Gateway_CC {
* @return array
*/
protected function get_hosted_payments_args( $order ) {
$args = apply_filters( 'woocommerce_simplify_commerce_hosted_args', array(
'sc-key' => $this->public_key,
'amount' => $order->get_total() * 100,
'reference' => $order->get_id(),
'name' => esc_html( get_bloginfo( 'name', 'display' ) ),
'description' => sprintf( __( 'Order #%s', 'woocommerce' ), $order->get_order_number() ),
'receipt' => 'false',
'color' => $this->modal_color,
'redirect-url' => WC()->api_request_url( 'WC_Gateway_Simplify_Commerce' ),
'address' => $order->get_billing_address_1() . ' ' . $order->get_billing_address_2(),
'address-city' => $order->get_billing_city(),
'address-state' => $order->get_billing_state(),
'address-zip' => $order->get_billing_postcode(),
'address-country' => $order->get_billing_country(),
'operation' => 'create.token',
), $order->get_id() );
$args = apply_filters(
'woocommerce_simplify_commerce_hosted_args', array(
'sc-key' => $this->public_key,
'amount' => $order->get_total() * 100,
'reference' => $order->get_id(),
'name' => esc_html( get_bloginfo( 'name', 'display' ) ),
'description' => sprintf( __( 'Order #%s', 'woocommerce' ), $order->get_order_number() ),
'receipt' => 'false',
'color' => $this->modal_color,
'redirect-url' => WC()->api_request_url( 'WC_Gateway_Simplify_Commerce' ),
'address' => $order->get_billing_address_1() . ' ' . $order->get_billing_address_2(),
'address-city' => $order->get_billing_city(),
'address-state' => $order->get_billing_state(),
'address-zip' => $order->get_billing_postcode(),
'address-country' => $order->get_billing_country(),
'operation' => 'create.token',
), $order->get_id()
);
return $args;
}
@ -715,8 +721,8 @@ class WC_Gateway_Simplify_Commerce extends WC_Payment_Gateway_CC {
* Process refunds.
* WooCommerce 2.2 or later.
*
* @param int $order_id
* @param float $amount
* @param int $order_id
* @param float $amount
* @param string $reason
* @uses Simplify_ApiException
* @uses Simplify_BadRequestException
@ -726,12 +732,14 @@ class WC_Gateway_Simplify_Commerce extends WC_Payment_Gateway_CC {
try {
$payment_id = get_post_meta( $order_id, '_transaction_id', true );
$refund = Simplify_Refund::createRefund( array(
'amount' => $amount * 100, // In cents.
'payment' => $payment_id,
'reason' => $reason,
'reference' => $order_id,
) );
$refund = Simplify_Refund::createRefund(
array(
'amount' => $amount * 100, // In cents.
'payment' => $payment_id,
'reason' => $reason,
'reference' => $order_id,
)
);
if ( 'APPROVED' == $refund->paymentStatus ) {
return true;

View File

@ -1,6 +1,12 @@
<?php
/**
* Class WC_Log_Handler_DB file.
*
* @package WooCommerce\Log Handlers
*/
if ( ! defined( 'ABSPATH' ) ) {
exit; // Exit if accessed directly
exit; // Exit if accessed directly.
}
/**
@ -9,19 +15,17 @@ if ( ! defined( 'ABSPATH' ) ) {
* @class WC_Log_Handler_DB
* @version 1.0.0
* @package WooCommerce/Classes/Log_Handlers
* @category Class
* @author WooThemes
*/
class WC_Log_Handler_DB extends WC_Log_Handler {
/**
* Handle a log entry.
*
* @param int $timestamp Log timestamp.
* @param string $level emergency|alert|critical|error|warning|notice|info|debug
* @param int $timestamp Log timestamp.
* @param string $level emergency|alert|critical|error|warning|notice|info|debug.
* @param string $message Log message.
* @param array $context {
* Additional information for log handlers.
* @param array $context {
* Additional information for log handlers.
*
* @type string $source Optional. Source will be available in log table.
* If no source is provided, attempt to provide sensible default.
@ -45,13 +49,11 @@ class WC_Log_Handler_DB extends WC_Log_Handler {
/**
* Add a log entry to chosen file.
*
* @param int $timestamp Log timestamp.
* @param string $level emergency|alert|critical|error|warning|notice|info|debug
* @param int $timestamp Log timestamp.
* @param string $level emergency|alert|critical|error|warning|notice|info|debug.
* @param string $message Log message.
* @param string $source Log source. Useful for filtering and sorting.
* @param array $context {
* Context will be serialized and stored in database.
* }
* @param array $context Context will be serialized and stored in database.
*
* @return bool True if write was successful.
*/
@ -60,9 +62,9 @@ class WC_Log_Handler_DB extends WC_Log_Handler {
$insert = array(
'timestamp' => date( 'Y-m-d H:i:s', $timestamp ),
'level' => WC_Log_Levels::get_level_severity( $level ),
'message' => $message,
'source' => $source,
'level' => WC_Log_Levels::get_level_severity( $level ),
'message' => $message,
'source' => $source,
);
$format = array(
@ -70,7 +72,7 @@ class WC_Log_Handler_DB extends WC_Log_Handler {
'%d',
'%s',
'%s',
'%s', // possible serialized context
'%s', // possible serialized context.
);
if ( ! empty( $context ) ) {
@ -94,7 +96,7 @@ class WC_Log_Handler_DB extends WC_Log_Handler {
/**
* Delete selected logs from DB.
*
* @param int|string|array Log ID or array of Log IDs to be deleted.
* @param int|string|array $log_ids Log ID or array of Log IDs to be deleted.
*
* @return bool
*/
@ -109,12 +111,12 @@ class WC_Log_Handler_DB extends WC_Log_Handler {
$query_in = '(' . implode( ',', $format ) . ')';
$query = $wpdb->prepare(
"DELETE FROM {$wpdb->prefix}woocommerce_log WHERE log_id IN {$query_in}",
$log_ids
return $wpdb->query(
$wpdb->prepare(
"DELETE FROM {$wpdb->prefix}woocommerce_log WHERE log_id IN {$query_in}", // phpcs:ignore WordPress.WP.PreparedSQL.NotPrepared
$log_ids
)
);
return $wpdb->query( $query );
}
/**
@ -129,19 +131,20 @@ class WC_Log_Handler_DB extends WC_Log_Handler {
/**
* PHP < 5.3.6 correct behavior
*
* @see http://php.net/manual/en/function.debug-backtrace.php#refsect1-function.debug-backtrace-parameters
*/
if ( defined( 'DEBUG_BACKTRACE_IGNORE_ARGS' ) ) {
$debug_backtrace_arg = DEBUG_BACKTRACE_IGNORE_ARGS;
$debug_backtrace_arg = DEBUG_BACKTRACE_IGNORE_ARGS; // phpcs:ignore PHPCompatibility.PHP.NewConstants.debug_backtrace_ignore_argsFound
} else {
$debug_backtrace_arg = false;
}
$trace = debug_backtrace( $debug_backtrace_arg );
$trace = debug_backtrace( $debug_backtrace_arg ); // phpcs:ignore PHPCompatibility.PHP.NewFunctionParameters.debug_backtrace_optionsFound
foreach ( $trace as $t ) {
if ( isset( $t['file'] ) ) {
$filename = pathinfo( $t['file'], PATHINFO_FILENAME );
if ( ! in_array( $filename, $ignore_files ) ) {
if ( ! in_array( $filename, $ignore_files, true ) ) {
return $filename;
}
}

View File

@ -1,6 +1,12 @@
<?php
/**
* Class WC_Log_Handler_Email file.
*
* @package WooCommerce\Log Handlers
*/
if ( ! defined( 'ABSPATH' ) ) {
exit; // Exit if accessed directly
exit; // Exit if accessed directly.
}
/**
@ -23,8 +29,6 @@ if ( ! defined( 'ABSPATH' ) ) {
* @class WC_Log_Handler_Email
* @version 1.0.0
* @package WooCommerce/Classes/Log_Handlers
* @category Class
* @author WooThemes
*/
class WC_Log_Handler_Email extends WC_Log_Handler {
@ -60,8 +64,8 @@ class WC_Log_Handler_Email extends WC_Log_Handler {
* Constructor for log handler.
*
* @param string|array $recipients Optional. Email(s) to receive log messages. Defaults to site admin email.
* @param string $threshold Optional. Minimum level that should receive log messages.
* Default 'alert'. One of: emergency|alert|critical|error|warning|notice|info|debug
* @param string $threshold Optional. Minimum level that should receive log messages.
* Default 'alert'. One of: emergency|alert|critical|error|warning|notice|info|debug.
*/
public function __construct( $recipients = null, $threshold = 'alert' ) {
if ( null === $recipients ) {
@ -83,7 +87,7 @@ class WC_Log_Handler_Email extends WC_Log_Handler {
/**
* Set handler severity threshold.
*
* @param string $level emergency|alert|critical|error|warning|notice|info|debug
* @param string $level emergency|alert|critical|error|warning|notice|info|debug.
*/
public function set_threshold( $level ) {
$this->threshold = WC_Log_Levels::get_level_severity( $level );
@ -92,7 +96,7 @@ class WC_Log_Handler_Email extends WC_Log_Handler {
/**
* Determine whether handler should handle log.
*
* @param string $level emergency|alert|critical|error|warning|notice|info|debug
* @param string $level emergency|alert|critical|error|warning|notice|info|debug.
* @return bool True if the log should be handled.
*/
protected function should_handle( $level ) {
@ -102,10 +106,10 @@ class WC_Log_Handler_Email extends WC_Log_Handler {
/**
* Handle a log entry.
*
* @param int $timestamp Log timestamp.
* @param string $level emergency|alert|critical|error|warning|notice|info|debug
* @param int $timestamp Log timestamp.
* @param string $level emergency|alert|critical|error|warning|notice|info|debug.
* @param string $message Log message.
* @param array $context Optional. Additional information for log handlers.
* @param array $context Optional. Additional information for log handlers.
*
* @return bool False if value was not handled and true if value was handled.
*/
@ -129,8 +133,8 @@ class WC_Log_Handler_Email extends WC_Log_Handler {
if ( ! empty( $this->logs ) ) {
$subject = $this->get_subject();
$body = $this->get_body();
$result = wp_mail( $this->recipients, $subject, $body );
$body = $this->get_body();
$result = wp_mail( $this->recipients, $subject, $body );
$this->clear_logs();
}
@ -148,6 +152,7 @@ class WC_Log_Handler_Email extends WC_Log_Handler {
$log_count = count( $this->logs );
return sprintf(
/* translators: 1: Site name 2: Maximum level 3: Log count */
_n(
'[%1$s] %2$s: %3$s WooCommerce log message',
'[%1$s] %2$s: %3$s WooCommerce log messages',
@ -167,19 +172,19 @@ class WC_Log_Handler_Email extends WC_Log_Handler {
*/
protected function get_body() {
$site_name = get_bloginfo( 'name' );
$entries = implode( PHP_EOL, $this->logs );
$entries = implode( PHP_EOL, $this->logs );
$log_count = count( $this->logs );
return _n(
'You have received the following WooCommerce log message:',
'You have received the following WooCommerce log messages:',
$log_count,
'woocommerce'
)
. PHP_EOL
'You have received the following WooCommerce log message:',
'You have received the following WooCommerce log messages:',
$log_count,
'woocommerce'
) . PHP_EOL
. PHP_EOL
. $entries
. PHP_EOL
. PHP_EOL
/* translators: %s: Site name */
. sprintf( __( 'Visit %s admin area:', 'woocommerce' ), $site_name )
. PHP_EOL
. admin_url();
@ -188,7 +193,7 @@ class WC_Log_Handler_Email extends WC_Log_Handler {
/**
* Adds an email to the list of recipients.
*
* @param string email Email address to add
* @param string $email Email address to add.
*/
public function add_email( $email ) {
array_push( $this->recipients, $email );
@ -197,10 +202,10 @@ class WC_Log_Handler_Email extends WC_Log_Handler {
/**
* Add log message.
*
* @param int $timestamp Log timestamp.
* @param string $level emergency|alert|critical|error|warning|notice|info|debug
* @param int $timestamp Log timestamp.
* @param string $level emergency|alert|critical|error|warning|notice|info|debug.
* @param string $message Log message.
* @param array $context Additional information for log handlers.
* @param array $context Additional information for log handlers.
*/
protected function add_log( $timestamp, $level, $message, $context ) {
$this->logs[] = $this->format_entry( $timestamp, $level, $message, $context );

View File

@ -1,6 +1,12 @@
<?php
/**
* Class WC_Log_Handler_File file.
*
* @package WooCommerce\Log Handlers
*/
if ( ! defined( 'ABSPATH' ) ) {
exit; // Exit if accessed directly
exit; // Exit if accessed directly.
}
/**
@ -9,8 +15,6 @@ if ( ! defined( 'ABSPATH' ) ) {
* @class WC_Log_Handler_File
* @version 1.0.0
* @package WooCommerce/Classes/Log_Handlers
* @category Class
* @author WooThemes
*/
class WC_Log_Handler_File extends WC_Log_Handler {
@ -70,11 +74,11 @@ class WC_Log_Handler_File extends WC_Log_Handler {
/**
* Handle a log entry.
*
* @param int $timestamp Log timestamp.
* @param string $level emergency|alert|critical|error|warning|notice|info|debug
* @param int $timestamp Log timestamp.
* @param string $level emergency|alert|critical|error|warning|notice|info|debug.
* @param string $message Log message.
* @param array $context {
* Additional information for log handlers.
* @param array $context {
* Additional information for log handlers.
*
* @type string $source Optional. Determines log file to write to. Default 'log'.
* @type bool $_legacy Optional. Default false. True to use outdated log format
@ -99,10 +103,10 @@ class WC_Log_Handler_File extends WC_Log_Handler {
/**
* Builds a log entry text from timestamp, level and message.
*
* @param int $timestamp Log timestamp.
* @param string $level emergency|alert|critical|error|warning|notice|info|debug
* @param int $timestamp Log timestamp.
* @param string $level emergency|alert|critical|error|warning|notice|info|debug.
* @param string $message Log message.
* @param array $context Additional information for log handlers.
* @param array $context Additional information for log handlers.
*
* @return string Formatted log entry.
*/
@ -115,8 +119,8 @@ class WC_Log_Handler_File extends WC_Log_Handler {
$handle = 'log';
}
$message = apply_filters( 'woocommerce_logger_add_message', $message, $handle );
$time = date_i18n( 'm-d-Y @ H:i:s' );
$entry = "{$time} - {$message}";
$time = date_i18n( 'm-d-Y @ H:i:s' );
$entry = "{$time} - {$message}";
} else {
$entry = parent::format_entry( $timestamp, $level, $message, $context );
}
@ -144,11 +148,13 @@ class WC_Log_Handler_File extends WC_Log_Handler {
@fclose( $temphandle );
if ( defined( 'FS_CHMOD_FILE' ) ) {
@chmod( $file, FS_CHMOD_FILE );
@chmod( $file, FS_CHMOD_FILE ); // phpcs:ignore WordPress.VIP.FileSystemWritesDisallow.chmod_chmod
}
}
if ( $resource = @fopen( $file, $mode ) ) {
$resource = @fopen( $file, $mode );
if ( $resource ) {
$this->handles[ $handle ] = $resource;
return true;
}
@ -170,7 +176,7 @@ class WC_Log_Handler_File extends WC_Log_Handler {
/**
* Close a handle.
*
* @param string $handle
* @param string $handle Log handle.
* @return bool success
*/
protected function close( $handle ) {
@ -187,8 +193,8 @@ class WC_Log_Handler_File extends WC_Log_Handler {
/**
* Add a log entry to chosen file.
*
* @param string $entry Log entry text
* @param string $handle Log entry handle
* @param string $entry Log entry text.
* @param string $handle Log entry handle.
*
* @return bool True if write was successful.
*/
@ -211,7 +217,7 @@ class WC_Log_Handler_File extends WC_Log_Handler {
/**
* Clear entries from chosen file.
*
* @param string $handle
* @param string $handle Log handle.
*
* @return bool
*/
@ -237,7 +243,7 @@ class WC_Log_Handler_File extends WC_Log_Handler {
/**
* Remove/delete the chosen file.
*
* @param string $handle
* @param string $handle Log handle.
*
* @return bool
*/
@ -246,9 +252,9 @@ class WC_Log_Handler_File extends WC_Log_Handler {
$file = self::get_log_file_path( $handle );
if ( $file ) {
if ( is_file( $file ) && is_writable( $file ) ) {
if ( is_file( $file ) && is_writable( $file ) ) { // phpcs:ignore WordPress.VIP.FileSystemWritesDisallow.file_ops_is_writable
$this->close( $handle ); // Close first to be certain no processes keep it alive after it is unlinked.
$removed = unlink( $file );
$removed = unlink( $file ); // phpcs:ignore WordPress.VIP.FileSystemWritesDisallow.file_ops_unlink
}
do_action( 'woocommerce_log_remove', $handle, $removed );
}
@ -261,7 +267,7 @@ class WC_Log_Handler_File extends WC_Log_Handler {
*
* Compares the size of the log file to determine whether it is over the size limit.
*
* @param string $handle Log handle
* @param string $handle Log handle.
* @return bool True if if should be rotated.
*/
protected function should_rotate( $handle ) {
@ -292,7 +298,7 @@ class WC_Log_Handler_File extends WC_Log_Handler {
* base.0.log -> base.1.log
* base.log -> base.0.log
*
* @param string $handle Log handle
* @param string $handle Log handle.
*/
protected function log_rotate( $handle ) {
for ( $i = 8; $i >= 0; $i-- ) {
@ -304,28 +310,28 @@ class WC_Log_Handler_File extends WC_Log_Handler {
/**
* Increment a log file suffix.
*
* @param string $handle Log handle
* @param string $handle Log handle.
* @param null|int $number Optional. Default null. Log suffix number to be incremented.
* @return bool True if increment was successful, otherwise false.
*/
protected function increment_log_infix( $handle, $number = null ) {
if ( null === $number ) {
$suffix = '';
$suffix = '';
$next_suffix = '.0';
} else {
$suffix = '.' . $number;
$next_suffix = '.' . ($number + 1);
$suffix = '.' . $number;
$next_suffix = '.' . ( $number + 1 );
}
$rename_from = self::get_log_file_path( "{$handle}{$suffix}" );
$rename_to = self::get_log_file_path( "{$handle}{$next_suffix}" );
$rename_to = self::get_log_file_path( "{$handle}{$next_suffix}" );
if ( $this->is_open( $rename_from ) ) {
$this->close( $rename_from );
}
if ( is_writable( $rename_from ) ) {
return rename( $rename_from, $rename_to );
if ( is_writable( $rename_from ) ) { // phpcs:ignore WordPress.VIP.FileSystemWritesDisallow.file_ops_is_writable
return rename( $rename_from, $rename_to ); // phpcs:ignore WordPress.VIP.FileSystemWritesDisallow.file_ops_rename
} else {
return false;
}
@ -366,12 +372,12 @@ class WC_Log_Handler_File extends WC_Log_Handler {
/**
* Cache log to write later.
*
* @param string $entry Log entry text
* @param string $handle Log entry handle
* @param string $entry Log entry text.
* @param string $handle Log entry handle.
*/
protected function cache_log( $entry, $handle ) {
$this->cached_logs[] = array(
'entry' => $entry,
'entry' => $entry,
'handle' => $handle,
);
}

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