<?php
namespace AddonFlare\PaidRegistrations\XF\Pub\Controller;
use XF\ConnectedAccount\Provider\AbstractProvider;
use XF\ConnectedAccount\ProviderData\AbstractProviderData;
use XF\Mvc\ParameterBag;
class Register extends XFCP_Register
{
public function checkCsrfIfNeeded($action, ParameterBag $params)
{
if (in_array($action, ['Index', 'AccountType'])) return;
parent::checkCsrfIfNeeded($action, $params);
}
public function actionIndex()
{
if (!$this->options()->af_paidregistrations_guest)
{
return parent::actionIndex();
}
$accountTypeId = $this->filter('accountType', 'uint');
if (($purchaseRequestKey = $this->filter('custom', 'str')) || ($purchaseRequestKey = $this->filter('cm', 'str')) || ($purchaseRequestKey = $this->filter('prk', 'str')))
{
$purchaseRequest = $this->em()->findOne('XF:PurchaseRequest', [
'request_key' => $purchaseRequestKey,
'user_id' => 0,
'purchasable_type_id' => 'user_upgrade',
]);
if ($purchaseRequest)
{
$userUpgrade = $this->em()->find('XF:UserUpgrade', $purchaseRequest->extra_data['user_upgrade_id']);
if ($userUpgrade && $userUpgrade->can_purchase)
{
$reply = parent::actionIndex();
if ($reply instanceof \XF\Mvc\Reply\View)
{
if (!empty($purchaseRequest->extra_data['email']))
{
$this->assertPaidRegistrationEmailNotRegistered($purchaseRequest->extra_data['email']);
}
// use the purchase request cost amount instead just incase it was a custom amount
$userUpgrade->cost_amount = $purchaseRequest->cost_amount;
// set to read only just incase it somehow attempts to save, shouldn't happen though
$userUpgrade->setReadOnly(true);
$reply->setParam('purchaseRequest', $purchaseRequest);
$reply->setParam('userUpgrade', $userUpgrade);
$fields = $reply->getParam('fields');
$fields['email'] = $purchaseRequest->extra_data['email'];
$reply->setParam('fields', $fields);
}
return $reply;
}
}
}
$accountType = $this->getAccountType($accountTypeId);
// if no or invalid account type was chosen or a valid account type was chosen but it's not a "free" type
// entering a valid user_upgrade_id ex. register/?accountType=3 should still show the list because we handle the purchase in actionPurchase()
if (!$accountType || $accountType->user_upgrade_id != -1)
{
// at least one account type must be available
if ($this->getAccountTypeRepo()->findActiveAccountTypesForList()->total())
{
return $this->accountTypes();
}
}
// regular registration form, only executed by "free type"
return parent::actionIndex();
}
public function actionRegister()
{
if (!$this->options()->af_paidregistrations_guest)
{
return parent::actionRegister();
}
$purchaseRequest = null;
if ($purchaseRequestKey = $this->filter('prk', 'str'))
{
$purchaseRequest = $this->em()->findOne('XF:PurchaseRequest', [
'request_key' => $purchaseRequestKey,
'user_id' => 0,
'purchasable_type_id' => 'user_upgrade',
]);
if ($purchaseRequest && !empty($purchaseRequest->extra_data['email']))
{
$this->assertPaidRegistrationEmailNotRegistered($purchaseRequest->extra_data['email']);
}
}
$freeAccountTypes = $this->getAccountTypeRepo()->findActiveAccountTypesForList()
->where('user_upgrade_id', '=', -1)->fetch();
if (!$purchaseRequest && !$freeAccountTypes->count())
{
if ($this->getAccountTypeRepo()->findActiveAccountTypesForList()->total())
{
// there's no valid purchase request and there's no free account type and we have at least one active account type the guest could've used to register
return $this->error(\XF::phrase('invalid_purchase_request'));
}
}
// make sure the same email is being used to register
if ($this->options()->af_paidregistrations_force_same_email && $purchaseRequest && !empty($purchaseRequest->extra_data['email']))
{
$regForm = $this->service('XF:User\RegisterForm', $this->session());
if ($purchaseRequest->extra_data['email'] != $this->filter($regForm->getFieldName('email'), 'str'))
{
return $this->error(\XF::phrase('af_paidregistrations_must_use_same_email', ['email' => $purchaseRequest->extra_data['email']]));
}
}
// process normal registration
$reply = parent::actionRegister();
$visitor = \XF::visitor();
// if registration was successful & we have a purchase request, link it to the new user
if ($visitor->user_id && $purchaseRequest)
{
$purchaseRequest->fastUpdate('user_id', $visitor->user_id);
}
return $reply;
}
public function actionPurchase()
{
$accountTypeId = $this->filter('accountType', 'uint');
$accountType = $this->getAccountType($accountTypeId);
if
(
!$accountType ||
$accountType->user_upgrade_id == -1 ||
!$accountType->UserUpgrade ||
!$accountType->UserUpgrade->can_purchase ||
($accountType->allow_custom_amount && $accountType->disable_custom_amount_guest)
)
{
return $this->error(\XF::phrase('af_paidregistrations_invalid_accountType'));
}
/** @var \XF\Repository\Payment $paymentRepo */
$paymentRepo = $this->repository('XF:Payment');
$profiles = $paymentRepo->findPaymentProfilesForList()
->where(['Provider.provider_id', '=', \AddonFlare\PaidRegistrations\Entity\AccountType::getSupportedPaymentProviderIds()])
->pluckFrom(function ($e)
{
return ($e->display_title ?: $e->title);
})
->fetch();
$aliasUpgrades = [];
if ($accountType->alias_user_upgrades)
{
$aliasUserUpgradeIds = array_keys($accountType->alias_user_upgrades);
// add the main/parent user_upgrade_id
$aliasUserUpgradeIds[] = $accountType->user_upgrade_id;
$upgradeRepo = $this->repository('XF:UserUpgrade');
$aliasUpgrades = $upgradeRepo->findUserUpgradesForList()
->where('can_purchase', '=', 1)
->whereIds($aliasUserUpgradeIds)
->fetch();
}
$viewParams = [
'accountType' => $accountType,
'upgrade' => $accountType->UserUpgrade,
'profiles' => $profiles,
'aliasUpgrades' => $aliasUpgrades,
'isRegistration' => true,
'hasOnlyPayPal' => false, // never true for guests, they need to fill out email field
'allowCustomAmount' => $accountType->allow_custom_amount,
];
return $this->view('', 'af_paidregistrations_purchase', $viewParams);
}
protected function accountTypes()
{
if (\XF::visitor()->user_id)
{
return $this->redirect($this->getDynamicRedirectIfNot($this->buildLink('register')));
}
$this->assertRegistrationActive();
$purchasable = $this->em()->find('XF:Purchasable', 'user_upgrade', 'AddOn');
if (!$purchasable->isActive())
{
return $this->message(\XF::phrase('no_account_upgrades_can_be_purchased_at_this_time'));
}
$upgradeRepo = $this->repository('XF:UserUpgrade');
$upgrades = $upgradeRepo->findUserUpgradesForList()->fetch();
if (!$upgrades->count())
{
return $this->message(\XF::phrase('no_account_upgrades_can_be_purchased_at_this_time'));
}
$accountTypes = $this->getAccountTypeRepo()->findActiveAccountTypesForList()->fetch();
$has = false;
foreach ($accountTypes as $accountType)
{
if ($accountType->user_upgrade_id == -1 || $accountType->version)
{
$has = true;
break;
}
}
if (!$has)
{
$this->em()->create('AddonFlare\PaidRegistrations:AccountType')->save();
$accountTypes = $this->getAccountTypeRepo()->findActiveAccountTypesForList()->fetch();
}
// since this controller is used by guests only, make sure custom amount is disabled or allowed for guests
$accountTypes = $accountTypes->filter(function($accountType)
{
return (!$accountType->allow_custom_amount || !$accountType->disable_custom_amount_guest);
});
$accountTypeRows = $accountTypes->groupBy('row');
ksort($accountTypeRows);
$viewParams = [
'accountTypeRows' => $accountTypeRows,
];
return $this->view('', 'af_paidregistrations_accounttype', $viewParams);
}
protected function getAccountTypeRepo()
{
return $this->repository('AddonFlare\PaidRegistrations:AccountType');
}
protected function getAccountType($accountTypeId)
{
$accountType = $this->getAccountTypeRepo()->findAccountTypesForList()
->where('account_type_id', '=', $accountTypeId)
->fetchOne();
return $accountType;
}
protected function assertPaidRegistrationEmailNotRegistered($email)
{
if ($existingUser = \XF::finder('XF:User')->where('email', $email)->fetchOne())
{
throw $this->exception($this->error(\XF::phrase('af_paidregistrations_already_registered_username_x', ['username' => $existingUser['username']])));
}
return true;
}
}