2016-11-09 12:21:18 +00:00
< ? php
if ( ! defined ( 'ABSPATH' ) ) {
exit ;
}
/**
* WC Coupon Data Store : Custom Post Type .
*
2017-03-15 16:36:53 +00:00
* @ version 3.0 . 0
2016-11-09 12:21:18 +00:00
* @ category Class
* @ author WooThemes
*/
2016-11-22 13:54:51 +00:00
class WC_Coupon_Data_Store_CPT extends WC_Data_Store_WP implements WC_Coupon_Data_Store_Interface , WC_Object_Data_Store_Interface {
2016-11-21 23:48:49 +00:00
/**
* Internal meta type used to store coupon data .
2017-03-15 16:36:53 +00:00
* @ since 3.0 . 0
2016-11-21 23:48:49 +00:00
* @ var string
*/
protected $meta_type = 'post' ;
/**
* Data stored in meta keys , but not considered " meta " for a coupon .
2017-03-15 16:36:53 +00:00
* @ since 3.0 . 0
2016-11-21 23:48:49 +00:00
* @ var array
*/
protected $internal_meta_keys = array (
'discount_type' ,
'coupon_amount' ,
'expiry_date' ,
2017-03-15 14:38:57 +00:00
'date_expires' ,
2016-11-21 23:48:49 +00:00
'usage_count' ,
'individual_use' ,
'product_ids' ,
'exclude_product_ids' ,
'usage_limit' ,
'usage_limit_per_user' ,
'limit_usage_to_x_items' ,
'free_shipping' ,
'product_categories' ,
'exclude_product_categories' ,
'exclude_sale_items' ,
'minimum_amount' ,
'maximum_amount' ,
'customer_email' ,
'_used_by' ,
'_edit_lock' ,
'_edit_last' ,
);
2016-11-09 12:21:18 +00:00
/**
* Method to create a new coupon in the database .
2016-11-14 10:29:25 +00:00
*
2017-03-15 16:36:53 +00:00
* @ since 3.0 . 0
2016-11-09 12:21:18 +00:00
* @ param WC_Coupon
*/
public function create ( & $coupon ) {
2017-03-13 21:24:05 +00:00
$coupon -> set_date_created ( current_time ( 'timestamp' , true ) );
2016-11-09 12:21:18 +00:00
$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 (),
'post_content' => '' ,
'post_excerpt' => $coupon -> get_description (),
2017-03-22 12:01:38 +00:00
'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 () ),
2016-11-09 12:21:18 +00:00
) ), true );
if ( $coupon_id ) {
$coupon -> set_id ( $coupon_id );
2017-01-23 20:20:29 +00:00
$this -> update_post_meta ( $coupon );
2016-11-09 12:21:18 +00:00
$coupon -> save_meta_data ();
2016-11-15 23:25:36 +00:00
$coupon -> apply_changes ();
2016-11-09 12:21:18 +00:00
do_action ( 'woocommerce_new_coupon' , $coupon_id );
}
}
/**
* Method to read a coupon .
2016-11-14 10:29:25 +00:00
*
2017-03-15 16:36:53 +00:00
* @ since 3.0 . 0
2016-11-09 12:21:18 +00:00
* @ param WC_Coupon
*/
public function read ( & $coupon ) {
$coupon -> set_defaults ();
2017-01-10 22:43:33 +00:00
if ( ! $coupon -> get_id () || ! ( $post_object = get_post ( $coupon -> get_id () ) ) || 'shop_coupon' !== $post_object -> post_type ) {
2016-11-09 12:21:18 +00:00
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 ,
2017-03-23 00:10:29 +00:00
'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 ,
2017-03-15 14:38:57 +00:00
'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 ),
2016-11-09 12:21:18 +00:00
'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' => 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' ) ),
) );
$coupon -> read_meta_data ();
$coupon -> set_object_read ( true );
do_action ( 'woocommerce_coupon_loaded' , $coupon );
}
/**
* Updates a coupon in the database .
2016-11-14 10:29:25 +00:00
*
2017-03-15 16:36:53 +00:00
* @ since 3.0 . 0
2016-11-09 12:21:18 +00:00
* @ param WC_Coupon
*/
public function update ( & $coupon ) {
2017-04-05 21:39:41 +00:00
$coupon -> save_meta_data ();
2016-11-09 12:21:18 +00:00
$post_data = array (
'ID' => $coupon -> get_id (),
'post_title' => $coupon -> get_code (),
'post_excerpt' => $coupon -> get_description (),
);
wp_update_post ( $post_data );
2017-04-05 21:39:41 +00:00
$coupon -> read_meta_data ( true ); // Refresh internal meta data, in case things were hooked into `save_post` or another WP hook.
2016-11-09 12:21:18 +00:00
$this -> update_post_meta ( $coupon );
2016-11-15 23:25:36 +00:00
$coupon -> apply_changes ();
2016-11-09 12:21:18 +00:00
do_action ( 'woocommerce_update_coupon' , $coupon -> get_id () );
}
/**
* Deletes a coupon from the database .
2016-11-14 10:29:25 +00:00
*
2017-03-15 16:36:53 +00:00
* @ since 3.0 . 0
2016-11-09 12:21:18 +00:00
* @ param WC_Coupon
2016-11-15 18:11:25 +00:00
* @ param array $args Array of args to pass to the delete method .
2016-11-09 12:21:18 +00:00
*/
2016-11-15 18:11:25 +00:00
public function delete ( & $coupon , $args = array () ) {
$args = wp_parse_args ( $args , array (
'force_delete' => false ,
) );
2016-11-09 12:21:18 +00:00
$id = $coupon -> get_id ();
2016-11-15 18:11:25 +00:00
if ( $args [ 'force_delete' ] ) {
2016-11-09 12:21:18 +00:00
wp_delete_post ( $coupon -> get_id () );
$coupon -> set_id ( 0 );
2016-12-29 22:22:12 +00:00
do_action ( 'woocommerce_delete_coupon' , $id );
2016-11-09 12:21:18 +00:00
} else {
wp_trash_post ( $coupon -> get_id () );
2016-12-29 22:22:12 +00:00
do_action ( 'woocommerce_trash_coupon' , $id );
2016-11-09 12:21:18 +00:00
}
}
/**
* Helper method that updates all the post meta for a coupon based on it ' s settings in the WC_Coupon class .
2016-11-14 10:29:25 +00:00
*
2016-12-12 13:56:35 +00:00
* @ param WC_Coupon
2017-03-15 16:36:53 +00:00
* @ since 3.0 . 0
2016-11-09 12:21:18 +00:00
*/
2017-01-23 20:20:29 +00:00
private function update_post_meta ( & $coupon ) {
2016-11-09 12:21:18 +00:00
$updated_props = array ();
$meta_key_to_props = array (
'discount_type' => 'discount_type' ,
'coupon_amount' => 'amount' ,
'individual_use' => 'individual_use' ,
'product_ids' => 'product_ids' ,
'exclude_product_ids' => 'excluded_product_ids' ,
'usage_limit' => 'usage_limit' ,
'usage_limit_per_user' => 'usage_limit_per_user' ,
'limit_usage_to_x_items' => 'limit_usage_to_x_items' ,
'usage_count' => 'usage_count' ,
2017-03-15 14:38:57 +00:00
'date_expires' => 'date_expires' ,
2016-11-09 12:21:18 +00:00
'free_shipping' => 'free_shipping' ,
'product_categories' => 'product_categories' ,
'exclude_product_categories' => 'excluded_product_categories' ,
'exclude_sale_items' => 'exclude_sale_items' ,
'minimum_amount' => 'minimum_amount' ,
'maximum_amount' => 'maximum_amount' ,
'customer_email' => 'email_restrictions' ,
);
2017-01-23 20:20:29 +00:00
$props_to_update = $this -> get_props_to_update ( $coupon , $meta_key_to_props );
foreach ( $props_to_update as $meta_key => $prop ) {
2016-11-09 12:21:18 +00:00
$value = $coupon -> { " get_ $prop " }( 'edit' );
switch ( $prop ) {
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' :
2016-12-12 15:29:53 +00:00
$updated = update_post_meta ( $coupon -> get_id (), $meta_key , implode ( ',' , array_filter ( array_map ( 'intval' , $value ) ) ) );
break ;
2016-11-09 12:21:18 +00:00
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' :
$updated = update_post_meta ( $coupon -> get_id (), $meta_key , array_filter ( array_map ( 'sanitize_email' , $value ) ) );
break ;
2017-03-13 21:24:05 +00:00
case 'date_expires' :
2017-03-14 19:49:40 +00:00
$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.
2017-03-13 21:24:05 +00:00
break ;
2016-11-09 12:21:18 +00:00
default :
$updated = update_post_meta ( $coupon -> get_id (), $meta_key , $value );
break ;
}
if ( $updated ) {
$updated_props [] = $prop ;
}
}
2017-01-24 21:38:02 +00:00
2017-01-25 00:09:57 +00:00
do_action ( 'woocommerce_coupon_object_updated_props' , $coupon , $updated_props );
2016-11-09 12:21:18 +00:00
}
/**
* Increase usage count for current coupon .
2016-11-14 10:29:25 +00:00
*
2017-03-15 16:36:53 +00:00
* @ since 3.0 . 0
2016-11-09 12:21:18 +00:00
* @ param WC_Coupon
* @ param string $used_by Either user ID or billing email
2017-03-08 23:27:37 +00:00
* @ return int New usage count
2016-11-09 12:21:18 +00:00
*/
public function increase_usage_count ( & $coupon , $used_by = '' ) {
2017-03-10 17:18:14 +00:00
$new_count = $this -> update_usage_count_meta ( $coupon , 'increase' );
2016-11-09 12:21:18 +00:00
if ( $used_by ) {
add_post_meta ( $coupon -> get_id (), '_used_by' , strtolower ( $used_by ) );
$coupon -> set_used_by ( ( array ) get_post_meta ( $coupon -> get_id (), '_used_by' ) );
}
2017-03-08 23:27:37 +00:00
return $new_count ;
2016-11-09 12:21:18 +00:00
}
/**
* Decrease usage count for current coupon .
2016-11-14 10:29:25 +00:00
*
2017-03-15 16:36:53 +00:00
* @ since 3.0 . 0
2016-11-09 12:21:18 +00:00
* @ param WC_Coupon
* @ param string $used_by Either user ID or billing email
2017-03-08 23:27:37 +00:00
* @ return int New usage count
2016-11-09 12:21:18 +00:00
*/
public function decrease_usage_count ( & $coupon , $used_by = '' ) {
global $wpdb ;
2017-03-10 17:18:14 +00:00
$new_count = $this -> update_usage_count_meta ( $coupon , 'decrease' );
2016-11-09 12:21:18 +00:00
if ( $used_by ) {
/**
* We ' re doing this the long way because `delete_post_meta( $id, $key, $value )` deletes .
* all instances where the key and value match , and we only want to delete one .
*/
$meta_id = $wpdb -> get_var ( $wpdb -> prepare ( " SELECT meta_id FROM $wpdb->postmeta WHERE meta_key = '_used_by' AND meta_value = %s AND post_id = %d LIMIT 1; " , $used_by , $coupon -> get_id () ) );
if ( $meta_id ) {
delete_metadata_by_mid ( 'post' , $meta_id );
$coupon -> set_used_by ( ( array ) get_post_meta ( $coupon -> get_id (), '_used_by' ) );
}
}
2017-03-08 23:27:37 +00:00
return $new_count ;
}
/**
2017-03-09 16:51:47 +00:00
* Increase or decrease the usage count for a coupon by 1.
2017-03-08 23:27:37 +00:00
*
2017-03-15 16:36:53 +00:00
* @ since 3.0 . 0
2017-03-08 23:27:37 +00:00
* @ param WC_Coupon
2017-03-09 16:51:47 +00:00
* @ param string $operation 'increase' or 'decrease'
2017-03-08 23:27:37 +00:00
* @ return int New usage count
*/
2017-03-10 17:18:14 +00:00
private function update_usage_count_meta ( & $coupon , $operation = 'increase' ) {
2017-03-08 23:27:37 +00:00
global $wpdb ;
$id = $coupon -> get_id ();
2017-03-09 16:51:47 +00:00
$operator = ( 'increase' === $operation ) ? '+' : '-' ;
2017-03-08 23:27:37 +00:00
2017-03-10 18:28:56 +00:00
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 ) );
2017-03-08 23:27:37 +00:00
2017-03-10 18:28:56 +00:00
// 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 ) );
2016-11-09 12:21:18 +00:00
}
/**
* Get the number of uses for a coupon by user ID .
2016-11-14 10:29:25 +00:00
*
2017-03-15 16:36:53 +00:00
* @ since 3.0 . 0
2016-11-09 12:21:18 +00:00
* @ param WC_Coupon
* @ param id $user_id
* @ return int
*/
public function get_usage_by_user_id ( & $coupon , $user_id ) {
global $wpdb ;
return $wpdb -> get_var ( $wpdb -> prepare ( " SELECT COUNT( meta_id ) FROM { $wpdb -> postmeta } WHERE post_id = %d AND meta_key = '_used_by' AND meta_value = %d; " , $coupon -> get_id (), $user_id ) );
}
2016-11-14 10:29:25 +00:00
/**
* Return a coupon code for a specific ID .
*
2017-03-15 16:36:53 +00:00
* @ since 3.0 . 0
2016-11-14 10:29:25 +00:00
* @ param int $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 an array of IDs for for a specific coupon code .
* Can return multiple to check for existence .
*
2017-03-15 16:36:53 +00:00
* @ since 3.0 . 0
2016-11-14 10:29:25 +00:00
* @ param string $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 ) );
}
2016-11-09 12:21:18 +00:00
}