Initial Commit

This commit is contained in:
David Stone
2024-11-30 18:24:12 -07:00
commit e8f7955c1c
5432 changed files with 1397750 additions and 0 deletions

View File

@ -0,0 +1,954 @@
<?php
/**
* The Customer model.
*
* @package WP_Ultimo
* @subpackage Models
* @since 2.0.0
*/
namespace WP_Ultimo\Models;
use WP_Ultimo\Models\Base_Model;
use WP_Ultimo\Models\Membership;
use WP_Ultimo\Models\Site;
use WP_Ultimo\Models\Payment;
// Exit if accessed directly
defined('ABSPATH') || exit;
/**
* Customer model class. Implements the Base Model.
*
* @since 2.0.0
*/
class Customer extends Base_Model {
use Traits\Billable, Traits\Notable;
/**
* User ID of the associated user.
*
* @since 2.0.0
* @var int
*/
protected $user_id;
/**
* The type of customer.
*
* Almost a 100% of the time this will be 'customer'
* but since we use this table to store support-agents as well
* this can be 'support-agent'.
*
* @see \WP_Ultimo\Models\Support_Agent
*
* @since 2.0.0
* @var string
*/
protected $type;
/**
* Date when the customer was created.
*
* @since 2.0.0
* @var string
*/
protected $date_registered;
/**
* Email verification status - either `none`, `pending`, or `verified`.
*
* @since 2.0.0
* @var string
*/
protected $email_verification;
/**
* Date this customer last logged in.
*
* @since 2.0.0
* @var string
*/
protected $last_login;
/**
* Whether or not the customer has trialed before.
*
* @since 2.0.0
* @var null|bool
*/
protected $has_trialed;
/**
* If this customer is a VIP customer or not.
*
* @since 2.0.0
* @var bool
*/
protected $vip = false;
/**
* List of IP addresses used by this customer.
*
* @since 2.0.0
* @var string
*/
protected $ips;
/**
* The form used to signup.
*
* @since 2.0.0
* @var string
*/
protected $signup_form;
/**
* Extra information about this customer.
*
* @since 2.0.0
* @var array
*/
protected $extra_information;
/**
* Query Class to the static query methods.
*
* @since 2.0.0
* @var string
*/
protected $query_class = '\\WP_Ultimo\\Database\\Customers\\Customer_Query';
/**
* Allows injection, which is useful for mocking.
*
* @since 2.2.0
* @var string
*/
public $_user;
/**
* Save (create or update) the model on the database.
*
* @since 2.0.0
*/
public function save() {
return parent::save();
} // end save;
/**
* Set the validation rules for this particular model.
*
* To see how to setup rules, check the documentation of the
* validation library we are using: https://github.com/rakit/validation
*
* @since 2.0.0
* @link https://github.com/rakit/validation
* @return array
*/
public function validation_rules() {
$id = $this->get_id();
return array(
'user_id' => "required|integer|unique:\WP_Ultimo\Models\Customer,user_id,{$id}",
'email_verification' => 'required|in:none,pending,verified',
'type' => 'required|in:customer',
'last_login' => 'default:',
'has_trialed' => 'boolean|default:0',
'vip' => 'boolean|default:0',
'ips' => 'array',
'extra_information' => 'default:',
'signup_form' => 'default:',
);
} // end validation_rules;
/**
* Get user ID of the associated user.
*
* @since 2.0.0
* @return int
*/
public function get_user_id() {
return absint($this->user_id);
} // end get_user_id;
/**
* Set user ID of the associated user.
*
* @since 2.0.0
* @param int $user_id The WordPress user ID attached to this customer.
* @return void
*/
public function set_user_id($user_id) {
$this->user_id = $user_id;
} // end set_user_id;
/**
* Returns the user associated with this customer.
*
* @since 2.0.0
* @return WP_User
*/
public function get_user() {
return get_user_by('id', $this->get_user_id());
} // end get_user;
/**
* Returns the customer's display name.
*
* @since 2.0.0
* @return string
*/
public function get_display_name() {
$user = $this->get_user();
if (empty($user)) {
return __('User Deleted', 'wp-ultimo');
} // end if;
return $user->display_name;
} // end get_display_name;
/**
* Returns the default billing address.
*
* Classes that implement this trait need to implement
* this method.
*
* @since 2.0.0
* @return \WP_Ultimo\Objects\Billing_Address
*/
public function get_default_billing_address() {
return new \WP_Ultimo\Objects\Billing_Address(array(
'company_name' => $this->get_display_name(),
'billing_email' => $this->get_email_address(),
'billing_country' => $this->get_meta('ip_country'),
));
} // end get_default_billing_address;
/**
* Returns the customer country.
*
* @since 2.0.0
* @return string
*/
public function get_country() {
$billing_address = $this->get_billing_address();
$country = $billing_address->billing_country;
if (!$country) {
return $this->get_meta('ip_country');
} // end if;
return $country;
} // end get_country;
/**
* Returns the customer's username.
*
* @since 2.0.0
* @return string
*/
public function get_username() {
$user = $this->get_user();
if (empty($user)) {
return __('none', 'wp-ultimo');
} // end if;
return $user->user_login;
} // end get_username;
/**
* Returns the customer's email address.
*
* @since 2.0.0
* @return string
*/
public function get_email_address() {
$user = $this->get_user();
if (empty($user)) {
return __('none', 'wp-ultimo');
} // end if;
return $user->user_email;
} // end get_email_address;
/**
* Get date when the customer was created.
*
* @since 2.0.0
* @param bool $formatted To format or not.
* @return string
*/
public function get_date_registered($formatted = true) {
return $this->date_registered;
} // end get_date_registered;
/**
* Set date when the customer was created.
*
* @since 2.0.0
* @param string $date_registered Date when the customer was created.
* @return void
*/
public function set_date_registered($date_registered) {
$this->date_registered = $date_registered;
} // end set_date_registered;
/**
* Get email verification status - either `none`, `pending`, or `verified`.
*
* @since 2.0.0
* @return string
*/
public function get_email_verification() {
return $this->email_verification;
} // end get_email_verification;
/**
* Set email verification status - either `none`, `pending`, or `verified`.
*
* @since 2.0.0
* @param string $email_verification Email verification status - either `none`, `pending`, or `verified`.
* @return void
*/
public function set_email_verification($email_verification) {
$this->email_verification = $email_verification;
} // end set_email_verification;
/**
* Get date this customer last logged in.
*
* @since 2.0.0
* @param bool $formatted To format or not.
* @return string
*/
public function get_last_login($formatted = true) {
return $this->last_login;
} // end get_last_login;
/**
* Set date this customer last logged in.
*
* @since 2.0.0
* @param string $last_login Date this customer last logged in.
* @return void
*/
public function set_last_login($last_login) {
$this->last_login = $last_login;
} // end set_last_login;
/**
* Get whether or not the customer has trialed before.
*
* @since 2.0.0
* @return null|bool
*/
public function has_trialed() {
if ((bool) $this->has_trialed) {
return true;
} // end if;
$this->has_trialed = $this->get_meta('wu_has_trialed');
if (!$this->has_trialed) {
$trial = wu_get_memberships(array(
'customer_id' => $this->get_id(),
'date_trial_end__not_in' => array(null, '0000-00-00 00:00:00'),
'fields' => 'ids',
'number' => 1,
));
if (!empty($trial)) {
$this->update_meta('wu_has_trialed', true);
$this->has_trialed = true;
} // end if;
} // end if;
return $this->has_trialed;
} // end has_trialed;
/**
* Set whether or not the customer has trialed before.
*
* @since 2.0.0
* @param bool $has_trialed Whether or not the customer has trialed before.
* @return void
*/
public function set_has_trialed($has_trialed) {
$this->meta['wu_has_trialed'] = $has_trialed;
$this->has_trialed = $has_trialed;
} // end set_has_trialed;
/**
* Get if this customer is a VIP customer or not.
*
* @since 2.0.0
* @return bool
*/
public function is_vip() {
return (bool) $this->vip;
} // end is_vip;
/**
* Set if this customer is a VIP customer or not.
*
* @since 2.0.0
* @param bool $vip If this customer is a VIP customer or not.
* @return void
*/
public function set_vip($vip) {
$this->vip = $vip;
} // end set_vip;
/**
* Get list of IP addresses used by this customer.
*
* @since 2.0.0
* @return array
*/
public function get_ips() {
if (empty($this->ips)) {
return array();
} // end if;
if (is_string($this->ips)) {
$this->ips = maybe_unserialize($this->ips);
} // end if;
return $this->ips;
} // end get_ips;
/**
* Returns the last IP address recorded for the customer.
*
* @since 2.0.0
* @return string
*/
public function get_last_ip() {
$ips = $this->get_ips();
return array_pop($ips);
} // end get_last_ip;
/**
* Set list of IP addresses used by this customer.
*
* @since 2.0.0
* @param array $ips List of IP addresses used by this customer.
* @return void
*/
public function set_ips($ips) {
if (is_string($ips)) {
$ips = maybe_unserialize(wp_unslash($ips));
} // end if;
$this->ips = $ips;
} // end set_ips;
/**
* Adds a new IP to the IP list.
*
* @since 2.0.0
*
* @param string $ip New IP address to add.
* @return void
*/
public function add_ip($ip) {
$ips = $this->get_ips();
if (!is_array($ips)) {
$ips = array();
} // end if;
/*
* IP already exists.
*/
if (in_array($ip, $ips, true)) {
return;
} // end if;
$ips[] = sanitize_text_field($ip);
$this->set_ips($ips);
} // end add_ip;
/**
* Updates the last login, as well as the ip and country if necessary.
*
* @since 2.0.0
*
* @param boolean $update_ip If we want to update the IP address.
* @param boolean $update_country_and_state If we want to update country and state.
* @return boolean
*/
public function update_last_login($update_ip = true, $update_country_and_state = false) {
$this->attributes(array(
'last_login' => wu_get_current_time('mysql', true),
));
$geolocation = $update_ip || $update_country_and_state ? \WP_Ultimo\Geolocation::geolocate_ip('', true) : false;
if ($update_ip) {
$this->add_ip($geolocation['ip']);
} // end if;
if ($update_country_and_state) {
$this->update_meta('ip_country', $geolocation['country']);
$this->update_meta('ip_state', $geolocation['state']);
} // end if;
return $this->save();
} // end update_last_login;
/**
* Get extra information.
*
* @since 2.0.0
* @return array
*/
public function get_extra_information() {
if ($this->extra_information === null) {
$extra_information = (array) $this->get_meta('wu_customer_extra_information');
$this->extra_information = array_filter($extra_information);
} // end if;
return $this->extra_information;
} // end get_extra_information;
/**
* Set featured extra information.
*
* @since 2.0.0
* @param array $extra_information Any extra information related to this customer.
* @return void
*/
public function set_extra_information($extra_information) {
$extra_information = array_filter((array) $extra_information);
$this->extra_information = $extra_information;
$this->meta['wu_customer_extra_information'] = $extra_information;
} // end set_extra_information;
/**
* Returns the subscriptions attached to this customer.
*
* @since 2.0.0
* @return array
*/
public function get_memberships() {
return Membership::query(array(
'customer_id' => $this->get_id(),
));
} // end get_memberships;
/**
* Returns the sites attached to this customer.
*
* @since 2.0.0
* @param array $query_args Query arguments.
* @return array
*/
public function get_sites($query_args = array()) {
$query_args = array_merge(
$query_args,
array(
'meta_query' => array(
'customer_id' => array(
'key' => 'wu_customer_id',
'value' => $this->get_id(),
),
),
)
);
return Site::query($query_args);
} // end get_sites;
/**
* Returns all pending sites associated with a customer.
*
* @since 2.0.0
* @return array
*/
public function get_pending_sites() {
$pending_sites = array();
$memberships = $this->get_memberships();
foreach ($memberships as $membership) {
$pending_site = $membership->get_pending_site();
if ($pending_site) {
$pending_sites[] = $pending_site;
} // end if;
} // end foreach;
return $pending_sites;
} // end get_pending_sites;
/**
* The the primary site ID if available.
*
* In cases where none is set, we:
* - return the id of the first site on the list off sites
* belonging to this customer;
* - or return the main site id.
*
* @since 2.0.0
* @return int
*/
public function get_primary_site_id() {
$primary_site_id = get_user_option('primary_blog', $this->get_user_id());
if (!$primary_site_id) {
$sites = $this->get_sites();
$primary_site_id = $sites ? $sites[0]->get_id() : wu_get_main_site_id();
} // end if;
return $primary_site_id;
} // end get_primary_site_id;
/**
* Returns the payments attached to this customer.
*
* @since 2.0.0
* @return array
*/
public function get_payments() {
return Payment::query(array(
'customer_id' => $this->get_id(),
));
} // end get_payments;
/**
* By default, we just use the to_array method, but you can rewrite this.
*
* @since 2.0.0
* @return array
*/
public function to_search_results() {
$user = get_userdata($this->get_user_id());
if (isset($this->_user)) {
$user = $this->_user; // Allows for injection, which is useful for mocking.
unset($this->_user);
} // end if;
$search_result = $this->to_array();
if ($user) {
$user->data->avatar = get_avatar($user->data->user_email, 40, 'identicon', '', array(
'force_display' => true,
'class' => 'wu-rounded-full wu-mr-3',
));
$search_result = array_merge((array) $user->data, $search_result);
} // end if;
$search_result['billing_address_data'] = $this->get_billing_address()->to_array();
$search_result['billing_address'] = $this->get_billing_address()->to_string();
return $search_result;
} // end to_search_results;
/**
* Get the customer type.
*
* @since 2.0.0
* @return string
*/
public function get_type() {
return $this->type;
} // end get_type;
/**
* Get the customer type.
*
* @since 2.0.0
* @param string $type The customer type. Can be 'customer'.
* @options customer
* @return void
*/
public function set_type($type) {
$this->type = $type;
} // end set_type;
/**
* Gets the total grossed by the customer so far.
*
* @since 2.0.0
* @return float
*/
public function get_total_grossed() {
global $wpdb;
static $sum;
if ($sum === null) {
$sum = $wpdb->get_var(
$wpdb->prepare(
"SELECT SUM(total) FROM {$wpdb->base_prefix}wu_payments WHERE parent_id = 0 AND customer_id = %d",
$this->get_id()
)
);
} // end if;
return $sum;
} // end get_total_grossed;
/**
* Get if the customer is online or not.
*
* @since 2.0.0
* @return boolean
*/
public function is_online() {
if ($this->get_last_login() === '0000-00-00 00:00:00') {
return false;
} // end if;
$last_login_date = new \DateTime($this->get_last_login());
$now = new \DateTime('now');
$interval = $last_login_date->diff($now);
$minutes_interval = $interval->days * 24 * 60;
$minutes_interval += $interval->h * 60;
$minutes_interval += $interval->i;
return $minutes_interval <= apply_filters('wu_is_online_minutes_interval', 3) ? true : false;
} // end is_online;
/**
* Saves a verification key.
*
* @since 2.0.0
* @return bool
*/
public function generate_verification_key() {
$seed = time();
$hash = \WP_Ultimo\Helpers\Hash::encode($seed, 'verification-key');
return $this->update_meta('wu_verification_key', $hash);
} // end generate_verification_key;
/**
* Returns the saved verification key.
*
* @since 2.0.0
* @return string|bool
*/
public function get_verification_key() {
return $this->get_meta('wu_verification_key', false);
} // end get_verification_key;
/**
* Disabled the verification by setting the key to false.
*
* @since 2.0.0
* @return bool
*/
public function disable_verification_key() {
return $this->update_meta('wu_verification_key', false);
} // end disable_verification_key;
/**
* Returns the link of the email verification endpoint.
*
* @since 2.0.0
* @return string|bool
*/
public function get_verification_url() {
$key = $this->get_verification_key();
if (!$key) {
return get_site_url(wu_get_main_site_id());
} // end if;
return add_query_arg(array(
'email-verification-key' => $key,
'customer' => $this->get_hash(),
), get_site_url(wu_get_main_site_id()));
} // end get_verification_url;
/**
* Send verification email.
*
* @since 2.0.4
* @return void
*/
public function send_verification_email() {
$this->generate_verification_key();
$payload = array_merge(
array('verification_link' => $this->get_verification_url()),
wu_generate_event_payload('customer', $this)
);
wu_do_event('confirm_email_address', $payload);
} // end send_verification_email;
/**
* Get the form used to signup.
*
* @since 2.0.0
* @return string
*/
public function get_signup_form() {
return $this->signup_form;
} // end get_signup_form;
/**
* Set the form used to signup.
*
* @since 2.0.0
* @param string $signup_form The form used to signup.
* @return void
*/
public function set_signup_form($signup_form) {
$this->signup_form = $signup_form;
} // end set_signup_form;
} // end class Customer;