| Current Path : /var/www/html/plugins/system/membershippro/src/Extension/ |
| Current File : /var/www/html/plugins/system/membershippro/src/Extension/MembershipPro.php |
<?php
/**
* @package Joomla
* @subpackage Membership Pro
* @author Tuan Pham Ngoc
* @copyright Copyright (C) 2012 - 2026 Ossolution Team
* @license GNU/GPL, see LICENSE.php
*/
namespace JoomDonation\MembershipPro\Plugin\System\MembershipPro\Extension;
use Joomla\CMS\Component\ComponentHelper;
use Joomla\CMS\Factory;
use Joomla\CMS\Plugin\CMSPlugin;
use Joomla\CMS\Plugin\PluginHelper;
use Joomla\CMS\User\UserFactoryAwareTrait;
use Joomla\Component\Fields\Administrator\Model\FieldModel;
use Joomla\Database\DatabaseAwareTrait;
use Joomla\Database\ParameterType;
use Joomla\Event\DispatcherInterface;
use Joomla\Event\Event;
use Joomla\Event\SubscriberInterface;
use Joomla\Registry\Registry;
use OSSolution\MembershipPro\Admin\Event\Subscription\MembershipExpire;
defined('_JEXEC') or die;
class MembershipPro extends CMSPlugin implements SubscriberInterface
{
use DatabaseAwareTrait;
use UserFactoryAwareTrait;
/**
* Flag to see whether the plan subscription status for this record has been processed or not
*
* @var bool
*/
private $subscriptionProcessed = false;
public static function getSubscribedEvents(): array
{
return [
'onAfterStoreSubscription' => 'onAfterStoreSubscription',
'onMembershipActive' => 'onMembershipActive',
'onMembershipExpire' => 'onMembershipExpire',
'onMembershipUpdate' => 'onMembershipUpdate',
'onSubscriptionAfterDelete' => 'onSubscriptionAfterDelete',
'onUserAfterDelete' => 'onUserAfterDelete',
'onUserAfterLogin' => 'onUserAfterLogin',
'onUserAfterSave' => 'onUserAfterSave',
];
}
/**
* Constructor.
*
* @param DispatcherInterface $dispatcher The dispatcher
* @param array $config An optional associative array of configuration settings
*/
public function __construct(DispatcherInterface $dispatcher, array $config)
{
parent::__construct($dispatcher, $config);
}
/**
* This method is run after subscription record is successfully stored in database
*
* @param Event $event
*
* @return void
*/
public function onAfterStoreSubscription(Event $event): void
{
/* @var \OSMembershipTableSubscriber $row */
[$row] = array_values($event->getArguments());
// Set profile data (is_profile, profile_id) for the subscription
$this->setSubscriptionProfileData($row);
// Set plan main record data for the subscription
$this->setPlanMainRecordData($row);
// Set avatar for subscription
$this->setAvatarForSubscription($row);
$row->payment_method = (string) $row->payment_method;
if (str_contains($row->payment_method, 'os_offline'))
{
$config = \OSMembershipHelper::getConfig();
// Generate invoice for offline payment
if ($config->activate_invoice_feature && !$row->group_admin_id && !$row->invoice_number)
{
$this->generateInvoiceNumber($row);
}
// Generate Membership ID for offline payment subscription
if ($config->auto_generate_membership_id)
{
$this->generateMembershipId($row);
}
// Update coupon usage statistic
$this->updateCouponUsage($row);
}
// Move data of the fields which are not being shown on renewal form to renewal subscription
if ($row->act == 'renew' && $row->user_id > 0)
{
$this->moveHideOnMembershipRenewalData($row);
}
// Store the modified data for the subscription back to database
$row->store();
}
/**
* This method is run after subscription become active, ie after user complete payment or admin approve the subscription
*
* @param Event $event
*
* @return void
*
* @throws \Exception
*/
public function onMembershipActive(Event $event): void
{
/* @var \OSMembershipTableSubscriber $row */
[$row] = array_values($event->getArguments());
$config = \OSMembershipHelper::getConfig();
// Create user account (in case the system is configured to generate user account when subscription is active)
if (!$row->user_id && $row->username && $row->user_password)
{
$this->createUserAccount($row);
}
// Activate user account when subscription active (in case the system is configured to not send activation email)
if (!$config->send_activation_email)
{
$this->activateUserAccount($row);
}
/*
* Generate invoice for the subscription if it was not generated before (For example, when admin approve the
* offline payment subscription
*/
if ($config->activate_invoice_feature && !$row->group_admin_id && !$row->invoice_number)
{
$this->generateInvoiceNumber($row);
}
// In case system is configured to only has one subscription record for each plan, update the subscription
if ($row->act == 'renew' && $config->subscription_renew_behavior == 'update_subscription' && $row->user_id > 0)
{
$this->updateSubscriptionOnRenew($row);
}
// Update coupon usage statistic
$this->updateCouponUsage($row);
/*
* Generate Membership ID for the subscription if it was not generated before (For example, when admin approve
* the offline payment subscription
*/
if ($config->auto_generate_membership_id && !$row->membership_id)
{
$this->generateMembershipId($row);
}
// Disable reminder for appropriate records
if ($row->user_id > 0)
{
$groupingPlans = \OSMembershipHelperSubscription::getGroupingPlans($row);
if (empty($groupingPlans))
{
$groupingPlans[] = $row->plan_id;
}
$db = $this->getDatabase();
$query = $db->getQuery(true)
->update('#__osmembership_subscribers')
->set('first_reminder_sent = 1')
->set('second_reminder_sent = 1')
->set('third_reminder_sent = 1')
->where('user_id = ' . $row->user_id)
->whereIn('plan_id', $groupingPlans)
->where('id != ' . $row->id);
$extraReminderSentFields = [
'fourth_reminder_sent',
'fifth_reminder_sent',
'sixth_reminder_sent',
];
foreach ($extraReminderSentFields as $field)
{
if (property_exists($row, $field))
{
$query->set($field . ' = 1');
}
}
$db->setQuery($query)
->execute();
}
// Store modified subscription data back to database
$row->store();
$this->subscriptionProcessed = true;
if ($row->group_admin_id == 0)
{
$this->updateSubscriptionExpiredDate($row);
$this->updatePlanSubscriptionStatus($row);
$this->updateSendingReminderStatus($row);
}
}
/**
* Block the user account when membership is expired
*
* @param Event $event
*
* @return void
*/
public function onMembershipExpire(Event $event): void
{
/* @var \OSMembershipTableSubscriber $row */
[$row] = array_values($event->getArguments());
if ($row->user_id && $this->params->get('block_account_when_expired', 0))
{
$user = $this->getUserFactory()->loadUserById((int) $row->user_id);
// Only block account if the subscriber does not have any active subscription left
$db = $this->getDatabase();
$query = $db->getQuery(true)
->select('COUNT(*)')
->from('#__osmembership_subscribers')
->where('id != ' . $row->id)
->where('user_id = ' . $row->user_id)
->where('published = 1');
$db->setQuery($query);
if (!$db->loadResult() && !$user->authorise('core.admin'))
{
$user->block = 1;
$user->save(true);
}
}
$this->subscriptionProcessed = true;
if (!$row->group_admin_id)
{
$this->updatePlanSubscriptionStatus($row);
}
}
/**
* Recalculate some important subscription information when a subscription record is being deleted
*
* @param Event $event
*
* @return void
*/
public function onSubscriptionAfterDelete(Event $event): void
{
/**
* @var string $context
* @var \OSMembershipTableSubscriber $row
*/
[$context, $row] = array_values($event->getArguments());
if ($row->profile_id > 0 && $row->plan_id > 0)
{
$db = $this->getDatabase();
$query = $db->getQuery(true)
->select('id, profile_id, plan_id, published, from_date, to_date, plan_main_record')
->from('#__osmembership_subscribers')
->where('plan_id = ' . $row->plan_id)
->where('profile_id = ' . $row->profile_id)
->where('(published >= 1 OR payment_method LIKE "os_offline%")')
->order('id');
$db->setQuery($query);
$subscriptions = $db->loadObjectList();
if (!empty($subscriptions))
{
$isActive = false;
$isPending = false;
$isExpired = false;
$lastActiveDate = null;
$lastExpiredDate = null;
$planMainRecordId = 0;
$planFromDate = $subscriptions[0]->from_date;
foreach ($subscriptions as $subscription)
{
if ($subscription->plan_main_record)
{
$planMainRecordId = $subscription->id;
}
if ($subscription->published == 1)
{
$isActive = true;
$lastActiveDate = $subscription->to_date;
}
elseif ($subscription->published == 0)
{
$isPending = true;
}
elseif ($subscription->published == 2)
{
$isExpired = true;
$lastExpiredDate = $subscription->to_date;
}
}
if ($isActive)
{
$published = 1;
$planToDate = $lastActiveDate;
}
elseif ($isPending)
{
$published = 0;
}
elseif ($isExpired)
{
$published = 2;
$planToDate = $lastExpiredDate;
}
else
{
$published = 3;
$planToDate = $subscriptions[count($subscriptions) - 1]->to_date;
}
$query->clear()
->update('#__osmembership_subscribers')
->set('plan_subscription_status = ' . (int) $published)
->set('plan_subscription_from_date = ' . $db->quote($planFromDate))
->set('plan_subscription_to_date = ' . $db->quote($planToDate))
->where('plan_id = ' . $row->plan_id)
->where('profile_id = ' . $row->profile_id);
$db->setQuery($query);
$db->execute();
if (empty($planMainRecordId))
{
$planMainRecordId = $subscriptions[0]->id;
$query->clear()
->update('#__osmembership_subscribers')
->set('plan_main_record = 1')
->where('id = ' . $planMainRecordId);
$db->setQuery($query);
$db->execute();
}
}
}
if ($row->is_profile == 1 && $row->user_id > 0)
{
// We need to fix the profile record
\OSMembershipHelperSubscription::fixProfileId($row->user_id);
}
}
/**
* Update plan subscription status when subscription record updated
*
* @param Event $event
*
* @return void
*/
public function onMembershipUpdate(Event $event): void
{
/* @var \OSMembershipTableSubscriber $row */
[$row] = array_values($event->getArguments());
if (!$this->subscriptionProcessed && $this->getApplication()->isClient('administrator'))
{
$this->updateSubscriptionExpiredDate($row);
$this->updatePlanSubscriptionStatus($row);
}
}
/**
* Handle Login redirect
*
* @param Event $event
*
* @return void
*
* @throws \Exception
*/
public function onUserAfterLogin(Event $event): void
{
[$options] = array_values($event->getArguments());
$app = $this->getApplication();
if ($app->isClient('administrator'))
{
return;
}
$session = $app->getSession();
$sessionReturnUrl = $session->get('osm_return_url');
$sessionRequiredPlanIds = $session->get('required_plan_ids');
if (!empty($sessionReturnUrl) && !empty($sessionRequiredPlanIds))
{
$activePlans = \OSMembershipHelperSubscription::getActiveMembershipPlans();
if (count(array_intersect($activePlans, $sessionRequiredPlanIds)) > 0)
{
// Clear the old session data
$session->clear('osm_return_url');
$session->clear('required_plan_ids');
$app->setUserState('users.login.form.return', $sessionReturnUrl);
return;
}
}
if (!$app->getInput()->post->getInt('login_from_mp_subscription_form')
&& $loginRedirectUrl = \OSMembershipHelper::getLoginRedirectUrl())
{
$app->setUserState('users.login.form.return', $loginRedirectUrl);
}
}
/**
* Utility method to act on a user after it has been saved.
*
* This method creates a subscription record for the saved user
*
* @param Event $event
*
* @return void
*/
public function onUserAfterSave(Event $event)
{
[$user, $isnew, $success, $msg] = array_values($event->getArguments());
// If the user wasn't stored we don't resync
if (!$success)
{
return;
}
// If the user isn't new we don't sync
if ($isnew)
{
return;
}
// Ensure the user id is really an int
$userId = (int) $user['id'];
// If the user id appears invalid then bail out just in case
if (empty($userId))
{
return;
}
$config = \OSMembershipHelper::getConfig();
$app = $this->getApplication();
$option = $app->getInput()->getCmd('option');
$task = $app->getInput()->getCmd('task');
if (!empty($config->synchronize_email) && in_array($option, ['com_users', 'com_comprofiler']))
{
$db = $this->getDatabase();
$query = $db->getQuery(true)
->update('#__osmembership_subscribers')
->set('email = ' . $db->quote($user['email']))
->where('user_id = ' . $userId);
$db->setQuery($query);
$db->execute();
}
// Assign subscription records to user account in case they have existing subscription records before registering for new user account
if (in_array($option, ['com_users', 'com_comprofiler']))
{
$db = $this->getDatabase();
$query = $db->getQuery(true)
->update('#__osmembership_subscribers')
->set('user_id = ' . $userId)
->where('user_id = 0')
->where('email = ' . $db->quote($user['email']));
$db->setQuery($query);
$db->execute();
}
// Only synchronize data to subscriptions if it's enabled
if (!$config->synchronize_profile_data_to_subscriptions)
{
return;
}
// Only update data if data is updated via com_users
if ($option != 'com_users')
{
return;
}
if ($app->isClient('administrator') && !in_array($task, ['save', 'apply', 'save2new']))
{
return;
}
if ($app->isClient('site') && $task != 'save')
{
return;
}
$mpUserProfilePluginEnabled = PluginHelper::isEnabled('osmembership', 'userprofile');
if (!$mpUserProfilePluginEnabled)
{
return;
}
$db = $this->getDatabase();
$query = $db->getQuery(true)
->select('id')
->from('#__osmembership_subscribers')
->where('user_id = ' . $userId);
$db->setQuery($query);
$subscriptionIds = $db->loadColumn();
if (!count($subscriptionIds))
{
return;
}
$userProfilePluginEnabled = PluginHelper::isEnabled('user', 'profile');
$userFields = \OSMembershipHelper::getUserFields();
// Update user's profile data to subscription records of the user
if ($userProfilePluginEnabled)
{
$this->updateSubscriptionsFromUserProfile($user, $subscriptionIds);
}
// Update user's custom fields data to subscription records of the suer
if (count($userFields))
{
$this->updateSubscriptionsFromUserCustomFields($user, $subscriptionIds, $userFields);
}
}
/**
* Remove all subscriptions for the user if configured
*
* Method is called after user data is deleted from the database
*
* @param Event $event
*
* @return void
*/
public function onUserAfterDelete(Event $event)
{
/**
* @var array $user
* @var bool $success
* @var string $msg
*/
[$user, $success, $msg] = array_values($event->getArguments());
$config = \OSMembershipHelper::getConfig();
if ($config->delete_subscriptions_when_account_deleted)
{
$db = $this->getDatabase();
$row = new \OSMembershipTableSubscriber($db);
$query = $db->getQuery(true)
->select('id')
->from('#__osmembership_subscribers')
->where('user_id = ' . (int) $user['id']);
$db->setQuery($query);
$cid = $db->loadColumn();
if (count($cid))
{
$query->clear()
->delete('#__osmembership_field_value')
->whereIn('subscriber_id', $cid);
$db->setQuery($query);
$db->execute();
PluginHelper::importPlugin('osmembership');
$app = $this->getApplication();
foreach ($cid as $id)
{
$row->load($id);
$membershipExpireEvent = new MembershipExpire(['row' => $row]);
$app->getDispatcher()->dispatch($membershipExpireEvent->getName(), $membershipExpireEvent);
}
$query->clear()
->delete('#__osmembership_subscribers')
->where('user_id = ' . (int) $user['id']);
$db->setQuery($query);
$db->execute();
}
}
}
/**
* Register listeners
*
* @return void
*/
public function registerListeners()
{
if (!ComponentHelper::isEnabled('com_osmembership'))
{
return;
}
require_once JPATH_ADMINISTRATOR . '/components/com_osmembership/loader.php';
parent::registerListeners();
}
/**
* Move data for custom fields which is hide on membership renewal from original subscription to renewal subscription
*
* @param \OSMembershipTableSubscriber $row
*/
protected function moveHideOnMembershipRenewalData($row)
{
$db = $this->getDatabase();
$negPlanId = -1 * $row->plan_id;
$user = $this->getUserFactory()->loadUserById((int) $row->user_id);
// Prevent fatal error in case the user_id is invalid
if ($row->user_id > 0 && $user->id == null)
{
$user = Factory::getUser(0);
}
$viewLevels = $user->getAuthorisedViewLevels();
// Get the previous subscription
$query = $db->getQuery(true)
->select('*')
->from('#__osmembership_subscribers')
->where('plan_id = ' . (int) $row->plan_id)
->where('user_id = ' . $row->user_id)
->where('id < ' . $row->id)
->where('(published >= 1 OR (published = 0 AND payment_method LIKE "os_offline%"))')
->order('id DESC');
$db->setQuery($query);
$rowSubscriber = $db->loadObject();
if (!$rowSubscriber)
{
return;
}
$query->clear()
->select($db->quoteName(['id', 'name', 'is_core', 'access', 'hide_on_membership_renewal']))
->from('#__osmembership_fields')
->where('published = 1')
->where(
'(plan_id = 0 OR id IN (SELECT field_id FROM #__osmembership_field_plan WHERE plan_id = ' . $row->plan_id . ' OR plan_id < 0))'
)
->where('id NOT IN (SELECT field_id FROM #__osmembership_field_plan WHERE plan_id = ' . $negPlanId . ')');
$db->setQuery($query);
$rowFields = $db->loadObjectList();
// Get fields which already inserted
$query->clear()
->select('field_id')
->from('#__osmembership_field_value')
->where('subscriber_id = ' . $row->id);
$db->setQuery($query);
$insertedFieldIds = $db->loadColumn();
$updateRowRecord = false;
$moveFieldIds = [];
foreach ($rowFields as $rowField)
{
// The field is show on renewal form, no need to process it further
if (!$rowField->hide_on_membership_renewal
&& (in_array($rowField->access, $viewLevels) || $this->getApplication()->isClient('administrator')))
{
continue;
}
if ($rowField->is_core)
{
$fieldName = $rowField->name;
if (!$row->{$fieldName} && $rowSubscriber->{$fieldName})
{
$row->{$fieldName} = $rowSubscriber->{$fieldName};
}
$updateRowRecord = true;
}
elseif (!in_array($rowField->id, $insertedFieldIds))
{
$moveFieldIds[] = $rowField->id;
}
}
if ($updateRowRecord)
{
$row->store();
}
if (count($moveFieldIds) > 0)
{
$sql = 'INSERT INTO #__osmembership_field_value (subscriber_id, field_id, field_value)'
. " SELECT $row->id, field_id, field_value FROM #__osmembership_field_value WHERE subscriber_id = $rowSubscriber->id AND field_id IN (" . implode(
',',
$moveFieldIds
) . ')';
$db->setQuery($sql)
->execute();
}
}
/**
* Method to set profile data (is_profile, profile_id) for the subscription
*
* @param \OSMembershipTableSubscriber $row
*/
protected function setSubscriptionProfileData($row)
{
$row->is_profile = 1;
if ($row->user_id > 0)
{
$db = $this->getDatabase();
$query = $db->getQuery(true);
$query->select('id')
->from('#__osmembership_subscribers')
->where('user_id = ' . $row->user_id)
->where('(published >= 1 OR payment_method LIKE "os_offline%")')
->where('is_profile = 1');
$db->setQuery($query);
$profileId = $db->loadResult();
if ($profileId && $profileId != $row->id)
{
$row->is_profile = 0;
$row->profile_id = $profileId;
}
}
if ($row->is_profile == 1)
{
$row->profile_id = $row->id;
}
}
/**
* Method to set plan main record data (plan_main_record, plan_subscription_from_date) for the subscription.
*
* @param \OSMembershipTableSubscriber $row
*/
protected function setPlanMainRecordData($row)
{
$row->plan_main_record = 1;
if ($row->user_id > 0)
{
$db = $this->getDatabase();
$query = $db->getQuery(true);
$query->select('plan_subscription_from_date')
->from('#__osmembership_subscribers')
->where('plan_main_record = 1')
->where('user_id = ' . $row->user_id)
->where('plan_id = ' . $row->plan_id)
->where('id != ' . $row->id);
$db->setQuery($query);
if ($planMainRecord = $db->loadObject())
{
$row->plan_main_record = 0;
$row->plan_subscription_from_date = $planMainRecord->plan_subscription_from_date;
}
}
if ($row->plan_main_record == 1)
{
$row->plan_subscription_status = $row->published;
$row->plan_subscription_from_date = $row->from_date;
$row->plan_subscription_to_date = $row->to_date;
}
}
/**
* Method to generate invoice number for the subscription record
*
* @param \OSMembershipTableSubscriber $row
*/
protected function generateInvoiceNumber($row)
{
if (\OSMembershipHelper::callOverridableHelperMethod('Helper', 'needToCreateInvoice', [$row]))
{
$row->invoice_number = \OSMembershipHelper::getInvoiceNumber($row);
if (property_exists($row, 'formatted_invoice_number'))
{
$config = \OSMembershipHelper::getConfig();
$row->formatted_invoice_number = \OSMembershipHelper::formatInvoiceNumber($row, $config);
}
}
}
/**
* Create user account for subscriber after subscription being active
*
* @param \OSMembershipTableSubscriber $row
*
* @throws \Exception
*/
protected function createUserAccount($row)
{
$data['username'] = $row->username;
$data['first_name'] = $row->first_name;
$data['last_name'] = $row->last_name;
$data['email'] = $row->email;
//Password
$data['password1'] = \OSMembershipHelperCryptor::decrypt($row->user_password);
try
{
$row->user_id = (int) \OSMembershipHelper::saveRegistration($data);
if ($row->user_id > 0 && $row->language && $row->language !== '*')
{
$user = $this->getUserFactory()->loadUserById($row->user_id);
$user->setParam('language', $row->language);
$user->save();
}
$config = \OSMembershipHelper::getConfig();
if (PluginHelper::isEnabled('system', 'privacyconsent') && $config->show_privacy_policy_checkbox)
{
\OSMembershipHelperSubscription::acceptPrivacyConsent($row);
}
}
catch (\Exception $e)
{
\OSMembershipHelper::logData(JPATH_PLUGINS . '/system/membershippro/create_user_error.txt', $data, $e->getMessage());
}
}
/**
* Active user account automatically after subscription active
*
* @param $row
*/
protected function activateUserAccount($row)
{
if (ComponentHelper::getParams('com_users')->get('useractivation') != 2)
{
$user = $this->getUserFactory()->loadUserById((int) $row->user_id);
if ($user->block)
{
$user->block = 0;
$user->activation = '';
$user->save(true);
}
}
}
/**
* Generate Membership ID for a subscription record
*
* @param \OSMembershipTableSubscriber $row
*/
protected function generateMembershipId($row)
{
if ($row->user_id)
{
$db = $this->getDatabase();
$query = $db->getQuery(true);
$query->select('MAX(membership_id)')
->from('#__osmembership_subscribers')
->where('user_id = ' . $row->user_id);
$db->setQuery($query);
$row->membership_id = (int) $db->loadResult();
}
if (!$row->membership_id)
{
$row->membership_id = \OSMembershipHelper::callOverridableHelperMethod('Helper', 'getMembershipId', [$row]);
}
if ($row->membership_id > 0 && property_exists($row, 'formatted_membership_id'))
{
$config = \OSMembershipHelper::getConfig();
$row->formatted_membership_id = \OSMembershipHelper::formatMembershipId($row, $config);
}
}
/**
* Calculate and store subscription expired date of the user for the plan he just processed subscription
*
* @param \OSMembershipTableSubscriber $row
*/
protected function updateSubscriptionExpiredDate($row)
{
if (!$row->plan_id)
{
return;
}
$db = $this->getDatabase();
$query = $db->getQuery(true);
$query->select('MAX(to_date)')
->from('#__osmembership_subscribers')
->where('published = 1')
->where('profile_id = ' . $row->profile_id)
->where('plan_id = ' . $row->plan_id);
$db->setQuery($query);
$subscriptionExpiredDate = $db->loadResult();
if ($subscriptionExpiredDate)
{
$query->clear()
->update('#__osmembership_subscribers')
->set('plan_subscription_to_date = ' . $db->quote($subscriptionExpiredDate))
->where('profile_id = ' . $row->profile_id)
->where('plan_id = ' . $row->plan_id);
$db->setQuery($query)
->execute();
// Store plan_subscription_to_date back to $row object so that it can be used on other process
$row->plan_subscription_to_date = $subscriptionExpiredDate;
}
}
/**
* Update status of the plan for the user when subscription status change
*
* @param \OSMembershipTableSubscriber $row
*/
protected function updatePlanSubscriptionStatus($row)
{
if (!$row->plan_id)
{
return;
}
$subscriptionStatus = \OSMembershipHelperSubscription::getPlanSubscriptionStatusForUser(
$row->profile_id,
$row->plan_id
);
$db = $this->getDatabase();
$query = $db->getQuery(true);
$query->update('#__osmembership_subscribers')
->set('plan_subscription_status = ' . $subscriptionStatus)
->where('profile_id = ' . $row->profile_id)
->where('plan_id = ' . $row->plan_id);
$db->setQuery($query);
$db->execute();
// Store plan_subscription_status for this record to avoid it's changed by other plugin later
$row->plan_subscription_status = $subscriptionStatus;
}
/**
* Clear subscription expired reminder status
*
* @param \OSMembershipTableSubscriber $row
*/
protected function updateSendingReminderStatus($row)
{
if (!$row->plan_id || !$row->user_id)
{
return;
}
$db = $this->getDatabase();
$query = $db->getQuery(true);
$now = $db->quote(Factory::getDate()->toSql());
$query->update('#__osmembership_subscribers')
->set('first_reminder_sent = 1')
->set('second_reminder_sent = 1')
->set('third_reminder_sent = 1')
->set('first_reminder_sent_at = ' . $now)
->set('second_reminder_sent_at = ' . $now)
->set('third_reminder_sent_at = ' . $now)
->where('user_id = ' . $row->user_id)
->where('plan_id = ' . $row->plan_id)
->where('id != ' . $row->id);
$extraReminderSentFields = [
'fourth_reminder_sent',
'fifth_reminder_sent',
'sixth_reminder_sent',
];
foreach ($extraReminderSentFields as $extraField)
{
if (property_exists($row, $extraField))
{
$query->set($extraField . ' = 1')
->set($extraField . '_at = ' . $now);
}
}
$db->setQuery($query);
$db->execute();
}
/**
* Update subscription duration when membership is renewed.
*
* @param \OSMembershipTableSubscriber $row
*/
protected function updateSubscriptionOnRenew($row)
{
if (!$row->plan_id)
{
return;
}
$db = $this->getDatabase();
$query = $db->getQuery(true);
// Find the first subscription record of the user of this plan
$query->select('*')
->from('#__osmembership_subscribers')
->where('user_id = ' . $row->user_id)
->where('plan_id = ' . $row->plan_id)
->where('published IN (1, 2)')
->order('id');
$db->setQuery($query, 0, 1);
$rowSubscriber = $db->loadObject();
if (!$rowSubscriber)
{
return;
}
// Get subscription_id from the new subscription and set it for new subscription
if (!$row->subscription_id)
{
if ($rowSubscriber->subscription_id)
{
$row->subscription_id = $rowSubscriber->subscription_id;
}
else
{
$query->clear()
->select('subscription_id')
->from('#__osmembership_subscribers')
->where('user_id = ' . $row->user_id)
->where('plan_id = ' . $row->plan_id)
->where('published IN (1, 2)')
->where('LENGTH(subscription_id) > 0');
$db->setQuery($query);
$row->subscription_id = $db->loadResult();
}
}
// Keep payment_made parameter from original subscription
if ($rowSubscriber->payment_made > 0)
{
$row->payment_made = $rowSubscriber->payment_made;
}
if ($rowSubscriber->membership_id)
{
$row->membership_id = $rowSubscriber->membership_id;
}
// Delete all other subscription records to keep the management clean
$query->clear()
->delete('#__osmembership_subscribers')
->where('user_id = ' . $row->user_id)
->where('plan_id = ' . $row->plan_id)
->where('id != ' . $row->id);
$db->setQuery($query);
$db->execute();
// Set from_date is the date of the first_subscription record
$row->from_date = $rowSubscriber->from_date;
// Set profile data for the record
$this->setSubscriptionProfileData($row);
$row->plan_main_record = 1;
$row->plan_subscription_status = 1;
$row->plan_subscription_from_date = $row->from_date;
$row->plan_subscription_to_date = $row->to_date;
$row->store();
// Update profile_id for other subscription records from this user
if ($row->is_profile && $row->user_id)
{
$query->clear()
->update('#__osmembership_subscribers')
->set('profile_id = ' . $row->id)
->where('user_id = ' . $row->user_id)
->where('id != ' . $row->id);
$db->setQuery($query)
->execute();
}
}
/**
* Update subscription data from user profile data
*
* @param array $user
* @param array $subscriptionIds
*/
protected function updateSubscriptionsFromUserProfile($user, $subscriptionIds)
{
$profileFields = [
'address1',
'address2',
'city',
'region',
'country',
'postal_code',
'phone',
'website',
'favoritebook',
'aboutme',
'dob'
];
$db = $this->getDatabase();
$query = $db->getQuery(true)
->select('id, name, profile_field_mapping, is_core')
->from('#__osmembership_fields')
->whereIn('profile_field_mapping', $profileFields, ParameterType::STRING);
$db->setQuery($query);
$rowFields = $db->loadObjectList();
// No fields are mapped, don't process further
if (!count($rowFields))
{
return;
}
$name = $user['name'];
if ($name)
{
$pos = strpos($name, ' ');
if ($pos !== false)
{
$firstName = substr($name, 0, $pos);
$lastName = substr($name, $pos + 1);
}
else
{
$firstName = $name;
$lastName = '';
}
}
foreach ($subscriptionIds as $subscriptionId)
{
$rowSubscription = new \OSMembershipTableSubscriber($db);
$rowSubscription->load($subscriptionId);
$coreFieldsChange = false;
if (!empty($name))
{
$rowSubscription->first_name = $firstName;
$rowSubscription->last_name = $lastName;
$coreFieldsChange = true;
}
$query->clear()
->select('*')
->from('#__osmembership_field_value')
->where('subscriber_id = ' . $subscriptionId);
$db->setQuery($query);
$fieldValues = $db->loadObjectList('field_id');
foreach ($rowFields as $rowField)
{
if (isset($user['profile'][$rowField->profile_field_mapping]))
{
$userFieldValue = $user['profile'][$rowField->profile_field_mapping];
}
else
{
$userFieldValue = '';
}
if (is_array($userFieldValue))
{
$userFieldValue = json_encode($userFieldValue);
}
if ($rowField->is_core)
{
$rowSubscription->{$rowField->name} = $userFieldValue;
$coreFieldsChange = true;
}
elseif (array_key_exists($rowField->id, $fieldValues))
{
// Field is already exist, update
$query->clear()
->update('#__osmembership_field_value')
->set('field_value = ' . $db->quote($userFieldValue))
->where('id = ' . $fieldValues[$rowField->id]->id);
$db->setQuery($query)
->execute();
}
else
{
// Field is not existed, insert new record
$query->clear()
->insert('#__osmembership_field_value')
->columns($db->quoteName(['subscriber_id', 'field_id', 'field_value']))
->values(implode(',', $db->quote([$subscriptionId, $rowField->id, $userFieldValue])));
$db->setQuery($query)
->execute();
}
}
if ($coreFieldsChange)
{
$rowSubscription->store();
}
}
}
/***
* Update subscription data from user custom fields data
*
* @param array $user
* @param array $subscriptionIds
* @param array $userFields
*/
protected function updateSubscriptionsFromUserCustomFields($user, $subscriptionIds, $userFields)
{
$userFieldIds = [];
$userFieldNames = [];
$userFieldNameIdMapping = [];
foreach ($userFields as $field)
{
$userFieldIds[] = $field->id;
$userFieldNames[] = $field->name;
$userFieldNameIdMapping[$field->name] = $field->id;
}
$db = $this->getDatabase();
$query = $db->getQuery(true)
->select('id, name, profile_field_mapping, is_core')
->from('#__osmembership_fields')
->whereIn('profile_field_mapping', $userFieldNames, ParameterType::STRING);
$db->setQuery($query);
$rowFields = $db->loadObjectList();
// No fields are mapped, don't process further
if (!count($rowFields))
{
return;
}
$userId = (int) $user['id'];
/* @var FieldModel $model */
$model = $this->getApplication()->bootComponent('com_fields')->getMVCFactory()
->createModel('Field', 'Administrator', ['ignore_request' => true]);
$userFieldValues = $model->getFieldValues($userFieldIds, $userId);
foreach ($subscriptionIds as $subscriptionId)
{
$rowSubscription = new \OSMembershipTableSubscriber($db);
$rowSubscription->load($subscriptionId);
$coreFieldsChange = false;
$query->clear()
->select('*')
->from('#__osmembership_field_value')
->where('subscriber_id = ' . $subscriptionId);
$db->setQuery($query);
$fieldValues = $db->loadObjectList('field_id');
foreach ($rowFields as $rowField)
{
if (!isset($userFieldNameIdMapping[$rowField->profile_field_mapping]))
{
continue;
}
$userFieldId = $userFieldNameIdMapping[$rowField->profile_field_mapping];
if (array_key_exists($userFieldId, $userFieldValues))
{
$userFieldValue = $userFieldValues[$userFieldId];
}
else
{
$userFieldValue = '';
}
if (is_array($userFieldValue))
{
$userFieldValue = json_encode($userFieldValue);
}
if ($rowField->is_core)
{
$rowSubscription->{$rowField->name} = $userFieldValue;
$coreFieldsChange = true;
}
elseif (array_key_exists($rowField->id, $fieldValues))
{
// Field is already exist, update
$query->clear()
->update('#__osmembership_field_value')
->set('field_value = ' . $db->quote($userFieldValue))
->where('id = ' . $fieldValues[$rowField->id]->id);
$db->setQuery($query)
->execute();
}
else
{
// Field is not existed, insert new record
$query->clear()
->insert('#__osmembership_field_value')
->columns($db->quoteName(['subscriber_id', 'field_id', 'field_value']))
->values(implode(',', $db->quote([$subscriptionId, $rowField->id, $userFieldValue])));
$db->setQuery($query)
->execute();
}
}
if ($coreFieldsChange)
{
$rowSubscription->store();
}
}
}
/**
* Set avatar for subscription if it's not set and there is avatar from user account
*
* @param \OSMembershipTableSubscriber $row
*
* @return void
*/
protected function setAvatarForSubscription($row)
{
$config = \OSMembershipHelper::getConfig();
if ($config->enable_avatar && !$row->avatar && $row->user_id)
{
$db = $this->getDatabase();
$query = $db->getQuery(true)
->select('avatar')
->from('#__osmembership_subscribers')
->where('user_id = ' . $row->user_id)
->where('LENGTH(avatar) > 0');
$db->setQuery($query);
$avatar = $db->loadResult();
if ($avatar)
{
$row->avatar = $avatar;
}
}
}
/**
* Update coupon used statistic
*
* @param \OSMembershipTableSubscriber $row
*
* @return void
*/
protected function updateCouponUsage($row): void
{
// Early return if there is no coupon used for the coupon
if (!$row->coupon_id)
{
return;
}
$params = new Registry($row->params ?? '{}');
// Early return if the usage is already calculated for the coupon
if ($params->get('coupon_usage_calculated'))
{
return;
}
// Update the usage
$db = $this->getDatabase();
$query = $db->getQuery(true)
->update('#__osmembership_coupons')
->set('used = used + 1')
->where('id = ' . $row->coupon_id);
$db->setQuery($query);
$db->execute();
$params->set('coupon_usage_calculated', 1);
$row->params = $params->toString();
$row->store();
}
}