1247 lines
		
	
	
		
			31 KiB
		
	
	
	
		
			PHP
		
	
	
	
	
	
			
		
		
	
	
			1247 lines
		
	
	
		
			31 KiB
		
	
	
	
		
			PHP
		
	
	
	
	
	
| <?php
 | |
| /**
 | |
|  * Customer Object
 | |
|  *
 | |
|  * @package     EDD
 | |
|  * @subpackage  Customers
 | |
|  * @copyright   Copyright (c) 2018, Easy Digital Downloads, LLC
 | |
|  * @license     http://opensource.org/licenses/gpl-2.0.php GNU Public License
 | |
|  * @since       2.3
 | |
|  */
 | |
| 
 | |
| // Exit if accessed directly
 | |
| defined( 'ABSPATH' ) || exit;
 | |
| 
 | |
| /**
 | |
|  * EDD_Customer Class.
 | |
|  *
 | |
|  * @since 2.3
 | |
|  * @since 3.0 No longer extends EDD_DB_Customer.
 | |
|  *
 | |
|  * @property int $id
 | |
|  * @property int $purchase_count
 | |
|  * @property float $purchase_value
 | |
|  * @property array $emails
 | |
|  * @property string $name
 | |
|  * @property string $status
 | |
|  * @property string $date_created
 | |
|  * @property string $payment_ids
 | |
|  * @property int $user_id
 | |
|  * @property string $notes
 | |
|  */
 | |
