Seditio Source
Root |
./othercms/xenForo 2.2.8/src/XF/Purchasable/UserUpgrade.php
<?php

namespace XF\Purchasable;

use
XF\Payment\CallbackState;

use function
in_array, is_array;

class
UserUpgrade extends AbstractPurchasable
{
    public function
getTitle()
    {
        return \
XF::phrase('user_upgrades');
    }

    public function
getPurchaseFromRequest(\XF\Http\Request $request, \XF\Entity\User $purchaser, &$error = null)
    {
        if (!
$purchaser->user_id)
        {
           
$error = \XF::phrase('login_required');
            return
false;
        }

       
$profileId = $request->filter('payment_profile_id', 'uint');
       
$paymentProfile = \XF::em()->find('XF:PaymentProfile', $profileId);
        if (!
$paymentProfile || !$paymentProfile->active)
        {
           
$error = \XF::phrase('please_choose_valid_payment_profile_to_continue_with_your_purchase');
            return
false;
        }

       
$userUpgradeId = $request->filter('user_upgrade_id', 'uint');
       
$userUpgrade = \XF::em()->find('XF:UserUpgrade', $userUpgradeId);
        if (!
$userUpgrade || !$userUpgrade->canPurchase())
        {
           
$error = \XF::phrase('this_item_cannot_be_purchased_at_moment');
            return
false;
        }

        if (!
in_array($profileId, $userUpgrade->payment_profile_ids))
        {
           
$error = \XF::phrase('selected_payment_profile_is_not_valid_for_this_purchase');
            return
false;
        }

        return
$this->getPurchaseObject($paymentProfile, $userUpgrade, $purchaser);
    }

    public function
validatePurchasable(CallbackState $state, &$error = null): bool
   
{
       
$purchaseRequest = $state->getPurchaseRequest();
       
$extraData = $purchaseRequest->extra_data;

       
$userUpgrade = \XF::em()->find('XF:UserUpgrade', $extraData['user_upgrade_id']);
        if (!
$userUpgrade)
        {
           
$error = "Unable to find user upgrade '$extraData[user_upgrade_id]'";
            return
false;
        }

        return
true;
    }

    public function
getPurchasableFromExtraData(array $extraData)
    {
       
$output = [
           
'link' => '',
           
'title' => '',
           
'purchasable' => null
       
];
       
$userUpgrade = \XF::em()->find('XF:UserUpgrade', $extraData['user_upgrade_id']);
        if (
$userUpgrade)
        {
           
$output['link'] = \XF::app()->router('admin')->buildLink('user-upgrades/edit', $userUpgrade);
           
$output['title'] = $userUpgrade->title;
           
$output['purchasable'] = $userUpgrade;
        }
        return
$output;
    }

    public function
getPurchaseFromExtraData(array $extraData, \XF\Entity\PaymentProfile $paymentProfile, \XF\Entity\User $purchaser, &$error = null)
    {
       
$userUpgrade = $this->getPurchasableFromExtraData($extraData);
        if (!
$userUpgrade['purchasable'] || !$userUpgrade['purchasable']->canPurchase())
        {
           
$error = \XF::phrase('this_item_cannot_be_purchased_at_moment');
            return
false;
        }

        if (!
in_array($paymentProfile->payment_profile_id, $userUpgrade['purchasable']->payment_profile_ids))
        {
           
$error = \XF::phrase('selected_payment_profile_is_not_valid_for_this_purchase');
            return
false;
        }

        return
$this->getPurchaseObject($paymentProfile, $userUpgrade['purchasable'], $purchaser);
    }

   
/**
     * @param \XF\Entity\PaymentProfile $paymentProfile
     * @param \XF\Entity\UserUpgrade $purchasable
     * @param \XF\Entity\User $purchaser
     *
     * @return Purchase
     */
   
public function getPurchaseObject(\XF\Entity\PaymentProfile $paymentProfile, $purchasable, \XF\Entity\User $purchaser)
    {
       
$purchase = new Purchase();

       
$purchase->title = \XF::phrase('account_upgrade') . ': ' . $purchasable->title . ' (' . $purchaser->username . ')';
       
$purchase->description = $purchasable->description;
       
$purchase->cost = $purchasable->cost_amount;
       
$purchase->currency = $purchasable->cost_currency;
       
$purchase->recurring = ($purchasable->recurring && $purchasable->length_unit);
       
$purchase->lengthAmount = $purchasable->length_amount;
       
$purchase->lengthUnit = $purchasable->length_unit;
       
$purchase->purchaser = $purchaser;
       
$purchase->paymentProfile = $paymentProfile;
       
$purchase->purchasableTypeId = $this->purchasableTypeId;
       
$purchase->purchasableId = $purchasable->user_upgrade_id;
       
$purchase->purchasableTitle = $purchasable->title;
       
$purchase->extraData = [
           
'user_upgrade_id' => $purchasable->user_upgrade_id
       
];

       
$router = \XF::app()->router('public');

       
$purchase->returnUrl = $router->buildLink('canonical:account/upgrade-purchase');
       
$purchase->cancelUrl = $router->buildLink('canonical:account/upgrades');

        return
$purchase;
    }

    public function
completePurchase(CallbackState $state)
    {
        if (
$state->legacy)
        {
           
$purchaseRequest = null;
           
$userUpgradeId = $state->userUpgrade->user_upgrade_id;
           
$userUpgradeRecordId = $state->userUpgradeRecordId;
        }
        else
        {
           
$purchaseRequest = $state->getPurchaseRequest();
           
$userUpgradeId = $purchaseRequest->extra_data['user_upgrade_id'];
           
$userUpgradeRecordId = $purchaseRequest->extra_data['user_upgrade_record_id'] ?? null;
        }

       
$paymentResult = $state->paymentResult;
       
$purchaser = $state->getPurchaser();

       
$userUpgrade = \XF::em()->find(
           
'XF:UserUpgrade', $userUpgradeId, 'Active|' . $purchaser->user_id
       
);

       
/** @var \XF\Service\User\Upgrade $upgradeService */
       
$upgradeService = \XF::app()->service('XF:User\Upgrade', $userUpgrade, $purchaser);

        if (
$state->extraData && is_array($state->extraData))
        {
           
$upgradeService->setExtraData($state->extraData);
        }

       
$activeUpgrade = null;

        switch (
$paymentResult)
        {
            case
CallbackState::PAYMENT_RECEIVED:
               
$upgradeService->setPurchaseRequestKey($state->requestKey);
               
$activeUpgrade = $upgradeService->upgrade();

               
$state->logType = 'payment';
               
$state->logMessage = 'Payment received, upgraded/extended.';
                break;

            case
CallbackState::PAYMENT_REINSTATED:
                if (
$userUpgradeRecordId)
                {
                   
$existingRecord = \XF::em()->find('XF:UserUpgradeActive', $userUpgradeRecordId);
                   
$endColumn = 'end_date';

                    if (!
$existingRecord)
                    {
                       
$existingRecord = \XF::em()->find('XF:UserUpgradeExpired', $userUpgradeRecordId);
                       
$endColumn = 'original_end_date';
                    }
                    if (
$existingRecord)
                    {
                       
$upgradeService->setEndDate($existingRecord->$endColumn);
                    }
                   
$upgradeService->ignoreUnpurchasable(true);
                   
$activeUpgrade = $upgradeService->upgrade();

                   
$state->logType = 'payment';
                   
$state->logMessage = 'Reversal cancelled, upgrade reactivated.';
                }
                else
                {
                   
// We can't reinstate the upgrade because there doesn't appear to be an existing record.
                   
$state->logType = 'info';
                   
$state->logMessage = 'OK, no action.';
                }
                break;
        }

        if (
$activeUpgrade && $purchaseRequest)
        {
           
$extraData = $purchaseRequest->extra_data;
           
$extraData['user_upgrade_record_id'] = $activeUpgrade->user_upgrade_record_id;
           
$purchaseRequest->extra_data = $extraData;
           
$purchaseRequest->save();
        }
    }

    public function
reversePurchase(CallbackState $state)
    {
        if (
$state->legacy)
        {
           
$purchaseRequest = null;
           
$userUpgradeId = $state->userUpgrade->user_upgrade_id;
        }
        else
        {
           
$purchaseRequest = $state->getPurchaseRequest();
           
$userUpgradeId = $purchaseRequest->extra_data['user_upgrade_id'];
        }

       
$purchaser = $state->getPurchaser();

       
$userUpgrade = \XF::em()->find(
           
'XF:UserUpgrade', $userUpgradeId, 'Active|' . $purchaser->user_id
       
);

       
/** @var \XF\Service\User\Downgrade $downgradeService */
       
$downgradeService = \XF::app()->service('XF:User\Downgrade', $userUpgrade, $purchaser);
       
$downgradeService->setSendAlert(false);
       
$downgradeService->downgrade();

       
$state->logType = 'cancel';
       
$state->logMessage = 'Payment refunded/reversed, downgraded.';
    }

    public function
getPurchasablesByProfileId($profileId)
    {
       
$finder = \XF::finder('XF:UserUpgrade');

       
$quotedProfileId = $finder->quote($profileId);
       
$columnName = $finder->columnSqlName('payment_profile_ids');

       
$router = \XF::app()->router('admin');
       
$upgrades = $finder->whereSql("FIND_IN_SET($quotedProfileId, $columnName)")->fetch();
        return
$upgrades->pluck(function(\XF\Entity\UserUpgrade $upgrade, $key) use ($router)
        {
            return [
'user_upgrade_' . $key, [
               
'title' => $this->getTitle() . ': ' . $upgrade->title,
               
'link' => $router->buildLink('user-upgrades/edit', $upgrade)
            ]];
        },
false);
    }
}