480 lines
9.7 KiB
PHP
480 lines
9.7 KiB
PHP
<?php
|
|
/**
|
|
* Membership Manager
|
|
*
|
|
* Handles processes related to memberships.
|
|
*
|
|
* @package WP_Ultimo
|
|
* @subpackage Managers/Membership_Manager
|
|
* @since 2.0.0
|
|
*/
|
|
|
|
namespace WP_Ultimo\Managers;
|
|
|
|
use \WP_Ultimo\Dependencies\Psr\Log\LogLevel;
|
|
use \WP_Ultimo\Managers\Base_Manager;
|
|
use \WP_Ultimo\Database\Memberships\Membership_Status;
|
|
|
|
// Exit if accessed directly
|
|
defined('ABSPATH') || exit;
|
|
|
|
/**
|
|
* Handles processes related to memberships.
|
|
*
|
|
* @since 2.0.0
|
|
*/
|
|
class Membership_Manager extends Base_Manager {
|
|
|
|
use \WP_Ultimo\Apis\Rest_Api, \WP_Ultimo\Apis\WP_CLI, \WP_Ultimo\Traits\Singleton;
|
|
|
|
/**
|
|
* The manager slug.
|
|
*
|
|
* @since 2.0.0
|
|
* @var string
|
|
*/
|
|
protected $slug = 'membership';
|
|
|
|
/**
|
|
* The model class associated to this manager.
|
|
*
|
|
* @since 2.0.0
|
|
* @var string
|
|
*/
|
|
protected $model_class = '\\WP_Ultimo\\Models\\Membership';
|
|
|
|
/**
|
|
* Instantiate the necessary hooks.
|
|
*
|
|
* @since 2.0.0
|
|
* @return void
|
|
*/
|
|
public function init() {
|
|
|
|
$this->enable_rest_api();
|
|
|
|
$this->enable_wp_cli();
|
|
|
|
Event_Manager::register_model_events('membership', __('Membership', 'wp-ultimo'), array('created', 'updated'));
|
|
|
|
add_action('wu_async_transfer_membership', array($this, 'async_transfer_membership'), 10, 2);
|
|
|
|
add_action('wu_async_delete_membership', array($this, 'async_delete_membership'), 10);
|
|
|
|
/*
|
|
* Transitions
|
|
*/
|
|
add_action('wu_transition_membership_status', array($this, 'mark_cancelled_date'), 10, 3);
|
|
|
|
add_action('wu_transition_membership_status', array($this, 'transition_membership_status'), 10, 3);
|
|
|
|
/*
|
|
* Deal with delayed/schedule swaps
|
|
*/
|
|
add_action('wu_async_membership_swap', array($this, 'async_membership_swap'), 10);
|
|
|
|
/*
|
|
* Deal with pending sites creation
|
|
*/
|
|
add_action('wp_ajax_wu_publish_pending_site', array($this, 'publish_pending_site'));
|
|
|
|
add_action('wp_ajax_wu_check_pending_site_created', array($this, 'check_pending_site_created'));
|
|
|
|
add_action('wu_async_publish_pending_site', array($this, 'async_publish_pending_site'), 10);
|
|
|
|
} // end init;
|
|
|
|
/**
|
|
* Processes a delayed site publish action.
|
|
*
|
|
* @since 2.0.11
|
|
*/
|
|
public function publish_pending_site() {
|
|
|
|
check_ajax_referer('wu_publish_pending_site');
|
|
|
|
ignore_user_abort(true);
|
|
|
|
// Don't make the request block till we finish, if possible.
|
|
if ( function_exists( 'fastcgi_finish_request' ) && version_compare( phpversion(), '7.0.16', '>=' ) ) {
|
|
|
|
wp_send_json(array( 'status' => 'creating-site'));
|
|
|
|
fastcgi_finish_request();
|
|
|
|
} // end if;
|
|
|
|
$membership_id = wu_request('membership_id');
|
|
|
|
$this->async_publish_pending_site($membership_id);
|
|
|
|
exit; // Just exit the request
|
|
|
|
} // end publish_pending_site;
|
|
/**
|
|
* Processes a delayed site publish action.
|
|
*
|
|
* @since 2.0.0
|
|
*
|
|
* @param int $membership_id The membership id.
|
|
* @return bool|\WP_Error
|
|
*/
|
|
public function async_publish_pending_site($membership_id) {
|
|
|
|
$membership = wu_get_membership($membership_id);
|
|
|
|
if (!$membership) {
|
|
|
|
return new \WP_Error('error', __('An unexpected error happened.', 'wp-ultimo'));
|
|
|
|
} // end if;
|
|
|
|
$status = $membership->publish_pending_site();
|
|
|
|
if (is_wp_error($status)) {
|
|
|
|
wu_log_add('site-errors', $status, LogLevel::ERROR);
|
|
|
|
} // end if;
|
|
|
|
return $status;
|
|
|
|
} // end async_publish_pending_site;
|
|
|
|
/**
|
|
* Processes a delayed site publish action.
|
|
*
|
|
* @since 2.0.11
|
|
*/
|
|
public function check_pending_site_created() {
|
|
|
|
$membership_id = wu_request('membership_hash');
|
|
|
|
$membership = wu_get_membership_by_hash($membership_id);
|
|
|
|
if (!$membership) {
|
|
|
|
return new \WP_Error('error', __('An unexpected error happened.', 'wp-ultimo'));
|
|
|
|
} // end if;
|
|
|
|
$pending_site = $membership->get_pending_site();
|
|
|
|
if (!$pending_site) {
|
|
/**
|
|
* We do not have a pending site, so we can assume the site was created.
|
|
*/
|
|
wp_send_json(array('publish_status' => 'completed'));
|
|
|
|
exit;
|
|
|
|
} // end if;
|
|
|
|
wp_send_json(array('publish_status' => $pending_site->is_publishing() ? 'running' : 'stopped'));
|
|
|
|
exit;
|
|
|
|
} // end check_pending_site_created;
|
|
/**
|
|
* Processes a membership swap.
|
|
*
|
|
* @since 2.0.0
|
|
*
|
|
* @param int $membership_id The membership id.
|
|
* @return bool|\WP_Error
|
|
*/
|
|
public function async_membership_swap($membership_id) {
|
|
|
|
global $wpdb;
|
|
|
|
$membership = wu_get_membership($membership_id);
|
|
|
|
if (!$membership) {
|
|
|
|
return new \WP_Error('error', __('An unexpected error happened.', 'wp-ultimo'));
|
|
|
|
} // end if;
|
|
|
|
$scheduled_swap = $membership->get_scheduled_swap();
|
|
|
|
if (empty($scheduled_swap)) {
|
|
|
|
return new \WP_Error('error', __('An unexpected error happened.', 'wp-ultimo'));
|
|
|
|
} // end if;
|
|
|
|
$order = $scheduled_swap->order;
|
|
|
|
$wpdb->query('START TRANSACTION');
|
|
|
|
try {
|
|
|
|
$membership->swap($order);
|
|
|
|
$status = $membership->save();
|
|
|
|
if (is_wp_error($status)) {
|
|
|
|
$wpdb->query('ROLLBACK');
|
|
|
|
return new \WP_Error('error', __('An unexpected error happened.', 'wp-ultimo'));
|
|
|
|
} // end if;
|
|
|
|
} catch (\Throwable $exception) {
|
|
|
|
$wpdb->query('ROLLBACK');
|
|
|
|
return new \WP_Error('error', __('An unexpected error happened.', 'wp-ultimo'));
|
|
|
|
} // end try;
|
|
|
|
/*
|
|
* Clean up the membership swap order.
|
|
*/
|
|
$membership->delete_scheduled_swap();
|
|
|
|
$wpdb->query('COMMIT');
|
|
|
|
return true;
|
|
|
|
} // end async_membership_swap;
|
|
|
|
/**
|
|
* Watches the change in payment status to take action when needed.
|
|
*
|
|
* @todo Publishing sites should be done in async.
|
|
*
|
|
* @since 2.0.0
|
|
*
|
|
* @param string $old_status The old status of the membership.
|
|
* @param string $new_status The new status of the membership.
|
|
* @param integer $membership_id Payment ID.
|
|
* @return void
|
|
*/
|
|
public function transition_membership_status($old_status, $new_status, $membership_id) {
|
|
|
|
$allowed_previous_status = array(
|
|
Membership_Status::PENDING,
|
|
Membership_Status::ON_HOLD,
|
|
);
|
|
|
|
if (!in_array($old_status, $allowed_previous_status, true)) {
|
|
|
|
return;
|
|
|
|
} // end if;
|
|
|
|
$allowed_status = array(
|
|
Membership_Status::ACTIVE,
|
|
Membership_Status::TRIALING,
|
|
);
|
|
|
|
if (!in_array($new_status, $allowed_status, true)) {
|
|
|
|
return;
|
|
|
|
} // end if;
|
|
|
|
/*
|
|
* Create pending sites.
|
|
*/
|
|
$membership = wu_get_membership($membership_id);
|
|
|
|
$status = $membership->publish_pending_site_async();
|
|
|
|
if (is_wp_error($status)) {
|
|
|
|
wu_log_add('site-errors', $status, LogLevel::ERROR);
|
|
|
|
} // end if;
|
|
|
|
} // end transition_membership_status;
|
|
|
|
/**
|
|
* Mark the membership date of cancellation.
|
|
*
|
|
* @since 2.0.0
|
|
*
|
|
* @param string $old_value Old status value.
|
|
* @param string $new_value New status value.
|
|
* @param int $item_id The membership id.
|
|
* @return void
|
|
*/
|
|
public function mark_cancelled_date($old_value, $new_value, $item_id) {
|
|
|
|
if ($new_value === 'cancelled' && $new_value !== $old_value) {
|
|
|
|
$membership = wu_get_membership($item_id);
|
|
|
|
$membership->set_date_cancellation(wu_get_current_time('mysql', true));
|
|
|
|
$membership->save();
|
|
|
|
} // end if;
|
|
|
|
} // end mark_cancelled_date;
|
|
|
|
/**
|
|
* Transfer a membership from a user to another.
|
|
*
|
|
* @since 2.0.0
|
|
*
|
|
* @param int $membership_id The ID of the membership being transferred.
|
|
* @param int $target_customer_id The new owner.
|
|
* @return mixed
|
|
*/
|
|
public function async_transfer_membership($membership_id, $target_customer_id) {
|
|
|
|
global $wpdb;
|
|
|
|
$membership = wu_get_membership($membership_id);
|
|
|
|
$target_customer = wu_get_customer($target_customer_id);
|
|
|
|
if (!$membership || !$target_customer || absint($membership->get_customer_id()) === absint($target_customer->get_id())) {
|
|
|
|
return new \WP_Error('error', __('An unexpected error happened.', 'wp-ultimo'));
|
|
|
|
} // end if;
|
|
|
|
$wpdb->query('START TRANSACTION');
|
|
|
|
try {
|
|
/*
|
|
* Get Sites and move them over.
|
|
*/
|
|
$sites = wu_get_sites(array(
|
|
'meta_query' => array(
|
|
'membership_id' => array(
|
|
'key' => 'wu_membership_id',
|
|
'value' => $membership->get_id(),
|
|
),
|
|
),
|
|
));
|
|
|
|
foreach ($sites as $site) {
|
|
|
|
$site->set_customer_id($target_customer_id);
|
|
|
|
$saved = $site->save();
|
|
|
|
if (is_wp_error($saved)) {
|
|
|
|
$wpdb->query('ROLLBACK');
|
|
|
|
return $saved;
|
|
|
|
} // end if;
|
|
|
|
} // end foreach;
|
|
|
|
/*
|
|
* Change the membership
|
|
*/
|
|
$membership->set_customer_id($target_customer_id);
|
|
|
|
$saved = $membership->save();
|
|
|
|
if (is_wp_error($saved)) {
|
|
|
|
$wpdb->query('ROLLBACK');
|
|
|
|
return $saved;
|
|
|
|
} // end if;
|
|
|
|
} catch (\Throwable $e) {
|
|
|
|
$wpdb->query('ROLLBACK');
|
|
|
|
return new \WP_Error('exception', $e->getMessage());
|
|
|
|
} // end try;
|
|
|
|
$wpdb->query('COMMIT');
|
|
|
|
$membership->unlock();
|
|
|
|
return true;
|
|
|
|
} // end async_transfer_membership;
|
|
|
|
/**
|
|
* Delete a membership.
|
|
*
|
|
* @since 2.0.0
|
|
*
|
|
* @param int $membership_id The ID of the membership being deleted.
|
|
* @return mixed
|
|
*/
|
|
public function async_delete_membership($membership_id) {
|
|
|
|
global $wpdb;
|
|
|
|
$membership = wu_get_membership($membership_id);
|
|
|
|
if (!$membership) {
|
|
|
|
return new \WP_Error('error', __('An unexpected error happened.', 'wp-ultimo'));
|
|
|
|
} // end if;
|
|
|
|
$wpdb->query('START TRANSACTION');
|
|
|
|
try {
|
|
/*
|
|
* Get Sites and delete them.
|
|
*/
|
|
$sites = wu_get_sites(array(
|
|
'meta_query' => array(
|
|
'membership_id' => array(
|
|
'key' => 'wu_membership_id',
|
|
'value' => $membership->get_id(),
|
|
),
|
|
),
|
|
));
|
|
|
|
foreach ($sites as $site) {
|
|
|
|
$saved = $site->delete();
|
|
|
|
if (is_wp_error($saved)) {
|
|
|
|
$wpdb->query('ROLLBACK');
|
|
|
|
return $saved;
|
|
|
|
} // end if;
|
|
|
|
} // end foreach;
|
|
|
|
/*
|
|
* Delete the membership
|
|
*/
|
|
$saved = $membership->delete();
|
|
|
|
if (is_wp_error($saved)) {
|
|
|
|
$wpdb->query('ROLLBACK');
|
|
|
|
return $saved;
|
|
|
|
} // end if;
|
|
|
|
} catch (\Throwable $e) {
|
|
|
|
$wpdb->query('ROLLBACK');
|
|
|
|
return new \WP_Error('exception', $e->getMessage());
|
|
|
|
} // end try;
|
|
|
|
$wpdb->query('COMMIT');
|
|
|
|
return true;
|
|
|
|
} // end async_delete_membership;
|
|
|
|
} // end class Membership_Manager;
|