From c6d0d059fdd87d9ce24d0a04aefc282b9550860c Mon Sep 17 00:00:00 2001 From: Mike Jolley Date: Fri, 26 Aug 2016 12:22:05 +0100 Subject: [PATCH 01/14] Remove typecasts on get --- includes/class-wc-coupon.php | 42 ++++++++++++++++++++++++++++++------ 1 file changed, 35 insertions(+), 7 deletions(-) diff --git a/includes/class-wc-coupon.php b/includes/class-wc-coupon.php index 5210a460601..2f227269126 100644 --- a/includes/class-wc-coupon.php +++ b/includes/class-wc-coupon.php @@ -91,6 +91,8 @@ class WC_Coupon extends WC_Legacy_Coupon { * @param mixed $code code of the coupon to load */ public function __construct( $code = '' ) { + parent::__construct( $code ); + if ( $code instanceof WC_Coupon ) { $this->read( absint( $code->get_id() ) ); } elseif ( $coupon = apply_filters( 'woocommerce_get_shop_coupon_data', false, $code ) ) { @@ -126,7 +128,7 @@ class WC_Coupon extends WC_Legacy_Coupon { * @return integer */ public function get_id() { - return absint( $this->_data['id'] ); + return $this->_data['id']; } /** @@ -180,7 +182,7 @@ class WC_Coupon extends WC_Legacy_Coupon { * @return integer */ public function get_usage_count() { - return absint( $this->_data['usage_count'] ); + return $this->_data['usage_count']; } /** @@ -189,7 +191,7 @@ class WC_Coupon extends WC_Legacy_Coupon { * @return bool */ public function get_individual_use() { - return (bool) $this->_data['individual_use']; + return $this->_data['individual_use']; } /** @@ -216,7 +218,7 @@ class WC_Coupon extends WC_Legacy_Coupon { * @return integer */ public function get_usage_limit() { - return absint( $this->_data['usage_limit'] ); + return $this->_data['usage_limit']; } /** @@ -225,7 +227,7 @@ class WC_Coupon extends WC_Legacy_Coupon { * @return integer */ public function get_usage_limit_per_user() { - return absint( $this->_data['usage_limit_per_user'] ); + return $this->_data['usage_limit_per_user']; } /** @@ -243,7 +245,7 @@ class WC_Coupon extends WC_Legacy_Coupon { * @return bool */ public function get_free_shipping() { - return (bool) $this->_data['free_shipping']; + return $this->_data['free_shipping']; } /** @@ -270,7 +272,7 @@ class WC_Coupon extends WC_Legacy_Coupon { * @return bool */ public function get_exclude_sale_items() { - return (bool) $this->_data['exclude_sale_items']; + return $this->_data['exclude_sale_items']; } /** @@ -607,6 +609,32 @@ class WC_Coupon extends WC_Legacy_Coupon { return; } + + parent::read( $id ); + + if ( ! $this->get_id() ) { + return; + } + + + + $this->set_props( array( + 'product_id' => get_metadata( 'order_item', $this->get_id(), '_product_id', true ), + 'variation_id' => get_metadata( 'order_item', $this->get_id(), '_variation_id', true ), + 'quantity' => get_metadata( 'order_item', $this->get_id(), '_qty', true ), + 'tax_class' => get_metadata( 'order_item', $this->get_id(), '_tax_class', true ), + 'subtotal' => get_metadata( 'order_item', $this->get_id(), '_line_subtotal', true ), + 'total' => get_metadata( 'order_item', $this->get_id(), '_line_total', true ), + 'taxes' => get_metadata( 'order_item', $this->get_id(), '_line_tax_data', true ), + ) ); + + + + + + + + $post_object = get_post( $id ); // Only continue reading if this coupon exists... From 48243109c0eae40a1ab89acd003ddecd785e1d62 Mon Sep 17 00:00:00 2001 From: Mike Jolley Date: Fri, 26 Aug 2016 12:23:53 +0100 Subject: [PATCH 02/14] This is ran on set --- includes/class-wc-coupon.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/includes/class-wc-coupon.php b/includes/class-wc-coupon.php index 2f227269126..029b61add49 100644 --- a/includes/class-wc-coupon.php +++ b/includes/class-wc-coupon.php @@ -137,7 +137,7 @@ class WC_Coupon extends WC_Legacy_Coupon { * @return string */ public function get_code() { - return apply_filters( 'woocommerce_coupon_code', $this->_data['code'] ); + return $this->_data['code']; } /** From 7405053a6a6d95eca75cd30cd55e44cd1a670ba2 Mon Sep 17 00:00:00 2001 From: Mike Jolley Date: Fri, 26 Aug 2016 12:33:33 +0100 Subject: [PATCH 03/14] Add exceptions --- includes/class-wc-coupon.php | 39 +++++++++++++++++++++++++++++++----- 1 file changed, 34 insertions(+), 5 deletions(-) diff --git a/includes/class-wc-coupon.php b/includes/class-wc-coupon.php index 029b61add49..d16a8fd1e06 100644 --- a/includes/class-wc-coupon.php +++ b/includes/class-wc-coupon.php @@ -406,6 +406,7 @@ class WC_Coupon extends WC_Legacy_Coupon { * Set coupon code. * @since 2.7.0 * @param string $code + * @throws WC_Data_Exception */ public function set_code( $code ) { $this->_data['code'] = apply_filters( 'woocommerce_coupon_code', $code ); @@ -415,6 +416,7 @@ class WC_Coupon extends WC_Legacy_Coupon { * Set coupon description. * @since 2.7.0 * @param string $description + * @throws WC_Data_Exception */ public function set_description( $description ) { $this->_data['description'] = $description; @@ -424,8 +426,12 @@ class WC_Coupon extends WC_Legacy_Coupon { * Set discount type. * @since 2.7.0 * @param string $discount_type + * @throws WC_Data_Exception */ public function set_discount_type( $discount_type ) { + if ( ! in_array( $discount_type, wc_get_coupon_types() ) ) { + $this->error( 'coupon_invalid_discount_type', __( 'Invalid discount type', 'woocommerce' ) ); + } $this->_data['discount_type'] = $discount_type; } @@ -433,6 +439,7 @@ class WC_Coupon extends WC_Legacy_Coupon { * Set amount. * @since 2.7.0 * @param float $amount + * @throws WC_Data_Exception */ public function set_amount( $amount ) { $this->_data['amount'] = wc_format_decimal( $amount ); @@ -442,6 +449,7 @@ class WC_Coupon extends WC_Legacy_Coupon { * Set expiration date. * @since 2.7.0 * @param string $date + * @throws WC_Data_Exception */ public function set_expiry_date( $date ) { if ( ! is_numeric( $date ) ) { @@ -455,6 +463,7 @@ class WC_Coupon extends WC_Legacy_Coupon { * Set how many times this coupon has been used. * @since 2.7.0 * @param int $usage_count + * @throws WC_Data_Exception */ public function set_usage_count( $usage_count ) { $this->_data['usage_count'] = absint( $usage_count ); @@ -464,6 +473,7 @@ class WC_Coupon extends WC_Legacy_Coupon { * Set if this coupon can only be used once. * @since 2.7.0 * @param bool $is_individual_use + * @throws WC_Data_Exception */ public function set_individual_use( $is_individual_use ) { $this->_data['individual_use'] = (bool) $is_individual_use; @@ -473,24 +483,27 @@ class WC_Coupon extends WC_Legacy_Coupon { * Set the product IDs this coupon can be used with. * @since 2.7.0 * @param array $product_ids + * @throws WC_Data_Exception */ public function set_product_ids( $product_ids ) { - $this->_data['product_ids'] = $product_ids; + $this->_data['product_ids'] = (array) $product_ids; } /** * Set the product IDs this coupon cannot be used with. * @since 2.7.0 * @param array $excluded_product_ids + * @throws WC_Data_Exception */ public function set_excluded_product_ids( $excluded_product_ids ) { - $this->_data['exclude_product_ids'] = $excluded_product_ids; + $this->_data['exclude_product_ids'] = (array) $excluded_product_ids; } /** * Set the amount of times this coupon can be used. * @since 2.7.0 * @param int $usage_limit + * @throws WC_Data_Exception */ public function set_usage_limit( $usage_limit ) { $this->_data['usage_limit'] = absint( $usage_limit ); @@ -500,6 +513,7 @@ class WC_Coupon extends WC_Legacy_Coupon { * Set the amount of times this coupon can be used per user. * @since 2.7.0 * @param int $usage_limit + * @throws WC_Data_Exception */ public function set_usage_limit_per_user( $usage_limit ) { $this->_data['usage_limit_per_user'] = absint( $usage_limit ); @@ -509,6 +523,7 @@ class WC_Coupon extends WC_Legacy_Coupon { * Set usage limit to x number of items. * @since 2.7.0 * @param int $limit_usage_to_x_items + * @throws WC_Data_Exception */ public function set_limit_usage_to_x_items( $limit_usage_to_x_items ) { $this->_data['limit_usage_to_x_items'] = $limit_usage_to_x_items; @@ -518,6 +533,7 @@ class WC_Coupon extends WC_Legacy_Coupon { * Set if this coupon enables free shipping or not. * @since 2.7.0 * @param bool $free_shipping + * @throws WC_Data_Exception */ public function set_free_shipping( $free_shipping ) { $this->_data['free_shipping'] = (bool) $free_shipping; @@ -527,24 +543,27 @@ class WC_Coupon extends WC_Legacy_Coupon { * Set the product category IDs this coupon can be used with. * @since 2.7.0 * @param array $product_categories + * @throws WC_Data_Exception */ public function set_product_categories( $product_categories ) { - $this->_data['product_categories'] = $product_categories; + $this->_data['product_categories'] = (array) $product_categories; } /** * Set the product category IDs this coupon cannot be used with. * @since 2.7.0 * @param array $excluded_product_categories + * @throws WC_Data_Exception */ public function set_excluded_product_categories( $excluded_product_categories ) { - $this->_data['exclude_product_categories'] = $excluded_product_categories; + $this->_data['exclude_product_categories'] = (array) $excluded_product_categories; } /** * Set if this coupon should excluded sale items or not. * @since 2.7.0 * @param bool $exclude_sale_items + * @throws WC_Data_Exception */ public function set_exclude_sale_items( $exclude_sale_items ) { $this->_data['exclude_sale_items'] = (bool) $exclude_sale_items; @@ -554,6 +573,7 @@ class WC_Coupon extends WC_Legacy_Coupon { * Set the minimum spend amount. * @since 2.7.0 * @param float $amount + * @throws WC_Data_Exception */ public function set_minimum_amount( $amount ) { $this->_data['minimum_amount'] = wc_format_decimal( $amount ); @@ -563,6 +583,7 @@ class WC_Coupon extends WC_Legacy_Coupon { * Set the maximum spend amount. * @since 2.7.0 * @param float $amount + * @throws WC_Data_Exception */ public function set_maximum_amount( $amount ) { $this->_data['maximum_amount'] = wc_format_decimal( $amount ); @@ -572,15 +593,23 @@ class WC_Coupon extends WC_Legacy_Coupon { * Set email restrictions. * @since 2.7.0 * @param array $emails + * @throws WC_Data_Exception */ public function set_email_restrictions( $emails = array() ) { - $this->_data['customer_email'] = array_map( 'sanitize_email', $emails ); + $emails = array_filter( array_map( 'sanitize_email', (array) $emails ) ); + foreach ( $emails as $email ) { + if ( ! is_email( $email ) ) { + $this->error( 'coupon_invalid_email_address', __( 'Invalid email address restriction', 'woocommerce' ) ); + } + } + $this->_data['customer_email'] = $emails; } /** * Set which users have used this coupon. * @since 2.7.0 * @param array $used_by + * @throws WC_Data_Exception */ public function set_used_by( $used_by ) { $this->_data['used_by'] = array_filter( $used_by ); From cd81622d15264761efb0d717f0d1f0fb1cbca323 Mon Sep 17 00:00:00 2001 From: Mike Jolley Date: Fri, 26 Aug 2016 12:52:22 +0100 Subject: [PATCH 04/14] Read props --- includes/class-wc-coupon.php | 87 +++++++++++------------------------- 1 file changed, 25 insertions(+), 62 deletions(-) diff --git a/includes/class-wc-coupon.php b/includes/class-wc-coupon.php index d16a8fd1e06..6508b24cdef 100644 --- a/includes/class-wc-coupon.php +++ b/includes/class-wc-coupon.php @@ -633,80 +633,43 @@ class WC_Coupon extends WC_Legacy_Coupon { * @param int $id */ public function read( $id ) { - if ( 0 === $id ) { - $this->_data['id'] = 0; - return; - } - - parent::read( $id ); if ( ! $this->get_id() ) { return; } - - - $this->set_props( array( - 'product_id' => get_metadata( 'order_item', $this->get_id(), '_product_id', true ), - 'variation_id' => get_metadata( 'order_item', $this->get_id(), '_variation_id', true ), - 'quantity' => get_metadata( 'order_item', $this->get_id(), '_qty', true ), - 'tax_class' => get_metadata( 'order_item', $this->get_id(), '_tax_class', true ), - 'subtotal' => get_metadata( 'order_item', $this->get_id(), '_line_subtotal', true ), - 'total' => get_metadata( 'order_item', $this->get_id(), '_line_total', true ), - 'taxes' => get_metadata( 'order_item', $this->get_id(), '_line_tax_data', true ), - ) ); - - - - - - - - $post_object = get_post( $id ); - // Only continue reading if this coupon exists... - if ( empty( $post_object ) || empty( $post_object->ID ) ) { - $this->_data['id'] = 0; + if ( ! $post_object ) { return; } - $coupon_id = $this->_data['id'] = absint( $post_object->ID ); - - // Map standard coupon data - $this->set_code( $post_object->post_title ); - $this->set_description( $post_object->post_excerpt ); - $this->set_discount_type( get_post_meta( $coupon_id, 'discount_type', true ) ); - $this->set_amount( get_post_meta( $coupon_id, 'coupon_amount', true ) ); - $this->set_expiry_date( get_post_meta( $coupon_id, 'expiry_date', true ) ); - $this->set_usage_count( get_post_meta( $coupon_id, 'usage_count', true ) ); - // Map meta data - $individual_use = ( 'yes' === get_post_meta( $coupon_id, 'individual_use', true ) ); - $this->set_individual_use( $individual_use ); - $product_ids = explode( ',', get_post_meta( $coupon_id, 'product_ids', true ), -1 ); - $this->set_product_ids( $product_ids ); - $exclude_product_ids = explode( ',', get_post_meta( $coupon_id, 'exclude_product_ids', true ), -1 ); - $this->set_excluded_product_ids( $exclude_product_ids ); - $this->set_usage_limit( get_post_meta( $coupon_id, 'usage_limit', true ) ); - $this->set_usage_limit_per_user( get_post_meta( $coupon_id, 'usage_limit_per_user', true ) ); - $this->set_limit_usage_to_x_items( get_post_meta( $coupon_id, 'limit_usage_to_x_items', true ) ); - $free_shipping = ( 'yes' === get_post_meta( $coupon_id, 'free_shipping', true ) ); - $this->set_free_shipping( $free_shipping ); - $product_categories = get_post_meta( $coupon_id, 'product_categories', true ); - $product_categories = ( ! empty( $product_categories ) ? $product_categories : array() ); - $this->set_product_categories( $product_categories ); - $exclude_product_categories = get_post_meta( $coupon_id, 'exclude_product_categories', true ); - $exclude_product_categories = ( ! empty( $exclude_product_categories ) ? $exclude_product_categories : array() ); - $this->set_excluded_product_categories( $exclude_product_categories ); - $exclude_sale_items = ( 'yes' === get_post_meta( $coupon_id, 'exclude_sale_items', true ) ); - $this->set_exclude_sale_items( $exclude_sale_items ); - $this->set_minimum_amount( get_post_meta( $coupon_id, 'minimum_amount', true ) ); - $this->set_maximum_amount( get_post_meta( $coupon_id, 'maximum_amount', true ) ); - $email_restrictions = get_post_meta( $coupon_id, 'customer_email', true ) ; - $this->set_email_restrictions( ! empty( $email_restrictions ) ? $email_restrictions : array() ); - $this->set_used_by( (array) get_post_meta( $coupon_id, '_used_by' ) ); + $coupon_id = absint( $post_object->ID ); + $this->set_props( array( + 'id' => $coupon_id, + 'code' => $post_object->post_title, + 'description' => $post_object->post_excerpt, + 'discount_type' => get_post_meta( $coupon_id, 'discount_type', true ), + 'amount' => get_post_meta( $coupon_id, 'coupon_amount', true ), + 'expiry_date' => get_post_meta( $coupon_id, 'expiry_date', true ), + 'usage_count' => get_post_meta( $coupon_id, 'usage_count', true ), + 'individual_use' => 'yes' === get_post_meta( $coupon_id, 'individual_use', true ), + 'product_ids' => explode( ',', get_post_meta( $coupon_id, 'product_ids', true ), -1 ), + 'excluded_product_ids' => explode( ',', get_post_meta( $coupon_id, 'exclude_product_ids', true ), -1 ), + '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' => get_post_meta( $coupon_id, 'limit_usage_to_x_items', true ), + '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' ) ), + ) ); $this->read_meta_data(); do_action( 'woocommerce_coupon_loaded', $this ); From 69c48db0a80c330c4e9756662a639040b0d0978d Mon Sep 17 00:00:00 2001 From: Mike Jolley Date: Fri, 26 Aug 2016 12:53:02 +0100 Subject: [PATCH 05/14] Correct ids method --- includes/class-wc-coupon.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/includes/class-wc-coupon.php b/includes/class-wc-coupon.php index 6508b24cdef..e6031977d18 100644 --- a/includes/class-wc-coupon.php +++ b/includes/class-wc-coupon.php @@ -747,7 +747,7 @@ class WC_Coupon extends WC_Legacy_Coupon { update_post_meta( $coupon_id, 'coupon_amount', $this->get_amount() ); update_post_meta( $coupon_id, 'individual_use', ( true === $this->get_individual_use() ) ? 'yes' : 'no' ); update_post_meta( $coupon_id, 'product_ids', implode( ',', array_filter( array_map( 'intval', $this->get_product_ids() ) ) ) ); - update_post_meta( $coupon_id, 'exclude_product_ids', implode( ',', array_filter( array_map( 'intval', $this->get_excluded_product_categories() ) ) ) ); + update_post_meta( $coupon_id, 'exclude_product_ids', implode( ',', array_filter( array_map( 'intval', $this->get_excluded_product_ids() ) ) ) ); update_post_meta( $coupon_id, 'usage_limit', $this->get_usage_limit() ); update_post_meta( $coupon_id, 'usage_limit_per_user', $this->get_usage_limit_per_user() ); update_post_meta( $coupon_id, 'limit_usage_to_x_items', $this->get_limit_usage_to_x_items() ); From b4746e28cf1d2b534a14e6f0d09fdd64f97d3f6b Mon Sep 17 00:00:00 2001 From: Mike Jolley Date: Fri, 26 Aug 2016 13:13:50 +0100 Subject: [PATCH 06/14] Optimise read_manual_coupon --- includes/class-wc-coupon.php | 17 +++-------------- 1 file changed, 3 insertions(+), 14 deletions(-) diff --git a/includes/class-wc-coupon.php b/includes/class-wc-coupon.php index e6031977d18..0e41f4c5f97 100644 --- a/includes/class-wc-coupon.php +++ b/includes/class-wc-coupon.php @@ -769,23 +769,12 @@ class WC_Coupon extends WC_Legacy_Coupon { * @param array $coupon Array of coupon properties */ public function read_manual_coupon( $code, $coupon ) { - // This will set most of our fields correctly - foreach ( $this->_data as $key => $value ) { - if ( isset( $coupon[ $key ] ) ) { - $this->_data[ $key ] = $coupon[ $key ]; - } - } - // product_ids and exclude_product_ids could be passed in as an empty string '', or comma separated values, when it should be an empty array for the new format. $convert_fields_to_array = array( 'product_ids', 'exclude_product_ids' ); foreach ( $convert_fields_to_array as $field ) { if ( ! is_array( $coupon[ $field ] ) ) { _doing_it_wrong( $field, $field . ' should be an array instead of a string.', '2.7' ); - if ( empty( $coupon[ $field ] ) ) { - $this->_data[ $field ] = array(); - } else { - $this->_data[ $field ] = explode( ',', $coupon[ $field ] ); - } + $coupon[ $field ] = array_filter( explode( ',', (array) $coupon[ $field ] ) ); } } @@ -794,12 +783,12 @@ class WC_Coupon extends WC_Legacy_Coupon { foreach ( $yes_no_fields as $field ) { if ( 'yes' === $coupon[ $field ] || 'no' === $coupon[ $field ] ) { _doing_it_wrong( $field, $field . ' should be true or false instead of yes or no.', '2.7' ); - $this->_data[ $field ] = ( 'yes' === $coupon[ $field ] ); + $coupon[ $field ] = 'yes' === $coupon[ $field ]; } } - // set our code $this->set_code( $code ); + $this->set_props( $coupon ); } /* From 210763e5369c056fd7dd4c2a4cd0a968827fdc62 Mon Sep 17 00:00:00 2001 From: Mike Jolley Date: Fri, 26 Aug 2016 14:50:17 +0100 Subject: [PATCH 07/14] use CRUD in admin --- .../class-wc-meta-box-coupon-data.php | 144 ++++++++++-------- includes/class-wc-coupon.php | 59 ++++--- 2 files changed, 114 insertions(+), 89 deletions(-) diff --git a/includes/admin/meta-boxes/class-wc-meta-box-coupon-data.php b/includes/admin/meta-boxes/class-wc-meta-box-coupon-data.php index 495d36c3f60..f0488f215d6 100644 --- a/includes/admin/meta-boxes/class-wc-meta-box-coupon-data.php +++ b/includes/admin/meta-boxes/class-wc-meta-box-coupon-data.php @@ -26,6 +26,8 @@ class WC_Meta_Box_Coupon_Data { */ public static function output( $post ) { wp_nonce_field( 'woocommerce_save_data', 'woocommerce_meta_nonce' ); + + $coupon = new WC_Coupon( $post->ID ); ?>