Files
IPB/applications/nexus/modules/front/subscriptions/subscriptions.php
T
2025-12-19 05:55:31 -08:00

321 lines
10 KiB
PHP

<?php
/**
* @brief subscriptions
* @author <a href='https://www.invisioncommunity.com'>Invision Power Services, Inc.</a>
* @copyright (c) Invision Power Services, Inc.
* @license https://www.invisioncommunity.com/legal/standards/
* @package Invision Community
* @subpackage Commerce
* @since 09 Feb 2018
*/
namespace IPS\nexus\modules\front\subscriptions;
/* To prevent PHP errors (extending class does not exist) revealing path */
if ( !\defined( '\IPS\SUITE_UNIQUE_KEY' ) )
{
header( ( isset( $_SERVER['SERVER_PROTOCOL'] ) ? $_SERVER['SERVER_PROTOCOL'] : 'HTTP/1.0' ) . ' 403 Forbidden' );
exit;
}
/**
* subscriptions
*/
class _subscriptions extends \IPS\Dispatcher\Controller
{
/**
* Execute
*
* @return void
*/
public function execute()
{
/* Work out currency */
if ( isset( \IPS\Request::i()->currency ) and \in_array( \IPS\Request::i()->currency, \IPS\nexus\Money::currencies() ) )
{
if ( isset( \IPS\Request::i()->csrfKey ) and \IPS\Login::compareHashes( (string) \IPS\Session::i()->csrfKey, (string) \IPS\Request::i()->csrfKey ) )
{
$_SESSION['cart'] = array();
\IPS\Request::i()->setCookie( 'currency', \IPS\Request::i()->currency );
\IPS\Output::i()->redirect( \IPS\Http\Url::internal( 'app=nexus&module=subscriptions&controller=subscriptions', 'front', 'nexus_subscriptions' ) );
}
}
parent::execute();
}
/**
* Show the subscription packages
*
* @return void
*/
protected function manage()
{
if ( ! \IPS\Settings::i()->nexus_subs_enabled )
{
\IPS\Output::i()->error( 'nexus_no_subs', '2X379/1', 404, '' );
}
/* Create the table */
$table = new \IPS\nexus\Subscription\Table( \IPS\Http\Url::internal( 'app=nexus&module=subscriptions&controller=subscriptions', 'front', 'nexus_subscriptions' ) );
$current = \IPS\nexus\Subscription::loadByMember( \IPS\Member::loggedIn(), FALSE );
if ( $current AND ( !$current->purchase OR !$current->purchase->cancelled OR $current->purchase->can_reactivate ) )
{
$table->activeSubscription = $current;
}
if ( isset( \IPS\Request::i()->purchased ) and $table->activeSubscription )
{
try
{
$invoice = \IPS\nexus\Invoice::load( $table->activeSubscription->invoice_id );
/* Fire the pixel event */
\IPS\core\Facebook\Pixel::i()->Purchase = array( 'value' => $invoice->total->amount, 'currency' => $invoice->total->currency );
\IPS\Output::i()->inlineMessage = \IPS\Member::loggedIn()->language()->addToStack( 'nexus_subs_paid_flash_msg');
}
catch( \Exception $e ) { }
}
\IPS\Output::i()->jsFiles = array_merge( \IPS\Output::i()->jsFiles, \IPS\Output::i()->js( 'front_subscriptions.js', 'nexus', 'front' ) );
\IPS\Output::i()->cssFiles = array_merge( \IPS\Output::i()->cssFiles, \IPS\Theme::i()->css( 'subscriptions.css', 'nexus' ) );
\IPS\Output::i()->breadcrumb['module'] = array( \IPS\Http\Url::internal( 'app=nexus&module=subscriptions&controller=subscriptions', 'front', 'nexus_subscriptions' ), \IPS\Member::loggedIn()->language()->addToStack('nexus_front_subscriptions') );
\IPS\Output::i()->title = \IPS\Member::loggedIn()->language()->addToStack('nexus_front_subscriptions');
\IPS\Output::i()->output = $table;
}
/**
* Change packages. It allows you to change packages. I mean again, the whole concept of PHPDoc seems to point out the obvious. A bit like GPS navigation for your front room. There's the sofa. There's the cat.
*
* @return void just like life, it is meaningless and temporary so live in the moment, enjoy each day and eat chocolate unless you have an allergy in which case don't. See your GP before starting any new diet.
*/
protected function change()
{
/* CSRF Check */
\IPS\Session::i()->csrfCheck();
try
{
$newPackage = \IPS\nexus\Subscription\Package::load( \IPS\Request::i()->id );
}
catch( \OutOfRangeException $e )
{
\IPS\Output::i()->error( 'nexus_no_subs_package', '2X379/2', 404, '' );
}
/* Is the subscription purchasable ? */
if ( !$newPackage->enabled )
{
\IPS\Output::i()->error( 'node_error', '2X379/7', 403, '' );
}
try
{
$subscription = \IPS\nexus\Subscription::loadActiveByMember( \IPS\Member::loggedIn() );
}
catch( \OutOfRangeException $e )
{
\IPS\Output::i()->error( 'nexus_no_subs_subs', '2X379/3', 404, '' );
}
/* Fetch purchase */
$purchase = NULL;
if( $subscription )
{
foreach ( \IPS\nexus\extensions\nexus\Item\Subscription::getPurchases( \IPS\nexus\Customer::loggedIn(), $subscription->package->id ) as $row )
{
if ( $row->active and ! $row->cancelled )
{
$purchase = $row;
break;
}
}
}
if ( $purchase === NULL )
{
\IPS\Output::i()->error( 'nexus_sub_no_purchase', '2X379/4', 404, '' );
}
/* Right, that's all the "I'll tamper with the URLs for a laugh" stuff out of the way... */
$upgradeCost = $newPackage->costToUpgrade( $subscription->package, \IPS\nexus\Customer::loggedIn() );
if ( $upgradeCost === NULL )
{
\IPS\Output::i()->error( 'nexus_no_subs_nocost', '2X379/5', 404, '' );
}
$invoice = $subscription->package->upgradeDowngrade( $purchase, $newPackage );
if ( $invoice )
{
\IPS\Output::i()->redirect( $invoice->checkoutUrl() );
}
$purchase->member->log( 'subscription', array( 'type' => 'change', 'id' => $purchase->id, 'old' => $purchase->name, 'name' => $newPackage->titleForLog(), 'system' => FALSE ) );
\IPS\Output::i()->redirect( \IPS\Http\Url::internal( 'app=nexus&module=subscriptions&controller=subscriptions', 'front', 'nexus_subscriptions' ) );
}
/**
* Purchase
*
* @return void
*/
protected function purchase()
{
/* CSRF Check */
\IPS\Session::i()->csrfCheck();
/* Already purchased a subscription which was not cancelled? */
if ( $current = \IPS\nexus\Subscription::loadByMember( \IPS\nexus\Customer::loggedIn(), FALSE ) AND ( $current->purchase AND !$current->cancelled AND ( !$current->purchase->cancelled OR $current->purchase->can_reactivate ) ) )
{
\IPS\Output::i()->error( 'nexus_subs_already_got_package', '2X379/6', 403, '' );
}
$package = \IPS\nexus\Subscription\Package::load( \IPS\Request::i()->id );
/* Is the subscription purchasable ? */
if ( !$package->enabled )
{
\IPS\Output::i()->error( 'node_error', '2X379/7', 403, '' );
}
$price = $package->price();
$item = new \IPS\nexus\extensions\nexus\Item\Subscription( \IPS\nexus\Customer::loggedIn()->language()->get( $package->_titleLanguageKey ), $price );
$item->id = $package->id;
try
{
$item->tax = \IPS\nexus\Tax::load( $package->tax );
}
catch ( \OutOfRangeException $e ) { }
if ( $package->gateways !== '*' )
{
$item->paymentMethodIds = explode( ',', $package->gateways );
}
$item->renewalTerm = $package->renewalTerm( $price->currency );
if ( $package->price and $costs = json_decode( $package->price, TRUE ) and isset( $costs['cost'] ) )
{
$item->initialInterval = new \DateInterval( 'P' . $costs['term'] . mb_strtoupper( $costs['unit'] ) );
}
/* Generate the invoice */
$invoice = new \IPS\nexus\Invoice;
$invoice->currency = $price->currency;
$invoice->member = \IPS\nexus\Customer::loggedIn();
$invoice->addItem( $item );
$invoice->return_uri = "app=nexus&module=subscriptions&controller=subscriptions&purchased=1";
$invoice->save();
/* Take them to it */
\IPS\Output::i()->redirect( $invoice->checkoutUrl() );
}
/**
* Reactivate
*
* @return void
*/
protected function reactivate()
{
/* CSRF Check */
\IPS\Session::i()->csrfCheck();
/* Get subscription and purchase */
try
{
$package = \IPS\nexus\Subscription\Package::load( \IPS\Request::i()->id );
}
catch( \OutOfRangeException $e )
{
\IPS\Output::i()->error( 'nexus_no_subs_package', '2X379/2', 404, '' );
}
try
{
$subscription = \IPS\nexus\Subscription::loadByMemberAndPackage( \IPS\Member::loggedIn(), $package, FALSE );
}
catch( \OutOfRangeException $e )
{
\IPS\Output::i()->error( 'nexus_no_subs_subs', '2X379/8', 404, '' );
}
$purchase = NULL;
foreach ( \IPS\nexus\extensions\nexus\Item\Subscription::getPurchases( \IPS\nexus\Customer::loggedIn(), $subscription->package->id, TRUE, TRUE ) as $row )
{
if ( $row->can_reactivate )
{
$purchase = $row;
break;
}
}
if ( $purchase === NULL )
{
\IPS\Output::i()->error( 'nexus_sub_no_purchase', '2X379/9', 404, '' );
}
/* Set renewal terms */
$currency = $purchase->original_invoice->currency;
$purchase->renewals = $package->renewalTerm( $currency );
$purchase->cancelled = FALSE;
$purchase->save();
$purchase->member->log( 'purchase', array( 'type' => 'info', 'id' => $purchase->id, 'name' => $purchase->name, 'info' => 'change_renewals', 'to' => array( 'cost' => $purchase->renewals->cost->amount, 'currency' => $purchase->renewals->cost->currency, 'term' => $purchase->renewals->getTerm() ) ) );
/* Either send to renewal invoice or just back to subscriptions list */
if ( !$purchase->active and $cycles = $purchase->canRenewUntil( NULL, TRUE ) AND $cycles !== FALSE )
{
$url = $cycles === 1 ? $purchase->url()->setQueryString( 'do', 'renew' )->csrf() : $purchase->url()->setQueryString( 'do', 'renew' );
\IPS\Output::i()->redirect( $url );
}
else
{
\IPS\Output::i()->redirect( \IPS\Http\Url::internal( 'app=nexus&module=subscriptions&controller=subscriptions', 'front', 'nexus_subscriptions' ) );
}
}
/**
* Cancel an expired subscription so that we can purchase another subscription
*/
public function cancel()
{
/* CSRF Check */
\IPS\Session::i()->csrfCheck();
try
{
$purchase = \IPS\nexus\Purchase::load( \IPS\Request::i()->id );
}
catch( \OutOfRangeException $e )
{
\IPS\Output::i()->error( 'nexus_no_subs_package', '2X379/8', 404, '' );
}
try
{
$subscription = \IPS\nexus\Subscription::loadByMemberAndPurchase( \IPS\Member::loggedIn(), $purchase, FALSE );
}
catch( \OutOfRangeException $e )
{
\IPS\Output::i()->error( 'nexus_no_subs_subs', '2X379/9', 404, '' );
}
if( !$subscription->canCancel() )
{
\IPS\Output::i()->error( 'no_module_permission', '1X379/A', 403, '' );
}
foreach ( \IPS\nexus\extensions\nexus\Item\Subscription::getPurchases( \IPS\nexus\Customer::loggedIn(), $subscription->package->id, TRUE, TRUE ) as $row )
{
$row->cancelled = TRUE;
$row->save();
}
$subscription->cancelled = TRUE;
$subscription->save();
\IPS\Output::i()->redirect( \IPS\Http\Url::internal( 'app=nexus&module=subscriptions&controller=subscriptions', 'front', 'nexus_subscriptions' ), 'cancelled' );
}
}