| class EDD_Customer extends \EDD\Database\Rows\Customer {
 | |
| 
 | |
| 	/**
 | |
| 	 * Customer ID.
 | |
| 	 *
 | |
| 	 * @since 2.3
 | |
| 	 * @var int
 | |
| 	 */
 | |
| 	public $id = 0;
 | |
| 
 | |
| 	/**
 | |
| 	 * The customer's purchase count
 | |
| 	 *
 | |
| 	 * @since 2.3
 | |
| 	 * @var int
 | |
| 	 */
 | |
| 	public $purchase_count = 0;
 | |
| 
 | |
| 	/**
 | |
| 	 * Lifetime value of a customer.
 | |
| 	 *
 | |
| 	 * @since 2.3
 | |
| 	 * @var float
 | |
| 	 */
 | |
| 	public $purchase_value = 0;
 | |
| 
 | |
| 	/**
 | |
| 	 * Customer's primary email.
 | |
| 	 *
 | |
| 	 * @since 2.3
 | |
| 	 * @var string
 | |
| 	 */
 | |
| 	public $email;
 | |
| 
 | |
| 	/**
 | |
| 	 * Email addresses associated with customer.
 | |
| 	 *
 | |
| 	 * @since 2.6
 | |
| 	 * @var array
 | |
| 	 */
 | |
| 	protected $emails;
 | |
| 
 | |
| 	/**
 | |
| 	 * Customer's name.
 | |
| 	 *
 | |
| 	 * @since 2.3
 | |
| 	 * @since 3.0 Visibility set to `protected`.
 | |
| 	 * @var string
 | |
| 	 */
 | |
| 	public $name;
 | |
| 
 | |
| 	/**
 | |
| 	 * The customer's status
 | |
| 	 *
 | |
| 	 * @since 3.0
 | |
| 	 * @since 3.0 Visibility set to `protected`.
 | |
| 	 * @var string
 | |
| 	 */
 | |
| 	public $status;
 | |
| 
 | |
| 	/**
 | |
| 	 * The customer's creation date
 | |
| 	 *
 | |
| 	 * @since 2.3
 | |
| 	 * @since 3.0 Visibility set to `protected`.
 | |
| 	 * @var string
 | |
| 	 */
 | |
| 	public $date_created;
 | |
| 
 | |
| 	/**
 | |
| 	 * The payment IDs associated with the customer
 | |
| 	 *
 | |
| 	 * @since 2.3
 | |
| 	 * @var string
 | |
| 	 */
 | |
| 	protected $payment_ids;
 | |
| 
 | |
| 	/**
 | |
| 	 * The user ID associated with the customer
 | |
| 	 *
 | |
| 	 * @since 2.3
 | |
| 	 * @since 3.0 Visibility set to `protected`.
 | |
| 	 * @var int
 | |
| 	 */
 | |
| 	public $user_id;
 | |
| 
 | |
| 	/**
 | |
| 	 * Notes attached to the customer record.
 | |
| 	 *
 | |
| 	 * @since 2.3
 | |
| 	 * @var string
 | |
| 	 */
 | |
| 	protected $notes;
 | |
| 
 | |
| 	/**
 | |
| 	 * Get things going
 | |
| 	 *
 | |
| 	 * @since 2.3
 | |
| 	 */
 | |
| 	public function __construct( $_id_or_email = false, $by_user_id = false ) {
 | |
| 		if ( false === $_id_or_email || ( is_numeric( $_id_or_email ) && absint( $_id_or_email ) !== (int) $_id_or_email ) ) {
 | |
| 			return false;
 | |
| 		}
 | |
| 
 | |
| 		$by_user_id = is_bool( $by_user_id ) ? $by_user_id : false;
 | |
| 
 | |
| 		if ( is_object( $_id_or_email ) ) {
 | |
| 			$customer = $_id_or_email;
 | |
| 		} else {
 | |
| 			if ( is_numeric( $_id_or_email ) ) {
 | |
| 				$field = $by_user_id ? 'user_id' : 'id';
 | |
| 			} else {
 | |
| 				$field = 'email';
 | |
| 			}
 | |
| 
 | |
| 			$customer = edd_get_customer_by( $field, $_id_or_email );
 | |
| 		}
 | |
| 
 | |
| 		if ( empty( $customer ) || ! is_object( $customer ) ) {
 | |
| 			return false;
 | |
| 		}
 | |
| 
 | |
| 		$this->setup_customer( $customer );
 | |
| 	}
 | |
| 
 | |
| 	/**
 | |
| 	 * Given the customer data, let's set the variables
 | |
| 	 *
 | |
| 	 * @since  2.3
 | |
| 	 *
 | |
| 	 * @param  object $customer Customer object.
 | |
| 	 * @return bool True if the object was setup correctly, false otherwise.
 | |
| 	 */
 | |
| 	private function setup_customer( $customer ) {
 | |
| 		if ( ! is_object( $customer ) ) {
 | |
| 			return false;
 | |
| 		}
 | |
| 
 | |
| 		foreach ( $customer as $key => $value ) {
 | |
| 			switch ( $key ) {
 | |
| 				case 'purchase_value':
 | |
| 					$this->$key = floatval( $value );
 | |
| 					break;
 | |
| 				case 'purchase_count':
 | |
| 					$this->$key = absint( $value );
 | |
| 					break;
 | |
| 				default:
 | |
| 					$this->$key = $value;
 | |
| 					break;
 | |
| 			}
 | |
| 		}
 | |
| 
 | |
| 		// Customer ID and email are the only things that are necessary, make sure they exist
 | |
| 		if ( ! empty( $this->id ) && ! empty( $this->email ) ) {
 | |
| 			return true;
 | |
| 		}
 | |
| 
 | |
| 		return false;
 | |
| 	}
 | |
| 
 | |
| 	/**
 | |
| 	 * Magic __get method to dispatch a call to retrieve a protected property.
 | |
| 	 *
 | |
| 	 * @since 3.0
 | |
| 	 *
 | |
| 	 * @param string $key
 | |
| 	 * @return mixed
 | |
| 	 */
 | |
| 	public function __get( $key = '' ) {
 | |
| 		switch ( $key ) {
 | |
| 			case 'emails':
 | |
| 				return $this->get_emails();
 | |
| 			case 'payment_ids':
 | |
| 				$payment_ids = $this->get_payment_ids();
 | |
| 				$payment_ids = implode( ',', $payment_ids );
 | |
| 				return $payment_ids;
 | |
| 			default:
 | |
| 				return isset( $this->{$key} )
 | |
| 					? $this->{$key}
 | |
| 					: edd_get_customer_meta( $this->id, $key );
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	/**
 | |
| 	 * Magic __set method to dispatch a call to update a protected property.
 | |
| 	 *
 | |
| 	 * @since 3.0
 | |
| 	 *
 | |
| 	 * @param string $key   Property name.
 | |
| 	 * @param mixed  $value Property value.
 | |
| 	 *
 | |
| 	 * @return mixed Return value of setter being dispatched to.
 | |
| 	 */
 | |
| 	public function __set( $key, $value ) {
 | |
| 		$key = sanitize_key( $key );
 | |
| 
 | |
| 		// Only real properties can be saved.
 | |
| 		$keys = array_keys( get_class_vars( get_called_class() ) );
 | |
| 
 | |
| 		if ( ! in_array( $key, $keys, true ) ) {
 | |
| 			return false;
 | |
| 		}
 | |
| 
 | |
| 		// Dispatch to setter method if value needs to be sanitized.
 | |
| 		if ( method_exists( $this, 'set_' . $key ) ) {
 | |
| 			return call_user_func( array( $this, 'set_' . $key ), $key, $value );
 | |
| 		} else {
 | |
| 			$this->{$key} = $value;
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	/**
 | |
| 	 * Creates a customer based on class vars.
 | |
| 	 *
 | |
| 	 * @since 2.3
 | |
| 	 *
 | |
| 	 * @param  array  $data Array of attributes for a customer
 | |
| 	 * @return mixed        False if not a valid creation, Customer ID if user is found or valid creation
 | |
| 	 */
 | |
| 	public function create( $data = array() ) {
 | |
| 		if ( 0 !== $this->id || empty( $data ) ) {
 | |
| 			return false;
 | |
| 		}
 | |
| 
 | |
| 		$defaults = array(
 | |
| 			'payment_ids' => '',
 | |
| 		);
 | |
| 
 | |
| 		$args = wp_parse_args( $data, $defaults );
 | |
| 		$args = $this->sanitize_columns( $args );
 | |
| 
 | |
| 		if ( empty( $args['email'] ) || ! is_email( $args['email'] ) ) {
 | |
| 			return false;
 | |
| 		}
 | |
| 
 | |
| 		/**
 | |
| 		 * Fires before a customer is created
 | |
| 		 *
 | |
| 		 * @param array $args Contains customer information such as payment ID, name, and email.
 | |
| 		 */
 | |
| 		do_action( 'edd_customer_pre_create', $args );
 | |
| 
 | |
| 		$created = false;
 | |
| 
 | |
| 		// Add the customer
 | |
| 		$customer_id = edd_add_customer( $args );
 | |
| 
 | |
| 		if ( ! empty( $customer_id ) ) {
 | |
| 
 | |
| 			// Add the primary email address for this customer
 | |
| 			edd_add_customer_email_address( array(
 | |
| 				'customer_id' => $customer_id,
 | |
| 				'email'       => $args['email'],
 | |
| 				'type'        => 'primary'
 | |
| 			) );
 | |
| 
 | |
| 			// Maybe add payments
 | |
| 			if ( ! empty( $args['payment_ids'] ) && is_array( $args['payment_ids'] ) ) {
 | |
| 				$payment_ids = array_unique( array_values( $args['payment_ids'] ) );
 | |
| 
 | |
| 				foreach ( $payment_ids as $payment_id ) {
 | |
| 					edd_update_order( $payment_id, array(
 | |
| 						'customer_id' => $customer_id
 | |
| 					) );
 | |
| 				}
 | |
| 			}
 | |
| 
 | |
| 			// We've successfully added/updated the customer, reset the class vars with the new data
 | |
| 			$customer = edd_get_customer( $customer_id );
 | |
| 
 | |
| 			// Setup the customer data with the values from DB
 | |
| 			$this->setup_customer( $customer );
 | |
| 
 | |
| 			$created = $this->id;
 | |
| 		}
 | |
| 
 | |
| 		/**
 | |
| 		 * Fires after a customer is created
 | |
| 		 *
 | |
| 		 * @param int   $created If created successfully, the customer ID.  Defaults to false.
 | |
| 		 * @param array $args Contains customer information such as payment ID, name, and email.
 | |
| 		 */
 | |
| 		do_action( 'edd_customer_post_create', $created, $args );
 | |
| 
 | |
| 		return $created;
 | |
| 	}
 | |
| 
 | |
| 	/**
 | |
| 	 * Update a customer record.
 | |
| 	 *
 | |
| 	 * @since 2.3
 | |
| 	 *
 | |
| 	 * @param array $data Array of data attributes for a customer (checked via whitelist)
 | |
| 	 * @return bool True if update was successful, false otherwise.
 | |
| 	 */
 | |
| 	public function update( $data = array() ) {
 | |
| 		if ( empty( $data ) ) {
 | |
| 			return false;
 | |
| 		}
 | |
| 
 | |
| 		$data = $this->sanitize_columns( $data );
 | |
| 
 | |
| 		do_action( 'edd_customer_pre_update', $this->id, $data );
 | |
| 
 | |
| 		$updated = false;
 | |
| 
 | |
| 		if ( edd_update_customer( $this->id, $data ) ) {
 | |
| 			$customer = edd_get_customer( $this->id );
 | |
| 			$this->setup_customer( $customer );
 | |
| 
 | |
| 			$updated = true;
 | |
| 		}
 | |
| 
 | |
| 		do_action( 'edd_customer_post_update', $updated, $this->id, $data );
 | |
| 
 | |
| 		return $updated;
 | |
| 	}
 | |
| 
 | |
| 	/**
 | |
| 	 * Attach an email address to the customer.
 | |
| 	 *
 | |
| 	 * @since 2.6
 | |
| 	 * @since 3.0.1 This method will return customer email ID or false, instead of bool
 | |
| 	 *
 | |
| 	 * @param string $email The email address to remove from the customer.
 | |
| 	 * @param bool   $primary Allows setting the email added as the primary.
 | |
| 	 *
 | |
| 	 * @return int|false ID of newly created customer email address, false on error.
 | |
| 	 */
 | |
| 	public function add_email( $email = '', $primary = false ) {
 | |
| 		if ( ! is_email( $email ) ) {
 | |
| 			return false;
 | |
| 		}
 | |
| 
 | |
| 		// Bail if email exists in the universe.
 | |
| 		if ( $this->email_exists( $email ) ) {
 | |
| 			return false;
 | |
| 		}
 | |
| 
 | |
| 		do_action( 'edd_customer_pre_add_email', $email, $this->id, $this );
 | |
| 
 | |
| 		// Primary or secondary
 | |
| 		$type = ( true === $primary )
 | |
| 			? 'primary'
 | |
| 			: 'secondary';
 | |
| 
 | |
| 		// Update is used to ensure duplicate emails are not added.
 | |
| 		$ret = edd_add_customer_email_address(
 | |
| 			array(
 | |
| 				'customer_id' => $this->id,
 | |
| 				'email'       => $email,
 | |
| 				'type'        => $type,
 | |
| 			)
 | |
| 		);
 | |
| 
 | |
| 		do_action( 'edd_customer_post_add_email', $email, $this->id, $this );
 | |
| 
 | |
| 		if ( $ret && true === $primary ) {
 | |
| 			$this->set_primary_email( $email );
 | |
| 		}
 | |
| 
 | |
| 		return $ret;
 | |
| 	}
 | |
| 
 | |
| 	/**
 | |
| 	 * Remove an email address from the customer.
 | |
| 	 *
 | |
| 	 * @since 2.6
 | |
| 	 * @since 3.0 Updated to use custom table.
 | |
| 	 *
 | |
| 	 * @param string $email The email address to remove from the customer.
 | |
| 	 * @return bool True if the email was removed successfully, false otherwise.
 | |
| 	 */
 | |
| 	public function remove_email( $email = '' ) {
 | |
| 		if ( ! is_email( $email ) ) {
 | |
| 			return false;
 | |
| 		}
 | |
| 
 | |
| 		do_action( 'edd_customer_pre_remove_email', $email, $this->id, $this );
 | |
| 
 | |
| 		$email_address = edd_get_customer_email_address_by( 'email', $email );
 | |
| 
 | |
| 		$ret = $email_address
 | |
| 			? (bool) edd_delete_customer_email_address( $email_address->id )
 | |
| 			: false;
 | |
| 
 | |
| 		do_action( 'edd_customer_post_remove_email', $email, $this->id, $this );
 | |
| 
 | |
| 		return $ret;
 | |
| 	}
 | |
| 
 | |
| 	/**
 | |
| 	 * Check if an email address already exists somewhere in the known universe
 | |
| 	 * of WordPress Users, or EDD customer email addresses.
 | |
| 	 *
 | |
| 	 * We intentionally skip the edd_customers table, to avoid race conditions
 | |
| 	 * when adding new customers and their email addresses at the same time.
 | |
| 	 *
 | |
| 	 * @since 3.0
 | |
| 	 *
 | |
| 	 * @param string $email Email address to check.
 | |
| 	 * @return boolean True if assigned to existing customer, false otherwise.
 | |
| 	 */
 | |
| 	public function email_exists( $email = '' ) {
 | |
| 
 | |
| 		// Bail if not an email address
 | |
| 		if ( ! is_email( $email ) ) {
 | |
| 			return false;
 | |
| 		}
 | |
| 
 | |
| 		// Return true if found in users table
 | |
| 		if ( email_exists( $email ) ) {
 | |
| 			return true;
 | |
| 		}
 | |
| 
 | |
| 		// Query email addresses table for this address
 | |
| 		$exists = edd_get_customer_email_address_by( 'email' , $email );
 | |
| 
 | |
| 		// Return true if found in email addresses table
 | |
| 		if ( ! empty( $exists ) ) {
 | |
| 			return true;
 | |
| 		}
 | |
| 
 | |
| 		// Not found
 | |
| 		return false;
 | |
| 	}
 | |
| 
 | |
| 	/**
 | |
| 	 * Set an email address as the customer's primary email.
 | |
| 	 *
 | |
| 	 * This will move the customer's previous primary email to an additional email.
 | |
| 	 *
 | |
| 	 * @since 2.6
 | |
| 	 * @param string $new_primary_email The email address to remove from the customer.
 | |
| 	 * @return bool True if the email was set as primary successfully, false otherwise.
 | |
| 	 */
 | |
| 	public function set_primary_email( $new_primary_email = '' ) {
 | |
| 
 | |
| 		// Default return value
 | |
| 		$retval = false;
 | |
| 
 | |
| 		// Bail if not an email
 | |
| 		if ( ! is_email( $new_primary_email ) ) {
 | |
| 			return $retval;
 | |
| 		}
 | |
| 
 | |
| 		do_action( 'edd_customer_pre_set_primary_email', $new_primary_email, $this->id, $this );
 | |
| 
 | |
| 		// Bail if already primary
 | |
| 		if ( $new_primary_email === $this->email ) {
 | |
| 			return true;
 | |
| 		}
 | |
| 
 | |
| 		// Get customer emails
 | |
| 		$emails = edd_get_customer_email_addresses( array(
 | |
| 			'customer_id' => $this->id
 | |
| 		) );
 | |
| 
 | |
| 		// Pluck addresses, to help with in_array() calls
 | |
| 		$plucked = wp_list_pluck( $emails, 'email' );
 | |
| 
 | |
| 		// Maybe fix a missing primary email address in the new table
 | |
| 		if ( ! in_array( $this->email, $plucked, true ) ) {
 | |
| 
 | |
| 			// Attempt to add the current primary if it's missing
 | |
| 			$added = edd_add_customer_email_address( array(
 | |
| 				'customer_id' => $this->id,
 | |
| 				'email'       => $this->email,
 | |
| 				'type'        => 'primary'
 | |
| 			) );
 | |
| 
 | |
| 			// Maybe re-get all customer emails and re-pluck them
 | |
| 			if ( ! empty( $added ) ) {
 | |
| 
 | |
| 				// Get customer emails
 | |
| 				$emails = edd_get_customer_email_addresses( array(
 | |
| 					'customer_id' => $this->id
 | |
| 				) );
 | |
| 
 | |
| 				// Pluck addresses, and look for the new one
 | |
| 				$plucked = wp_list_pluck( $emails, 'email' );
 | |
| 			}
 | |
| 		}
 | |
| 
 | |
| 		// Bail if not an address for this customer
 | |
| 		if ( ! in_array( $new_primary_email, $plucked, true ) ) {
 | |
| 			return $retval;
 | |
| 		}
 | |
| 
 | |
| 		// Loop through addresses and juggle them
 | |
| 		foreach ( $emails as $email ) {
 | |
| 
 | |
| 			// Make old primary a secondary
 | |
| 			if ( ( 'primary' === $email->type ) && ( $new_primary_email !== $email->email ) ) {
 | |
| 				edd_update_customer_email_address( $email->id, array(
 | |
| 					'type' => 'secondary'
 | |
| 				) );
 | |
| 			}
 | |
| 
 | |
| 			// Make new address primary
 | |
| 			if ( ( 'secondary' === $email->type ) && ( $new_primary_email === $email->email ) ) {
 | |
| 				edd_update_customer_email_address( $email->id, array(
 | |
| 					'type' => 'primary'
 | |
| 				) );
 | |
| 			}
 | |
| 		}
 | |
| 
 | |
| 		// Mismatch, so update the customer column
 | |
| 		if ( $this->email !== $new_primary_email ) {
 | |
| 
 | |
| 			// Update the email column on the customer row
 | |
| 			$this->update( array( 'email' => $new_primary_email ) );
 | |
| 
 | |
| 			// Reload the customer emails for this object
 | |
| 			$this->email  = $new_primary_email;
 | |
| 			$this->emails = $this->get_emails();
 | |
| 			$retval       = true;
 | |
| 		}
 | |
| 
 | |
| 		do_action( 'edd_customer_post_set_primary_email', $new_primary_email, $this->id, $this );
 | |
| 
 | |
| 		return (bool) $retval;
 | |
| 	}
 | |
| 
 | |
| 	/**
 | |
| 	 * Before 3.0, when the primary email address was changed, it would cascade
 | |
| 	 * through all previous purchases and update the email address associated
 | |
| 	 * with it. Since 3.0, that is no longer the case.
 | |
| 	 *
 | |
| 	 * This method contains code that is no longer used, and is provided here as
 | |
| 	 * a convenience function if needed.
 | |
| 	 *
 | |
| 	 * @since 3.0
 | |
| 	 */
 | |
| 	public function update_order_email_addresses( $email = '' ) {
 | |
| 
 | |
| 		// Get the payments
 | |
| 		$payment_ids = $this->get_payment_ids();
 | |
| 
 | |
| 		// Bail if no payments
 | |
| 		if ( empty( $payment_ids ) ) {
 | |
| 			return;
 | |
| 		}
 | |
| 
 | |
| 		// Update payment emails to primary email
 | |
| 		foreach ( $payment_ids as $payment_id ) {
 | |
| 			edd_update_payment_meta( $payment_id, 'email', $email );
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	/**
 | |
| 	 * Get the payment ids of the customer in an array.
 | |
| 	 *
 | |
| 	 * @since 2.6
 | |
| 	 *
 | |
| 	 * @return array An array of payment IDs for the customer, or an empty array if none exist.
 | |
| 	 */
 | |
| 	public function get_payment_ids() {
 | |
| 
 | |
| 		// Bail if no customer
 | |
| 		if ( empty( $this->id ) ) {
 | |
| 			return array();
 | |
| 		}
 | |
| 
 | |
| 		// Get total orders
 | |
| 		$count = edd_count_orders( array(
 | |
| 			'customer_id' => $this->id
 | |
| 		) );
 | |
| 
 | |
| 		// Get order IDs
 | |
| 		$ids = edd_get_orders( array(
 | |
| 			'customer_id'   => $this->id,
 | |
| 			'number'        => $count,
 | |
| 			'fields'        => 'ids',
 | |
| 			'no_found_rows' => true
 | |
| 		) );
 | |
| 
 | |
| 		// Cast IDs to ints
 | |
| 		return array_map( 'absint', $ids );
 | |
| 	}
 | |
| 
 | |
| 	/**
 | |
| 	 * Get an array of EDD_Payment objects from the payment_ids attached to the customer.
 | |
| 	 *
 | |
| 	 * @since 2.6
 | |
| 	 *
 | |
| 	 * @param  array|string  $status A single status as a string or an array of statuses.
 | |
| 	 * @return array An array of EDD_Payment objects or an empty array.
 | |
| 	 */
 | |
| 	public function get_payments( $status = array() ) {
 | |
| 
 | |
| 		// Get payment IDs
 | |
| 		$payment_ids = $this->get_payment_ids();
 | |
| 		$payments    = array();
 | |
| 
 | |
| 		// Bail if no IDs
 | |
| 		if ( empty( $payment_ids ) ) {
 | |
| 			return $payments;
 | |
| 		}
 | |
| 
 | |
| 		// Get payments one at a time (ugh...)
 | |
| 		foreach ( $payment_ids as $payment_id ) {
 | |
| 			$payment = new EDD_Payment( $payment_id );
 | |
| 
 | |
| 			if ( empty( $status ) || ( is_array( $status ) && in_array( $payment->status, $status, true ) ) || $status === $payment->status ) {
 | |
| 				$payments[] = $payment;
 | |
| 			}
 | |
| 		}
 | |
| 
 | |
| 		return $payments;
 | |
| 	}
 | |
| 
 | |
| 	/**
 | |
| 	 * Attach payment to the customer then triggers increasing statistics.
 | |
| 	 *
 | |
| 	 * @since 2.3
 | |
| 	 *
 | |
| 	 * @param int  $order_id     The Order ID to attach to the customer.
 | |
| 	 * @param bool $update_stats For backwards compatibility, if we should increase the stats or not.
 | |
| 	 *
 | |
| 	 * @return bool True if the attachment was successfully, false otherwise.
 | |
| 	 */
 | |
| 	public function attach_payment( $order_id = 0, $update_stats = true ) {
 | |
| 
 | |
| 		// Bail if no payment ID.
 | |
| 		if ( empty( $order_id ) ) {
 | |
| 			return false;
 | |
| 		}
 | |
| 
 | |
| 		// Get order.
 | |
| 		$order = edd_get_order( $order_id );
 | |
| 
 | |
| 		// Bail if payment does not exist.
 | |
| 		if ( empty( $order ) ) {
 | |
| 			return false;
 | |
| 		}
 | |
| 
 | |
| 		do_action( 'edd_customer_pre_attach_payment', $order->id, $this->id, $this );
 | |
| 
 | |
| 		$success = (int) $order->customer_id === (int) $this->id;
 | |
| 
 | |
| 		// Update the order if it isn't already attached.
 | |
| 		if ( ! $success ) {
 | |
| 			// Update the order.
 | |
| 			$success = (bool) edd_update_order(
 | |
| 				$order_id,
 | |
| 				array(
 | |
| 					'customer_id' => $this->id,
 | |
| 					'email'       => $this->email,
 | |
| 				)
 | |
| 			);
 | |
| 		}
 | |
| 
 | |
| 		// Maybe update stats.
 | |
| 		if ( ! empty( $success ) && ! empty( $update_stats ) ) {
 | |
| 			$this->recalculate_stats();
 | |
| 		}
 | |
| 
 | |
| 		do_action( 'edd_customer_post_attach_payment', $success, $order->id, $this->id, $this );
 | |
| 
 | |
| 		return $success;
 | |
| 	}
 | |
| 
 | |
| 	/**
 | |
| 	 * Remove a payment from this customer, then triggers reducing stats
 | |
| 	 *
 | |
| 	 * @since 2.3
 | |
| 	 *
 | |
| 	 * @param integer $payment_id   The Payment ID to remove.
 | |
| 	 * @param bool    $update_stats For backwards compatibility, if we should increase the stats or not.
 | |
| 	 *
 | |
| 	 * @return bool $detached True if removed successfully, false otherwise.
 | |
| 	 */
 | |
| 	public function remove_payment( $payment_id = 0, $update_stats = true ) {
 | |
| 
 | |
| 		// Bail if no payment ID
 | |
| 		if ( empty( $payment_id ) ) {
 | |
| 			return false;
 | |
| 		}
 | |
| 
 | |
| 		// Get payment
 | |
| 		$payment = edd_get_payment( $payment_id );
 | |
| 
 | |
| 		// Bail if payment does not exist
 | |
| 		if ( empty( $payment ) ) {
 | |
| 			return false;
 | |
| 		}
 | |
| 
 | |
| 		// Get all previous payment IDs
 | |
| 		$payments = $this->get_payment_ids();
 | |
| 
 | |
| 		// Bail if already attached
 | |
| 		if ( ! in_array( $payment_id, $payments, true ) ) {
 | |
| 			return true;
 | |
| 		}
 | |
| 
 | |
| 		// Only update stats when published or revoked
 | |
| 		if ( ! in_array( $payment->status, array( 'complete', 'revoked' ), true ) ) {
 | |
| 			$update_stats = false;
 | |
| 		}
 | |
| 
 | |
| 		do_action( 'edd_customer_pre_remove_payment', $payment->ID, $this->id, $this );
 | |
| 
 | |
| 		// Update the order
 | |
| 		$success = (bool) edd_update_order( $payment_id, array(
 | |
| 			'customer_id' => 0,
 | |
| 			'email'       => ''
 | |
| 		) );
 | |
| 
 | |
| 		// Maybe update stats
 | |
| 		if ( ! empty( $success ) && ! empty( $update_stats ) ) {
 | |
| 			$this->recalculate_stats();
 | |
| 		}
 | |
| 
 | |
| 		do_action( 'edd_customer_post_remove_payment', $success, $payment->ID, $this->id, $this );
 | |
| 
 | |
| 		return $success;
 | |
| 	}
 | |
| 
 | |
| 	/**
 | |
| 	 * Recalculate stats for this customer.
 | |
| 	 *
 | |
| 	 * This replaces the older, less accurate increase/decrease methods.
 | |
| 	 *
 | |
| 	 * @since 3.0
 | |
| 	 */
 | |
| 	public function recalculate_stats() {
 | |
| 		$this->purchase_count = edd_count_orders(
 | |
| 			array(
 | |
| 				'customer_id' => $this->id,
 | |
| 				'status'      => edd_get_net_order_statuses(),
 | |
| 				'type'        => 'sale',
 | |
| 			)
 | |
| 		);
 | |
| 
 | |
| 		global $wpdb;
 | |
| 		$statuses      = edd_get_gross_order_statuses();
 | |
| 		$status_string = implode(', ', array_fill( 0, count( $statuses ), '%s' ) );
 | |
| 
 | |
| 		$this->purchase_value = (float) $wpdb->get_var( $wpdb->prepare(
 | |
| 			"SELECT SUM(total / rate)
 | |
| 			FROM {$wpdb->edd_orders}
 | |
| 			WHERE customer_id = %d
 | |
| 			AND status IN({$status_string})",
 | |
| 			$this->id,
 | |
| 			...$statuses
 | |
| 		) );
 | |
| 
 | |
| 		// Update the customer purchase count & value
 | |
| 		return $this->update(
 | |
| 			array(
 | |
| 				'purchase_count' => $this->purchase_count,
 | |
| 				'purchase_value' => $this->purchase_value,
 | |
| 			)
 | |
| 		);
 | |
| 	}
 | |
| 
 | |
| 	/** Notes *****************************************************************/
 | |
| 
 | |
| 	/**
 | |
| 	 * Get the parsed notes for a customer as an array.
 | |
| 	 *
 | |
| 	 * @since 2.3
 | |
| 	 * @since 3.0 Use the new Notes component & API.
 | |
| 	 *
 | |
| 	 * @param integer $length The number of notes to get.
 | |
| 	 * @param integer $paged What note to start at.
 | |
| 	 *
 | |
| 	 * @return array The notes requested.
 | |
| 	 */
 | |
| 	public function get_notes( $length = 20, $paged = 1 ) {
 | |
| 
 | |
| 		// Number
 | |
| 		$length = is_numeric( $length )
 | |
| 			? absint( $length )
 | |
| 			: 20;
 | |
| 
 | |
| 		// Offset
 | |
| 		$offset = is_numeric( $paged ) && ( 1 !== $paged )
 | |
| 			? ( ( absint( $paged ) - 1 ) * $length )
 | |
| 			: 0;
 | |
| 
 | |
| 		// Return the paginated notes for back-compat
 | |
| 		return edd_get_notes( array(
 | |
| 			'object_id'   => $this->id,
 | |
| 			'object_type' => 'customer',
 | |
| 			'number'      => $length,
 | |
| 			'offset'      => $offset,
 | |
| 			'order'       => 'desc',
 | |
| 		) );
 | |
| 	}
 | |
| 
 | |
| 	/**
 | |
| 	 * Get the total number of notes we have after parsing.
 | |
| 	 *
 | |
| 	 * @since 2.3
 | |
| 	 * @since 3.0 Use the new Notes component & API.
 | |
| 	 *
 | |
| 	 * @return int The number of notes for the customer.
 | |
| 	 */
 | |
| 	public function get_notes_count() {
 | |
| 		return edd_count_notes( array(
 | |
| 			'object_id'   => $this->id,
 | |
| 			'object_type' => 'customer',
 | |
| 		) );
 | |
| 	}
 | |
| 
 | |
| 	/**
 | |
| 	 * Add a customer note.
 | |
| 	 *
 | |
| 	 * @since 2.3
 | |
| 	 * @since 3.0 Use the new Notes component & API
 | |
| 	 *
 | |
| 	 * @param string $note The note to add
 | |
| 	 * @return string|boolean The new note if added successfully, false otherwise
 | |
| 	 */
 | |
| 	public function add_note( $note = '' ) {
 | |
| 
 | |
| 		// Bail if note content is empty
 | |
| 		$note = trim( $note );
 | |
| 		if ( empty( $note ) ) {
 | |
| 			return false;
 | |
| 		}
 | |
| 
 | |
| 		/**
 | |
| 		 * Filter the note of a customer before it's added
 | |
| 		 *
 | |
| 		 * @since 2.3
 | |
| 		 * @since 3.0 No longer includes the datetime stamp
 | |
| 		 *
 | |
| 		 * @param string $note The content of the note to add
 | |
| 		 * @return string
 | |
| 		 */
 | |
| 		$note = apply_filters( 'edd_customer_add_note_string', $note );
 | |
| 
 | |
| 		/**
 | |
| 		 * Allow actions before a note is added
 | |
| 		 *
 | |
| 		 * @since 2.3
 | |
| 		 */
 | |
| 		do_action( 'edd_customer_pre_add_note', $note, $this->id, $this );
 | |
| 
 | |
| 		// Sanitize note
 | |
| 		$note = trim( wp_kses( stripslashes( $note ), edd_get_allowed_tags() ) );
 | |
| 
 | |
| 		// Try to add the note
 | |
| 		edd_add_note( array(
 | |
| 			'user_id'     => 0, // Authored by System/Bot
 | |
| 			'object_id'   => $this->id,
 | |
| 			'object_type' => 'customer',
 | |
| 			'content'     => $note,
 | |
| 		) );
 | |
| 
 | |
| 		/**
 | |
| 		 * Allow actions after a note is added
 | |
| 		 *
 | |
| 		 * @since 3.0 Changed to an empty string since notes were moved out
 | |
| 		 */
 | |
| 		do_action( 'edd_customer_post_add_note', '', $note, $this->id, $this );
 | |
| 
 | |
| 		// Return the formatted note, so we can test, as well as update any displays
 | |
| 		return $note;
 | |
| 	}
 | |
| 
 | |
| 	/** Meta ******************************************************************/
 | |
| 
 | |
| 	/**
 | |
| 	 * Retrieve customer meta field for a customer.
 | |
| 	 *
 | |
| 	 * @since 2.6
 | |
| 	 *
 | |
| 	 * @param string  $key    Optional. The meta key to retrieve. By default, returns data for all keys. Default empty.
 | |
| 	 * @param bool    $single Optional, default is false. If true, return only the first value of the specified meta_key.
 | |
| 	 *                        This parameter has no effect if meta_key is not specified.
 | |
| 	 *
 | |
| 	 * @return mixed Will be an array if $single is false. Will be value of meta data field if $single is true.
 | |
| 	 */
 | |
| 	public function get_meta( $key = '', $single = true ) {
 | |
| 		return edd_get_customer_meta( $this->id, $key, $single );
 | |
| 	}
 | |
| 
 | |
| 	/**
 | |
| 	 * Add meta data field to a customer.
 | |
| 	 *
 | |
| 	 * @since 2.6
 | |
| 	 *
 | |
| 	 * @param string $meta_key   Meta data name.
 | |
| 	 * @param mixed  $meta_value Meta data value. Must be serializable if non-scalar.
 | |
| 	 * @param bool   $unique     Optional. Whether the same key should not be added. Default false.
 | |
| 	 *
 | |
| 	 * @return int|false Meta ID on success, false on failure.
 | |
| 	 */
 | |
| 	public function add_meta( $meta_key = '', $meta_value = '', $unique = false ) {
 | |
| 		return edd_add_customer_meta( $this->id, $meta_key, $meta_value, $unique );
 | |
| 	}
 | |
| 
 | |
| 	/**
 | |
| 	 * Update customer meta field based on customer ID.
 | |
| 	 *
 | |
| 	 * Use the $prev_value parameter to differentiate between meta fields with the
 | |
| 	 * same key and order ID.
 | |
| 	 *
 | |
| 	 * If the meta field for the order does not exist, it will be added.
 | |
| 	 *
 | |
| 	 * @since 2.6
 | |
| 	 *
 | |
| 	 * @param string $meta_key   Meta data key.
 | |
| 	 * @param mixed  $meta_value Meta data value. Must be serializable if non-scalar.
 | |
| 	 * @param mixed  $prev_value Optional. Previous value to check before removing. Default empty.
 | |
| 	 *
 | |
| 	 * @return int|bool Meta ID if the key didn't exist, true on successful update, false on failure.
 | |
| 	 */
 | |
| 	public function update_meta( $meta_key = '', $meta_value = '', $prev_value = '' ) {
 | |
| 		return edd_update_customer_meta( $this->id, $meta_key, $meta_value, $prev_value );
 | |
| 	}
 | |
| 
 | |
| 	/**
 | |
| 	 * Remove meta data matching criteria from a customer.
 | |
| 	 *
 | |
| 	 * You can match based on the key, or key and value. Removing based on key and value, will keep from removing duplicate
 | |
| 	 * meta data with the same key. It also allows removing all meta data matching key, if needed.
 | |
| 	 *
 | |
| 	 * @since 2.6
 | |
| 	 *
 | |
| 	 * @param string $meta_key   Meta data name.
 | |
| 	 * @param mixed  $meta_value Optional. Meta data value. Must be serializable if non-scalar. Default empty.
 | |
| 	 *
 | |
| 	 * @return bool True on success, false on failure.
 | |
| 	 */
 | |
| 	public function delete_meta( $meta_key = '', $meta_value = '' ) {
 | |
| 		return edd_delete_customer_meta( $this->id, $meta_key, $meta_value );
 | |
| 	}
 | |
| 
 | |
| 	/** Private ***************************************************************/
 | |
| 
 | |
| 	/**
 | |
| 	 * Sanitize the data for update/create.
 | |
| 	 *
 | |
| 	 * @since 2.3
 | |
| 	 *
 | |
| 	 * @param array $data The data to sanitize.
 | |
| 	 * @return array The sanitized data, based off column defaults.
 | |
| 	 */
 | |
| 	private function sanitize_columns( $data = array() ) {
 | |
| 		$default_values = array();
 | |
| 
 | |
| 		foreach ( $data as $key => $type ) {
 | |
| 
 | |
| 			// Only sanitize data that we were provided
 | |
| 			if ( ! array_key_exists( $key, $data ) ) {
 | |
| 				continue;
 | |
| 			}
 | |
| 
 | |
| 			switch ( $type ) {
 | |
| 				case '%s':
 | |
| 					if ( 'email' === $key ) {
 | |
| 						$data[ $key ] = sanitize_email( $data[ $key ] );
 | |
| 					} else {
 | |
| 						$data[ $key ] = sanitize_text_field( $data[ $key ] );
 | |
| 					}
 | |
| 					break;
 | |
| 
 | |
| 				case '%d':
 | |
| 					if ( ! is_numeric( $data[ $key ] ) || absint( $data[ $key ] ) !== (int) $data[ $key ] ) {
 | |
| 						$data[ $key ] = $default_values[ $key ];
 | |
| 					} else {
 | |
| 						$data[ $key ] = absint( $data[ $key ] );
 | |
| 					}
 | |
| 					break;
 | |
| 
 | |
| 				case '%f':
 | |
| 					// Convert what was given to a float
 | |
| 					$value = floatval( $data[ $key ] );
 | |
| 
 | |
| 					if ( ! is_float( $value ) ) {
 | |
| 						$data[ $key ] = $default_values[ $key ];
 | |
| 					} else {
 | |
| 						$data[ $key ] = $value;
 | |
| 					}
 | |
| 					break;
 | |
| 
 | |
| 				default:
 | |
| 					$data[ $key ] = sanitize_text_field( $data[ $key ] );
 | |
| 					break;
 | |
| 			}
 | |
| 		}
 | |
| 
 | |
| 		return $data;
 | |
| 	}
 | |
| 
 | |
| 	/** Helpers ***************************************************************/
 | |
| 
 | |
| 	/**
 | |
| 	 * Retrieve all of the IP addresses used by the customer.
 | |
| 	 *
 | |
| 	 * @since 3.0
 | |
| 	 *
 | |
| 	 * @return array Array of objects containing IP address.
 | |
| 	 */
 | |
| 	public function get_ips() {
 | |
| 		return edd_get_orders( array(
 | |
| 			'customer_id' => $this->id,
 | |
| 			'fields'      => 'ip',
 | |
| 			'groupby'     => 'ip',
 | |
| 		) );
 | |
| 	}
 | |
| 
 | |
| 	/**
 | |
| 	 * Retrieve all the email addresses associated with this customer.
 | |
| 	 *
 | |
| 	 * @since 3.0
 | |
| 	 *
 | |
| 	 * @return array
 | |
| 	 */
 | |
| 	public function get_emails() {
 | |
| 
 | |
| 		// Add primary email.
 | |
| 		$retval = array( $this->email );
 | |
| 
 | |
| 		// Fetch email addresses from the database.
 | |
| 		$emails = edd_get_customer_email_addresses( array(
 | |
| 			'customer_id' => $this->id
 | |
| 		) );
 | |
| 
 | |
| 		// Pluck addresses and merg them
 | |
| 		if ( ! empty( $emails ) ) {
 | |
| 
 | |
| 			// We only want the email addresses
 | |
| 			$emails = wp_list_pluck( $emails, 'email' );
 | |
| 
 | |
| 			// Merge with primary email
 | |
| 			$retval = array_merge( $retval, $emails );
 | |
| 		}
 | |
| 
 | |
| 		// Return unique results (to avoid duplicates)
 | |
| 		return array_unique( $retval );
 | |
| 	}
 | |
| 
 | |
| 	/**
 | |
| 	 * Retrieve an address.
 | |
| 	 *
 | |
| 	 * @since 3.0
 | |
| 	 *
 | |
| 	 * @param boolean $is_primary Whether the address is the primary address. Default true.
 | |
| 	 *
 | |
| 	 * @return array|\EDD\Customers\Customer_Address|null Object if primary address requested, array otherwise. Null if no result for primary address.
 | |
| 	 */
 | |
| 	public function get_address( $is_primary = true ) {
 | |
| 		$args = array(
 | |
| 			'customer_id' => $this->id,
 | |
| 			'is_primary'  => $is_primary,
 | |
| 		);
 | |
| 		if ( $is_primary ) {
 | |
| 			$args['number']  = 1;
 | |
| 			$args['orderby'] = 'date_created';
 | |
| 			$args['order']   = 'desc';
 | |
| 		}
 | |
| 		$address = edd_get_customer_addresses( $args );
 | |
| 		if ( ! $is_primary ) {
 | |
| 			return $address;
 | |
| 		}
 | |
| 		if ( is_array( $address ) && ! empty( $address[0] ) ) {
 | |
| 			return $address[0];
 | |
| 		}
 | |
| 
 | |
| 		return null;
 | |
| 	}
 | |
| 
 | |
| 	/**
 | |
| 	 * Retrieve all addresses.
 | |
| 	 *
 | |
| 	 * @since 3.0
 | |
| 	 *
 | |
| 	 * @param string $type Address type. Default empty.
 | |
| 	 *
 | |
| 	 * @return \EDD\Customers\Customer_Address[] Array of addresses.
 | |
| 	 */
 | |
| 	public function get_addresses( $type = '' ) {
 | |
| 		$addresses = edd_get_customer_addresses( array(
 | |
| 			'customer_id' => $this->id,
 | |
| 		) );
 | |
| 
 | |
| 		if ( ! empty( $type ) ) {
 | |
| 			$addresses = wp_filter_object_list( $addresses, array( 'type' => $type ) );
 | |
| 		}
 | |
| 
 | |
| 		return $addresses;
 | |
| 	}
 | |
| 
 | |
| 	/** Deprecated ************************************************************/
 | |
| 
 | |
| 	/**
 | |
| 	 * Increase the purchase count of a customer.
 | |
| 	 *
 | |
| 	 * @since 2.3
 | |
| 	 * @deprecated 3.0 Use recalculate_stats()
 | |
| 	 *
 | |
| 	 * @param int $count The number to increment purchase count by. Default 1.
 | |
| 	 * @return int New purchase count.
 | |
| 	 */
 | |
| 	public function increase_purchase_count( $count = 1 ) {
 | |
| 
 | |
| 		_edd_deprecated_function( __METHOD__, '3.0', 'EDD_Customer::recalculate_stats()' );
 | |
| 
 | |
| 		// Make sure it's numeric and not negative
 | |
| 		if ( ! is_numeric( $count ) || absint( $count ) !== $count ) {
 | |
| 			return false;
 | |
| 		}
 | |
| 
 | |
| 		$new_total = (int) $this->purchase_count + (int) $count;
 | |
| 
 | |
| 		do_action( 'edd_customer_pre_increase_purchase_count', $count, $this->id, $this );
 | |
| 
 | |
| 		if ( $this->update( array( 'purchase_count' => $new_total ) ) ) {
 | |
| 			$this->purchase_count = $new_total;
 | |
| 		}
 | |
| 
 | |
| 		do_action( 'edd_customer_post_increase_purchase_count', $this->purchase_count, $count, $this->id, $this );
 | |
| 
 | |
| 		return $this->purchase_count;
 | |
| 	}
 | |
| 
 | |
| 	/**
 | |
| 	 * Decrease the customer's purchase count.
 | |
| 	 *
 | |
| 	 * @since 2.3
 | |
| 	 * @deprecated 3.0 Use recalculate_stats()
 | |
| 	 *
 | |
| 	 * @param int $count The number to decrement purchase count by. Default 1.
 | |
| 	 * @return mixed New purchase count if successful, false otherwise.
 | |
| 	 */
 | |
| 	public function decrease_purchase_count( $count = 1 ) {
 | |
| 
 | |
| 		_edd_deprecated_function( __METHOD__, '3.0', 'EDD_Customer::recalculate_stats()' );
 | |
| 
 | |
| 		// Make sure it's numeric and not negative
 | |
| 		if ( ! is_numeric( $count ) || absint( $count ) !== $count ) {
 | |
| 			return false;
 | |
| 		}
 | |
| 
 | |
| 		$new_total = (int) $this->purchase_count - (int) $count;
 | |
| 
 | |
| 		if ( $new_total < 0 ) {
 | |
| 			$new_total = 0;
 | |
| 		}
 | |
| 
 | |
| 		do_action( 'edd_customer_pre_decrease_purchase_count', $count, $this->id, $this );
 | |
| 
 | |
| 		if ( $this->update( array( 'purchase_count' => $new_total ) ) ) {
 | |
| 			$this->purchase_count = $new_total;
 | |
| 		}
 | |
| 
 | |
| 		do_action( 'edd_customer_post_decrease_purchase_count', $this->purchase_count, $count, $this->id, $this );
 | |
| 
 | |
| 		return $this->purchase_count;
 | |
| 	}
 | |
| 
 | |
| 	/**
 | |
| 	 * Increase the customer's lifetime value.
 | |
| 	 *
 | |
| 	 * @since 2.3
 | |
| 	 * @deprecated 3.0 Use recalculate_stats()
 | |
| 	 *
 | |
| 	 * @param float $value The value to increase by.
 | |
| 	 * @return mixed New lifetime value if successful, false otherwise.
 | |
| 	 */
 | |
| 	public function increase_value( $value = 0.00 ) {
 | |
| 
 | |
| 		_edd_deprecated_function( __METHOD__, '3.0', 'EDD_Customer::recalculate_stats()' );
 | |
| 
 | |
| 		$value     = floatval( apply_filters( 'edd_customer_increase_value', $value, $this ) );
 | |
| 		$new_value = floatval( $this->purchase_value ) + $value;
 | |
| 
 | |
| 		do_action( 'edd_customer_pre_increase_value', $value, $this->id, $this );
 | |
| 
 | |
| 		if ( $this->update( array( 'purchase_value' => $new_value ) ) ) {
 | |
| 			$this->purchase_value = $new_value;
 | |
| 		}
 | |
| 
 | |
| 		do_action( 'edd_customer_post_increase_value', $this->purchase_value, $value, $this->id, $this );
 | |
| 
 | |
| 		return $this->purchase_value;
 | |
| 	}
 | |
| 
 | |
| 	/**
 | |
| 	 * Decrease a customer's lifetime value.
 | |
| 	 *
 | |
| 	 * @since 2.3
 | |
| 	 * @deprecated 3.0 Use recalculate_stats()
 | |
| 	 *
 | |
| 	 * @param float $value The value to decrease by.
 | |
| 	 * @return mixed New lifetime value if successful, false otherwise.
 | |
| 	 */
 | |
| 	public function decrease_value( $value = 0.00 ) {
 | |
| 
 | |
| 		_edd_deprecated_function( __METHOD__, '3.0', 'EDD_Customer::recalculate_stats()' );
 | |
| 
 | |
| 		$value     = floatval( apply_filters( 'edd_customer_decrease_value', $value, $this ) );
 | |
| 		$new_value = floatval( $this->purchase_value ) - $value;
 | |
| 
 | |
| 		if ( $new_value < 0 ) {
 | |
| 			$new_value = 0.00;
 | |
| 		}
 | |
| 
 | |
| 		do_action( 'edd_customer_pre_decrease_value', $value, $this->id, $this );
 | |
| 
 | |
| 		if ( $this->update( array( 'purchase_value' => $new_value ) ) ) {
 | |
| 			$this->purchase_value = $new_value;
 | |
| 		}
 | |
| 
 | |
| 		do_action( 'edd_customer_post_decrease_value', $this->purchase_value, $value, $this->id, $this );
 | |
| 
 | |
| 		return $this->purchase_value;
 | |
| 	}
 | |
| }
 |