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,479 @@
<?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;