Version 5.0.0 beta 1
This commit is contained in:
1 parent
25ddeb65d6
commit
15c7beabc5
6736 files changed
+627902
-497943
No files matched your search
File diff suppressed because it is too large.
Load diff
@@ -12,38 +12,56 @@
|
||||
namespace IPS\nexus\modules\front\clients;
|
||||
|
||||
/* To prevent PHP errors (extending class does not exist) revealing path */
|
||||
if ( !\defined( '\IPS\SUITE_UNIQUE_KEY' ) )
|
||||
|
||||
use IPS\Db;
|
||||
use IPS\Dispatcher\Controller;
|
||||
use IPS\Helpers\Form;
|
||||
use IPS\Http\Url;
|
||||
use IPS\Member;
|
||||
use IPS\MFA\MFAHandler;
|
||||
use IPS\nexus\Customer;
|
||||
use IPS\nexus\Customer\Address;
|
||||
use IPS\nexus\Tax;
|
||||
use IPS\Output;
|
||||
use IPS\Patterns\ActiveRecordIterator;
|
||||
use IPS\Request;
|
||||
use IPS\Session;
|
||||
use IPS\Theme;
|
||||
use OutOfRangeException;
|
||||
use function defined;
|
||||
|
||||
if ( !defined( '\IPS\SUITE_UNIQUE_KEY' ) )
|
||||
{
|
||||
header( ( isset( $_SERVER['SERVER_PROTOCOL'] ) ? $_SERVER['SERVER_PROTOCOL'] : 'HTTP/1.0' ) . ' 403 Forbidden' );
|
||||
header( ( $_SERVER['SERVER_PROTOCOL'] ?? 'HTTP/1.0' ) . ' 403 Forbidden' );
|
||||
exit;
|
||||
}
|
||||
|
||||
/**
|
||||
* Addresses
|
||||
*/
|
||||
class _addresses extends \IPS\Dispatcher\Controller
|
||||
class addresses extends Controller
|
||||
{
|
||||
/**
|
||||
* Execute
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function execute()
|
||||
public function execute() : void
|
||||
{
|
||||
if ( !\IPS\Member::loggedIn()->member_id )
|
||||
if ( !Member::loggedIn()->member_id )
|
||||
{
|
||||
\IPS\Output::i()->error( 'no_module_permission_guest', '2X235/1', 403, '' );
|
||||
Output::i()->error( 'no_module_permission_guest', '2X235/1', 403, '' );
|
||||
}
|
||||
|
||||
\IPS\Output::i()->jsFiles = array_merge( \IPS\Output::i()->jsFiles, \IPS\Output::i()->js( 'global_forms.js', 'nexus', 'global' ) );
|
||||
\IPS\Output::i()->cssFiles = array_merge( \IPS\Output::i()->cssFiles, \IPS\Theme::i()->css( 'clients.css', 'nexus' ) );
|
||||
\IPS\Output::i()->breadcrumb[] = array( \IPS\Http\Url::internal( 'app=nexus&module=clients&controller=addresses', 'front', 'clientsaddresses' ), \IPS\Member::loggedIn()->language()->addToStack('client_addresses') );
|
||||
\IPS\Output::i()->title = \IPS\Member::loggedIn()->language()->addToStack('client_addresses');
|
||||
\IPS\Output::i()->sidebar['enabled'] = FALSE;
|
||||
Output::i()->jsFiles = array_merge( Output::i()->jsFiles, Output::i()->js( 'global_forms.js', 'nexus', 'global' ) );
|
||||
Output::i()->cssFiles = array_merge( Output::i()->cssFiles, Theme::i()->css( 'clients.css', 'nexus' ) );
|
||||
Output::i()->breadcrumb[] = array( Url::internal( 'app=nexus&module=clients&controller=addresses', 'front', 'clientsaddresses' ), Member::loggedIn()->language()->addToStack('client_addresses') );
|
||||
Output::i()->title = Member::loggedIn()->language()->addToStack('client_addresses');
|
||||
Output::i()->sidebar['enabled'] = FALSE;
|
||||
|
||||
if ( $output = \IPS\MFA\MFAHandler::accessToArea( 'nexus', 'Addresses', \IPS\Http\Url::internal( 'app=nexus&module=clients&controller=addresses', 'front', 'clientsaddresses' ) ) )
|
||||
if ( $output = MFAHandler::accessToArea( 'nexus', 'Addresses', Url::internal( 'app=nexus&module=clients&controller=addresses', 'front', 'clientsaddresses' ) ) )
|
||||
{
|
||||
\IPS\Output::i()->output = \IPS\Theme::i()->getTemplate('clients')->addresses( NULL, NULL, array() ) . $output;
|
||||
Output::i()->output = Theme::i()->getTemplate('clients')->addresses( NULL, NULL, array() ) . $output;
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -55,11 +73,10 @@ class _addresses extends \IPS\Dispatcher\Controller
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
protected function manage()
|
||||
protected function manage() : void
|
||||
{
|
||||
$addresses = new \IPS\Patterns\ActiveRecordIterator( \IPS\Db::i()->select( '*', 'nexus_customer_addresses', array( '`member`=?', \IPS\Member::loggedIn()->member_id ) ), 'IPS\nexus\Customer\Address' );
|
||||
$addresses = new ActiveRecordIterator( Db::i()->select( '*', 'nexus_customer_addresses', array( '`member`=?', Member::loggedIn()->member_id ) ), 'IPS\nexus\Customer\Address' );
|
||||
|
||||
$shippingAddress = NULL;
|
||||
$billingAddress = NULL;
|
||||
$otherAddresses = array();
|
||||
|
||||
@@ -69,19 +86,13 @@ class _addresses extends \IPS\Dispatcher\Controller
|
||||
{
|
||||
$billingAddress = $address;
|
||||
}
|
||||
|
||||
if( $address->primary_shipping )
|
||||
{
|
||||
$shippingAddress = $address;
|
||||
}
|
||||
|
||||
if( !$address->primary_shipping && !$address->primary_billing )
|
||||
else
|
||||
{
|
||||
$otherAddresses[] = $address;
|
||||
}
|
||||
}
|
||||
|
||||
\IPS\Output::i()->output = \IPS\Theme::i()->getTemplate('clients')->addresses( $billingAddress, $shippingAddress, $otherAddresses );
|
||||
Output::i()->output = Theme::i()->getTemplate('clients')->addresses( $billingAddress, $otherAddresses );
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -89,27 +100,27 @@ class _addresses extends \IPS\Dispatcher\Controller
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
protected function form()
|
||||
protected function form() : void
|
||||
{
|
||||
$existing = NULL;
|
||||
if ( isset( \IPS\Request::i()->id ) )
|
||||
if ( isset( Request::i()->id ) )
|
||||
{
|
||||
try
|
||||
{
|
||||
$existing = \IPS\nexus\Customer\Address::load( \IPS\Request::i()->id );
|
||||
if ( $existing->member->member_id != \IPS\Member::loggedIn()->member_id )
|
||||
$existing = Address::load( Request::i()->id );
|
||||
if ( $existing->member->member_id != Member::loggedIn()->member_id )
|
||||
{
|
||||
throw new \OutOfRangeException;
|
||||
throw new OutOfRangeException;
|
||||
}
|
||||
}
|
||||
catch ( \OutOfRangeException $e )
|
||||
catch ( OutOfRangeException )
|
||||
{
|
||||
$existing = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
$needTaxStatus = NULL;
|
||||
foreach ( \IPS\nexus\Tax::roots() as $tax )
|
||||
foreach ( Tax::roots() as $tax )
|
||||
{
|
||||
if ( $tax->type === 'eu' )
|
||||
{
|
||||
@@ -124,41 +135,40 @@ class _addresses extends \IPS\Dispatcher\Controller
|
||||
$addressHelperClass = $needTaxStatus ? 'IPS\nexus\Form\BusinessAddress' : 'IPS\Helpers\Form\Address';
|
||||
$addressHelperOptions = ( $needTaxStatus === 'eu' ) ? array( 'vat' => TRUE ) : array();
|
||||
|
||||
$form = new \IPS\Helpers\Form;
|
||||
$form->add( new $addressHelperClass( 'address', $existing ? $existing->address : NULL, TRUE, $addressHelperOptions ) );
|
||||
$form = new Form;
|
||||
$form->add( new $addressHelperClass( 'address', $existing?->address, TRUE, $addressHelperOptions ) );
|
||||
|
||||
if ( $values = $form->values() )
|
||||
{
|
||||
if ( !$existing )
|
||||
{
|
||||
$existing = new \IPS\nexus\Customer\Address;
|
||||
$existing->member = \IPS\Member::loggedIn();
|
||||
$existing->primary_billing = !\IPS\Db::i()->select( 'count(*)', 'nexus_customer_addresses', array( '`member`=? AND primary_billing=1', \IPS\Member::loggedIn()->member_id ) )->first();
|
||||
$existing->primary_shipping = !\IPS\Db::i()->select( 'count(*)', 'nexus_customer_addresses', array( '`member`=? AND primary_shipping=1', \IPS\Member::loggedIn()->member_id ) )->first();
|
||||
|
||||
\IPS\nexus\Customer::loggedIn()->log( 'address', array( 'type' => 'add', 'details' => json_encode( $values['address'] ) ) );
|
||||
$existing = new Address;
|
||||
$existing->member = Member::loggedIn();
|
||||
$existing->primary_billing = !Db::i()->select( 'count(*)', 'nexus_customer_addresses', array( '`member`=? AND primary_billing=1', Member::loggedIn()->member_id ) )->first();
|
||||
|
||||
Customer::loggedIn()->log( 'address', array( 'type' => 'add', 'details' => json_encode( $values['address'] ) ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
\IPS\nexus\Customer::loggedIn()->log( 'address', array( 'type' => 'edit', 'new' => json_encode( $values['address'] ), 'old' => json_encode( $existing->address ) ) );
|
||||
Customer::loggedIn()->log( 'address', array( 'type' => 'edit', 'new' => json_encode( $values['address'] ), 'old' => json_encode( $existing->address ) ) );
|
||||
}
|
||||
|
||||
$existing->address = $values['address'];
|
||||
$existing->save();
|
||||
|
||||
\IPS\Request::i()->setCookie( 'location', NULL );
|
||||
Request::i()->setCookie( 'location', NULL );
|
||||
|
||||
\IPS\Output::i()->redirect( \IPS\Http\Url::internal( 'app=nexus&module=clients&controller=addresses', 'front', 'clientsaddresses' ) );
|
||||
Output::i()->redirect( Url::internal( 'app=nexus&module=clients&controller=addresses', 'front', 'clientsaddresses' ) );
|
||||
}
|
||||
|
||||
if ( \IPS\Request::i()->isAjax() )
|
||||
if ( Request::i()->isAjax() )
|
||||
{
|
||||
$form->class = 'ipsForm_vertical ipsForm_noLabels';
|
||||
\IPS\Output::i()->sendOutput( $form->customTemplate( array( \IPS\Theme::i()->getTemplate( 'forms', 'core' ), 'popupTemplate' ) ) );
|
||||
$form->class = 'ipsForm--vertical ipsForm--edit-address ipsForm--noLabels';
|
||||
Output::i()->sendOutput( $form->customTemplate( array( Theme::i()->getTemplate( 'forms', 'core' ), 'popupTemplate' ) ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
\IPS\Output::i()->output = $form;
|
||||
Output::i()->output = $form;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -167,28 +177,27 @@ class _addresses extends \IPS\Dispatcher\Controller
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
protected function primary()
|
||||
protected function primary() : void
|
||||
{
|
||||
\IPS\Session::i()->csrfCheck();
|
||||
Session::i()->csrfCheck();
|
||||
|
||||
try
|
||||
{
|
||||
$address = \IPS\nexus\Customer\Address::load( \IPS\Request::i()->id );
|
||||
if ( $address->member->member_id == \IPS\Member::loggedIn()->member_id )
|
||||
$address = Address::load( Request::i()->id );
|
||||
if ( $address->member->member_id == Member::loggedIn()->member_id )
|
||||
{
|
||||
$field = \IPS\Request::i()->primary === 'billing' ? 'primary_billing' : 'primary_shipping';
|
||||
\IPS\Db::i()->update( 'nexus_customer_addresses', array( $field => 0 ), array( '`member`=?', \IPS\Member::loggedIn()->member_id ) );
|
||||
$address->$field = TRUE;
|
||||
Db::i()->update( 'nexus_customer_addresses', array( 'primary_billing' => 0 ), array( '`member`=?', Member::loggedIn()->member_id ) );
|
||||
$address->primary_billing = TRUE;
|
||||
$address->save();
|
||||
|
||||
\IPS\nexus\Customer::loggedIn()->log( 'address', array( 'type' => ( \IPS\Request::i()->primary === 'billing' ? 'primary_billing' : 'primary_shipping' ), 'details' => json_encode( $address->address ) ) );
|
||||
Customer::loggedIn()->log( 'address', array( 'type' => 'primary_billing', 'details' => json_encode( $address->address ) ) );
|
||||
}
|
||||
}
|
||||
catch ( \OutOfRangeException $e ) {}
|
||||
catch ( OutOfRangeException ) {}
|
||||
|
||||
\IPS\Request::i()->setCookie( 'location', NULL );
|
||||
Request::i()->setCookie( 'location', NULL );
|
||||
|
||||
\IPS\Output::i()->redirect( \IPS\Http\Url::internal( 'app=nexus&module=clients&controller=addresses', 'front', 'clientsaddresses' ) );
|
||||
Output::i()->redirect( Url::internal( 'app=nexus&module=clients&controller=addresses', 'front', 'clientsaddresses' ) );
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -196,24 +205,24 @@ class _addresses extends \IPS\Dispatcher\Controller
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
protected function delete()
|
||||
protected function delete() : void
|
||||
{
|
||||
\IPS\Session::i()->csrfCheck();
|
||||
Session::i()->csrfCheck();
|
||||
|
||||
/* Make sure the user confirmed the deletion */
|
||||
\IPS\Request::i()->confirmedDelete();
|
||||
Request::i()->confirmedDelete();
|
||||
|
||||
try
|
||||
{
|
||||
$address = \IPS\nexus\Customer\Address::load( \IPS\Request::i()->id );
|
||||
if ( $address->member->member_id == \IPS\Member::loggedIn()->member_id )
|
||||
$address = Address::load( Request::i()->id );
|
||||
if ( $address->member->member_id == Member::loggedIn()->member_id )
|
||||
{
|
||||
$address->delete();
|
||||
\IPS\nexus\Customer::loggedIn()->log( 'address', array( 'type' => 'delete', 'details' => json_encode( $address->address ) ) );
|
||||
Customer::loggedIn()->log( 'address', array( 'type' => 'delete', 'details' => json_encode( $address->address ) ) );
|
||||
}
|
||||
}
|
||||
catch ( \OutOfRangeException $e ) {}
|
||||
catch ( OutOfRangeException ) {}
|
||||
|
||||
\IPS\Output::i()->redirect( \IPS\Http\Url::internal( 'app=nexus&module=clients&controller=addresses', 'front', 'clientsaddresses' ) );
|
||||
Output::i()->redirect( Url::internal( 'app=nexus&module=clients&controller=addresses', 'front', 'clientsaddresses' ) );
|
||||
}
|
||||
}
|
||||
@@ -12,155 +12,173 @@
|
||||
namespace IPS\nexus\modules\front\clients;
|
||||
|
||||
/* To prevent PHP errors (extending class does not exist) revealing path */
|
||||
if ( !\defined( '\IPS\SUITE_UNIQUE_KEY' ) )
|
||||
|
||||
use DomainException;
|
||||
use IPS\Db;
|
||||
use IPS\Dispatcher\Controller;
|
||||
use IPS\Helpers\Form;
|
||||
use IPS\Helpers\Form\Checkbox;
|
||||
use IPS\Helpers\Form\Email;
|
||||
use IPS\Helpers\Form\Node;
|
||||
use IPS\Http\Url;
|
||||
use IPS\Member;
|
||||
use IPS\MFA\MFAHandler;
|
||||
use IPS\nexus\Customer;
|
||||
use IPS\nexus\Customer\AlternativeContact;
|
||||
use IPS\Output;
|
||||
use IPS\Request;
|
||||
use IPS\Session;
|
||||
use IPS\Theme;
|
||||
use UnderflowException;
|
||||
use function defined;
|
||||
|
||||
if ( !defined( '\IPS\SUITE_UNIQUE_KEY' ) )
|
||||
{
|
||||
header( ( isset( $_SERVER['SERVER_PROTOCOL'] ) ? $_SERVER['SERVER_PROTOCOL'] : 'HTTP/1.0' ) . ' 403 Forbidden' );
|
||||
header( ( $_SERVER['SERVER_PROTOCOL'] ?? 'HTTP/1.0' ) . ' 403 Forbidden' );
|
||||
exit;
|
||||
}
|
||||
|
||||
/**
|
||||
* Alternative Contacts
|
||||
*/
|
||||
class _alternatives extends \IPS\Dispatcher\Controller
|
||||
class alternatives extends Controller
|
||||
{
|
||||
/**
|
||||
* Execute
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function execute()
|
||||
public function execute() : void
|
||||
{
|
||||
if ( !\IPS\Member::loggedIn()->member_id )
|
||||
if ( !Member::loggedIn()->member_id )
|
||||
{
|
||||
\IPS\Output::i()->error( 'no_module_permission_guest', '2X237/1', 403, '' );
|
||||
Output::i()->error( 'no_module_permission_guest', '2X237/1', 403, '' );
|
||||
}
|
||||
|
||||
\IPS\Output::i()->cssFiles = array_merge( \IPS\Output::i()->cssFiles, \IPS\Theme::i()->css( 'clients.css', 'nexus' ) );
|
||||
\IPS\Output::i()->breadcrumb[] = array( \IPS\Http\Url::internal( 'app=nexus&module=clients&controller=alternatives', 'front', 'clientsalternatives' ), \IPS\Member::loggedIn()->language()->addToStack('client_alternatives') );
|
||||
\IPS\Output::i()->title = \IPS\Member::loggedIn()->language()->addToStack('client_alternatives');
|
||||
\IPS\Output::i()->sidebar['enabled'] = FALSE;
|
||||
|
||||
if ( $output = \IPS\MFA\MFAHandler::accessToArea( 'nexus', 'Alternatives', \IPS\Http\Url::internal( 'app=nexus&module=clients&controller=alternatives', 'front', 'clientsalternatives' ) ) )
|
||||
|
||||
Output::i()->cssFiles = array_merge( Output::i()->cssFiles, Theme::i()->css( 'clients.css', 'nexus' ) );
|
||||
Output::i()->breadcrumb[] = array( Url::internal( 'app=nexus&module=clients&controller=alternatives', 'front', 'clientsalternatives' ), Member::loggedIn()->language()->addToStack('client_alternatives') );
|
||||
Output::i()->title = Member::loggedIn()->language()->addToStack('client_alternatives');
|
||||
Output::i()->sidebar['enabled'] = FALSE;
|
||||
|
||||
if ( $output = MFAHandler::accessToArea( 'nexus', 'Alternatives', Url::internal( 'app=nexus&module=clients&controller=alternatives', 'front', 'clientsalternatives' ) ) )
|
||||
{
|
||||
\IPS\Output::i()->output = \IPS\Theme::i()->getTemplate('clients')->alternatives( TRUE ) . $output;
|
||||
Output::i()->output = Theme::i()->getTemplate('clients')->alternatives( TRUE ) . $output;
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
parent::execute();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* View List
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
protected function manage()
|
||||
protected function manage() : void
|
||||
{
|
||||
foreach ( \IPS\nexus\Customer::loggedIn()->alternativeContacts() as $contact )
|
||||
foreach ( Customer::loggedIn()->alternativeContacts() as $contact )
|
||||
{
|
||||
$contact->alt_id;
|
||||
}
|
||||
|
||||
\IPS\Output::i()->output = \IPS\Theme::i()->getTemplate('clients')->alternatives();
|
||||
|
||||
Output::i()->output = Theme::i()->getTemplate('clients')->alternatives();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Add/Edit
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
protected function form()
|
||||
protected function form() : void
|
||||
{
|
||||
$existing = NULL;
|
||||
if ( isset( \IPS\Request::i()->id ) )
|
||||
if ( isset( Request::i()->id ) )
|
||||
{
|
||||
try
|
||||
{
|
||||
$existing = \IPS\nexus\Customer\AlternativeContact::constructFromData( \IPS\Db::i()->select( '*', 'nexus_alternate_contacts', array( 'main_id=? AND alt_id=?', \IPS\nexus\Customer::loggedIn()->member_id, \IPS\Request::i()->id ) )->first() );
|
||||
$existing = AlternativeContact::constructFromData( Db::i()->select( '*', 'nexus_alternate_contacts', array( 'main_id=? AND alt_id=?', Customer::loggedIn()->member_id, Request::i()->id ) )->first() );
|
||||
}
|
||||
catch ( \UnderflowException $e ) {}
|
||||
catch ( UnderflowException ) {}
|
||||
}
|
||||
|
||||
$form = new \IPS\Helpers\Form;
|
||||
$form->class = 'ipsForm_vertical';
|
||||
|
||||
$form = new Form;
|
||||
$form->class = 'ipsForm--vertical ipsForm--edit-alernatives';
|
||||
if ( !$existing )
|
||||
{
|
||||
$form->add( new \IPS\Helpers\Form\Email( 'altcontact_email', NULL, TRUE, array(), function( $val )
|
||||
$form->add( new Email( 'altcontact_email', NULL, TRUE, array(), function( $val )
|
||||
{
|
||||
if( \IPS\Member::loggedIn()->email == $val )
|
||||
if( Member::loggedIn()->email == $val )
|
||||
{
|
||||
throw new \DomainException('altcontact_email_self');
|
||||
throw new DomainException('altcontact_email_self');
|
||||
}
|
||||
|
||||
$member = \IPS\Member::load( $val, 'email' );
|
||||
$member = Member::load( $val, 'email' );
|
||||
if ( !$member->member_id )
|
||||
{
|
||||
throw new \DomainException('altcontact_email_error');
|
||||
throw new DomainException('altcontact_email_error');
|
||||
}
|
||||
|
||||
|
||||
try
|
||||
{
|
||||
\IPS\Db::i()->select( '*', 'nexus_alternate_contacts', array( 'main_id=? AND alt_id=?', \IPS\nexus\Customer::loggedIn()->member_id, $member->member_id ) )->first();
|
||||
throw new \DomainException('altcontact_already_exists');
|
||||
Db::i()->select( '*', 'nexus_alternate_contacts', array( 'main_id=? AND alt_id=?', Customer::loggedIn()->member_id, $member->member_id ) )->first();
|
||||
throw new DomainException('altcontact_already_exists');
|
||||
}
|
||||
catch ( \UnderflowException $e ) {}
|
||||
catch ( UnderflowException ) {}
|
||||
} ) );
|
||||
}
|
||||
$form->add( new \IPS\Helpers\Form\Node( 'altcontact_purchases', $existing ? iterator_to_array( $existing->purchases ) : NULL, FALSE, array( 'class' => 'IPS\nexus\Purchase', 'forceOwner' => \IPS\Member::loggedIn(), 'multiple' => TRUE ) ) );
|
||||
$form->add( new \IPS\Helpers\Form\Checkbox( 'altcontact_support', $existing ? $existing->support : FALSE ) );
|
||||
$form->add( new \IPS\Helpers\Form\Checkbox( 'altcontact_billing', $existing ? $existing->billing : FALSE ) );
|
||||
$form->add( new Node( 'altcontact_purchases', $existing ? iterator_to_array( $existing->purchases ) : NULL, FALSE, array( 'class' => 'IPS\nexus\Purchase', 'forceOwner' => Member::loggedIn(), 'multiple' => TRUE ) ) );
|
||||
$form->add( new Checkbox( 'altcontact_billing', $existing ? $existing->billing : FALSE ) );
|
||||
if ( $values = $form->values() )
|
||||
{
|
||||
if ( $existing )
|
||||
{
|
||||
$altContact = $existing;
|
||||
\IPS\nexus\Customer::loggedIn()->log( 'alternative', array( 'type' => 'edit', 'alt_id' => $altContact->alt_id->member_id, 'alt_name' => $altContact->alt_id->name, 'purchases' => json_encode( $values['altcontact_purchases'] ? $values['altcontact_purchases'] : array() ), 'billing' => $values['altcontact_billing'], 'support' => $values['altcontact_support'] ) );
|
||||
Customer::loggedIn()->log( 'alternative', array( 'type' => 'edit', 'alt_id' => $altContact->alt_id->member_id, 'alt_name' => $altContact->alt_id->name, 'purchases' => json_encode( $values['altcontact_purchases'] ?: array() ), 'billing' => $values['altcontact_billing'] ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
$altContact = new \IPS\nexus\Customer\AlternativeContact;
|
||||
$altContact->main_id = \IPS\nexus\Customer::loggedIn();
|
||||
$altContact->alt_id = \IPS\Member::load( $values['altcontact_email'], 'email' );
|
||||
\IPS\nexus\Customer::loggedIn()->log( 'alternative', array( 'type' => 'add', 'alt_id' => $altContact->alt_id->member_id, 'alt_name' => $altContact->alt_id->name, 'purchases' => json_encode( $values['altcontact_purchases'] ? $values['altcontact_purchases'] : array() ), 'billing' => $values['altcontact_billing'], 'support' => $values['altcontact_support'] ) );
|
||||
$altContact = new AlternativeContact;
|
||||
$altContact->main_id = Customer::loggedIn();
|
||||
$altContact->alt_id = Member::load( $values['altcontact_email'], 'email' );
|
||||
Customer::loggedIn()->log( 'alternative', array( 'type' => 'add', 'alt_id' => $altContact->alt_id->member_id, 'alt_name' => $altContact->alt_id->name, 'purchases' => json_encode( $values['altcontact_purchases'] ?: array() ), 'billing' => $values['altcontact_billing'] ) );
|
||||
}
|
||||
$altContact->purchases = $values['altcontact_purchases'] ? $values['altcontact_purchases'] : array();
|
||||
$altContact->purchases = $values['altcontact_purchases'] ?: array();
|
||||
$altContact->billing = $values['altcontact_billing'];
|
||||
$altContact->support = $values['altcontact_support'];
|
||||
$altContact->save();
|
||||
|
||||
\IPS\Output::i()->redirect( \IPS\Http\Url::internal( 'app=nexus&module=clients&controller=alternatives', 'front', 'clientsalternatives' ) );
|
||||
|
||||
Output::i()->redirect( Url::internal( 'app=nexus&module=clients&controller=alternatives', 'front', 'clientsalternatives' ) );
|
||||
}
|
||||
|
||||
if( \IPS\Request::i()->isAjax() )
|
||||
if( Request::i()->isAjax() )
|
||||
{
|
||||
\IPS\Output::i()->sendOutput( $form->customTemplate( array( \IPS\Theme::i()->getTemplate( 'forms', 'core' ), 'popupTemplate' ) ) );
|
||||
Output::i()->sendOutput( $form->customTemplate( array( Theme::i()->getTemplate( 'forms', 'core' ), 'popupTemplate' ) ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
\IPS\Output::i()->output = $form;
|
||||
}
|
||||
Output::i()->output = $form;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Delete
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
protected function delete()
|
||||
protected function delete() : void
|
||||
{
|
||||
\IPS\Session::i()->csrfCheck();
|
||||
|
||||
Session::i()->csrfCheck();
|
||||
|
||||
/* Make sure the user confirmed the deletion */
|
||||
\IPS\Request::i()->confirmedDelete();
|
||||
|
||||
Request::i()->confirmedDelete();
|
||||
|
||||
try
|
||||
{
|
||||
$contact = \IPS\nexus\Customer\AlternativeContact::constructFromData( \IPS\Db::i()->select( '*', 'nexus_alternate_contacts', array( 'main_id=? AND alt_id=?', \IPS\nexus\Customer::loggedIn()->member_id, \IPS\Request::i()->id ) )->first() );
|
||||
$contact = AlternativeContact::constructFromData( Db::i()->select( '*', 'nexus_alternate_contacts', array( 'main_id=? AND alt_id=?', Customer::loggedIn()->member_id, Request::i()->id ) )->first() );
|
||||
$contact->delete();
|
||||
\IPS\nexus\Customer::loggedIn()->log( 'alternative', array( 'type' => 'delete', 'alt_id' => $contact->alt_id->member_id, 'alt_name' => $contact->alt_id->name ) );
|
||||
Customer::loggedIn()->log( 'alternative', array( 'type' => 'delete', 'alt_id' => $contact->alt_id->member_id, 'alt_name' => $contact->alt_id->name ) );
|
||||
}
|
||||
catch ( \UnderflowException $e ) {}
|
||||
|
||||
\IPS\Output::i()->redirect( \IPS\Http\Url::internal( 'app=nexus&module=clients&controller=alternatives', 'front', 'clientsalternatives' ) );
|
||||
catch (UnderflowException ) {}
|
||||
|
||||
Output::i()->redirect( Url::internal( 'app=nexus&module=clients&controller=alternatives', 'front', 'clientsalternatives' ) );
|
||||
}
|
||||
}
|
||||
@@ -12,37 +12,58 @@
|
||||
namespace IPS\nexus\modules\front\clients;
|
||||
|
||||
/* To prevent PHP errors (extending class does not exist) revealing path */
|
||||
if ( !\defined( '\IPS\SUITE_UNIQUE_KEY' ) )
|
||||
|
||||
use DomainException;
|
||||
use IPS\Db;
|
||||
use IPS\Dispatcher\Controller;
|
||||
use IPS\Http\Url;
|
||||
use IPS\Member;
|
||||
use IPS\MFA\MFAHandler;
|
||||
use IPS\nexus\Customer;
|
||||
use IPS\nexus\Customer\BillingAgreement;
|
||||
use IPS\nexus\Gateway\PayPal\Exception;
|
||||
use IPS\Output;
|
||||
use IPS\Patterns\ActiveRecordIterator;
|
||||
use IPS\Request;
|
||||
use IPS\Session;
|
||||
use IPS\Theme;
|
||||
use OutOfRangeException;
|
||||
use function count;
|
||||
use function defined;
|
||||
use function in_array;
|
||||
use function intval;
|
||||
|
||||
if ( !defined( '\IPS\SUITE_UNIQUE_KEY' ) )
|
||||
{
|
||||
header( ( isset( $_SERVER['SERVER_PROTOCOL'] ) ? $_SERVER['SERVER_PROTOCOL'] : 'HTTP/1.0' ) . ' 403 Forbidden' );
|
||||
header( ( $_SERVER['SERVER_PROTOCOL'] ?? 'HTTP/1.0' ) . ' 403 Forbidden' );
|
||||
exit;
|
||||
}
|
||||
|
||||
/**
|
||||
* Billing Agreements
|
||||
*/
|
||||
class _billingagreements extends \IPS\Dispatcher\Controller
|
||||
class billingagreements extends Controller
|
||||
{
|
||||
/**
|
||||
* Execute
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function execute()
|
||||
public function execute() : void
|
||||
{
|
||||
if ( !\IPS\Member::loggedIn()->member_id )
|
||||
if ( !Member::loggedIn()->member_id )
|
||||
{
|
||||
\IPS\Output::i()->error( 'no_module_permission_guest', '2X321/1', 403, '' );
|
||||
Output::i()->error( 'no_module_permission_guest', '2X321/1', 403, '' );
|
||||
}
|
||||
|
||||
\IPS\Output::i()->cssFiles = array_merge( \IPS\Output::i()->cssFiles, \IPS\Theme::i()->css( 'clients.css', 'nexus' ) );
|
||||
\IPS\Output::i()->breadcrumb[] = array( \IPS\Http\Url::internal( 'app=nexus&module=clients&controller=billingagreements', 'front', 'clientsbillingagreements' ), \IPS\Member::loggedIn()->language()->addToStack('client_billing_agreements') );
|
||||
\IPS\Output::i()->title = \IPS\Member::loggedIn()->language()->addToStack('client_billing_agreements');
|
||||
\IPS\Output::i()->sidebar['enabled'] = FALSE;
|
||||
Output::i()->cssFiles = array_merge( Output::i()->cssFiles, Theme::i()->css( 'clients.css', 'nexus' ) );
|
||||
Output::i()->breadcrumb[] = array( Url::internal( 'app=nexus&module=clients&controller=billingagreements', 'front', 'clientsbillingagreements' ), Member::loggedIn()->language()->addToStack('client_billing_agreements') );
|
||||
Output::i()->title = Member::loggedIn()->language()->addToStack('client_billing_agreements');
|
||||
Output::i()->sidebar['enabled'] = FALSE;
|
||||
|
||||
if ( $output = \IPS\MFA\MFAHandler::accessToArea( 'nexus', 'BillingAgreements', \IPS\Http\Url::internal( 'app=nexus&module=clients&controller=billingagreements', 'front', 'clientsbillingagreements' ) ) )
|
||||
if ( $output = MFAHandler::accessToArea( 'nexus', 'BillingAgreements', Url::internal( 'app=nexus&module=clients&controller=billingagreements', 'front', 'clientsbillingagreements' ) ) )
|
||||
{
|
||||
\IPS\Output::i()->output = \IPS\Theme::i()->getTemplate('clients')->billingAgreements( array() ) . $output;
|
||||
Output::i()->output = Theme::i()->getTemplate('clients')->billingAgreements( array() ) . $output;
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -54,15 +75,14 @@ class _billingagreements extends \IPS\Dispatcher\Controller
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
protected function manage()
|
||||
protected function manage() : void
|
||||
{
|
||||
$billingAgreements = array();
|
||||
|
||||
$where = array( 'ba_member=?', \IPS\Member::loggedIn()->member_id );
|
||||
$parentContacts = \IPS\nexus\Customer::loggedIn()->parentContacts( array( 'billing=1' ) );
|
||||
if ( \count( $parentContacts ) )
|
||||
$where = array( 'ba_member=?', Member::loggedIn()->member_id );
|
||||
$parentContacts = Customer::loggedIn()->parentContacts( array( 'billing=1' ) );
|
||||
if ( count( $parentContacts ) )
|
||||
{
|
||||
$or = array();
|
||||
foreach ( array_keys( iterator_to_array( $parentContacts ) ) as $id )
|
||||
{
|
||||
$where[0] .= ' OR ba_member=?';
|
||||
@@ -70,13 +90,14 @@ class _billingagreements extends \IPS\Dispatcher\Controller
|
||||
}
|
||||
}
|
||||
|
||||
foreach ( new \IPS\Patterns\ActiveRecordIterator( \IPS\Db::i()->select( '*', 'nexus_billing_agreements', $where ), 'IPS\nexus\Customer\BillingAgreement' ) as $billingAgreement )
|
||||
{
|
||||
foreach ( new ActiveRecordIterator( Db::i()->select( '*', 'nexus_billing_agreements', $where ), 'IPS\nexus\Customer\BillingAgreement' ) as $billingAgreement )
|
||||
{
|
||||
/* @var BillingAgreement $billingAgreement */
|
||||
try
|
||||
{
|
||||
$status = $billingAgreement->status();
|
||||
}
|
||||
catch ( \Exception $e )
|
||||
catch ( \Exception )
|
||||
{
|
||||
$status = NULL;
|
||||
}
|
||||
@@ -85,7 +106,7 @@ class _billingagreements extends \IPS\Dispatcher\Controller
|
||||
{
|
||||
$term = $billingAgreement->term();
|
||||
}
|
||||
catch ( \Exception $e )
|
||||
catch ( \Exception )
|
||||
{
|
||||
$term = NULL;
|
||||
}
|
||||
@@ -98,7 +119,7 @@ class _billingagreements extends \IPS\Dispatcher\Controller
|
||||
);
|
||||
}
|
||||
|
||||
\IPS\Output::i()->output = \IPS\Theme::i()->getTemplate('clients')->billingAgreements( $billingAgreements );
|
||||
Output::i()->output = Theme::i()->getTemplate('clients')->billingAgreements( $billingAgreements );
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -106,48 +127,48 @@ class _billingagreements extends \IPS\Dispatcher\Controller
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
protected function view()
|
||||
protected function view() : void
|
||||
{
|
||||
/* Load Billing Agreement */
|
||||
try
|
||||
{
|
||||
$billingAgreement = \IPS\nexus\Customer\BillingAgreement::loadAndCheckPerms( \IPS\Request::i()->id );
|
||||
$billingAgreement = BillingAgreement::loadAndCheckPerms( Request::i()->id );
|
||||
$billingAgreement->status(); // Just to make the API call so we can catch the error if there is one
|
||||
}
|
||||
catch ( \OutOfRangeException $e )
|
||||
catch ( OutOfRangeException )
|
||||
{
|
||||
\IPS\Output::i()->error( 'node_error', '2X320/4', 404, '' );
|
||||
Output::i()->error( 'node_error', '2X320/4', 404, '' );
|
||||
}
|
||||
catch ( \IPS\nexus\Gateway\PayPal\Exception $e )
|
||||
catch ( Exception $e )
|
||||
{
|
||||
\IPS\Output::i()->error( 'billing_agreement_error', '4X321/5', 500, '', array(), $e->getName() );
|
||||
Output::i()->error( 'billing_agreement_error', '4X321/5', 500, '', array(), $e->getName() );
|
||||
}
|
||||
|
||||
/* Get associated purchases */
|
||||
$purchases = array();
|
||||
foreach( new \IPS\Patterns\ActiveRecordIterator( \IPS\Db::i()->select( '*', 'nexus_purchases', array( 'ps_billing_agreement=?', $billingAgreement->id ) ), 'IPS\nexus\Purchase' ) as $purchase )
|
||||
foreach( new ActiveRecordIterator( Db::i()->select( '*', 'nexus_purchases', array( 'ps_billing_agreement=?', $billingAgreement->id ) ), 'IPS\nexus\Purchase' ) as $purchase )
|
||||
{
|
||||
$purchases[0][ $purchase->id ] = $purchase;
|
||||
}
|
||||
|
||||
/* Transactions */
|
||||
$currentPage = isset( \IPS\Request::i()->page ) ? \intval( \IPS\Request::i()->page ) : 1;
|
||||
$currentPage = isset( Request::i()->page ) ? intval( Request::i()->page ) : 1;
|
||||
$perPage = 25;
|
||||
$invoices = new \IPS\Patterns\ActiveRecordIterator(
|
||||
\IPS\Db::i()->select(
|
||||
$invoices = new ActiveRecordIterator(
|
||||
Db::i()->select(
|
||||
'*',
|
||||
'nexus_invoices',
|
||||
array( 'i_id IN(?)', \IPS\Db::i()->select( 't_invoice', 'nexus_transactions', array( 't_billing_agreement=?', $billingAgreement->id ) ) ),
|
||||
array( 'i_id IN(?)', Db::i()->select( 't_invoice', 'nexus_transactions', array( 't_billing_agreement=?', $billingAgreement->id ) ) ),
|
||||
'i_date DESC',
|
||||
array( ( $currentPage - 1 ) * $perPage, $perPage )
|
||||
),
|
||||
'IPS\nexus\Invoice'
|
||||
);
|
||||
$invoicesCount = \IPS\Db::i()->select( 'COUNT(*)', 'nexus_invoices', array( 'i_id IN(?)', \IPS\Db::i()->select( 't_invoice', 'nexus_transactions', array( 't_billing_agreement=?', $billingAgreement->id ) ) ) )->first();
|
||||
$pagination = \IPS\Theme::i()->getTemplate( 'global', 'core', 'global' )->pagination( $billingAgreement->url(), ceil( $invoicesCount / $perPage ), $currentPage, $perPage );
|
||||
$invoicesCount = Db::i()->select( 'COUNT(*)', 'nexus_invoices', array( 'i_id IN(?)', Db::i()->select( 't_invoice', 'nexus_transactions', array( 't_billing_agreement=?', $billingAgreement->id ) ) ) )->first();
|
||||
$pagination = Theme::i()->getTemplate( 'global', 'core', 'global' )->pagination( $billingAgreement->url(), ceil( $invoicesCount / $perPage ), $currentPage, $perPage );
|
||||
|
||||
\IPS\Output::i()->breadcrumb[] = array( $billingAgreement->url(), $billingAgreement->gw_id );
|
||||
\IPS\Output::i()->output = \IPS\Theme::i()->getTemplate('clients')->billingAgreement( $billingAgreement, $purchases, $invoices, $pagination );
|
||||
Output::i()->breadcrumb[] = array( $billingAgreement->url(), $billingAgreement->gw_id );
|
||||
Output::i()->output = Theme::i()->getTemplate('clients')->billingAgreement( $billingAgreement, $purchases, $invoices, $pagination );
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -155,25 +176,25 @@ class _billingagreements extends \IPS\Dispatcher\Controller
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
protected function act()
|
||||
protected function act() : void
|
||||
{
|
||||
\IPS\Session::i()->csrfCheck();
|
||||
Session::i()->csrfCheck();
|
||||
|
||||
/* Check act */
|
||||
$act = \IPS\Request::i()->act;
|
||||
if ( !\in_array( $act, array( 'suspend', 'reactivate', 'cancel' ) ) )
|
||||
$act = Request::i()->act;
|
||||
if ( !in_array( $act, array( 'suspend', 'reactivate', 'cancel' ) ) )
|
||||
{
|
||||
\IPS\Output::i()->error( 'node_error', '3X321/3', 403, '' );
|
||||
Output::i()->error( 'node_error', '3X321/3', 403, '' );
|
||||
}
|
||||
|
||||
/* Load Billing Agreement */
|
||||
try
|
||||
{
|
||||
$billingAgreement = \IPS\nexus\Customer\BillingAgreement::loadAndCheckPerms( \IPS\Request::i()->id );
|
||||
$billingAgreement = BillingAgreement::loadAndCheckPerms( Request::i()->id );
|
||||
}
|
||||
catch ( \OutOfRangeException $e )
|
||||
catch ( OutOfRangeException )
|
||||
{
|
||||
\IPS\Output::i()->error( 'node_error', '2X321/2', 404, '' );
|
||||
Output::i()->error( 'node_error', '2X321/2', 404, '' );
|
||||
}
|
||||
|
||||
/* Perform Action */
|
||||
@@ -181,11 +202,11 @@ class _billingagreements extends \IPS\Dispatcher\Controller
|
||||
{
|
||||
$billingAgreement->$act();
|
||||
|
||||
\IPS\Output::i()->redirect( $billingAgreement->url() );
|
||||
Output::i()->redirect( $billingAgreement->url() );
|
||||
}
|
||||
catch ( \DomainException $e )
|
||||
catch ( DomainException )
|
||||
{
|
||||
\IPS\Output::i()->error( 'billing_agreement_error_public', '3X321/4', 500, '' );
|
||||
Output::i()->error( 'billing_agreement_error_public', '3X321/4', 500, '' );
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -12,37 +12,54 @@
|
||||
namespace IPS\nexus\modules\front\clients;
|
||||
|
||||
/* To prevent PHP errors (extending class does not exist) revealing path */
|
||||
if ( !\defined( '\IPS\SUITE_UNIQUE_KEY' ) )
|
||||
|
||||
use Exception;
|
||||
use IPS\Db;
|
||||
use IPS\Dispatcher\Controller;
|
||||
use IPS\Http\Url;
|
||||
use IPS\Member;
|
||||
use IPS\MFA\MFAHandler;
|
||||
use IPS\nexus\Customer;
|
||||
use IPS\nexus\Customer\CreditCard;
|
||||
use IPS\Output;
|
||||
use IPS\Patterns\ActiveRecordIterator;
|
||||
use IPS\Request;
|
||||
use IPS\Session;
|
||||
use IPS\Theme;
|
||||
use function defined;
|
||||
use function is_null;
|
||||
|
||||
if ( !defined( '\IPS\SUITE_UNIQUE_KEY' ) )
|
||||
{
|
||||
header( ( isset( $_SERVER['SERVER_PROTOCOL'] ) ? $_SERVER['SERVER_PROTOCOL'] : 'HTTP/1.0' ) . ' 403 Forbidden' );
|
||||
header( ( $_SERVER['SERVER_PROTOCOL'] ?? 'HTTP/1.0' ) . ' 403 Forbidden' );
|
||||
exit;
|
||||
}
|
||||
|
||||
/**
|
||||
* Cards
|
||||
*/
|
||||
class _cards extends \IPS\Dispatcher\Controller
|
||||
class cards extends Controller
|
||||
{
|
||||
/**
|
||||
* Execute
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function execute()
|
||||
public function execute() : void
|
||||
{
|
||||
if ( !\IPS\Member::loggedIn()->member_id )
|
||||
if ( !Member::loggedIn()->member_id )
|
||||
{
|
||||
\IPS\Output::i()->error( 'no_module_permission_guest', '2X236/1', 403, '' );
|
||||
Output::i()->error( 'no_module_permission_guest', '2X236/1', 403, '' );
|
||||
}
|
||||
|
||||
\IPS\Output::i()->cssFiles = array_merge( \IPS\Output::i()->cssFiles, \IPS\Theme::i()->css( 'clients.css', 'nexus' ) );
|
||||
\IPS\Output::i()->breadcrumb[] = array( \IPS\Http\Url::internal( 'app=nexus&module=clients&controller=cards', 'front', 'clientscards' ), \IPS\Member::loggedIn()->language()->addToStack('client_cards') );
|
||||
\IPS\Output::i()->title = \IPS\Member::loggedIn()->language()->addToStack('client_cards');
|
||||
\IPS\Output::i()->sidebar['enabled'] = FALSE;
|
||||
Output::i()->cssFiles = array_merge( Output::i()->cssFiles, Theme::i()->css( 'clients.css', 'nexus' ) );
|
||||
Output::i()->breadcrumb[] = array( Url::internal( 'app=nexus&module=clients&controller=cards', 'front', 'clientscards' ), Member::loggedIn()->language()->addToStack('client_cards') );
|
||||
Output::i()->title = Member::loggedIn()->language()->addToStack('client_cards');
|
||||
Output::i()->sidebar['enabled'] = FALSE;
|
||||
|
||||
if ( $output = \IPS\MFA\MFAHandler::accessToArea( 'nexus', 'Cards', \IPS\Http\Url::internal( 'app=nexus&module=clients&controller=cards', 'front', 'clientscards' ) ) )
|
||||
if ( $output = MFAHandler::accessToArea( 'nexus', 'Cards', Url::internal( 'app=nexus&module=clients&controller=cards', 'front', 'clientscards' ) ) )
|
||||
{
|
||||
\IPS\Output::i()->output = \IPS\Theme::i()->getTemplate('clients')->cards( array() ) . $output;
|
||||
Output::i()->output = Theme::i()->getTemplate('clients')->cards( array() ) . $output;
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -54,10 +71,10 @@ class _cards extends \IPS\Dispatcher\Controller
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
protected function manage()
|
||||
protected function manage() : void
|
||||
{
|
||||
$cards = array();
|
||||
foreach ( new \IPS\Patterns\ActiveRecordIterator( \IPS\Db::i()->select( '*', 'nexus_customer_cards', array( 'card_member=?', \IPS\nexus\Customer::loggedIn()->member_id ) ), 'IPS\nexus\Customer\CreditCard' ) as $card )
|
||||
foreach ( new ActiveRecordIterator( Db::i()->select( '*', 'nexus_customer_cards', array( 'card_member=?', Customer::loggedIn()->member_id ) ), 'IPS\nexus\Customer\CreditCard' ) as $card )
|
||||
{
|
||||
try
|
||||
{
|
||||
@@ -66,13 +83,13 @@ class _cards extends \IPS\Dispatcher\Controller
|
||||
'id' => $card->id,
|
||||
'card_type' => $cardData->type,
|
||||
'card_number' => $cardData->lastFour ?: $cardData->number,
|
||||
'card_expire' => ( !\is_null( $cardData->expMonth ) AND !\is_null( $cardData->expYear ) ) ? str_pad( $cardData->expMonth , 2, '0', STR_PAD_LEFT ). '/' . $cardData->expYear : NULL
|
||||
'card_expire' => ( !is_null( $cardData->expMonth ) AND !is_null( $cardData->expYear ) ) ? str_pad( $cardData->expMonth , 2, '0', STR_PAD_LEFT ). '/' . $cardData->expYear : NULL
|
||||
);
|
||||
}
|
||||
catch ( \Exception $e ) { }
|
||||
catch ( Exception ) { }
|
||||
}
|
||||
|
||||
\IPS\Output::i()->output = \IPS\Theme::i()->getTemplate('clients')->cards( $cards );
|
||||
Output::i()->output = Theme::i()->getTemplate('clients')->cards( $cards );
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -80,19 +97,19 @@ class _cards extends \IPS\Dispatcher\Controller
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function add()
|
||||
public function add() : void
|
||||
{
|
||||
\IPS\Output::i()->cssFiles = array_merge( \IPS\Output::i()->cssFiles, \IPS\Theme::i()->css( 'checkout.css', 'nexus' ) );
|
||||
\IPS\Output::i()->jsFiles = array_merge( \IPS\Output::i()->jsFiles, \IPS\Output::i()->js( 'global_gateways.js', 'nexus', 'global' ) );
|
||||
$form = \IPS\nexus\Customer\CreditCard::create( \IPS\nexus\Customer::loggedIn(), FALSE );
|
||||
if ( $form instanceof \IPS\nexus\Customer\CreditCard )
|
||||
Output::i()->cssFiles = array_merge( Output::i()->cssFiles, Theme::i()->css( 'checkout.css', 'nexus' ) );
|
||||
Output::i()->jsFiles = array_merge( Output::i()->jsFiles, Output::i()->js( 'global_gateways.js', 'nexus', 'global' ) );
|
||||
$form = CreditCard::create( Customer::loggedIn(), FALSE );
|
||||
if ( $form instanceof CreditCard )
|
||||
{
|
||||
\IPS\nexus\Customer::loggedIn()->log( 'card', array( 'type' => 'add', 'number' => $form->card->lastFour ) );
|
||||
\IPS\Output::i()->redirect( \IPS\Http\Url::internal( 'app=nexus&module=clients&controller=cards', 'front', 'clientscards' ) );
|
||||
Customer::loggedIn()->log( 'card', array( 'type' => 'add', 'number' => $form->card->lastFour ) );
|
||||
Output::i()->redirect( Url::internal( 'app=nexus&module=clients&controller=cards', 'front', 'clientscards' ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
\IPS\Output::i()->output = $form;
|
||||
Output::i()->output = $form;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -101,26 +118,26 @@ class _cards extends \IPS\Dispatcher\Controller
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function delete()
|
||||
public function delete() : void
|
||||
{
|
||||
\IPS\Session::i()->csrfCheck();
|
||||
Session::i()->csrfCheck();
|
||||
|
||||
/* Make sure the user confirmed the deletion */
|
||||
\IPS\Request::i()->confirmedDelete();
|
||||
Request::i()->confirmedDelete();
|
||||
|
||||
try
|
||||
{
|
||||
$card = \IPS\nexus\Customer\CreditCard::load( \IPS\Request::i()->id );
|
||||
if ( $card->member->member_id === \IPS\nexus\Customer::loggedIn()->member_id )
|
||||
$card = CreditCard::load( Request::i()->id );
|
||||
if ( $card->member->member_id === Customer::loggedIn()->member_id )
|
||||
{
|
||||
$cardData = $card->card;
|
||||
|
||||
$card->delete();
|
||||
\IPS\nexus\Customer::loggedIn()->log( 'card', array( 'type' => 'delete', 'number' => $cardData->lastFour ) );
|
||||
Customer::loggedIn()->log( 'card', array( 'type' => 'delete', 'number' => $cardData->lastFour ) );
|
||||
}
|
||||
}
|
||||
catch ( \Exception $e ) { }
|
||||
catch ( Exception ) { }
|
||||
|
||||
\IPS\Output::i()->redirect( \IPS\Http\Url::internal( 'app=nexus&module=clients&controller=cards', 'front', 'clientscards' ) );
|
||||
Output::i()->redirect( Url::internal( 'app=nexus&module=clients&controller=cards', 'front', 'clientscards' ) );
|
||||
}
|
||||
}
|
||||
@@ -12,37 +12,72 @@
|
||||
namespace IPS\nexus\modules\front\clients;
|
||||
|
||||
/* To prevent PHP errors (extending class does not exist) revealing path */
|
||||
if ( !\defined( '\IPS\SUITE_UNIQUE_KEY' ) )
|
||||
|
||||
use DateInterval;
|
||||
use DomainException;
|
||||
use Exception;
|
||||
use IPS\core\AdminNotification;
|
||||
use IPS\DateTime;
|
||||
use IPS\Db;
|
||||
use IPS\Dispatcher\Controller;
|
||||
use IPS\Helpers\Form;
|
||||
use IPS\Helpers\Form\Number;
|
||||
use IPS\Helpers\Form\Radio;
|
||||
use IPS\Http\Url;
|
||||
use IPS\Member;
|
||||
use IPS\MFA\MFAHandler;
|
||||
use IPS\nexus\Customer;
|
||||
use IPS\nexus\Customer\AlternativeContact;
|
||||
use IPS\nexus\extensions\nexus\Item\AccountCreditIncrease;
|
||||
use IPS\nexus\Gateway;
|
||||
use IPS\nexus\Invoice;
|
||||
use IPS\nexus\Money;
|
||||
use IPS\nexus\Payout;
|
||||
use IPS\Output;
|
||||
use IPS\Patterns\ActiveRecordIterator;
|
||||
use IPS\Request;
|
||||
use IPS\Session;
|
||||
use IPS\Settings;
|
||||
use IPS\Theme;
|
||||
use OutOfRangeException;
|
||||
use function count;
|
||||
use function defined;
|
||||
use function in_array;
|
||||
use function intval;
|
||||
use function is_countable;
|
||||
use function is_null;
|
||||
|
||||
if ( !defined( '\IPS\SUITE_UNIQUE_KEY' ) )
|
||||
{
|
||||
header( ( isset( $_SERVER['SERVER_PROTOCOL'] ) ? $_SERVER['SERVER_PROTOCOL'] : 'HTTP/1.0' ) . ' 403 Forbidden' );
|
||||
header( ( $_SERVER['SERVER_PROTOCOL'] ?? 'HTTP/1.0' ) . ' 403 Forbidden' );
|
||||
exit;
|
||||
}
|
||||
|
||||
/**
|
||||
* Account Credit
|
||||
*/
|
||||
class _credit extends \IPS\Dispatcher\Controller
|
||||
class credit extends Controller
|
||||
{
|
||||
/**
|
||||
* Execute
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function execute()
|
||||
public function execute() : void
|
||||
{
|
||||
if ( !\IPS\Member::loggedIn()->member_id )
|
||||
if ( !Member::loggedIn()->member_id )
|
||||
{
|
||||
\IPS\Output::i()->error( 'no_module_permission_guest', '2X239/1', 403, '' );
|
||||
Output::i()->error( 'no_module_permission_guest', '2X239/1', 403, '' );
|
||||
}
|
||||
|
||||
\IPS\Output::i()->cssFiles = array_merge( \IPS\Output::i()->cssFiles, \IPS\Theme::i()->css( 'clients.css', 'nexus' ) );
|
||||
\IPS\Output::i()->breadcrumb[] = array( \IPS\Http\Url::internal( 'app=nexus&module=clients&controller=credit', 'front', 'clientscredit' ), \IPS\Member::loggedIn()->language()->addToStack('client_credit') );
|
||||
\IPS\Output::i()->title = \IPS\Member::loggedIn()->language()->addToStack('client_credit');
|
||||
\IPS\Output::i()->sidebar['enabled'] = FALSE;
|
||||
Output::i()->cssFiles = array_merge( Output::i()->cssFiles, Theme::i()->css( 'clients.css', 'nexus' ) );
|
||||
Output::i()->breadcrumb[] = array( Url::internal( 'app=nexus&module=clients&controller=credit', 'front', 'clientscredit' ), Member::loggedIn()->language()->addToStack('client_credit') );
|
||||
Output::i()->title = Member::loggedIn()->language()->addToStack('client_credit');
|
||||
Output::i()->sidebar['enabled'] = FALSE;
|
||||
|
||||
if ( $output = \IPS\MFA\MFAHandler::accessToArea( 'nexus', 'AccountCredit', \IPS\Http\Url::internal( 'app=nexus&module=clients&controller=credit', 'front', 'clientscredit' ) ) )
|
||||
if ( $output = MFAHandler::accessToArea( 'nexus', 'AccountCredit', Url::internal( 'app=nexus&module=clients&controller=credit', 'front', 'clientscredit' ) ) )
|
||||
{
|
||||
\IPS\Output::i()->output = \IPS\Theme::i()->getTemplate('clients')->credit( NULL, array(), NULL, FALSE, FALSE ) . $output;
|
||||
Output::i()->output = Theme::i()->getTemplate('clients')->credit( NULL, array(), NULL, FALSE, FALSE ) . $output;
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -54,38 +89,38 @@ class _credit extends \IPS\Dispatcher\Controller
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
protected function manage()
|
||||
protected function manage() : void
|
||||
{
|
||||
/* Get Balance(s) */
|
||||
$balance = array_filter( \IPS\nexus\Customer::loggedIn()->cm_credits, function( $val )
|
||||
$balance = array_filter( Customer::loggedIn()->cm_credits, function( $val )
|
||||
{
|
||||
return $val->amount;
|
||||
} );
|
||||
|
||||
/* Pending Withdrawls */
|
||||
$perPage = 10;
|
||||
$page = isset( \IPS\Request::i()->page ) ? \intval( \IPS\Request::i()->page ) : 1;
|
||||
$page = isset( Request::i()->page ) ? intval( Request::i()->page ) : 1;
|
||||
|
||||
if( $page < 1 )
|
||||
{
|
||||
$page = 1;
|
||||
}
|
||||
|
||||
$pastWithdrawalsSelect = \IPS\Db::i()->select( '*', 'nexus_payouts', array( 'po_member=?', \IPS\nexus\Customer::loggedIn()->member_id ), 'po_date DESC', array( ( $page - 1 ) * $perPage, $perPage ) );
|
||||
$pastWithdrawalsPagination = \IPS\Theme::i()->getTemplate( 'global', 'core', 'global' )->pagination(
|
||||
\IPS\Http\Url::internal( 'app=nexus&module=clients&controller=credit', 'front', 'clientscredit' ),
|
||||
ceil( \IPS\Db::i()->select( 'COUNT(*)', 'nexus_payouts', array( 'po_member=?', \IPS\nexus\Customer::loggedIn()->member_id ) )->first() / $perPage ),
|
||||
$pastWithdrawalsSelect = Db::i()->select( '*', 'nexus_payouts', array( 'po_member=?', Customer::loggedIn()->member_id ), 'po_date DESC', array( ( $page - 1 ) * $perPage, $perPage ) );
|
||||
$pastWithdrawalsPagination = Theme::i()->getTemplate( 'global', 'core', 'global' )->pagination(
|
||||
Url::internal( 'app=nexus&module=clients&controller=credit', 'front', 'clientscredit' ),
|
||||
ceil( Db::i()->select( 'COUNT(*)', 'nexus_payouts', array( 'po_member=?', Customer::loggedIn()->member_id ) )->first() / $perPage ),
|
||||
$page,
|
||||
$perPage
|
||||
);
|
||||
$pastWithdrawals = new \IPS\Patterns\ActiveRecordIterator( $pastWithdrawalsSelect, 'IPS\nexus\Payout' );
|
||||
$pastWithdrawals = new ActiveRecordIterator( $pastWithdrawalsSelect, 'IPS\nexus\Payout' );
|
||||
|
||||
$activePayouts = [];
|
||||
if( !\IPS\Settings::i()->nexus_payout_unlimited_times )
|
||||
if( !Settings::i()->nexus_payout_unlimited_times )
|
||||
{
|
||||
foreach ( $pastWithdrawals as $payout )
|
||||
{
|
||||
if ( $payout->status == \IPS\nexus\Payout::STATUS_PENDING )
|
||||
if ( $payout->status == Payout::STATUS_PENDING )
|
||||
{
|
||||
$activePayouts[ $payout->currency ] = TRUE;
|
||||
}
|
||||
@@ -94,10 +129,10 @@ class _credit extends \IPS\Dispatcher\Controller
|
||||
|
||||
/* Can we withdraw? */
|
||||
$canWithdraw = FALSE;
|
||||
$withdrawOptions = json_decode( \IPS\Settings::i()->nexus_payout, TRUE );
|
||||
if( \is_countable( $withdrawOptions ) AND \count( $withdrawOptions ) )
|
||||
$withdrawOptions = json_decode( Settings::i()->nexus_payout, TRUE );
|
||||
if( is_countable( $withdrawOptions ) AND count( $withdrawOptions ) )
|
||||
{
|
||||
foreach ( \IPS\nexus\Money::currencies() as $currency )
|
||||
foreach ( Money::currencies() as $currency )
|
||||
{
|
||||
if ( isset( $balance[ $currency ] ) and $balance[ $currency ]->amount->isGreaterThanZero() and !isset( $activePayouts[ $currency ] ) )
|
||||
{
|
||||
@@ -108,22 +143,20 @@ class _credit extends \IPS\Dispatcher\Controller
|
||||
|
||||
/* Can we topup? */
|
||||
$canTopup = FALSE;
|
||||
if ( \IPS\Settings::i()->nexus_min_topup )
|
||||
if ( Settings::i()->nexus_min_topup )
|
||||
{
|
||||
$minimumTopupAmounts = ( \IPS\Settings::i()->nexus_min_topup and \IPS\Settings::i()->nexus_min_topup !== '*' ) ? json_decode( \IPS\Settings::i()->nexus_min_topup, TRUE ) : NULL;
|
||||
$maximumBalanceAmounts = ( \IPS\Settings::i()->nexus_max_credit and \IPS\Settings::i()->nexus_max_credit !== '*' ) ? json_decode( \IPS\Settings::i()->nexus_max_credit, TRUE ) : NULL;
|
||||
$maximumBalanceAmounts = ( Settings::i()->nexus_max_credit and Settings::i()->nexus_max_credit !== '*' ) ? json_decode( Settings::i()->nexus_max_credit, TRUE ) : NULL;
|
||||
|
||||
$maximums = array();
|
||||
foreach ( array_merge( array( \IPS\nexus\Customer::loggedIn() ), iterator_to_array( \IPS\nexus\Customer::loggedIn()->parentContacts( array('billing=1') ) ) ) as $account )
|
||||
foreach ( array_merge( array( Customer::loggedIn() ), iterator_to_array( Customer::loggedIn()->parentContacts( array('billing=1') ) ) ) as $account )
|
||||
{
|
||||
if ( $account instanceof \IPS\nexus\Customer\AlternativeContact )
|
||||
if ( $account instanceof AlternativeContact )
|
||||
{
|
||||
$account = $account->main_id;
|
||||
}
|
||||
|
||||
foreach ( $account->cm_credits as $value )
|
||||
{
|
||||
if ( $maximumBalanceAmounts === NULL or $value->amount->compare( new \IPS\Math\Number( number_format( $maximumBalanceAmounts[ $value->currency ]['amount'], \IPS\nexus\Money::numberOfDecimalsForCurrency( $value->currency ), '.', '' ) ) ) === -1 )
|
||||
if ( $maximumBalanceAmounts === NULL or $value->amount->compare( new \IPS\Math\Number( number_format( $maximumBalanceAmounts[ $value->currency ]['amount'], Money::numberOfDecimalsForCurrency( $value->currency ), '.', '' ) ) ) === -1 )
|
||||
{
|
||||
$canTopup = TRUE;
|
||||
}
|
||||
@@ -132,7 +165,7 @@ class _credit extends \IPS\Dispatcher\Controller
|
||||
}
|
||||
|
||||
/* Display */
|
||||
\IPS\Output::i()->output = \IPS\Theme::i()->getTemplate('clients')->credit( $balance, $pastWithdrawals, $pastWithdrawalsPagination, $canWithdraw, $canTopup );
|
||||
Output::i()->output = Theme::i()->getTemplate('clients')->credit( $balance, $pastWithdrawals, $pastWithdrawalsPagination, $canWithdraw, $canTopup );
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -140,47 +173,47 @@ class _credit extends \IPS\Dispatcher\Controller
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
protected function withdraw()
|
||||
protected function withdraw() : void
|
||||
{
|
||||
$activeWithdrawals = \IPS\Settings::i()->nexus_payout_unlimited_times ? [] : iterator_to_array( \IPS\Db::i()->select( 'po_currency', 'nexus_payouts', array( 'po_status=? AND po_member=?', \IPS\nexus\Payout::STATUS_PENDING, \IPS\nexus\Customer::loggedIn()->member_id ) ) );
|
||||
$activeWithdrawals = Settings::i()->nexus_payout_unlimited_times ? [] : iterator_to_array( Db::i()->select( 'po_currency', 'nexus_payouts', array( 'po_status=? AND po_member=?', Payout::STATUS_PENDING, Customer::loggedIn()->member_id ) ) );
|
||||
$withdrawForm = NULL;
|
||||
$withdrawOptions = json_decode( \IPS\Settings::i()->nexus_payout, TRUE );
|
||||
$withdrawOptions = json_decode( Settings::i()->nexus_payout, TRUE );
|
||||
if ( isset( $withdrawOptions['Stripe'] ) )
|
||||
{
|
||||
unset( $withdrawOptions['Stripe'] );
|
||||
}
|
||||
if ( \is_countable( $withdrawOptions ) AND \count( $withdrawOptions ) )
|
||||
if ( is_countable( $withdrawOptions ) AND count( $withdrawOptions ) )
|
||||
{
|
||||
$withdrawForm = new \IPS\Helpers\Form( 'withdraw', 'withdraw_credit' );
|
||||
$withdrawForm = new Form( 'withdraw', 'withdraw_credit' );
|
||||
|
||||
$minimumWithdrawalsAmounts = ( \IPS\Settings::i()->nexus_payout_min and \IPS\Settings::i()->nexus_payout_min !== '*' ) ? json_decode( \IPS\Settings::i()->nexus_payout_min, TRUE ) : NULL;
|
||||
$maximumWithdrawalsAmounts = ( \IPS\Settings::i()->nexus_payout_max and \IPS\Settings::i()->nexus_payout_max !== '*' ) ? json_decode( \IPS\Settings::i()->nexus_payout_max, TRUE ) : NULL;
|
||||
$minimumWithdrawalsAmounts = ( Settings::i()->nexus_payout_min and Settings::i()->nexus_payout_min !== '*' ) ? json_decode( Settings::i()->nexus_payout_min, TRUE ) : NULL;
|
||||
$maximumWithdrawalsAmounts = ( Settings::i()->nexus_payout_max and Settings::i()->nexus_payout_max !== '*' ) ? json_decode( Settings::i()->nexus_payout_max, TRUE ) : NULL;
|
||||
|
||||
$balance = array_filter( \IPS\nexus\Customer::loggedIn()->cm_credits, function( $val )
|
||||
$balance = array_filter( Customer::loggedIn()->cm_credits, function( $val )
|
||||
{
|
||||
return $val->amount;
|
||||
} );
|
||||
|
||||
$currencyOptions = array();
|
||||
if ( \count( $balance ) > 1 )
|
||||
if ( count( $balance ) > 1 )
|
||||
{
|
||||
$currencyToggles = array();
|
||||
foreach ( \IPS\nexus\Money::currencies() as $currency )
|
||||
foreach ( Money::currencies() as $currency )
|
||||
{
|
||||
if ( isset( $balance[ $currency ] ) AND !\in_array( $currency, $activeWithdrawals ) )
|
||||
if ( isset( $balance[ $currency ] ) AND !in_array( $currency, $activeWithdrawals ) )
|
||||
{
|
||||
$currencyOptions[ $currency ] = $currency;
|
||||
$currencyToggles[ $currency ] = array( 'withdraw_amount_' . $currency );
|
||||
}
|
||||
}
|
||||
|
||||
$withdrawForm->add( new \IPS\Helpers\Form\Radio( 'withdraw_currency', NULL, TRUE, array( 'options' => $currencyOptions, 'toggles' => $currencyToggles ) ) );
|
||||
$withdrawForm->add( new Radio( 'withdraw_currency', NULL, TRUE, array( 'options' => $currencyOptions, 'toggles' => $currencyToggles ) ) );
|
||||
}
|
||||
|
||||
$canWithdraw = FALSE;
|
||||
foreach ( \IPS\nexus\Money::currencies() as $currency )
|
||||
foreach ( Money::currencies() as $currency )
|
||||
{
|
||||
if ( !isset( $balance[ $currency ] ) OR ( !\IPS\Settings::i()->nexus_payout_unlimited_times AND \in_array( $currency, $activeWithdrawals ) ) )
|
||||
if ( !isset( $balance[ $currency ] ) OR ( !Settings::i()->nexus_payout_unlimited_times AND in_array( $currency, $activeWithdrawals ) ) )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
@@ -197,13 +230,13 @@ class _credit extends \IPS\Dispatcher\Controller
|
||||
$upperLimit = $maximumWithdrawalsAmounts[ $currency ];
|
||||
|
||||
/* Determine our date cutoff */
|
||||
$periodRestrictions = json_decode( \IPS\Settings::i()->nexus_payout_max_period, TRUE );
|
||||
$periodRestrictions = json_decode( Settings::i()->nexus_payout_max_period, TRUE );
|
||||
|
||||
$interval = 'P' . (int) $periodRestrictions[0] . ( mb_strtoupper( mb_substr( $periodRestrictions[1], 0, 1 ) ) );
|
||||
$date = \IPS\DateTime::create()->sub( new \DateInterval( $interval ) )->getTimestamp();
|
||||
$date = DateTime::create()->sub( new DateInterval( $interval ) )->getTimestamp();
|
||||
|
||||
/* Get our (non-cancelled) payout requests since the date cutoff */
|
||||
foreach( \IPS\Db::i()->select( '*', 'nexus_payouts', array( 'po_member=? AND po_date>? AND po_status NOT IN(?) AND po_currency=?', \IPS\nexus\Customer::loggedIn()->member_id, $date, 'canc', $currency ) ) as $request )
|
||||
foreach( Db::i()->select( '*', 'nexus_payouts', array( 'po_member=? AND po_date>? AND po_status NOT IN(?) AND po_currency=?', Customer::loggedIn()->member_id, $date, 'canc', $currency ) ) as $request )
|
||||
{
|
||||
$upperLimit -= $request['po_amount'];
|
||||
}
|
||||
@@ -217,17 +250,17 @@ class _credit extends \IPS\Dispatcher\Controller
|
||||
|
||||
if( $max <= 0 )
|
||||
{
|
||||
\IPS\Member::loggedIn()->language()->words[ 'withdraw_amount_' . $currency . '_desc' ] = \IPS\Member::loggedIn()->language()->addToStack( 'max_withdrawl_exceeded' );
|
||||
Member::loggedIn()->language()->words[ 'withdraw_amount_' . $currency . '_desc' ] = Member::loggedIn()->language()->addToStack( 'max_withdrawl_exceeded' );
|
||||
}
|
||||
|
||||
$field = new \IPS\Helpers\Form\Number( 'withdraw_amount_' . $currency, (string) $max, \count( $currencyOptions ) ? NULL : TRUE, array( 'min' => $min, 'max' => (string) $max, 'decimals' => \IPS\nexus\Money::numberOfDecimalsForCurrency( $currency ), 'disabled' => ( $max <= 0 ) ), \count( $currencyOptions ) ? NULL : function( $val ) use ( $currency )
|
||||
$field = new Number( 'withdraw_amount_' . $currency, (string) $max, count( $currencyOptions ) ? NULL : TRUE, array( 'min' => $min, 'max' => (string) $max, 'decimals' => Money::numberOfDecimalsForCurrency( $currency ), 'disabled' => ( $max <= 0 ) ), count( $currencyOptions ) ? NULL : function( $val ) use ( $currency )
|
||||
{
|
||||
if ( !$val and \IPS\Request::i()->withdraw_currency === $currency )
|
||||
if ( !$val and Request::i()->withdraw_currency === $currency )
|
||||
{
|
||||
throw new \DomainException('form_required');
|
||||
throw new DomainException('form_required');
|
||||
}
|
||||
}, NULL, $currency, 'withdraw_amount_' . $currency );
|
||||
$field->label = \IPS\Member::loggedIn()->language()->addToStack('withdraw_amount');
|
||||
$field->label = Member::loggedIn()->language()->addToStack('withdraw_amount');
|
||||
$withdrawForm->add( $field );
|
||||
|
||||
$canWithdraw = TRUE;
|
||||
@@ -242,7 +275,9 @@ class _credit extends \IPS\Dispatcher\Controller
|
||||
{
|
||||
$options[ $k ] = $k === 'Manual' ? $settings['name'] : 'withdraw__' . $k;
|
||||
$toggles[ $k ] = array();
|
||||
$class = \IPS\nexus\Gateway::payoutGateways()[ $k ];
|
||||
|
||||
/* @var Payout $class */
|
||||
$class = Gateway::payoutGateways()[ $k ];
|
||||
foreach ( $class::form() as $field )
|
||||
{
|
||||
if ( !$field->htmlId )
|
||||
@@ -254,9 +289,9 @@ class _credit extends \IPS\Dispatcher\Controller
|
||||
}
|
||||
}
|
||||
|
||||
if ( \is_countable( $withdrawOptions ) AND \count( $withdrawOptions ) > 1 )
|
||||
if ( is_countable( $withdrawOptions ) AND count( $withdrawOptions ) > 1 )
|
||||
{
|
||||
$withdrawForm->add( new \IPS\Helpers\Form\Radio( 'withdraw_method', NULL, TRUE, array( 'options' => $options, 'toggles' => $toggles ) ) );
|
||||
$withdrawForm->add( new Radio( 'withdraw_method', NULL, TRUE, array( 'options' => $options, 'toggles' => $toggles ) ) );
|
||||
}
|
||||
|
||||
foreach ( $fields as $field )
|
||||
@@ -266,55 +301,55 @@ class _credit extends \IPS\Dispatcher\Controller
|
||||
if ( $values = $withdrawForm->values() )
|
||||
{
|
||||
$currencies = array_keys( $balance );
|
||||
$currency = \count( $currencyOptions ) ? $values['withdraw_currency'] : array_pop( $currencies );
|
||||
$currency = count( $currencyOptions ) ? $values['withdraw_currency'] : array_pop( $currencies );
|
||||
|
||||
$withdrawMethods = array_keys( $options );
|
||||
if ( \count( $withdrawMethods ) === 1 )
|
||||
if ( count( $withdrawMethods ) === 1 )
|
||||
{
|
||||
$key = array_pop( $withdrawMethods );
|
||||
$class = \IPS\nexus\Gateway::payoutGateways()[ $key ];
|
||||
$class = Gateway::payoutGateways()[ $key ];
|
||||
}
|
||||
else
|
||||
{
|
||||
$class = \IPS\nexus\Gateway::payoutGateways()[ $values['withdraw_method'] ];
|
||||
$class = Gateway::payoutGateways()[ $values['withdraw_method'] ];
|
||||
}
|
||||
|
||||
$payout = new $class;
|
||||
$payout->amount = new \IPS\nexus\Money( $values[ 'withdraw_amount_' . $currency ], $currency );
|
||||
$payout->member = \IPS\nexus\Customer::loggedIn();
|
||||
$payout->amount = new Money( $values[ 'withdraw_amount_' . $currency ], $currency );
|
||||
$payout->member = Customer::loggedIn();
|
||||
try
|
||||
{
|
||||
$payout->data = $payout->getData( $values );
|
||||
}
|
||||
catch ( \DomainException $e )
|
||||
catch ( DomainException $e )
|
||||
{
|
||||
\IPS\Output::i()->error( $e->getMessage(), '1X239/2', 403, '' );
|
||||
Output::i()->error( $e->getMessage(), '1X239/2', 403, '' );
|
||||
}
|
||||
$payout->ip = \IPS\Request::i()->ipAddress();
|
||||
$payout->ip = Request::i()->ipAddress();
|
||||
$payout->save();
|
||||
|
||||
$credits = \IPS\nexus\Customer::loggedIn()->cm_credits;
|
||||
$credits[ $currency ]->amount = $credits[ $currency ]->amount->subtract( new \IPS\Math\Number( number_format( $values[ 'withdraw_amount_' . $currency ], \IPS\nexus\Money::numberOfDecimalsForCurrency( $currency ), '.', '' ) ) );
|
||||
\IPS\nexus\Customer::loggedIn()->cm_credits = $credits;
|
||||
\IPS\nexus\Customer::loggedIn()->save();
|
||||
$credits = Customer::loggedIn()->cm_credits;
|
||||
$credits[ $currency ]->amount = $credits[ $currency ]->amount->subtract( new \IPS\Math\Number( number_format( $values[ 'withdraw_amount_' . $currency ], Money::numberOfDecimalsForCurrency( $currency ), '.', '' ) ) );
|
||||
Customer::loggedIn()->cm_credits = $credits;
|
||||
Customer::loggedIn()->save();
|
||||
|
||||
if ( !\IPS\Settings::i()->nexus_payout_approve and !$payout::$requiresApproval )
|
||||
if ( !Settings::i()->nexus_payout_approve and !$payout::$requiresApproval )
|
||||
{
|
||||
try
|
||||
{
|
||||
$payout->process();
|
||||
\IPS\nexus\Customer::loggedIn()->log( 'payout', array( 'type' => 'autoprocess', 'amount' => $values[ 'withdraw_amount_' . $currency ], 'currency' => $currency, 'payout_id' => $payout->id ) );
|
||||
\IPS\Output::i()->redirect( \IPS\Http\Url::internal( 'app=nexus&module=clients&controller=credit&withdraw=success', 'front', 'clientscredit' ) );
|
||||
Customer::loggedIn()->log( 'payout', array( 'type' => 'autoprocess', 'amount' => $values[ 'withdraw_amount_' . $currency ], 'currency' => $currency, 'payout_id' => $payout->id ) );
|
||||
Output::i()->redirect( Url::internal( 'app=nexus&module=clients&controller=credit&withdraw=success', 'front', 'clientscredit' ) );
|
||||
}
|
||||
catch ( \Exception $e ) {}
|
||||
catch ( Exception ) {}
|
||||
}
|
||||
else
|
||||
{
|
||||
\IPS\core\AdminNotification::send( 'nexus', 'Withdrawal', NULL, TRUE, $payout );
|
||||
AdminNotification::send( 'nexus', 'Withdrawal', NULL, TRUE, $payout );
|
||||
}
|
||||
|
||||
\IPS\nexus\Customer::loggedIn()->log( 'payout', array( 'type' => 'request', 'amount' => $values[ 'withdraw_amount_' . $currency ], 'currency' => $currency, 'payout_id' => $payout->id ) );
|
||||
\IPS\Output::i()->redirect( \IPS\Http\Url::internal( 'app=nexus&module=clients&controller=credit&withdraw=pending', 'front', 'clientscredit' ) );
|
||||
Customer::loggedIn()->log( 'payout', array( 'type' => 'request', 'amount' => $values[ 'withdraw_amount_' . $currency ], 'currency' => $currency, 'payout_id' => $payout->id ) );
|
||||
Output::i()->redirect( Url::internal( 'app=nexus&module=clients&controller=credit&withdraw=pending', 'front', 'clientscredit' ) );
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -325,10 +360,10 @@ class _credit extends \IPS\Dispatcher\Controller
|
||||
|
||||
if ( !$withdrawForm )
|
||||
{
|
||||
\IPS\Output::i()->error( 'no_module_permission', '2X239/3', 403, '' );
|
||||
Output::i()->error( 'no_module_permission', '2X239/3', 403, '' );
|
||||
}
|
||||
|
||||
\IPS\Output::i()->output = $withdrawForm->customTemplate( array( \IPS\Theme::i()->getTemplate( 'forms', 'core' ), 'popupTemplate' ) );
|
||||
Output::i()->output = $withdrawForm->customTemplate( array( Theme::i()->getTemplate( 'forms', 'core' ), 'popupTemplate' ) );
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -336,54 +371,55 @@ class _credit extends \IPS\Dispatcher\Controller
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
protected function topup()
|
||||
protected function topup() : void
|
||||
{
|
||||
$topupForm = NULL;
|
||||
if ( \IPS\Settings::i()->nexus_min_topup )
|
||||
if ( Settings::i()->nexus_min_topup )
|
||||
{
|
||||
$minimumTopupAmounts = ( \IPS\Settings::i()->nexus_min_topup and \IPS\Settings::i()->nexus_min_topup !== '*' ) ? json_decode( \IPS\Settings::i()->nexus_min_topup, TRUE ) : NULL;
|
||||
$maximumBalanceAmounts = ( \IPS\Settings::i()->nexus_max_credit and \IPS\Settings::i()->nexus_max_credit !== '*' ) ? json_decode( \IPS\Settings::i()->nexus_max_credit, TRUE ) : NULL;
|
||||
$minimumTopupAmounts = ( Settings::i()->nexus_min_topup and Settings::i()->nexus_min_topup !== '*' ) ? json_decode( Settings::i()->nexus_min_topup, TRUE ) : NULL;
|
||||
$maximumBalanceAmounts = ( Settings::i()->nexus_max_credit and Settings::i()->nexus_max_credit !== '*' ) ? json_decode( Settings::i()->nexus_max_credit, TRUE ) : NULL;
|
||||
|
||||
$maximums = array();
|
||||
foreach ( array_merge( array( \IPS\nexus\Customer::loggedIn() ), iterator_to_array( \IPS\nexus\Customer::loggedIn()->parentContacts( array('billing=1') ) ) ) as $account )
|
||||
foreach ( array_merge( array( Customer::loggedIn() ), iterator_to_array( Customer::loggedIn()->parentContacts( array('billing=1') ) ) ) as $account )
|
||||
{
|
||||
if ( $account instanceof \IPS\nexus\Customer\AlternativeContact )
|
||||
if ( $account instanceof AlternativeContact )
|
||||
{
|
||||
$account = $account->main_id;
|
||||
}
|
||||
|
||||
foreach ( $account->cm_credits as $value )
|
||||
{
|
||||
$max = $maximumBalanceAmounts ? ( ( new \IPS\Math\Number( number_format( $maximumBalanceAmounts[ $value->currency ]['amount'], \IPS\nexus\Money::numberOfDecimalsForCurrency( $value->currency ), '.', '' ) ) )->subtract( $value->amount ) ) : NULL;
|
||||
if ( \is_null( $max ) or $max->isGreaterThanZero() )
|
||||
$max = $maximumBalanceAmounts ? ( ( new \IPS\Math\Number( number_format( $maximumBalanceAmounts[ $value->currency ]['amount'], Money::numberOfDecimalsForCurrency( $value->currency ), '.', '' ) ) )->subtract( $value->amount ) ) : NULL;
|
||||
if ( is_null( $max ) or $max->isGreaterThanZero() )
|
||||
{
|
||||
$maximums[ $account->member_id ][ $value->currency ] = \is_null( $max ) ? NULL : (string) $max;
|
||||
$maximums[ $account->member_id ][ $value->currency ] = is_null( $max ) ? NULL : (string) $max;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ( \count( $maximums ) )
|
||||
if ( count( $maximums ) )
|
||||
{
|
||||
$topupForm = new \IPS\Helpers\Form( 'topup', 'checkout' );
|
||||
$topupForm = new Form( 'topup', 'checkout' );
|
||||
|
||||
$accountOptions = array();
|
||||
$accountOptionToggles = array();
|
||||
foreach ( $maximums as $accountId => $data )
|
||||
{
|
||||
$currency = NULL;
|
||||
if ( \count( $data ) === 1 )
|
||||
if ( count( $data ) === 1 )
|
||||
{
|
||||
$currencies = array_keys( $data );
|
||||
$currency = array_pop( $currencies );
|
||||
}
|
||||
|
||||
$accountOptions[ $accountId ] = $accountId === \IPS\nexus\Customer::loggedIn()->id ? \IPS\nexus\Customer::loggedIn()->language()->addToStack( 'my_account', FALSE, array( 'sprintf' => array( \IPS\nexus\Customer::loggedIn()->cm_name ) ) ) : \IPS\nexus\Customer::load( $accountId )->cm_name;
|
||||
$accountOptionToggles[ $accountId ] = ( \count( $data ) > 1 ) ? array( 'topup_currency_' . $accountId ) : array( 'topup_amount_' . $accountId . '_' . $currency );
|
||||
$accountOptions[ $accountId ] = $accountId === Customer::loggedIn()->id ? Customer::loggedIn()->language()->addToStack( 'my_account', FALSE, array( 'sprintf' => array( Customer::loggedIn()->cm_name ) ) ) : Customer::load( $accountId )->cm_name;
|
||||
$accountOptionToggles[ $accountId ] = ( count( $data ) > 1 ) ? array( 'topup_currency_' . $accountId ) : array( 'topup_amount_' . $accountId . '_' . $currency );
|
||||
}
|
||||
$topupForm->add( new \IPS\Helpers\Form\Radio( 'topup_account', NULL, TRUE, array( 'options' => $accountOptions, 'parse' => 'normal', 'toggles' => $accountOptionToggles ) ) );
|
||||
$topupForm->add( new Radio( 'topup_account', NULL, TRUE, array( 'options' => $accountOptions, 'parse' => 'normal', 'toggles' => $accountOptionToggles ) ) );
|
||||
|
||||
foreach ( $maximums as $accountId => $data )
|
||||
{
|
||||
if ( \count( $data ) > 1 )
|
||||
if ( count( $data ) > 1 )
|
||||
{
|
||||
$currencyToggles = array();
|
||||
foreach ( $data as $currency => $maximum )
|
||||
@@ -391,8 +427,8 @@ class _credit extends \IPS\Dispatcher\Controller
|
||||
$currencyToggles[ $currency ] = array( 'topup_amount_' . $accountId . '_' . $currency );
|
||||
}
|
||||
|
||||
$field = new \IPS\Helpers\Form\Radio( 'topup_currency_' . $accountId, NULL, NULL, array( 'options' => array_combine( array_keys( $data ), array_keys( $data ) ), 'toggles' => $currencyToggles ), NULL, NULL, NULL, 'topup_currency_' . $accountId );
|
||||
$field->label = \IPS\Member::loggedIn()->language()->addToStack( 'topup_currency' );
|
||||
$field = new Radio( 'topup_currency_' . $accountId, NULL, NULL, array( 'options' => array_combine( array_keys( $data ), array_keys( $data ) ), 'toggles' => $currencyToggles ), NULL, NULL, NULL, 'topup_currency_' . $accountId );
|
||||
$field->label = Member::loggedIn()->language()->addToStack( 'topup_currency' );
|
||||
$topupForm->add( $field );
|
||||
}
|
||||
|
||||
@@ -400,29 +436,29 @@ class _credit extends \IPS\Dispatcher\Controller
|
||||
{
|
||||
$min = $minimumTopupAmounts ? ( $minimumTopupAmounts[ $currency ]['amount'] ) : 0.01;
|
||||
|
||||
$field = new \IPS\Helpers\Form\Number( 'topup_amount_' . $accountId . '_' . $currency, NULL, NULL, array( 'decimals' => \IPS\nexus\Money::numberOfDecimalsForCurrency( $currency ) ), function( $val ) use ( $currency, $accountOptions, $accountId, $data, $min, $maximum )
|
||||
$field = new Number( 'topup_amount_' . $accountId . '_' . $currency, NULL, NULL, array( 'decimals' => Money::numberOfDecimalsForCurrency( $currency ) ), function( $val ) use ( $currency, $accountOptions, $accountId, $data, $min, $maximum )
|
||||
{
|
||||
if ( \count( $accountOptions ) === 1 or \IPS\Request::i()->topup_account == $accountId )
|
||||
if ( count( $accountOptions ) === 1 or Request::i()->topup_account == $accountId )
|
||||
{
|
||||
$key = "topup_currency_{$accountId}";
|
||||
if ( \count( $data ) === 1 or \IPS\Request::i()->$key == $currency )
|
||||
if ( count( $data ) === 1 or Request::i()->$key == $currency )
|
||||
{
|
||||
if ( !$val )
|
||||
{
|
||||
throw new \DomainException('form_required');
|
||||
throw new DomainException('form_required');
|
||||
}
|
||||
elseif ( !\is_null( $min ) and $val < $min )
|
||||
elseif ( !is_null( $min ) and $val < $min )
|
||||
{
|
||||
throw new \DomainException( \IPS\Member::loggedIn()->language()->addToStack( 'form_number_min', FALSE, array( 'sprintf' => array( $min ) ) ) );
|
||||
throw new DomainException( Member::loggedIn()->language()->addToStack( 'form_number_min', FALSE, array( 'sprintf' => array( $min ) ) ) );
|
||||
}
|
||||
elseif ( $maximum and $val > $maximum )
|
||||
{
|
||||
throw new \DomainException( \IPS\Member::loggedIn()->language()->addToStack( 'form_number_max', FALSE, array( 'sprintf' => array( $maximum ) ) ) );
|
||||
throw new DomainException( Member::loggedIn()->language()->addToStack( 'form_number_max', FALSE, array( 'sprintf' => array( $maximum ) ) ) );
|
||||
}
|
||||
}
|
||||
}
|
||||
}, NULL, $currency, 'topup_amount_' . $accountId . '_' . $currency );
|
||||
$field->label = \IPS\Member::loggedIn()->language()->addToStack('topup_amount');
|
||||
$field->label = Member::loggedIn()->language()->addToStack('topup_amount');
|
||||
$topupForm->add( $field );
|
||||
}
|
||||
}
|
||||
@@ -430,7 +466,7 @@ class _credit extends \IPS\Dispatcher\Controller
|
||||
if ( $values = $topupForm->values() )
|
||||
{
|
||||
|
||||
$account = isset( $values['topup_account'] ) ? \IPS\nexus\Customer::load( $values['topup_account'] ) : \IPS\nexus\Customer::loggedIn();
|
||||
$account = isset( $values['topup_account'] ) ? Customer::load( $values['topup_account'] ) : Customer::loggedIn();
|
||||
if ( isset( $values[ 'topup_currency_' . $account->member_id ] ) )
|
||||
{
|
||||
$currency = $values[ 'topup_currency_' . $account->member_id ];
|
||||
@@ -441,22 +477,22 @@ class _credit extends \IPS\Dispatcher\Controller
|
||||
$currency = array_pop( $currencies );
|
||||
}
|
||||
|
||||
$invoice = new \IPS\nexus\Invoice;
|
||||
$invoice = new Invoice;
|
||||
$invoice->member = $account;
|
||||
$invoice->currency = $currency;
|
||||
$invoice->return_uri = 'app=nexus&module=clients&controller=credit';
|
||||
$invoice->addItem( new \IPS\nexus\extensions\nexus\Item\AccountCreditIncrease( \IPS\nexus\Customer::loggedIn()->language()->get('account_credit'), new \IPS\nexus\Money( $values["topup_amount_{$account->member_id}_{$currency}"], $currency ) ) );
|
||||
\IPS\Output::i()->redirect( $invoice->checkoutUrl() );
|
||||
$invoice->addItem( new AccountCreditIncrease( Customer::loggedIn()->language()->get('account_credit'), new Money( $values["topup_amount_{$account->member_id}_{$currency}"], $currency ) ) );
|
||||
Output::i()->redirect( $invoice->checkoutUrl() );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ( !$topupForm )
|
||||
{
|
||||
\IPS\Output::i()->error( 'no_module_permission', '2X239/4', 403, '' );
|
||||
Output::i()->error( 'no_module_permission', '2X239/4', 403, '' );
|
||||
}
|
||||
|
||||
\IPS\Output::i()->output = $topupForm->customTemplate( array( \IPS\Theme::i()->getTemplate( 'forms', 'core' ), 'popupTemplate' ) );
|
||||
Output::i()->output = $topupForm->customTemplate( array( Theme::i()->getTemplate( 'forms', 'core' ), 'popupTemplate' ) );
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -464,14 +500,14 @@ class _credit extends \IPS\Dispatcher\Controller
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
protected function cancel()
|
||||
protected function cancel() : void
|
||||
{
|
||||
\IPS\Session::i()->csrfCheck();
|
||||
Session::i()->csrfCheck();
|
||||
|
||||
try
|
||||
{
|
||||
$payout = \IPS\nexus\Payout::load( \IPS\Request::i()->id );
|
||||
if ( $payout->member->member_id === \IPS\nexus\Customer::loggedIn()->member_id and $payout->status === $payout::STATUS_PENDING )
|
||||
$payout = Payout::load( Request::i()->id );
|
||||
if ( $payout->member->member_id === Customer::loggedIn()->member_id and $payout->status === $payout::STATUS_PENDING )
|
||||
{
|
||||
$payout->status = $payout::STATUS_CANCELED;
|
||||
$payout->save();
|
||||
@@ -481,11 +517,11 @@ class _credit extends \IPS\Dispatcher\Controller
|
||||
$payout->member->cm_credits = $credits;
|
||||
$payout->member->save();
|
||||
|
||||
\IPS\nexus\Customer::loggedIn()->log( 'payout', array( 'type' => 'cancel', 'amount' => $payout->amount->amount, 'currency' => $payout->amount->currency, 'payout_id' => $payout->id ) );
|
||||
Customer::loggedIn()->log( 'payout', array( 'type' => 'cancel', 'amount' => $payout->amount->amount, 'currency' => $payout->amount->currency, 'payout_id' => $payout->id ) );
|
||||
}
|
||||
}
|
||||
catch ( \OutOfRangeException $e ) { }
|
||||
catch ( OutOfRangeException ) { }
|
||||
|
||||
\IPS\Output::i()->redirect( \IPS\Http\Url::internal( 'app=nexus&module=clients&controller=credit', 'front', 'clientscredit' ) );
|
||||
Output::i()->redirect( Url::internal( 'app=nexus&module=clients&controller=credit', 'front', 'clientscredit' ) );
|
||||
}
|
||||
}
|
||||
@@ -12,48 +12,60 @@
|
||||
namespace IPS\nexus\modules\front\clients;
|
||||
|
||||
/* To prevent PHP errors (extending class does not exist) revealing path */
|
||||
if ( !\defined( '\IPS\SUITE_UNIQUE_KEY' ) )
|
||||
|
||||
use IPS\Dispatcher\Controller;
|
||||
use IPS\Helpers\Form;
|
||||
use IPS\Helpers\Form\Number;
|
||||
use IPS\Helpers\Form\Radio;
|
||||
use IPS\Helpers\Form\YesNo;
|
||||
use IPS\Http\Url;
|
||||
use IPS\Member;
|
||||
use IPS\nexus\Customer;
|
||||
use IPS\nexus\Donation\Goal;
|
||||
use IPS\nexus\extensions\nexus\Item\Donation;
|
||||
use IPS\nexus\Invoice;
|
||||
use IPS\nexus\Money;
|
||||
use IPS\Output;
|
||||
use IPS\Request;
|
||||
use IPS\Theme;
|
||||
use OutOfRangeException;
|
||||
use function count;
|
||||
use function defined;
|
||||
|
||||
if ( !defined( '\IPS\SUITE_UNIQUE_KEY' ) )
|
||||
{
|
||||
header( ( isset( $_SERVER['SERVER_PROTOCOL'] ) ? $_SERVER['SERVER_PROTOCOL'] : 'HTTP/1.0' ) . ' 403 Forbidden' );
|
||||
header( ( $_SERVER['SERVER_PROTOCOL'] ?? 'HTTP/1.0' ) . ' 403 Forbidden' );
|
||||
exit;
|
||||
}
|
||||
|
||||
/**
|
||||
* Donations
|
||||
*/
|
||||
class _donations extends \IPS\Dispatcher\Controller
|
||||
class donations extends Controller
|
||||
{
|
||||
/**
|
||||
* View List
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
protected function manage()
|
||||
protected function manage() : void
|
||||
{
|
||||
if ( isset( \IPS\Request::i()->id ) )
|
||||
if ( isset( Request::i()->id ) and !Request::i()->isAjax() )
|
||||
{
|
||||
if ( \IPS\Request::i()->isAjax() )
|
||||
{
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
\IPS\Output::i()->redirect( \IPS\Http\Url::internal( 'app=nexus&module=clients&controller=donations', 'front', 'clientsdonations' ) );
|
||||
}
|
||||
Output::i()->redirect( Url::internal( 'app=nexus&module=clients&controller=donations', 'front', 'clientsdonations' ) );
|
||||
}
|
||||
|
||||
\IPS\Output::i()->breadcrumb[] = array( \IPS\Http\Url::internal( 'app=nexus&module=clients&controller=donations', 'front', 'clientsdonations' ), \IPS\Member::loggedIn()->language()->addToStack('client_donations') );
|
||||
\IPS\Output::i()->title = \IPS\Member::loggedIn()->language()->addToStack('client_donations');
|
||||
\IPS\Output::i()->sidebar['enabled'] = FALSE;
|
||||
\IPS\Output::i()->cssFiles = array_merge( \IPS\Output::i()->cssFiles, \IPS\Theme::i()->css( 'donations.css' ) );
|
||||
Output::i()->breadcrumb[] = array( Url::internal( 'app=nexus&module=clients&controller=donations', 'front', 'clientsdonations' ), Member::loggedIn()->language()->addToStack('client_donations') );
|
||||
Output::i()->title = Member::loggedIn()->language()->addToStack('client_donations');
|
||||
Output::i()->sidebar['enabled'] = FALSE;
|
||||
|
||||
/* "Nowt 'ere lad, may as well knock it over tut 404" - Marc */
|
||||
if( \count( \IPS\nexus\Donation\Goal::roots() ) === 0 )
|
||||
if( count( Goal::roots() ) === 0 )
|
||||
{
|
||||
\IPS\Output::i()->error( 'nexus_no_donations_found', '1X238/2', 404, '' );
|
||||
Output::i()->error( 'nexus_no_donations_found', '1X238/2', 404, '' );
|
||||
}
|
||||
|
||||
\IPS\Output::i()->output = \IPS\Theme::i()->getTemplate('clients')->donations();
|
||||
Output::i()->output = Theme::i()->getTemplate('clients')->donations();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -61,45 +73,80 @@ class _donations extends \IPS\Dispatcher\Controller
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function donate()
|
||||
public function donate() : void
|
||||
{
|
||||
if( !\IPS\Member::loggedIn()->member_id )
|
||||
if( !Member::loggedIn()->member_id )
|
||||
{
|
||||
\IPS\Output::i()->error( 'no_module_permission_guest', '1X238/3', 403, '' );
|
||||
Output::i()->error( 'no_module_permission_guest', '1X238/3', 403, '' );
|
||||
}
|
||||
try
|
||||
{
|
||||
$goal = \IPS\nexus\Donation\Goal::load( \IPS\Request::i()->id );
|
||||
$goal = Goal::load( Request::i()->id );
|
||||
}
|
||||
catch ( \OutOfRangeException $e )
|
||||
catch ( OutOfRangeException )
|
||||
{
|
||||
\IPS\Output::i()->error( 'node_error', '2X238/1', 404, '' );
|
||||
Output::i()->error( 'node_error', '2X238/1', 404, '' );
|
||||
}
|
||||
|
||||
$form = new \IPS\Helpers\Form( 'donate', 'donate' );
|
||||
$form->class = 'ipsForm_vertical';
|
||||
if ( !isset( \IPS\Request::i()->noDesc ) and $desc = \IPS\Member::loggedIn()->language()->get("nexus_donategoal_{$goal->id}_desc") )
|
||||
$form = new Form( 'donate', 'donate' );
|
||||
$form->class = 'ipsForm--vertical ipsForm--donate';
|
||||
if ( !isset( Request::i()->noDesc ) and $desc = Member::loggedIn()->language()->get("nexus_donategoal_{$goal->id}_desc") )
|
||||
{
|
||||
$form->addMessage( $desc, '', FALSE );
|
||||
}
|
||||
$form->add( new \IPS\Helpers\Form\Number( 'donate_amount', 0, TRUE, array( 'decimals' => TRUE, 'min' => 0.01 ), NULL, NULL, $goal->currency ) );
|
||||
|
||||
|
||||
/* Work out what our options are */
|
||||
$options = array();
|
||||
|
||||
if( $goal->suggestions )
|
||||
{
|
||||
foreach ( json_decode( $goal->suggestions ) as $suggestion )
|
||||
{
|
||||
$options[ $suggestion ] = new Money( $suggestion, $goal->currency );
|
||||
}
|
||||
}
|
||||
|
||||
if ( empty( $options ) )
|
||||
{
|
||||
$form->add( new Number( 'donate_amount', 0, TRUE, array( 'decimals' => TRUE, 'min' => 0.01 ), NULL, NULL, $goal->currency ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
if( $goal->suggestions_open )
|
||||
{
|
||||
$options['x'] = Member::loggedIn()->language()->addToStack('other');
|
||||
}
|
||||
|
||||
$form->add( new Radio( 'donate_amount', NULL, TRUE, array( 'options' => $options, 'parse' => 'normal', 'userSuppliedInput' => 'x' ) ) );
|
||||
}
|
||||
|
||||
$form->add( new YesNo( 'donate_anonymous', FALSE ) );
|
||||
|
||||
if ( $values = $form->values() )
|
||||
{
|
||||
$item = new \IPS\nexus\extensions\nexus\Item\Donation( \IPS\Member::loggedIn()->language()->get( 'nexus_donategoal_' . $goal->_id ), new \IPS\nexus\Money( $values['donate_amount'], $goal->currency ) );
|
||||
$item->id = $goal->_id;
|
||||
|
||||
$invoice = new \IPS\nexus\Invoice;
|
||||
$invoice->member = \IPS\nexus\Customer::loggedIn();
|
||||
$invoice->currency = $goal->currency;
|
||||
$invoice->addItem( $item );
|
||||
$invoice->return_uri = 'app=nexus&module=clients&controller=donations&thanks=1';
|
||||
$invoice->save();
|
||||
|
||||
\IPS\Output::i()->redirect( $invoice->checkoutUrl() );
|
||||
if( !is_numeric( $values['donate_amount'] ) )
|
||||
{
|
||||
$form->error = Member::loggedIn()->language()->addToStack( 'donation_invalid_amount' );
|
||||
}
|
||||
|
||||
if( !$form->error )
|
||||
{
|
||||
$item = new Donation( Member::loggedIn()->language()->get( 'nexus_donategoal_' . $goal->_id ), new Money( $values['donate_amount'], $goal->currency ) );
|
||||
$item->id = $goal->_id;
|
||||
$item->extra = array( 'anonymous' => $values['donate_anonymous'] );
|
||||
|
||||
$invoice = new Invoice;
|
||||
$invoice->member = Customer::loggedIn();
|
||||
$invoice->currency = $goal->currency;
|
||||
$invoice->addItem( $item );
|
||||
$invoice->return_uri = 'app=nexus&module=clients&controller=donations&thanks=1';
|
||||
$invoice->save();
|
||||
|
||||
Output::i()->redirect( $invoice->checkoutUrl() );
|
||||
}
|
||||
}
|
||||
|
||||
\IPS\Output::i()->title = $goal->_title;
|
||||
\IPS\Output::i()->output = $form->customTemplate( array( \IPS\Theme::i()->getTemplate( 'forms', 'core' ), 'popupTemplate' ) );
|
||||
Output::i()->title = $goal->_title;
|
||||
Output::i()->output = $form->customTemplate( array( Theme::i()->getTemplate( 'forms', 'core' ), 'popupTemplate' ) );
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,5 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @brief Custom Fields
|
||||
* @author <a href='https://www.invisioncommunity.com'>Invision Power Services, Inc.</a>
|
||||
@@ -12,41 +13,55 @@
|
||||
namespace IPS\nexus\modules\front\clients;
|
||||
|
||||
/* To prevent PHP errors (extending class does not exist) revealing path */
|
||||
if ( !\defined( '\IPS\SUITE_UNIQUE_KEY' ) )
|
||||
|
||||
use IPS\Dispatcher\Controller;
|
||||
use IPS\Helpers\Form;
|
||||
use IPS\Helpers\Form\Text;
|
||||
use IPS\Helpers\Form\Upload;
|
||||
use IPS\Http\Url;
|
||||
use IPS\Member;
|
||||
use IPS\MFA\MFAHandler;
|
||||
use IPS\nexus\Customer;
|
||||
use IPS\nexus\Customer\CustomField;
|
||||
use IPS\Output;
|
||||
use IPS\Theme;
|
||||
use function defined;
|
||||
|
||||
if ( !defined( '\IPS\SUITE_UNIQUE_KEY' ) )
|
||||
{
|
||||
header( ( isset( $_SERVER['SERVER_PROTOCOL'] ) ? $_SERVER['SERVER_PROTOCOL'] : 'HTTP/1.0' ) . ' 403 Forbidden' );
|
||||
header( ( $_SERVER['SERVER_PROTOCOL'] ?? 'HTTP/1.0' ) . ' 403 Forbidden' );
|
||||
exit;
|
||||
}
|
||||
|
||||
/**
|
||||
* Custom Fields
|
||||
*/
|
||||
class _info extends \IPS\Dispatcher\Controller
|
||||
class info extends Controller
|
||||
{
|
||||
/**
|
||||
* Execute
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function execute()
|
||||
public function execute() : void
|
||||
{
|
||||
if ( !\IPS\Member::loggedIn()->member_id )
|
||||
if ( !Member::loggedIn()->member_id )
|
||||
{
|
||||
\IPS\Output::i()->error( 'no_module_permission_guest', '2X242/1', 403, '' );
|
||||
Output::i()->error( 'no_module_permission_guest', '2X242/1', 403, '' );
|
||||
}
|
||||
|
||||
\IPS\Output::i()->breadcrumb[] = array( \IPS\Http\Url::internal( 'app=nexus&module=clients&controller=info', 'front', 'clientsinfo' ), \IPS\Member::loggedIn()->language()->addToStack('client_info') );
|
||||
\IPS\Output::i()->title = \IPS\Member::loggedIn()->language()->addToStack('client_info');
|
||||
\IPS\Output::i()->sidebar['enabled'] = FALSE;
|
||||
Output::i()->breadcrumb[] = array( Url::internal( 'app=nexus&module=clients&controller=info', 'front', 'clientsinfo' ), Member::loggedIn()->language()->addToStack('client_info') );
|
||||
Output::i()->title = Member::loggedIn()->language()->addToStack('client_info');
|
||||
Output::i()->sidebar['enabled'] = FALSE;
|
||||
|
||||
if ( $output = \IPS\MFA\MFAHandler::accessToArea( 'nexus', 'BillingInfo', \IPS\Http\Url::internal( 'app=nexus&module=clients&controller=info', 'front', 'clientsinfo' ) ) )
|
||||
if ( $output = MFAHandler::accessToArea( 'nexus', 'BillingInfo', Url::internal( 'app=nexus&module=clients&controller=info', 'front', 'clientsinfo' ) ) )
|
||||
{
|
||||
$form = new \IPS\Helpers\Form;
|
||||
$form = new Form;
|
||||
foreach( $this->_buildInfoForm( TRUE ) AS $formElement )
|
||||
{
|
||||
$form->add( $formElement );
|
||||
}
|
||||
\IPS\Output::i()->output = \IPS\Theme::i()->getTemplate('clients')->info( $form ) . $output;
|
||||
Output::i()->output = Theme::i()->getTemplate('clients')->info( $form ) . $output;
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -58,9 +73,9 @@ class _info extends \IPS\Dispatcher\Controller
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
protected function manage()
|
||||
protected function manage() : void
|
||||
{
|
||||
$form = new \IPS\Helpers\Form;
|
||||
$form = new Form;
|
||||
foreach( $this->_buildInfoForm() AS $formElement )
|
||||
{
|
||||
$form->add( $formElement );
|
||||
@@ -73,24 +88,25 @@ class _info extends \IPS\Dispatcher\Controller
|
||||
{
|
||||
if ( isset( $values[ $nameField ] ) )
|
||||
{
|
||||
if ( $values[ $nameField ] != \IPS\nexus\Customer::loggedIn()->$nameField )
|
||||
if ( $values[ $nameField ] != Customer::loggedIn()->$nameField )
|
||||
{
|
||||
/* We only need to log this once, so do it if it isn't set */
|
||||
if ( !isset( $changes['name'] ) )
|
||||
{
|
||||
$changes['name'] = \IPS\nexus\Customer::loggedIn()->cm_name;
|
||||
$changes['name'] = Customer::loggedIn()->cm_name;
|
||||
}
|
||||
|
||||
\IPS\nexus\Customer::loggedIn()->$nameField = $values[ $nameField ];
|
||||
Customer::loggedIn()->$nameField = $values[ $nameField ];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
foreach ( \IPS\nexus\Customer\CustomField::roots() as $field )
|
||||
foreach ( CustomField::roots() as $field )
|
||||
{
|
||||
/* @var CustomField $field */
|
||||
$column = $field->column;
|
||||
$helper = $field->buildHelper();
|
||||
if ( $helper instanceof \IPS\Helpers\Form\Upload )
|
||||
if ( $helper instanceof Upload )
|
||||
{
|
||||
$valueToSave = (string) $values["nexus_ccfield_{$field->id}"];
|
||||
}
|
||||
@@ -98,26 +114,26 @@ class _info extends \IPS\Dispatcher\Controller
|
||||
{
|
||||
$valueToSave = $helper::stringValue( $values["nexus_ccfield_{$field->id}"] );
|
||||
}
|
||||
if ( \IPS\nexus\Customer::loggedIn()->$column != $valueToSave )
|
||||
if ( Customer::loggedIn()->$column != $valueToSave )
|
||||
{
|
||||
$changes['other'][] = array( 'name' => 'nexus_ccfield_' . $field->id, 'value' => $field->displayValue( $valueToSave ), 'old' => $field->displayValue( \IPS\nexus\Customer::loggedIn()->$column ) );
|
||||
\IPS\nexus\Customer::loggedIn()->$column = $valueToSave;
|
||||
$changes['other'][] = array( 'name' => 'nexus_ccfield_' . $field->id, 'value' => $field->displayValue( $valueToSave ), 'old' => $field->displayValue( Customer::loggedIn()->$column ) );
|
||||
Customer::loggedIn()->$column = $valueToSave;
|
||||
}
|
||||
|
||||
if ( $field->type === 'Editor' )
|
||||
{
|
||||
$field->claimAttachments( \IPS\nexus\Customer::loggedIn()->member_id );
|
||||
$field->claimAttachments( Customer::loggedIn()->member_id );
|
||||
}
|
||||
}
|
||||
if ( !empty( $changes ) )
|
||||
{
|
||||
\IPS\nexus\Customer::loggedIn()->log( 'info', $changes );
|
||||
Customer::loggedIn()->log( 'info', $changes );
|
||||
}
|
||||
\IPS\nexus\Customer::loggedIn()->save();
|
||||
\IPS\Output::i()->redirect( \IPS\Http\Url::internal( 'app=nexus&module=clients&controller=info', 'front', 'clientsinfo' ) );
|
||||
Customer::loggedIn()->save();
|
||||
Output::i()->redirect( Url::internal( 'app=nexus&module=clients&controller=info', 'front', 'clientsinfo' ) );
|
||||
}
|
||||
|
||||
\IPS\Output::i()->output = \IPS\Theme::i()->getTemplate('clients')->info( $form );
|
||||
Output::i()->output = Theme::i()->getTemplate('clients')->info( $form );
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -126,19 +142,20 @@ class _info extends \IPS\Dispatcher\Controller
|
||||
* @param bool $protected If TRUE, current values will be blanked out
|
||||
* @return array
|
||||
*/
|
||||
protected function _buildInfoForm( $protected = FALSE )
|
||||
protected function _buildInfoForm( bool $protected = FALSE ) : array
|
||||
{
|
||||
$formElements = array();
|
||||
$formElements['cm_first_name'] = new \IPS\Helpers\Form\Text( 'cm_first_name', $protected ? NULL : \IPS\nexus\Customer::loggedIn()->cm_first_name, TRUE );
|
||||
$formElements['cm_last_name'] = new \IPS\Helpers\Form\Text( 'cm_last_name', $protected ? NULL : \IPS\nexus\Customer::loggedIn()->cm_last_name, TRUE );
|
||||
foreach ( \IPS\nexus\Customer\CustomField::roots() as $field )
|
||||
$formElements['cm_first_name'] = new Text( 'cm_first_name', $protected ? NULL : Customer::loggedIn()->cm_first_name, TRUE );
|
||||
$formElements['cm_last_name'] = new Text( 'cm_last_name', $protected ? NULL : Customer::loggedIn()->cm_last_name, TRUE );
|
||||
foreach ( CustomField::roots() as $field )
|
||||
{
|
||||
/* @var CustomField $field */
|
||||
$column = $field->column;
|
||||
if ( $field->type === 'Editor' )
|
||||
{
|
||||
$field::$editorOptions = array_merge( $field::$editorOptions, array( 'attachIds' => array( \IPS\nexus\Customer::loggedIn()->member_id ) ) );
|
||||
$field::$editorOptions = array_merge( $field::$editorOptions, array( 'attachIds' => array( Customer::loggedIn()->member_id ) ) );
|
||||
}
|
||||
$formElements[ $column ] = $field->buildHelper( $protected ? NULL : \IPS\nexus\Customer::loggedIn()->$column );
|
||||
$formElements[ $column ] = $field->buildHelper( $protected ? NULL : Customer::loggedIn()->$column );
|
||||
}
|
||||
|
||||
return $formElements;
|
||||
|
||||
@@ -12,101 +12,128 @@
|
||||
namespace IPS\nexus\modules\front\clients;
|
||||
|
||||
/* To prevent PHP errors (extending class does not exist) revealing path */
|
||||
if ( !\defined( '\IPS\SUITE_UNIQUE_KEY' ) )
|
||||
|
||||
use Exception;
|
||||
use IPS\Db;
|
||||
use IPS\Dispatcher\Controller;
|
||||
use IPS\Events\Event;
|
||||
use IPS\Helpers\Form;
|
||||
use IPS\Helpers\Form\Text;
|
||||
use IPS\Helpers\Form\TextArea;
|
||||
use IPS\Http\Url;
|
||||
use IPS\Login;
|
||||
use IPS\Member;
|
||||
use IPS\nexus\Customer;
|
||||
use IPS\nexus\Invoice;
|
||||
use IPS\nexus\Transaction;
|
||||
use IPS\Output;
|
||||
use IPS\Patterns\ActiveRecordIterator;
|
||||
use IPS\Request;
|
||||
use IPS\Session;
|
||||
use IPS\Theme;
|
||||
use OutOfRangeException;
|
||||
use function count;
|
||||
use function defined;
|
||||
|
||||
if ( !defined( '\IPS\SUITE_UNIQUE_KEY' ) )
|
||||
{
|
||||
header( ( isset( $_SERVER['SERVER_PROTOCOL'] ) ? $_SERVER['SERVER_PROTOCOL'] : 'HTTP/1.0' ) . ' 403 Forbidden' );
|
||||
header( ( $_SERVER['SERVER_PROTOCOL'] ?? 'HTTP/1.0' ) . ' 403 Forbidden' );
|
||||
exit;
|
||||
}
|
||||
|
||||
/**
|
||||
* Invoices
|
||||
*/
|
||||
class _invoices extends \IPS\Dispatcher\Controller
|
||||
class invoices extends Controller
|
||||
{
|
||||
/**
|
||||
* @var Invoice|null
|
||||
*/
|
||||
protected ?Invoice $invoice = null;
|
||||
|
||||
/**
|
||||
* Execute
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function execute()
|
||||
public function execute() : void
|
||||
{
|
||||
/* Load Invoice */
|
||||
if ( isset( \IPS\Request::i()->id ) )
|
||||
if ( isset( Request::i()->id ) )
|
||||
{
|
||||
if ( isset( \IPS\Request::i()->printout ) )
|
||||
if ( isset( Request::i()->printout ) )
|
||||
{
|
||||
\IPS\Request::i()->do = 'printout';
|
||||
Request::i()->do = 'printout';
|
||||
}
|
||||
|
||||
if ( \IPS\Member::loggedIn()->member_id )
|
||||
if ( Member::loggedIn()->member_id )
|
||||
{
|
||||
try
|
||||
{
|
||||
$this->invoice = \IPS\nexus\Invoice::loadAndCheckPerms( \IPS\Request::i()->id );
|
||||
$this->invoice = Invoice::loadAndCheckPerms( Request::i()->id );
|
||||
}
|
||||
catch ( \OutOfRangeException $e )
|
||||
catch ( OutOfRangeException )
|
||||
{
|
||||
\IPS\Output::i()->error( 'node_error', '2X215/1', 404, '' );
|
||||
Output::i()->error( 'node_error', '2X215/1', 404, '' );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Prevent the vid key from being exposed in referrers */
|
||||
\IPS\Output::i()->sendHeader( "Referrer-Policy: origin" );
|
||||
Output::i()->sendHeader( "Referrer-Policy: origin" );
|
||||
|
||||
$key = isset( \IPS\Request::i()->key ) ? \IPS\Request::i()->key : ( isset( \IPS\Request::i()->cookie['guestTransactionKey'] ) ? \IPS\Request::i()->cookie['guestTransactionKey'] : NULL );
|
||||
$this->invoice = \IPS\nexus\Invoice::load( \IPS\Request::i()->id );
|
||||
$key = isset( Request::i()->key ) ? Request::i()->key : ( isset( Request::i()->cookie['guestTransactionKey'] ) ? Request::i()->cookie['guestTransactionKey'] : NULL );
|
||||
$this->invoice = Invoice::load( Request::i()->id );
|
||||
|
||||
if( $this->invoice->member->member_id or !$key or !isset( $this->invoice->guest_data['guestTransactionKey'] ) or !\IPS\Login::compareHashes( $key, $this->invoice->guest_data['guestTransactionKey'] ) )
|
||||
if( $this->invoice->member->member_id or !$key or !isset( $this->invoice->guest_data['guestTransactionKey'] ) or !Login::compareHashes( $key, $this->invoice->guest_data['guestTransactionKey'] ) )
|
||||
{
|
||||
\IPS\Output::i()->error( 'no_module_permission_guest', '2X215/6', 404, '' );
|
||||
Output::i()->error( 'no_module_permission_guest', '2X215/6', 404, '' );
|
||||
}
|
||||
|
||||
/* Do not cache this guest view invoice */
|
||||
\IPS\Output::setCacheTime( false );
|
||||
Output::i()->pageCaching = FALSE;
|
||||
}
|
||||
|
||||
\IPS\Output::i()->breadcrumb[] = array( \IPS\Http\Url::internal( 'app=nexus&module=clients&controller=invoices', 'front', 'clientsinvoices' ), \IPS\Member::loggedIn()->language()->addToStack('client_invoices') );
|
||||
\IPS\Output::i()->breadcrumb[] = array( $this->invoice->url(), $this->invoice->title );
|
||||
\IPS\Output::i()->title = $this->invoice->title;
|
||||
Output::i()->breadcrumb[] = array( Url::internal( 'app=nexus&module=clients&controller=invoices', 'front', 'clientsinvoices' ), Member::loggedIn()->language()->addToStack('client_invoices') );
|
||||
Output::i()->breadcrumb[] = array( $this->invoice->url(), $this->invoice->title );
|
||||
Output::i()->title = $this->invoice->title;
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( !\IPS\Member::loggedIn()->member_id )
|
||||
if ( !Member::loggedIn()->member_id )
|
||||
{
|
||||
\IPS\Output::i()->error( 'no_module_permission_guest', '2X215/3', 403, '' );
|
||||
Output::i()->error( 'no_module_permission_guest', '2X215/3', 403, '' );
|
||||
}
|
||||
|
||||
\IPS\Output::i()->title = \IPS\Member::loggedIn()->language()->addToStack('client_invoices');
|
||||
if ( isset( \IPS\Request::i()->do ) )
|
||||
Output::i()->title = Member::loggedIn()->language()->addToStack('client_invoices');
|
||||
if ( isset( Request::i()->do ) )
|
||||
{
|
||||
\IPS\Output::i()->error( 'node_error', '2X215/2', 403, '' );
|
||||
Output::i()->error( 'node_error', '2X215/2', 403, '' );
|
||||
}
|
||||
}
|
||||
|
||||
/* Execute */
|
||||
\IPS\Output::i()->cssFiles = array_merge( \IPS\Output::i()->cssFiles, \IPS\Theme::i()->css( 'clients.css', 'nexus' ) );
|
||||
\IPS\Output::i()->sidebar['enabled'] = FALSE;
|
||||
Output::i()->cssFiles = array_merge( Output::i()->cssFiles, Theme::i()->css( 'clients.css', 'nexus' ) );
|
||||
Output::i()->sidebar['enabled'] = FALSE;
|
||||
parent::execute();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Invoices Per Page
|
||||
*/
|
||||
protected static $invoicesPerPage = 25;
|
||||
protected static int $invoicesPerPage = 25;
|
||||
|
||||
/**
|
||||
* View List
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
protected function manage()
|
||||
protected function manage() : void
|
||||
{
|
||||
$where = array( 'i_member=?', \IPS\Member::loggedIn()->member_id );
|
||||
$parentContacts = \IPS\nexus\Customer::loggedIn()->parentContacts( array( 'billing=1' ) );
|
||||
if ( \count( $parentContacts ) )
|
||||
$where = array( 'i_member=?', Member::loggedIn()->member_id );
|
||||
$parentContacts = Customer::loggedIn()->parentContacts( array( 'billing=1' ) );
|
||||
if ( count( $parentContacts ) )
|
||||
{
|
||||
$or = array();
|
||||
foreach ( array_keys( iterator_to_array( $parentContacts ) ) as $id )
|
||||
{
|
||||
$where[0] .= ' OR i_member=?';
|
||||
@@ -114,8 +141,8 @@ class _invoices extends \IPS\Dispatcher\Controller
|
||||
}
|
||||
}
|
||||
|
||||
$count = \IPS\Db::i()->select( 'COUNT(*)', 'nexus_invoices', $where )->first();
|
||||
$page = isset( \IPS\Request::i()->page ) ? \IPS\Request::i()->page : 1;
|
||||
$count = Db::i()->select( 'COUNT(*)', 'nexus_invoices', $where )->first();
|
||||
$page = isset( Request::i()->page ) ? Request::i()->page : 1;
|
||||
|
||||
if ( $page < 1 )
|
||||
{
|
||||
@@ -126,13 +153,13 @@ class _invoices extends \IPS\Dispatcher\Controller
|
||||
|
||||
if ( $page > $pages )
|
||||
{
|
||||
\IPS\Output::i()->redirect( \IPS\Http\Url::internal( "app=nexus&module=clients&controller=invoices", 'front', 'clientsinvoices' ) );
|
||||
Output::i()->redirect( Url::internal( "app=nexus&module=clients&controller=invoices", 'front', 'clientsinvoices' ) );
|
||||
}
|
||||
|
||||
$pagination = \IPS\Theme::i()->getTemplate( 'global', 'core', 'global' )->pagination( \IPS\Http\Url::internal( "app=nexus&module=clients&controller=invoices", 'front', 'clientsinvoices' ), $pages, $page, static::$invoicesPerPage );
|
||||
$pagination = Theme::i()->getTemplate( 'global', 'core', 'global' )->pagination( Url::internal( "app=nexus&module=clients&controller=invoices", 'front', 'clientsinvoices' ), $pages, $page, static::$invoicesPerPage );
|
||||
|
||||
$invoices = new \IPS\Patterns\ActiveRecordIterator( \IPS\Db::i()->select( '*', 'nexus_invoices', $where, 'i_date DESC', array( ( $page - 1 ) * static::$invoicesPerPage, static::$invoicesPerPage ) ), 'IPS\nexus\Invoice' );
|
||||
\IPS\Output::i()->output = \IPS\Theme::i()->getTemplate('clients')->invoices( $invoices, $pagination );
|
||||
$invoices = new ActiveRecordIterator( Db::i()->select( '*', 'nexus_invoices', $where, 'i_date DESC', array( ( $page - 1 ) * static::$invoicesPerPage, static::$invoicesPerPage ) ), 'IPS\nexus\Invoice' );
|
||||
Output::i()->output = Theme::i()->getTemplate('clients')->invoices( $invoices, $pagination );
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -140,10 +167,9 @@ class _invoices extends \IPS\Dispatcher\Controller
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function view()
|
||||
public function view() : void
|
||||
{
|
||||
$shipments = $this->invoice->shipments();
|
||||
\IPS\Output::i()->output = \IPS\Theme::i()->getTemplate('clients')->invoice( $this->invoice );
|
||||
Output::i()->output = Theme::i()->getTemplate('clients')->invoice( $this->invoice );
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -151,18 +177,18 @@ class _invoices extends \IPS\Dispatcher\Controller
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function poNumber()
|
||||
public function poNumber() : void
|
||||
{
|
||||
$form = new \IPS\Helpers\Form;
|
||||
$form->class = 'ipsForm_vertical ipsForm_noLabels';
|
||||
$form->add( new \IPS\Helpers\Form\Text( 'invoice_po_number', $this->invoice->po, FALSE, array( 'maxLength' => 255 ) ) );
|
||||
$form = new Form;
|
||||
$form->class = 'ipsForm--vertical ipsForm--po-number ipsForm--noLabels';
|
||||
$form->add( new Text( 'invoice_po_number', $this->invoice->po, FALSE, array( 'maxLength' => 255 ) ) );
|
||||
if ( $values = $form->values() )
|
||||
{
|
||||
$this->invoice->po = $values['invoice_po_number'];
|
||||
$this->invoice->save();
|
||||
\IPS\Output::i()->redirect( $this->invoice->url() );
|
||||
Output::i()->redirect( $this->invoice->url() );
|
||||
}
|
||||
\IPS\Output::i()->output = $form->customTemplate( array( \IPS\Theme::i()->getTemplate( 'forms', 'core' ), 'popupTemplate' ) );;
|
||||
Output::i()->output = $form->customTemplate( array( Theme::i()->getTemplate( 'forms', 'core' ), 'popupTemplate' ) );
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -170,19 +196,19 @@ class _invoices extends \IPS\Dispatcher\Controller
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function notes()
|
||||
public function notes() : void
|
||||
{
|
||||
$form = new \IPS\Helpers\Form;
|
||||
$form->class = 'ipsForm_vertical ipsForm_noLabels';
|
||||
$form->add( new \IPS\Helpers\Form\TextArea( 'invoice_notes', $this->invoice->notes ) );
|
||||
\IPS\Member::loggedIn()->language()->words['invoice_notes_desc'] = '';
|
||||
$form = new Form;
|
||||
$form->class = 'ipsForm--vertical ipsForm--invoice-notes ipsForm--noLabels';
|
||||
$form->add( new TextArea( 'invoice_notes', $this->invoice->notes ) );
|
||||
Member::loggedIn()->language()->words['invoice_notes_desc'] = '';
|
||||
if ( $values = $form->values() )
|
||||
{
|
||||
$this->invoice->notes = $values['invoice_notes'];
|
||||
$this->invoice->save();
|
||||
\IPS\Output::i()->redirect( $this->invoice->url() );
|
||||
Output::i()->redirect( $this->invoice->url() );
|
||||
}
|
||||
\IPS\Output::i()->output = $form->customTemplate( array( \IPS\Theme::i()->getTemplate( 'forms', 'core' ), 'popupTemplate' ) );;
|
||||
Output::i()->output = $form->customTemplate( array( Theme::i()->getTemplate( 'forms', 'core' ), 'popupTemplate' ) );
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -190,11 +216,11 @@ class _invoices extends \IPS\Dispatcher\Controller
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function printout()
|
||||
public function printout() : void
|
||||
{
|
||||
$output = \IPS\Theme::i()->getTemplate( 'invoices', 'nexus', 'global' )->printInvoice( $this->invoice, $this->invoice->summary(), $this->invoice->billaddress ?: $this->invoice->member->primaryBillingAddress() );
|
||||
\IPS\Output::i()->title = 'I' . $this->invoice->id;
|
||||
\IPS\Output::i()->sendOutput( \IPS\Theme::i()->getTemplate( 'global', 'core' )->blankTemplate( $output ) );
|
||||
$output = Theme::i()->getTemplate( 'invoices', 'nexus', 'global' )->printInvoice( $this->invoice, $this->invoice->summary(), $this->invoice->billaddress ?: $this->invoice->member->primaryBillingAddress() );
|
||||
Output::i()->title = 'I' . $this->invoice->id;
|
||||
Output::i()->sendOutput( Theme::i()->getTemplate( 'global', 'core' )->blankTemplate( $output ) );
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -202,42 +228,45 @@ class _invoices extends \IPS\Dispatcher\Controller
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function cancel()
|
||||
public function cancel() : void
|
||||
{
|
||||
/* CSRF check */
|
||||
\IPS\Session::i()->csrfCheck();
|
||||
Session::i()->csrfCheck();
|
||||
|
||||
/* Can only cancel the invoice if it's pending and there are no processing transactions */
|
||||
if ( $this->invoice->status !== \IPS\nexus\Invoice::STATUS_PENDING or \count( $this->invoice->transactions( [ \IPS\nexus\Transaction::STATUS_HELD, \IPS\nexus\Transaction::STATUS_REVIEW, \IPS\nexus\Transaction::STATUS_GATEWAY_PENDING, \IPS\nexus\Transaction::STATUS_DISPUTED ] ) ) )
|
||||
if ( $this->invoice->status !== Invoice::STATUS_PENDING or count( $this->invoice->transactions( [ Transaction::STATUS_HELD, Transaction::STATUS_REVIEW, Transaction::STATUS_GATEWAY_PENDING, Transaction::STATUS_DISPUTED ] ) ) )
|
||||
{
|
||||
\IPS\Output::i()->error( 'order_already_paid', '2X215/4', 403, '' );
|
||||
Output::i()->error( 'order_already_paid', '2X215/4', 403, '' );
|
||||
}
|
||||
|
||||
/* If they have already made a partial payment, refund it to their account credit */
|
||||
foreach ( $this->invoice->transactions( array( \IPS\nexus\Transaction::STATUS_PAID, \IPS\nexus\Transaction::STATUS_PART_REFUNDED ) ) as $transaction )
|
||||
foreach ( $this->invoice->transactions( array( Transaction::STATUS_PAID, Transaction::STATUS_PART_REFUNDED ) ) as $transaction )
|
||||
{
|
||||
/* @var Transaction $transaction */
|
||||
try
|
||||
{
|
||||
$transaction->refund( 'credit' );
|
||||
}
|
||||
catch ( \Exception $e )
|
||||
catch ( Exception $e )
|
||||
{
|
||||
\IPS\Output::i()->error( 'order_cancel_error', '4C171/5', 500, $e->getMessage() );
|
||||
Output::i()->error( 'order_cancel_error', '4C171/5', 500, $e->getMessage() );
|
||||
}
|
||||
}
|
||||
|
||||
/* Cancel the invoice */
|
||||
$this->invoice->status = \IPS\nexus\invoice::STATUS_CANCELED;
|
||||
$this->invoice->status = invoice::STATUS_CANCELED;
|
||||
$this->invoice->save();
|
||||
$this->invoice->member->log( 'invoice', array( 'type' => 'status', 'new' => 'canc', 'id' => $this->invoice->id, 'title' => $this->invoice->title ) );
|
||||
|
||||
/* Run any callbacks (for example, coupons get unmarked as being used) */
|
||||
foreach ( $this->invoice->items as $k => $item )
|
||||
foreach ( $this->invoice->items as $item )
|
||||
{
|
||||
$item->onInvoiceCancel( $this->invoice );
|
||||
|
||||
Event::fire( 'onInvoiceCancel', $item, array( $this->invoice ) );
|
||||
}
|
||||
|
||||
/* Redirect */
|
||||
\IPS\Output::i()->redirect( $this->invoice->url() );
|
||||
Output::i()->redirect( $this->invoice->url() );
|
||||
}
|
||||
}
|
||||
@@ -12,63 +12,91 @@
|
||||
namespace IPS\nexus\modules\front\clients;
|
||||
|
||||
/* To prevent PHP errors (extending class does not exist) revealing path */
|
||||
if ( !\defined( '\IPS\SUITE_UNIQUE_KEY' ) )
|
||||
|
||||
use IPS\Application;
|
||||
use IPS\Db;
|
||||
use IPS\Dispatcher\Controller;
|
||||
use IPS\Helpers\Form;
|
||||
use IPS\Helpers\Form\Number;
|
||||
use IPS\Http\Url;
|
||||
use IPS\Login;
|
||||
use IPS\Member;
|
||||
use IPS\nexus\Customer;
|
||||
use IPS\nexus\Invoice;
|
||||
use IPS\nexus\Invoice\Item\Renewal;
|
||||
use IPS\nexus\Purchase;
|
||||
use IPS\Output;
|
||||
use IPS\Patterns\ActiveRecordIterator;
|
||||
use IPS\Request;
|
||||
use IPS\Session;
|
||||
use IPS\Theme;
|
||||
use OutOfRangeException;
|
||||
use function count;
|
||||
use function defined;
|
||||
use function intval;
|
||||
|
||||
if ( !defined( '\IPS\SUITE_UNIQUE_KEY' ) )
|
||||
{
|
||||
header( ( isset( $_SERVER['SERVER_PROTOCOL'] ) ? $_SERVER['SERVER_PROTOCOL'] : 'HTTP/1.0' ) . ' 403 Forbidden' );
|
||||
header( ( $_SERVER['SERVER_PROTOCOL'] ?? 'HTTP/1.0' ) . ' 403 Forbidden' );
|
||||
exit;
|
||||
}
|
||||
|
||||
/**
|
||||
* Purchases
|
||||
*/
|
||||
class _purchases extends \IPS\Dispatcher\Controller
|
||||
class purchases extends Controller
|
||||
{
|
||||
/**
|
||||
* @brief Purchase object
|
||||
*/
|
||||
protected ?Purchase $purchase = NULL;
|
||||
|
||||
/**
|
||||
* Execute
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function execute()
|
||||
public function execute() : void
|
||||
{
|
||||
if ( !\IPS\Member::loggedIn()->member_id )
|
||||
if ( !Member::loggedIn()->member_id )
|
||||
{
|
||||
\IPS\Output::i()->error( 'no_module_permission_guest', '2X212/6', 403, '' );
|
||||
Output::i()->error( 'no_module_permission_guest', '2X212/6', 403, '' );
|
||||
}
|
||||
|
||||
/* Purchases breadcrumb */
|
||||
\IPS\Output::i()->breadcrumb[] = array( \IPS\Http\Url::internal( 'app=nexus&module=clients&controller=purchases', 'front', 'clientspurchases' ), \IPS\Member::loggedIn()->language()->addToStack('client_purchases') );
|
||||
Output::i()->breadcrumb[] = array( Url::internal( 'app=nexus&module=clients&controller=purchases', 'front', 'clientspurchases' ), Member::loggedIn()->language()->addToStack('client_purchases') );
|
||||
|
||||
/* Load Purchase */
|
||||
if ( isset( \IPS\Request::i()->id ) )
|
||||
if ( isset( Request::i()->id ) )
|
||||
{
|
||||
try
|
||||
{
|
||||
$this->purchase = \IPS\nexus\Purchase::load( \IPS\Request::i()->id );
|
||||
$this->purchase = Purchase::load( Request::i()->id );
|
||||
}
|
||||
catch ( \OutOfRangeException $e )
|
||||
catch ( OutOfRangeException )
|
||||
{
|
||||
\IPS\Output::i()->error( 'node_error', '2X212/1', 404, '' );
|
||||
Output::i()->error( 'node_error', '2X212/1', 404, '' );
|
||||
}
|
||||
if ( !$this->purchase->canView() )
|
||||
{
|
||||
\IPS\Output::i()->error( 'no_module_permission', '2X212/2', 403, '' );
|
||||
Output::i()->error( 'no_module_permission', '2X212/2', 403, '' );
|
||||
}
|
||||
|
||||
\IPS\Output::i()->breadcrumb[] = array( $this->purchase->url(), $this->purchase->name );
|
||||
\IPS\Output::i()->title = $this->purchase->name;
|
||||
Output::i()->breadcrumb[] = array( $this->purchase->url(), $this->purchase->name );
|
||||
Output::i()->title = $this->purchase->name;
|
||||
}
|
||||
else
|
||||
{
|
||||
\IPS\Output::i()->title = \IPS\Member::loggedIn()->language()->addToStack('client_purchases');
|
||||
if ( isset( \IPS\Request::i()->do ) )
|
||||
Output::i()->title = Member::loggedIn()->language()->addToStack('client_purchases');
|
||||
if ( isset( Request::i()->do ) )
|
||||
{
|
||||
\IPS\Output::i()->error( 'node_error', '2X212/3', 403, '' );
|
||||
Output::i()->error( 'node_error', '2X212/3', 403, '' );
|
||||
}
|
||||
}
|
||||
|
||||
/* Execute */
|
||||
\IPS\Output::i()->cssFiles = array_merge( \IPS\Output::i()->cssFiles, \IPS\Theme::i()->css( 'clients.css', 'nexus' ) );
|
||||
\IPS\Output::i()->sidebar['enabled'] = FALSE;
|
||||
Output::i()->cssFiles = array_merge( Output::i()->cssFiles, Theme::i()->css( 'clients.css', 'nexus' ) );
|
||||
Output::i()->sidebar['enabled'] = FALSE;
|
||||
parent::execute();
|
||||
}
|
||||
|
||||
@@ -77,30 +105,29 @@ class _purchases extends \IPS\Dispatcher\Controller
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
protected function manage()
|
||||
protected function manage() : void
|
||||
{
|
||||
$where = array( array( 'ps_member=?', \IPS\Member::loggedIn()->member_id ) );
|
||||
$where = array( array( 'ps_member=?', Member::loggedIn()->member_id ) );
|
||||
|
||||
$parentContacts = \IPS\nexus\Customer::loggedIn()->parentContacts();
|
||||
if ( \count( $parentContacts ) )
|
||||
$parentContacts = Customer::loggedIn()->parentContacts();
|
||||
if ( count( $parentContacts ) )
|
||||
{
|
||||
$or = array();
|
||||
foreach ( $parentContacts as $contact )
|
||||
{
|
||||
$where[0][0] .= ' OR ' . \IPS\Db::i()->in( 'ps_id', $contact->purchaseIds() );
|
||||
$where[0][0] .= ' OR ' . Db::i()->in( 'ps_id', $contact->purchaseIds() );
|
||||
}
|
||||
}
|
||||
$where[] = array( 'ps_show=1' );
|
||||
|
||||
/* Get only the purchases from active applications */
|
||||
$where[] = array( "ps_app IN('" . implode( "','", array_keys( \IPS\Application::enabledApplications() ) ) . "')" );
|
||||
$where[] = array( "ps_app IN('" . implode( "','", array_keys( Application::enabledApplications() ) ) . "')" );
|
||||
|
||||
$purchases = array();
|
||||
foreach( new \IPS\Patterns\ActiveRecordIterator( \IPS\Db::i()->select( '*', 'nexus_purchases', $where, 'ps_active DESC, ps_expire DESC, ps_start DESC' ), 'IPS\nexus\Purchase' ) as $purchase )
|
||||
foreach( new ActiveRecordIterator( Db::i()->select( '*', 'nexus_purchases', $where, 'ps_active DESC, ps_expire DESC, ps_start DESC' ), 'IPS\nexus\Purchase' ) as $purchase )
|
||||
{
|
||||
$purchases[ $purchase->parent ][ $purchase->id ] = $purchase;
|
||||
}
|
||||
\IPS\Output::i()->output = \IPS\Theme::i()->getTemplate('clients')->purchases( $purchases );
|
||||
Output::i()->output = Theme::i()->getTemplate('clients')->purchases( $purchases );
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -108,9 +135,9 @@ class _purchases extends \IPS\Dispatcher\Controller
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function view()
|
||||
public function view() : void
|
||||
{
|
||||
\IPS\Output::i()->output = \IPS\Theme::i()->getTemplate('clients')->purchase( $this->purchase );
|
||||
Output::i()->output = Theme::i()->getTemplate('clients')->purchase( $this->purchase );
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -118,23 +145,10 @@ class _purchases extends \IPS\Dispatcher\Controller
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
protected function extra()
|
||||
protected function extra() : void
|
||||
{
|
||||
if ( $output = $this->purchase->clientAreaAction() )
|
||||
{
|
||||
if ( \IPS\Request::i()->isAjax() )
|
||||
{
|
||||
\IPS\Output::i()->output = $output;
|
||||
}
|
||||
else
|
||||
{
|
||||
\IPS\Output::i()->output = $output;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
\IPS\Output::i()->redirect( $this->purchase->url() );
|
||||
}
|
||||
$this->purchase->clientAreaAction();
|
||||
Output::i()->redirect( $this->purchase->url() );
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -142,20 +156,20 @@ class _purchases extends \IPS\Dispatcher\Controller
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
protected function renew()
|
||||
protected function renew() : void
|
||||
{
|
||||
$cycles = $this->purchase->canRenewUntil( NULL, TRUE );
|
||||
if ( $cycles === FALSE )
|
||||
{
|
||||
\IPS\Output::i()->error( 'you_cannot_renew', '2X212/4', 403, '' );
|
||||
Output::i()->error( 'you_cannot_renew', '2X212/4', 403, '' );
|
||||
}
|
||||
elseif ( $cycles === 1 )
|
||||
{
|
||||
\IPS\Session::i()->csrfCheck();
|
||||
Session::i()->csrfCheck();
|
||||
}
|
||||
elseif ( isset( \IPS\Request::i()->cycles ) and \IPS\Login::compareHashes( (string) \IPS\Session::i()->csrfKey, (string) \IPS\Request::i()->csrfKey ) )
|
||||
elseif ( isset( Request::i()->cycles ) and Login::compareHashes( (string) Session::i()->csrfKey, (string) Request::i()->csrfKey ) )
|
||||
{
|
||||
$_cycles = \intval( \IPS\Request::i()->cycles );
|
||||
$_cycles = intval( Request::i()->cycles );
|
||||
if ( $_cycles >= 1 and ( $cycles === TRUE or $_cycles <= $cycles ) )
|
||||
{
|
||||
$cycles = $_cycles;
|
||||
@@ -172,31 +186,31 @@ class _purchases extends \IPS\Dispatcher\Controller
|
||||
switch( $term['unit'] )
|
||||
{
|
||||
case 'd':
|
||||
$suffix = \IPS\Member::loggedIn()->language()->addToStack('days');
|
||||
$suffix = Member::loggedIn()->language()->addToStack('days');
|
||||
break;
|
||||
case 'm':
|
||||
$suffix = \IPS\Member::loggedIn()->language()->addToStack('months');
|
||||
$suffix = Member::loggedIn()->language()->addToStack('months');
|
||||
break;
|
||||
case 'y':
|
||||
$suffix = \IPS\Member::loggedIn()->language()->addToStack('years');
|
||||
$suffix = Member::loggedIn()->language()->addToStack('years');
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
$form = new \IPS\Helpers\Form( 'form', 'continue' );
|
||||
$form->class = 'ipsForm_vertical';
|
||||
$form->add( new \IPS\Helpers\Form\Number( 'renew_for', 1, TRUE, array( 'min' => 1, 'max' => $cycles === TRUE ? NULL : $cycles ), NULL, NULL, $suffix ) );
|
||||
$form = new Form( 'form', 'continue' );
|
||||
$form->class = 'ipsForm--vertical ipsForm--renew';
|
||||
$form->add( new Number( 'renew_for', 1, TRUE, array( 'min' => 1, 'max' => $cycles === TRUE ? NULL : $cycles ), NULL, NULL, $suffix ) );
|
||||
if( $values = $form->values() or $cycles === 1 )
|
||||
{
|
||||
if ( $pendingInvoice = $this->purchase->invoice_pending and $pendingInvoice->status === $pendingInvoice::STATUS_PENDING )
|
||||
{
|
||||
if ( \count( $pendingInvoice->items ) === 1 )
|
||||
if ( count( $pendingInvoice->items ) === 1 )
|
||||
{
|
||||
foreach ( $pendingInvoice->items as $item )
|
||||
{
|
||||
if ( $item instanceof \IPS\nexus\Invoice\Item\Renewal and $item->id === $this->purchase->id and $item->quantity === ( $cycles === 1 ? 1 : $values['renew_for'] ) )
|
||||
if ( $item instanceof Renewal and $item->id === $this->purchase->id and $item->quantity === ( $cycles === 1 ? 1 : $values['renew_for'] ) )
|
||||
{
|
||||
\IPS\Output::i()->redirect( $pendingInvoice->checkoutUrl() );
|
||||
Output::i()->redirect( $pendingInvoice->checkoutUrl() );
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -206,19 +220,19 @@ class _purchases extends \IPS\Dispatcher\Controller
|
||||
$pendingInvoice->member->log( 'invoice', array( 'type' => 'status', 'new' => 'canc', 'id' => $pendingInvoice->id, 'title' => $pendingInvoice->title ) );
|
||||
}
|
||||
|
||||
$invoice = new \IPS\nexus\Invoice;
|
||||
$invoice->member = \IPS\nexus\Customer::loggedIn();
|
||||
$invoice = new Invoice;
|
||||
$invoice->member = Customer::loggedIn();
|
||||
$invoice->currency = $this->purchase->renewals->cost->currency;
|
||||
$invoice->addItem( \IPS\nexus\Invoice\Item\Renewal::create( $this->purchase, $cycles === 1 ? 1 : $values['renew_for'] ) );
|
||||
$invoice->addItem( Renewal::create( $this->purchase, $cycles === 1 ? 1 : $values['renew_for'] ) );
|
||||
$invoice->save();
|
||||
|
||||
$this->purchase->invoice_pending = $invoice;
|
||||
$this->purchase->save();
|
||||
|
||||
\IPS\Output::i()->redirect( $invoice->checkoutUrl() );
|
||||
Output::i()->redirect( $invoice->checkoutUrl() );
|
||||
}
|
||||
|
||||
\IPS\Output::i()->output = $form->customTemplate( array( \IPS\Theme::i()->getTemplate( 'forms', 'core' ), 'popupTemplate' ) );
|
||||
Output::i()->output = $form->customTemplate( array( Theme::i()->getTemplate( 'forms', 'core' ), 'popupTemplate' ) );
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -226,13 +240,13 @@ class _purchases extends \IPS\Dispatcher\Controller
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
protected function cancel()
|
||||
protected function cancel() : void
|
||||
{
|
||||
\IPS\Session::i()->csrfCheck();
|
||||
Session::i()->csrfCheck();
|
||||
|
||||
if ( !$this->purchase->canCancel() )
|
||||
{
|
||||
\IPS\Output::i()->error( 'you_cannot_cancel', '2X212/5', 403, '' );
|
||||
Output::i()->error( 'you_cannot_cancel', '2X212/5', 403, '' );
|
||||
}
|
||||
|
||||
$this->purchase->member->log( 'purchase', array( 'type' => 'info', 'id' => $this->purchase->id, 'name' => $this->purchase->name, 'info' => 'remove_renewals' ) );
|
||||
@@ -240,7 +254,7 @@ class _purchases extends \IPS\Dispatcher\Controller
|
||||
/* If we have a pending renewal invoice, cancel it (as at this point, we need to reactivate instead) */
|
||||
if ( $this->purchase->invoice_pending )
|
||||
{
|
||||
$this->purchase->invoice_pending->status = \IPS\nexus\Invoice::STATUS_CANCELED; # The constant has a typo and it make me sad
|
||||
$this->purchase->invoice_pending->status = Invoice::STATUS_CANCELED; # The constant has a typo and it make me sad
|
||||
$this->purchase->invoice_pending->save();
|
||||
|
||||
$this->purchase->invoice_pending = NULL;
|
||||
@@ -250,10 +264,10 @@ class _purchases extends \IPS\Dispatcher\Controller
|
||||
$this->purchase->can_reactivate = TRUE;
|
||||
$this->purchase->save();
|
||||
|
||||
if ( $ref = \IPS\Request::i()->referrer( FALSE, TRUE ) )
|
||||
if ( $ref = Request::i()->referrer( FALSE, TRUE ) )
|
||||
{
|
||||
\IPS\Output::i()->redirect( $ref );
|
||||
Output::i()->redirect( $ref );
|
||||
}
|
||||
\IPS\Output::i()->redirect( $this->purchase->url() );
|
||||
Output::i()->redirect( $this->purchase->url() );
|
||||
}
|
||||
}
|
||||
@@ -12,25 +12,31 @@
|
||||
namespace IPS\nexus\modules\front\clients;
|
||||
|
||||
/* To prevent PHP errors (extending class does not exist) revealing path */
|
||||
if ( !\defined( '\IPS\SUITE_UNIQUE_KEY' ) )
|
||||
|
||||
use IPS\Dispatcher\Controller;
|
||||
use IPS\Http\Url;
|
||||
use IPS\Output;
|
||||
use function defined;
|
||||
|
||||
if ( !defined( '\IPS\SUITE_UNIQUE_KEY' ) )
|
||||
{
|
||||
header( ( isset( $_SERVER['SERVER_PROTOCOL'] ) ? $_SERVER['SERVER_PROTOCOL'] : 'HTTP/1.0' ) . ' 403 Forbidden' );
|
||||
header( ( $_SERVER['SERVER_PROTOCOL'] ?? 'HTTP/1.0' ) . ' 403 Forbidden' );
|
||||
exit;
|
||||
}
|
||||
|
||||
/**
|
||||
* Legacy Referrals Controller
|
||||
*/
|
||||
class _referrals extends \IPS\Dispatcher\Controller
|
||||
class referrals extends Controller
|
||||
{
|
||||
/**
|
||||
* Manage
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
protected function manage()
|
||||
protected function manage() : void
|
||||
{
|
||||
/* Referrals have moved to the core. */
|
||||
\IPS\Output::i()->redirect( \IPS\Http\Url::internal( "app=core&module=system&controller=settings&area=referrals", 'front', 'settings_referrals' ) );
|
||||
Output::i()->redirect( Url::internal( "app=core&module=system&controller=settings&area=referrals", 'front', 'settings_referrals' ) );
|
||||
}
|
||||
}
|
||||
@@ -12,44 +12,53 @@
|
||||
namespace IPS\nexus\modules\front\clients;
|
||||
|
||||
/* To prevent PHP errors (extending class does not exist) revealing path */
|
||||
if ( !\defined( '\IPS\SUITE_UNIQUE_KEY' ) )
|
||||
|
||||
use IPS\Db;
|
||||
use IPS\Dispatcher\Controller;
|
||||
use IPS\Http\Url;
|
||||
use IPS\Member;
|
||||
use IPS\nexus\Customer;
|
||||
use IPS\Output;
|
||||
use function count;
|
||||
use function defined;
|
||||
|
||||
if ( !defined( '\IPS\SUITE_UNIQUE_KEY' ) )
|
||||
{
|
||||
header( ( isset( $_SERVER['SERVER_PROTOCOL'] ) ? $_SERVER['SERVER_PROTOCOL'] : 'HTTP/1.0' ) . ' 403 Forbidden' );
|
||||
header( ( $_SERVER['SERVER_PROTOCOL'] ?? 'HTTP/1.0' ) . ' 403 Forbidden' );
|
||||
exit;
|
||||
}
|
||||
|
||||
/**
|
||||
* Controller to redirect /clients to something sensible
|
||||
*/
|
||||
class _splash extends \IPS\Dispatcher\Controller
|
||||
class splash extends Controller
|
||||
{
|
||||
/**
|
||||
* Execute
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function execute()
|
||||
public function execute() : void
|
||||
{
|
||||
if ( \IPS\Member::loggedIn()->member_id )
|
||||
if ( Member::loggedIn()->member_id )
|
||||
{
|
||||
$where = array( array( 'ps_member=?', \IPS\Member::loggedIn()->member_id ) );
|
||||
$parentContacts = \IPS\nexus\Customer::loggedIn()->parentContacts();
|
||||
if ( \count( $parentContacts ) )
|
||||
$where = array( array( 'ps_member=?', Member::loggedIn()->member_id ) );
|
||||
$parentContacts = Customer::loggedIn()->parentContacts();
|
||||
if ( count( $parentContacts ) )
|
||||
{
|
||||
$or = array();
|
||||
foreach ( $parentContacts as $contact )
|
||||
{
|
||||
$where[0][0] .= ' OR ' . \IPS\Db::i()->in( 'ps_id', $contact->purchaseIds() );
|
||||
$where[0][0] .= ' OR ' . Db::i()->in( 'ps_id', $contact->purchaseIds() );
|
||||
}
|
||||
}
|
||||
$where[] = array( 'ps_show=1' );
|
||||
|
||||
if ( \IPS\Db::i()->select( 'COUNT(*)', 'nexus_purchases', $where )->first() )
|
||||
if ( Db::i()->select( 'COUNT(*)', 'nexus_purchases', $where )->first() )
|
||||
{
|
||||
\IPS\Output::i()->redirect( \IPS\Http\Url::internal( 'app=nexus&module=clients&controller=purchases', 'front', 'clientspurchases' ) );
|
||||
Output::i()->redirect( Url::internal( 'app=nexus&module=clients&controller=purchases', 'front', 'clientspurchases' ) );
|
||||
}
|
||||
}
|
||||
|
||||
\IPS\Output::i()->redirect( \IPS\Http\Url::internal( 'app=nexus&module=clients&controller=invoices', 'front', 'clientsinvoices' ) );
|
||||
Output::i()->redirect( Url::internal( 'app=nexus&module=clients&controller=invoices', 'front', 'clientsinvoices' ) );
|
||||
}
|
||||
}
|
||||
@@ -12,31 +12,49 @@
|
||||
namespace IPS\nexus\modules\front\store;
|
||||
|
||||
/* To prevent PHP errors (extending class does not exist) revealing path */
|
||||
if ( !\defined( '\IPS\SUITE_UNIQUE_KEY' ) )
|
||||
|
||||
use IPS\DateTime;
|
||||
use IPS\Db;
|
||||
use IPS\Dispatcher\Controller;
|
||||
use IPS\File;
|
||||
use IPS\GeoLocation;
|
||||
use IPS\Http\Url;
|
||||
use IPS\Math\Number;
|
||||
use IPS\Member;
|
||||
use IPS\nexus\Customer;
|
||||
use IPS\nexus\Invoice;
|
||||
use IPS\nexus\Money;
|
||||
use IPS\nexus\Package;
|
||||
use IPS\Output;
|
||||
use IPS\Request;
|
||||
use IPS\Session;
|
||||
use IPS\Settings;
|
||||
use IPS\Theme;
|
||||
use function count;
|
||||
use function defined;
|
||||
use function in_array;
|
||||
use const IPS\CACHE_PAGE_TIMEOUT;
|
||||
|
||||
if ( !defined( '\IPS\SUITE_UNIQUE_KEY' ) )
|
||||
{
|
||||
header( ( isset( $_SERVER['SERVER_PROTOCOL'] ) ? $_SERVER['SERVER_PROTOCOL'] : 'HTTP/1.0' ) . ' 403 Forbidden' );
|
||||
header( ( $_SERVER['SERVER_PROTOCOL'] ?? 'HTTP/1.0' ) . ' 403 Forbidden' );
|
||||
exit;
|
||||
}
|
||||
|
||||
/**
|
||||
* View Cart
|
||||
*/
|
||||
class _cart extends \IPS\Dispatcher\Controller
|
||||
class cart extends Controller
|
||||
{
|
||||
/**
|
||||
* Execute
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function execute()
|
||||
public function execute() : void
|
||||
{
|
||||
\IPS\Output::i()->cssFiles = array_merge( \IPS\Output::i()->cssFiles, \IPS\Theme::i()->css( 'store.css', 'nexus' ) );
|
||||
Output::i()->cssFiles = array_merge( Output::i()->cssFiles, Theme::i()->css( 'store.css', 'nexus' ) );
|
||||
|
||||
if ( \IPS\Theme::i()->settings['responsive'] )
|
||||
{
|
||||
\IPS\Output::i()->cssFiles = array_merge( \IPS\Output::i()->cssFiles, \IPS\Theme::i()->css( 'store_responsive.css', 'nexus', 'front' ) );
|
||||
}
|
||||
|
||||
parent::execute();
|
||||
}
|
||||
|
||||
@@ -45,20 +63,20 @@ class _cart extends \IPS\Dispatcher\Controller
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
protected function manage()
|
||||
protected function manage() : void
|
||||
{
|
||||
/* Init */
|
||||
if ( !isset( $_SESSION['cart'] ) )
|
||||
{
|
||||
$_SESSION['cart'] = array();
|
||||
}
|
||||
$currency = ( isset( \IPS\Request::i()->cookie['currency'] ) and \in_array( \IPS\Request::i()->cookie['currency'], \IPS\nexus\Money::currencies() ) ) ? \IPS\Request::i()->cookie['currency'] : \IPS\nexus\Customer::loggedIn()->defaultCurrency();
|
||||
$currency = ( isset( Request::i()->cookie['currency'] ) and in_array( Request::i()->cookie['currency'], Money::currencies() ) ) ? Request::i()->cookie['currency'] : Customer::loggedIn()->defaultCurrency();
|
||||
|
||||
/* Display */
|
||||
\IPS\Output::i()->bodyClasses[] = 'ipsLayout_minimal';
|
||||
\IPS\Output::i()->sidebar['enabled'] = FALSE;
|
||||
\IPS\Output::i()->title = \IPS\Member::loggedIn()->language()->addToStack('your_cart');
|
||||
\IPS\Output::i()->output = \IPS\Theme::i()->getTemplate('store')->cart( ( isset( \IPS\Request::i()->cookie['location'] ) and \IPS\Request::i()->cookie['location'] ) ? \IPS\GeoLocation::buildFromJson( \IPS\Request::i()->cookie['location'] ) : NULL, $currency );
|
||||
Output::i()->bodyClasses[] = 'ipsLayout_minimal';
|
||||
Output::i()->sidebar['enabled'] = FALSE;
|
||||
Output::i()->title = Member::loggedIn()->language()->addToStack('your_cart');
|
||||
Output::i()->output = Theme::i()->getTemplate('store')->cart( ( isset( Request::i()->cookie['location'] ) and Request::i()->cookie['location'] ) ? GeoLocation::buildFromJson( Request::i()->cookie['location'] ) : NULL, $currency );
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -66,15 +84,15 @@ class _cart extends \IPS\Dispatcher\Controller
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
protected function quantities()
|
||||
protected function quantities() : void
|
||||
{
|
||||
\IPS\Session::i()->csrfCheck();
|
||||
Session::i()->csrfCheck();
|
||||
|
||||
foreach ( \IPS\Request::i()->item as $k => $v )
|
||||
foreach ( Request::i()->item as $k => $v )
|
||||
{
|
||||
/* Get item */
|
||||
$item = $_SESSION['cart'][ $k ];
|
||||
$package = \IPS\nexus\Package::load( $item->id );
|
||||
$package = Package::load( $item->id );
|
||||
|
||||
/* Are any others just a duplicate for discount purposes? If so, condense them into this one */
|
||||
foreach ( $_SESSION['cart'] as $_k => $_item )
|
||||
@@ -88,7 +106,7 @@ class _cart extends \IPS\Dispatcher\Controller
|
||||
{
|
||||
$v += $_item->quantity;
|
||||
unset( $_SESSION['cart'][ $_k ] );
|
||||
\IPS\Db::i()->update( 'nexus_cart_uploads', array( 'item_id' => $k ), array( 'session_id=? AND item_id=?', \IPS\Session::i()->id, $_k ) );
|
||||
Db::i()->update( 'nexus_cart_uploads', array( 'item_id' => $k ), array( 'session_id=? AND item_id=?', Session::i()->id, $_k ) );
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -96,7 +114,7 @@ class _cart extends \IPS\Dispatcher\Controller
|
||||
/* Subscriptions can only have 1 */
|
||||
if ( $package->subscription and $v > 1 )
|
||||
{
|
||||
\IPS\Output::i()->error( 'err_subscription_qty', '1X214/4', 403, '' );
|
||||
Output::i()->error( 'err_subscription_qty', '1X214/4', 403, '' );
|
||||
}
|
||||
|
||||
/* Set the quantity back to 0 and "re-add" the item */
|
||||
@@ -106,7 +124,7 @@ class _cart extends \IPS\Dispatcher\Controller
|
||||
$data = $package->optionValuesStockAndPrice( $package->optionValues( $item->details ) );
|
||||
if ( $data['stock'] != -1 and ( $data['stock'] - $item->quantity ) < $v )
|
||||
{
|
||||
\IPS\Output::i()->error( \IPS\Member::loggedIn()->language()->addToStack( 'not_enough_in_stock', FALSE, array( 'sprintf' => array( $data['stock'] - $item->quantity ) ) ), '1X214/3', 403, '' );
|
||||
Output::i()->error( Member::loggedIn()->language()->addToStack( 'not_enough_in_stock', FALSE, array( 'sprintf' => array( $data['stock'] - $item->quantity ) ) ), '1X214/3', 403, '' );
|
||||
}
|
||||
|
||||
$package->addItemsToCartData( $item->details, $v, $item->renewalTerm, $item->parent );
|
||||
@@ -128,28 +146,28 @@ class _cart extends \IPS\Dispatcher\Controller
|
||||
unset( $_SESSION['cart'][ $k ] );
|
||||
|
||||
$ids = array();
|
||||
foreach ( \IPS\Db::i()->select( 'id', 'nexus_cart_uploads', array( 'session_id=? AND item_id=?', \IPS\Session::i()->id, $k ) ) as $id )
|
||||
foreach ( Db::i()->select( 'id', 'nexus_cart_uploads', array( 'session_id=? AND item_id=?', Session::i()->id, $k ) ) as $id )
|
||||
{
|
||||
\IPS\File::unclaimAttachments( 'nexus_Purchases', $id, NULL, 'cart' );
|
||||
File::unclaimAttachments( 'nexus_Purchases', $id, NULL, 'cart' );
|
||||
$ids[] = $id;
|
||||
}
|
||||
\IPS\Db::i()->delete( 'nexus_cart_uploads', \IPS\Db::i()->in( 'id', $ids ) );
|
||||
Db::i()->delete( 'nexus_cart_uploads', Db::i()->in( 'id', $ids ) );
|
||||
}
|
||||
}
|
||||
|
||||
if ( empty( $_SESSION['cart'] ) and \IPS\CACHE_PAGE_TIMEOUT and !\IPS\Member::loggedIn()->member_id )
|
||||
if ( empty( $_SESSION['cart'] ) and CACHE_PAGE_TIMEOUT and !Member::loggedIn()->member_id )
|
||||
{
|
||||
\IPS\Request::i()->setCookie( 'noCache', 0, \IPS\DateTime::ts( time() - 86400 ) );
|
||||
Request::i()->setCookie( 'noCache', 0, DateTime::ts( time() - 86400 ) );
|
||||
}
|
||||
|
||||
if ( \IPS\Request::i()->isAjax() )
|
||||
if ( Request::i()->isAjax() )
|
||||
{
|
||||
$currency = ( isset( \IPS\Request::i()->cookie['currency'] ) and \in_array( \IPS\Request::i()->cookie['currency'], \IPS\nexus\Money::currencies() ) ) ? \IPS\Request::i()->cookie['currency'] : \IPS\nexus\Customer::loggedIn()->defaultCurrency();
|
||||
\IPS\Output::i()->sendOutput( \IPS\Theme::i()->getTemplate('store')->cartContents( ( isset( \IPS\Request::i()->cookie['location'] ) and \IPS\Request::i()->cookie['location'] ) ? \IPS\GeoLocation::buildFromJson( \IPS\Request::i()->cookie['location'] ) : NULL, $currency ), 200, 'text/html' );
|
||||
$currency = ( isset( Request::i()->cookie['currency'] ) and in_array( Request::i()->cookie['currency'], Money::currencies() ) ) ? Request::i()->cookie['currency'] : Customer::loggedIn()->defaultCurrency();
|
||||
Output::i()->sendOutput( Theme::i()->getTemplate('store')->cartContents( ( isset( Request::i()->cookie['location'] ) and Request::i()->cookie['location'] ) ? GeoLocation::buildFromJson( Request::i()->cookie['location'] ) : NULL, $currency ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
\IPS\Output::i()->redirect( \IPS\Http\Url::internal('app=nexus&module=store&controller=cart', 'front', 'store_cart' ) );
|
||||
Output::i()->redirect( Url::internal('app=nexus&module=store&controller=cart', 'front', 'store_cart' ) );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -158,31 +176,31 @@ class _cart extends \IPS\Dispatcher\Controller
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
protected function clear()
|
||||
protected function clear() : void
|
||||
{
|
||||
\IPS\Session::i()->csrfCheck();
|
||||
Session::i()->csrfCheck();
|
||||
|
||||
$_SESSION['cart'] = array();
|
||||
$ids = array();
|
||||
foreach ( \IPS\Db::i()->select( 'id', 'nexus_cart_uploads', array( 'session_id=?', \IPS\Session::i()->id ) ) as $id )
|
||||
foreach ( Db::i()->select( 'id', 'nexus_cart_uploads', array( 'session_id=?', Session::i()->id ) ) as $id )
|
||||
{
|
||||
\IPS\File::unclaimAttachments( 'nexus_Purchases', $id, NULL, 'cart' );
|
||||
File::unclaimAttachments( 'nexus_Purchases', $id, NULL, 'cart' );
|
||||
$ids[] = $id;
|
||||
}
|
||||
\IPS\Db::i()->delete( 'nexus_cart_uploads', \IPS\Db::i()->in( 'id', $ids ) );
|
||||
Db::i()->delete( 'nexus_cart_uploads', Db::i()->in( 'id', $ids ) );
|
||||
|
||||
if ( \IPS\CACHE_PAGE_TIMEOUT and !\IPS\Member::loggedIn()->member_id )
|
||||
if ( CACHE_PAGE_TIMEOUT and !Member::loggedIn()->member_id )
|
||||
{
|
||||
\IPS\Request::i()->setCookie( 'noCache', 0, \IPS\DateTime::ts( time() - 86400 ) );
|
||||
Request::i()->setCookie( 'noCache', 0, DateTime::ts( time() - 86400 ) );
|
||||
}
|
||||
|
||||
if ( \IPS\Request::i()->isAjax() )
|
||||
if ( Request::i()->isAjax() )
|
||||
{
|
||||
\IPS\Output::i()->json( $_SESSION['cart'] );
|
||||
Output::i()->json( $_SESSION['cart'] );
|
||||
}
|
||||
else
|
||||
{
|
||||
\IPS\Output::i()->redirect( \IPS\Http\Url::internal('app=nexus&module=store&controller=cart', 'front', 'store_cart' ) );
|
||||
Output::i()->redirect( Url::internal('app=nexus&module=store&controller=cart', 'front', 'store_cart' ) );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -191,22 +209,22 @@ class _cart extends \IPS\Dispatcher\Controller
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
protected function checkout()
|
||||
protected function checkout() : void
|
||||
{
|
||||
\IPS\Session::i()->csrfCheck();
|
||||
Session::i()->csrfCheck();
|
||||
|
||||
$currency = ( isset( \IPS\Request::i()->cookie['currency'] ) and \in_array( \IPS\Request::i()->cookie['currency'], \IPS\nexus\Money::currencies() ) ) ? \IPS\Request::i()->cookie['currency'] : \IPS\nexus\Customer::loggedIn()->defaultCurrency();
|
||||
$currency = ( isset( Request::i()->cookie['currency'] ) and in_array( Request::i()->cookie['currency'], Money::currencies() ) ) ? Request::i()->cookie['currency'] : Customer::loggedIn()->defaultCurrency();
|
||||
|
||||
$canRegister = ( !\IPS\Settings::i()->nexus_reg_force or \IPS\Member::loggedIn()->member_id );
|
||||
$canRegister = ( !Settings::i()->nexus_reg_force or Member::loggedIn()->member_id );
|
||||
|
||||
$tempInvoiceKey = md5( mt_rand() );
|
||||
|
||||
$invoice = new \IPS\nexus\Invoice;
|
||||
$invoice->member = \IPS\nexus\Customer::loggedIn();
|
||||
$invoice = new Invoice;
|
||||
$invoice->member = Customer::loggedIn();
|
||||
$invoice->currency = $currency;
|
||||
foreach ( $_SESSION['cart'] as $k => $item )
|
||||
{
|
||||
if ( !$canRegister and \IPS\nexus\Package::load( $item->id )->reg )
|
||||
if ( !$canRegister and Package::load( $item->id )->reg )
|
||||
{
|
||||
$canRegister = TRUE;
|
||||
}
|
||||
@@ -214,39 +232,39 @@ class _cart extends \IPS\Dispatcher\Controller
|
||||
$itemId = $invoice->addItem( $item, $k );
|
||||
|
||||
$ids = array();
|
||||
foreach ( \IPS\Db::i()->select( 'id', 'nexus_cart_uploads', array( 'session_id=? AND item_id=?', \IPS\Session::i()->id, $k ) ) as $id )
|
||||
foreach ( Db::i()->select( 'id', 'nexus_cart_uploads', array( 'session_id=? AND item_id=?', Session::i()->id, $k ) ) as $id )
|
||||
{
|
||||
\IPS\Db::i()->update( 'core_attachments_map', array( 'id1' => $itemId, 'id3' => "invoice-{$tempInvoiceKey}" ), array( 'location_key=? AND id1=? AND id3=?', 'nexus_Purchases', $id, 'cart' ) );
|
||||
Db::i()->update( 'core_attachments_map', array( 'id1' => $itemId, 'id3' => "invoice-{$tempInvoiceKey}" ), array( 'location_key=? AND id1=? AND id3=?', 'nexus_Purchases', $id, 'cart' ) );
|
||||
$ids[] = $id;
|
||||
}
|
||||
\IPS\Db::i()->delete( 'nexus_cart_uploads', \IPS\Db::i()->in( 'id', $ids ) );
|
||||
Db::i()->delete( 'nexus_cart_uploads', Db::i()->in( 'id', $ids ) );
|
||||
}
|
||||
|
||||
if ( !\count( $invoice->items ) )
|
||||
if ( !count( $invoice->items ) )
|
||||
{
|
||||
\IPS\Output::i()->error( 'your_cart_empty', '2X214/2', 403, '' );
|
||||
Output::i()->error( 'your_cart_empty', '2X214/2', 403, '' );
|
||||
}
|
||||
|
||||
if ( !$canRegister )
|
||||
{
|
||||
\IPS\Output::i()->redirect( \IPS\Http\Url::internal( 'app=nexus&module=store&controller=store&do=register', 'front', 'store' ) );
|
||||
Output::i()->redirect( Url::internal( 'app=nexus&module=store&controller=store&do=register', 'front', 'store' ) );
|
||||
}
|
||||
|
||||
if ( $minimumOrderAmounts = json_decode( \IPS\Settings::i()->nexus_minimum_order, TRUE ) and ( new \IPS\Math\Number( number_format( $minimumOrderAmounts[ $currency ]['amount'], 2, '.', '' ) ) )->compare( $invoice->total->amount ) === 1 )
|
||||
if ( $minimumOrderAmounts = json_decode( Settings::i()->nexus_minimum_order, TRUE ) and ( new Number( number_format( $minimumOrderAmounts[ $currency ]['amount'], 2, '.', '' ) ) )->compare( $invoice->total->amount ) === 1 )
|
||||
{
|
||||
\IPS\Output::i()->error( \IPS\Member::loggedIn()->language()->addToStack( 'err_minimum_order', FALSE, array( 'sprintf' => array( new \IPS\nexus\Money( $minimumOrderAmounts[ $currency ]['amount'], $currency ) ) ) ), '1X214/1', 403, '' );
|
||||
Output::i()->error( Member::loggedIn()->language()->addToStack( 'err_minimum_order', FALSE, array( 'sprintf' => array( new Money( $minimumOrderAmounts[ $currency ]['amount'], $currency ) ) ) ), '1X214/1', 403, '' );
|
||||
}
|
||||
|
||||
$_SESSION['cart'] = array();
|
||||
|
||||
if ( \IPS\CACHE_PAGE_TIMEOUT and !\IPS\Member::loggedIn()->member_id )
|
||||
if ( CACHE_PAGE_TIMEOUT and !Member::loggedIn()->member_id )
|
||||
{
|
||||
\IPS\Request::i()->setCookie( 'noCache', 0, \IPS\DateTime::ts( time() - 86400 ) );
|
||||
Request::i()->setCookie( 'noCache', 0, DateTime::ts( time() - 86400 ) );
|
||||
}
|
||||
|
||||
$invoice->save();
|
||||
\IPS\Db::i()->update( 'core_attachments_map', array( 'id3' => "invoice-{$invoice->id}" ), array( 'location_key=? AND id3=?', 'nexus_Purchases', "invoice-{$tempInvoiceKey}" ) );
|
||||
Db::i()->update( 'core_attachments_map', array( 'id3' => "invoice-{$invoice->id}" ), array( 'location_key=? AND id3=?', 'nexus_Purchases', "invoice-{$tempInvoiceKey}" ) );
|
||||
|
||||
\IPS\Output::i()->redirect( $invoice->checkoutUrl() );
|
||||
Output::i()->redirect( $invoice->checkoutUrl() );
|
||||
}
|
||||
}
|
||||
@@ -12,16 +12,42 @@
|
||||
namespace IPS\nexus\modules\front\store;
|
||||
|
||||
/* To prevent PHP errors (extending class does not exist) revealing path */
|
||||
if ( !\defined( '\IPS\SUITE_UNIQUE_KEY' ) )
|
||||
|
||||
use DomainException;
|
||||
use InvalidArgumentException;
|
||||
use IPS\Dispatcher\Controller;
|
||||
use IPS\Helpers\Form;
|
||||
use IPS\Helpers\Form\Color;
|
||||
use IPS\Helpers\Form\Email;
|
||||
use IPS\Helpers\Form\Radio;
|
||||
use IPS\Helpers\Form\Text;
|
||||
use IPS\Helpers\Form\TextArea;
|
||||
use IPS\Http\Url;
|
||||
use IPS\Math\Number;
|
||||
use IPS\Member;
|
||||
use IPS\nexus\Customer;
|
||||
use IPS\nexus\extensions\nexus\Item\GiftVoucher;
|
||||
use IPS\nexus\Gateway;
|
||||
use IPS\nexus\Invoice;
|
||||
use IPS\nexus\Money;
|
||||
use IPS\Output;
|
||||
use IPS\Request;
|
||||
use IPS\Settings;
|
||||
use IPS\Theme;
|
||||
use function defined;
|
||||
use function in_array;
|
||||
use function is_numeric;
|
||||
|
||||
if ( !defined( '\IPS\SUITE_UNIQUE_KEY' ) )
|
||||
{
|
||||
header( ( isset( $_SERVER['SERVER_PROTOCOL'] ) ? $_SERVER['SERVER_PROTOCOL'] : 'HTTP/1.0' ) . ' 403 Forbidden' );
|
||||
header( ( $_SERVER['SERVER_PROTOCOL'] ?? 'HTTP/1.0' ) . ' 403 Forbidden' );
|
||||
exit;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gift Vouchers
|
||||
*/
|
||||
class _gifts extends \IPS\Dispatcher\Controller
|
||||
class gifts extends Controller
|
||||
{
|
||||
|
||||
/**
|
||||
@@ -29,15 +55,10 @@ class _gifts extends \IPS\Dispatcher\Controller
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function execute()
|
||||
public function execute() : void
|
||||
{
|
||||
\IPS\Output::i()->jsFiles = array_merge( \IPS\Output::i()->jsFiles, \IPS\Output::i()->js( 'front_store.js', 'nexus', 'front' ) );
|
||||
\IPS\Output::i()->cssFiles = array_merge( \IPS\Output::i()->cssFiles, \IPS\Theme::i()->css( 'store.css', 'nexus' ) );
|
||||
|
||||
if ( \IPS\Theme::i()->settings['responsive'] )
|
||||
{
|
||||
\IPS\Output::i()->cssFiles = array_merge( \IPS\Output::i()->cssFiles, \IPS\Theme::i()->css( 'store_responsive.css', 'nexus', 'front' ) );
|
||||
}
|
||||
Output::i()->jsFiles = array_merge( Output::i()->jsFiles, Output::i()->js( 'front_store.js', 'nexus', 'front' ) );
|
||||
Output::i()->cssFiles = array_merge( Output::i()->cssFiles, Theme::i()->css( 'store.css', 'nexus' ) );
|
||||
|
||||
parent::execute();
|
||||
}
|
||||
@@ -47,59 +68,60 @@ class _gifts extends \IPS\Dispatcher\Controller
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
protected function manage()
|
||||
protected function manage() : void
|
||||
{
|
||||
/* Work out what our options are */
|
||||
$memberCurrency = ( ( ( isset( \IPS\Request::i()->cookie['currency'] ) and \in_array( \IPS\Request::i()->cookie['currency'], \IPS\nexus\Money::currencies() ) ) and \in_array( \IPS\Request::i()->cookie['currency'], \IPS\nexus\Money::currencies() ) ) ? \IPS\Request::i()->cookie['currency'] : \IPS\nexus\Customer::loggedIn()->defaultCurrency() );
|
||||
$memberCurrency = ( ( ( isset( Request::i()->cookie['currency'] ) and in_array( Request::i()->cookie['currency'], Money::currencies() ) ) and in_array( Request::i()->cookie['currency'], Money::currencies() ) ) ? Request::i()->cookie['currency'] : Customer::loggedIn()->defaultCurrency() );
|
||||
$options = array();
|
||||
foreach ( json_decode( \IPS\Settings::i()->nexus_gift_vouchers, TRUE ) as $voucher )
|
||||
foreach ( json_decode( Settings::i()->nexus_gift_vouchers, TRUE ) as $voucher )
|
||||
{
|
||||
if ( isset( $voucher[ $memberCurrency ] ) and $voucher[ $memberCurrency ] )
|
||||
{
|
||||
$options[ $voucher[ $memberCurrency ] ] = new \IPS\nexus\Money( $voucher[ $memberCurrency ], $memberCurrency );
|
||||
$options[ $voucher[ $memberCurrency ] ] = new Money( $voucher[ $memberCurrency ], $memberCurrency );
|
||||
}
|
||||
}
|
||||
if ( \IPS\Settings::i()->nexus_gift_vouchers_free )
|
||||
if ( Settings::i()->nexus_gift_vouchers_free )
|
||||
{
|
||||
$options['x'] = \IPS\Member::loggedIn()->language()->addToStack('other');
|
||||
$options['x'] = Member::loggedIn()->language()->addToStack('other');
|
||||
}
|
||||
if ( empty( $options ) )
|
||||
{
|
||||
\IPS\Output::i()->error( 'no_module_permission', '4X213/2', 403, '' );
|
||||
Output::i()->error( 'no_module_permission', '4X213/2', 403, '' );
|
||||
}
|
||||
|
||||
$form = new \IPS\Helpers\Form( 'form', 'buy_gift_voucher' );
|
||||
$form->class = 'ipsForm_vertical';
|
||||
$form->add( new \IPS\Helpers\Form\Color( 'gift_voucher_color', '3b3b3b', FALSE ) );
|
||||
$form->add( new \IPS\Helpers\Form\Radio( 'gift_voucher_amount', NULL, TRUE, array( 'options' => $options, 'parse' => 'normal', 'userSuppliedInput' => 'x' ) ) );
|
||||
$form->add( new \IPS\Helpers\Form\Radio( 'gift_voucher_method', NULL, TRUE, array( 'options' => array( 'email' => 'email', 'print' => 'gift_voucher_print' ), 'toggles' => array( 'email' => array( 'gift_voucher_email' ) ) ) ) );
|
||||
$form->add( new \IPS\Helpers\Form\Email( 'gift_voucher_email', NULL, NULL, array(), function( $val )
|
||||
$form = new Form( 'form', 'buy_gift_voucher' );
|
||||
$form->class = 'ipsForm--vertical ipsForm--buy-gift-voucher';
|
||||
$form->add( new Color( 'gift_voucher_color', '3b3b3b', FALSE ) );
|
||||
$form->add( new Radio( 'gift_voucher_amount', NULL, TRUE, array( 'options' => $options, 'parse' => 'normal', 'userSuppliedInput' => 'x' ) ) );
|
||||
$form->add( new Radio( 'gift_voucher_method', NULL, TRUE, array( 'options' => array( 'email' => 'email', 'print' => 'gift_voucher_print' ), 'toggles' => array( 'email' => array( 'gift_voucher_email' ) ) ) ) );
|
||||
$form->add( new Email( 'gift_voucher_email', NULL, NULL, array(), function( $val )
|
||||
{
|
||||
if ( !$val and \IPS\Request::i()->gift_voucher_method === 'email' )
|
||||
if ( !$val and Request::i()->gift_voucher_method === 'email' )
|
||||
{
|
||||
throw new \DomainException('form_required');
|
||||
throw new DomainException('form_required');
|
||||
}
|
||||
}, NULL, NULL, 'gift_voucher_email' ) );
|
||||
$form->add( new \IPS\Helpers\Form\Text( 'gift_voucher_recipient' ) );
|
||||
$form->add( new \IPS\Helpers\Form\Text( 'gift_voucher_sender', \IPS\Member::loggedIn()->name ) );
|
||||
$form->add( new \IPS\Helpers\Form\TextArea( 'gift_voucher_message' ) );
|
||||
$form->add( new Text( 'gift_voucher_recipient' ) );
|
||||
$form->add( new Text( 'gift_voucher_sender', Member::loggedIn()->name ) );
|
||||
$form->add( new TextArea( 'gift_voucher_message' ) );
|
||||
|
||||
/* Handle submissions */
|
||||
if ( $values = $form->values() )
|
||||
{
|
||||
if( ! \is_numeric( $values['gift_voucher_amount'] ) )
|
||||
if( ! is_numeric( $values['gift_voucher_amount'] ) )
|
||||
{
|
||||
$form->error = \IPS\Member::loggedIn()->language()->addToStack( 'gift_voucher_invalid_value' );
|
||||
$form->error = Member::loggedIn()->language()->addToStack( 'gift_voucher_invalid_value' );
|
||||
}
|
||||
elseif( ! abs( $values['gift_voucher_amount'] ) )
|
||||
{
|
||||
$form->error = \IPS\Member::loggedIn()->language()->addToStack( 'gift_voucher_invalid_amount' );
|
||||
$form->error = Member::loggedIn()->language()->addToStack( 'gift_voucher_invalid_amount' );
|
||||
}
|
||||
|
||||
if( !$form->error )
|
||||
{
|
||||
$item = new \IPS\nexus\extensions\nexus\Item\GiftVoucher( \IPS\Member::loggedIn()->language()->get( 'gift_voucher' ), new \IPS\nexus\Money( abs( $values[ 'gift_voucher_amount' ] ), $memberCurrency ) );
|
||||
$item->paymentMethodIds = array_keys( \IPS\nexus\Gateway::roots( NULL, NULL, array( 'm_active=1 AND m_gateway<>?', 'TwoCheckout' ) ) ); // It is against 2CO terms to use them for buying gift vouchers
|
||||
$item = new GiftVoucher( Member::loggedIn()->language()->get( 'gift_voucher' ), new Money( abs( $values[ 'gift_voucher_amount' ] ), $memberCurrency ) );
|
||||
$item->paymentMethodIds = array_keys( Gateway::roots( NULL, NULL, array( 'm_active=1' ) ) );
|
||||
|
||||
$item->extra[ 'method' ] = $values[ 'gift_voucher_method' ];
|
||||
$item->extra[ 'recipient_email' ] = $values[ 'gift_voucher_email' ];
|
||||
$item->extra[ 'recipient_name' ] = $values[ 'gift_voucher_recipient' ];
|
||||
@@ -109,22 +131,22 @@ class _gifts extends \IPS\Dispatcher\Controller
|
||||
$item->extra[ 'color' ] = $values[ 'gift_voucher_color' ];
|
||||
$item->extra[ 'currency' ] = $memberCurrency;
|
||||
|
||||
$invoice = new \IPS\nexus\Invoice;
|
||||
$invoice = new Invoice;
|
||||
$invoice->currency = $memberCurrency;
|
||||
$invoice->member = \IPS\Member::loggedIn();
|
||||
$invoice->member = Customer::loggedIn();
|
||||
$invoice->addItem( $item );
|
||||
$invoice->save();
|
||||
|
||||
\IPS\Output::i()->redirect( $invoice->checkoutUrl() );
|
||||
Output::i()->redirect( $invoice->checkoutUrl() );
|
||||
}
|
||||
}
|
||||
|
||||
/* Display */
|
||||
$formTemplate = $form->customTemplate( array( \IPS\Theme::i()->getTemplate( 'store', 'nexus' ), 'giftCardForm' ) );
|
||||
$formTemplate = $form->customTemplate( array( Theme::i()->getTemplate( 'store', 'nexus' ), 'giftCardForm' ) );
|
||||
|
||||
\IPS\Output::i()->output = \IPS\Theme::i()->getTemplate('store')->giftCard( $formTemplate );
|
||||
\IPS\Output::i()->title = \IPS\Member::loggedIn()->language()->addToStack('buy_gift_voucher');
|
||||
\IPS\Output::i()->breadcrumb[] = array( NULL, \IPS\Member::loggedIn()->language()->addToStack('buy_gift_voucher') );
|
||||
Output::i()->output = Theme::i()->getTemplate('store')->giftCard( $formTemplate );
|
||||
Output::i()->title = Member::loggedIn()->language()->addToStack('buy_gift_voucher');
|
||||
Output::i()->breadcrumb[] = array( NULL, Member::loggedIn()->language()->addToStack('buy_gift_voucher') );
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -132,9 +154,9 @@ class _gifts extends \IPS\Dispatcher\Controller
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
protected function formatCurrency()
|
||||
protected function formatCurrency() : void
|
||||
{
|
||||
\IPS\Output::i()->json( (string) new \IPS\nexus\Money( \IPS\Request::i()->amount, ( ( isset( \IPS\Request::i()->cookie['currency'] ) and \in_array( \IPS\Request::i()->cookie['currency'], \IPS\nexus\Money::currencies() ) ) ? \IPS\Request::i()->cookie['currency'] : \IPS\nexus\Customer::loggedIn()->defaultCurrency() ) ) );
|
||||
Output::i()->json( (string) new Money( Request::i()->amount, ( ( isset( Request::i()->cookie['currency'] ) and in_array( Request::i()->cookie['currency'], Money::currencies() ) ) ? Request::i()->cookie['currency'] : Customer::loggedIn()->defaultCurrency() ) ) );
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -142,53 +164,53 @@ class _gifts extends \IPS\Dispatcher\Controller
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
protected function redeem()
|
||||
protected function redeem() : void
|
||||
{
|
||||
if ( !\IPS\nexus\Customer::loggedIn()->member_id )
|
||||
if ( !Customer::loggedIn()->member_id )
|
||||
{
|
||||
\IPS\Output::i()->error( 'redeem_must_be_logged_in', '1X213/1', 403, '' );
|
||||
Output::i()->error( 'redeem_must_be_logged_in', '1X213/1', 403, '' );
|
||||
}
|
||||
|
||||
$form = new \IPS\Helpers\Form( 'form', 'redeem_gift_voucher' );
|
||||
$form->add( new \IPS\Helpers\Form\Text( 'redemption_code', isset( \IPS\Request::i()->code ) ? \IPS\Request::i()->code : NULL, TRUE, array(), function( $val )
|
||||
$form = new Form( 'form', 'redeem_gift_voucher' );
|
||||
$form->add( new Text( 'redemption_code', isset( Request::i()->code ) ? Request::i()->code : NULL, TRUE, array(), function( $val )
|
||||
{
|
||||
try
|
||||
{
|
||||
\IPS\nexus\extensions\nexus\Item\GiftVoucher::getPurchase( $val );
|
||||
GiftVoucher::getPurchase( $val );
|
||||
}
|
||||
catch ( \InvalidArgumentException $e )
|
||||
catch ( InvalidArgumentException )
|
||||
{
|
||||
throw new \DomainException('redeem_gift_voucher_error');
|
||||
throw new DomainException('redeem_gift_voucher_error');
|
||||
}
|
||||
} ) );
|
||||
if ( $values = $form->values() )
|
||||
{
|
||||
$purchase = \IPS\nexus\extensions\nexus\Item\GiftVoucher::getPurchase( $values['redemption_code'] );
|
||||
$purchase = GiftVoucher::getPurchase( $values['redemption_code'] );
|
||||
$extra = $purchase->extra;
|
||||
$currency = isset( $extra['currency'] ) ? $extra['currency'] : \IPS\nexus\Customer::loggedIn()->defaultCurrency();
|
||||
$currency = isset( $extra['currency'] ) ? $extra['currency'] : Customer::loggedIn()->defaultCurrency();
|
||||
|
||||
$credits = \IPS\nexus\Customer::loggedIn()->cm_credits;
|
||||
$credits[ $currency ]->amount = $credits[ $currency ]->amount->add( new \IPS\Math\Number( number_format( $extra['amount'], \IPS\nexus\Money::numberOfDecimalsForCurrency( $currency ), '.', '' ) ) );
|
||||
\IPS\nexus\Customer::loggedIn()->cm_credits = $credits;
|
||||
\IPS\nexus\Customer::loggedIn()->save();
|
||||
$credits = Customer::loggedIn()->cm_credits;
|
||||
$credits[ $currency ]->amount = $credits[ $currency ]->amount->add( new Number( number_format( $extra['amount'], Money::numberOfDecimalsForCurrency( $currency ), '.', '' ) ) );
|
||||
Customer::loggedIn()->cm_credits = $credits;
|
||||
Customer::loggedIn()->save();
|
||||
|
||||
\IPS\nexus\Customer::loggedIn()->log( 'giftvoucher', array( 'type' => 'redeemed', 'code' => $values['redemption_code'], 'amount' => $extra['amount'], 'currency' => $extra['currency'], 'ps_member' => $purchase->member->member_id, 'newCreditAmount' => $credits[ $currency ]->amount ) );
|
||||
$purchase->member->log( 'giftvoucher', array( 'type' => 'used', 'code' => $values['redemption_code'], 'amount' => $extra['amount'], 'currency' => $extra['currency'], 'by' => \IPS\nexus\Customer::loggedIn()->member_id ) );
|
||||
Customer::loggedIn()->log( 'giftvoucher', array( 'type' => 'redeemed', 'code' => $values['redemption_code'], 'amount' => $extra['amount'], 'currency' => $extra['currency'], 'ps_member' => $purchase->member->member_id, 'newCreditAmount' => $credits[ $currency ]->amount ) );
|
||||
$purchase->member->log( 'giftvoucher', array( 'type' => 'used', 'code' => $values['redemption_code'], 'amount' => $extra['amount'], 'currency' => $extra['currency'], 'by' => Customer::loggedIn()->member_id ) );
|
||||
|
||||
$purchase->delete();
|
||||
|
||||
\IPS\Output::i()->redirect( \IPS\Http\Url::internal( "app=nexus&module=store&controller=store¤cy={$currency}", 'front', 'store' ) );
|
||||
Output::i()->redirect( Url::internal( "app=nexus&module=store&controller=store¤cy={$currency}", 'front', 'store' ) );
|
||||
}
|
||||
|
||||
if( \IPS\Request::i()->isAjax() )
|
||||
if( Request::i()->isAjax() )
|
||||
{
|
||||
$form->class = 'ipsForm_vertical';
|
||||
\IPS\Output::i()->output = $form->customTemplate( array( \IPS\Theme::i()->getTemplate( 'forms', 'core', 'front' ), 'popupTemplate' ) );
|
||||
$form->class = 'ipsForm--vertical ipsForm--redeem-voucher';
|
||||
Output::i()->output = $form->customTemplate( array( Theme::i()->getTemplate( 'forms', 'core', 'front' ), 'popupTemplate' ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
\IPS\Output::i()->title = \IPS\Member::loggedIn()->language()->addToStack( 'redemption_code' );
|
||||
\IPS\Output::i()->output = $form;
|
||||
Output::i()->title = Member::loggedIn()->language()->addToStack( 'redemption_code' );
|
||||
Output::i()->output = $form;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -12,38 +12,66 @@
|
||||
namespace IPS\nexus\modules\front\store;
|
||||
|
||||
/* To prevent PHP errors (extending class does not exist) revealing path */
|
||||
if ( !\defined( '\IPS\SUITE_UNIQUE_KEY' ) )
|
||||
|
||||
use DateInterval;
|
||||
use IPS\Content\Controller;
|
||||
use IPS\core\Facebook\Pixel;
|
||||
use IPS\Db;
|
||||
use IPS\Helpers\Form;
|
||||
use IPS\Helpers\Form\Radio;
|
||||
use IPS\Helpers\Form\Select;
|
||||
use IPS\Helpers\Form\Upload;
|
||||
use IPS\Http\Url;
|
||||
use IPS\Math\Number;
|
||||
use IPS\Member;
|
||||
use IPS\nexus\Customer;
|
||||
use IPS\nexus\Money;
|
||||
use IPS\nexus\Package;
|
||||
use IPS\nexus\Package\CustomField;
|
||||
use IPS\nexus\Package\Item;
|
||||
use IPS\nexus\Purchase;
|
||||
use IPS\nexus\Purchase\RenewalTerm;
|
||||
use IPS\nexus\Tax;
|
||||
use IPS\Output;
|
||||
use IPS\Patterns\ActiveRecordIterator;
|
||||
use IPS\Request;
|
||||
use IPS\Session;
|
||||
use IPS\Settings;
|
||||
use IPS\Theme;
|
||||
use OutOfBoundsException;
|
||||
use OutOfRangeException;
|
||||
use UnderflowException;
|
||||
use function count;
|
||||
use function defined;
|
||||
use function in_array;
|
||||
|
||||
if ( !defined( '\IPS\SUITE_UNIQUE_KEY' ) )
|
||||
{
|
||||
header( ( isset( $_SERVER['SERVER_PROTOCOL'] ) ? $_SERVER['SERVER_PROTOCOL'] : 'HTTP/1.0' ) . ' 403 Forbidden' );
|
||||
header( ( $_SERVER['SERVER_PROTOCOL'] ?? 'HTTP/1.0' ) . ' 403 Forbidden' );
|
||||
exit;
|
||||
}
|
||||
|
||||
/**
|
||||
* View product
|
||||
*/
|
||||
class _product extends \IPS\Content\Controller
|
||||
class product extends Controller
|
||||
{
|
||||
/**
|
||||
* [Content\Controller] Class
|
||||
*/
|
||||
protected static $contentModel = 'IPS\nexus\Package\Item';
|
||||
protected static string $contentModel = 'IPS\nexus\Package\Item';
|
||||
|
||||
/**
|
||||
* Execute
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function execute()
|
||||
public function execute() : void
|
||||
{
|
||||
\IPS\Output::i()->jsFiles = array_merge( \IPS\Output::i()->jsFiles, \IPS\Output::i()->js( 'front_store.js', 'nexus', 'front' ) );
|
||||
\IPS\Output::i()->cssFiles = array_merge( \IPS\Output::i()->cssFiles, \IPS\Theme::i()->css( 'store.css', 'nexus' ) );
|
||||
|
||||
if ( \IPS\Theme::i()->settings['responsive'] )
|
||||
{
|
||||
\IPS\Output::i()->cssFiles = array_merge( \IPS\Output::i()->cssFiles, \IPS\Theme::i()->css( 'store_responsive.css', 'nexus', 'front' ) );
|
||||
}
|
||||
|
||||
\IPS\Output::setCacheTime( false );
|
||||
Output::i()->jsFiles = array_merge( Output::i()->jsFiles, Output::i()->js( 'front_store.js', 'nexus', 'front' ) );
|
||||
Output::i()->cssFiles = array_merge( Output::i()->cssFiles, Theme::i()->css( 'store.css', 'nexus' ) );
|
||||
|
||||
Output::i()->pageCaching = FALSE;
|
||||
|
||||
parent::execute();
|
||||
}
|
||||
@@ -51,24 +79,24 @@ class _product extends \IPS\Content\Controller
|
||||
/**
|
||||
* View
|
||||
*
|
||||
* @return void
|
||||
* @return mixed
|
||||
*/
|
||||
protected function manage()
|
||||
protected function manage() : mixed
|
||||
{
|
||||
/* Init */
|
||||
if ( !isset( $_SESSION['cart'] ) )
|
||||
{
|
||||
$_SESSION['cart'] = array();
|
||||
}
|
||||
$memberCurrency = ( ( isset( \IPS\Request::i()->cookie['currency'] ) and \in_array( \IPS\Request::i()->cookie['currency'], \IPS\nexus\Money::currencies() ) ) ? \IPS\Request::i()->cookie['currency'] : \IPS\nexus\Customer::loggedIn()->defaultCurrency() );
|
||||
$memberCurrency = ( ( isset( Request::i()->cookie['currency'] ) and in_array( Request::i()->cookie['currency'], Money::currencies() ) ) ? Request::i()->cookie['currency'] : Customer::loggedIn()->defaultCurrency() );
|
||||
|
||||
/* Load Package */
|
||||
$item = parent::manage();
|
||||
if ( !$item )
|
||||
{
|
||||
\IPS\Output::i()->error( 'node_error', '2X240/1', 404, '' );
|
||||
Output::i()->error( 'node_error', '2X240/1', 404, '' );
|
||||
}
|
||||
$package = \IPS\nexus\Package::load( $item->id );
|
||||
$package = Package::load( $item->id );
|
||||
|
||||
/* Do we have any in the cart already (this will affect stock level)? */
|
||||
$inCart = array();
|
||||
@@ -91,100 +119,25 @@ class _product extends \IPS\Content\Controller
|
||||
}
|
||||
|
||||
/* Showing just the form to purchase, or full product page? */
|
||||
if ( \IPS\Request::i()->purchase )
|
||||
if ( Request::i()->purchase )
|
||||
{
|
||||
\IPS\Output::i()->output = \IPS\Theme::i()->getTemplate('store')->purchaseForm( $package, $item, $this->_getForm( $package, $inCart, TRUE ) );
|
||||
Output::i()->output = Theme::i()->getTemplate('store')->purchaseForm( $package, $item, $this->_getForm( $package, $inCart, TRUE ) );
|
||||
}
|
||||
|
||||
/* No - show the full page */
|
||||
else
|
||||
{
|
||||
/* We need to create a dummy item so we can work out ship times/prices */
|
||||
$itemDataForShipping = NULL;
|
||||
if ( $package->physical )
|
||||
{
|
||||
try
|
||||
{
|
||||
$itemDataForShipping = $package->createItemForCart( $package->price() );
|
||||
}
|
||||
catch ( \OutOfBoundsException $e ) { }
|
||||
}
|
||||
|
||||
/* If physical, get available shipping methods */
|
||||
$shippingMethods = array();
|
||||
$locationType = 'none';
|
||||
if ( $package->physical )
|
||||
{
|
||||
/* Where are we shipping to? */
|
||||
$shipAddress = NULL;
|
||||
if ( \IPS\Member::loggedIn()->member_id and $primaryBillingAddress = \IPS\nexus\Customer::loggedIn()->primaryBillingAddress() )
|
||||
{
|
||||
$shipAddress = $primaryBillingAddress;
|
||||
$locationType = 'address';
|
||||
}
|
||||
if ( !$shipAddress )
|
||||
{
|
||||
try
|
||||
{
|
||||
$shipAddress = \IPS\GeoLocation::getRequesterLocation();
|
||||
$locationType = 'geo';
|
||||
}
|
||||
catch ( \Exception $e ) { }
|
||||
}
|
||||
|
||||
/* Standard */
|
||||
$where = NULL;
|
||||
if ( $package->shipping != '*' )
|
||||
{
|
||||
$where = \IPS\Db::i()->in( 's_id', explode( ',', $package->shipping ) );
|
||||
}
|
||||
foreach ( \IPS\nexus\Shipping\FlatRate::roots( NULL, NULL, $where ) as $rate )
|
||||
{
|
||||
if ( ( $shipAddress and $rate->isAvailable( $shipAddress, array( $itemDataForShipping ), $memberCurrency ) ) or ( $rate->locations === '*' ) )
|
||||
{
|
||||
$shippingMethods[] = $rate;
|
||||
}
|
||||
}
|
||||
|
||||
/* Easypost */
|
||||
if ( $shipAddress and \IPS\Settings::i()->easypost_api_key and \IPS\Settings::i()->easypost_show_rates and ( $package->shipping == '*' or \in_array( 'easypost', explode( ',', $package->shipping ) ) ) )
|
||||
{
|
||||
try
|
||||
{
|
||||
$fromAddress = \IPS\GeoLocation::buildFromJson( \IPS\Settings::i()->easypost_address ?: \IPS\Settings::i()->site_address );
|
||||
|
||||
$length = new \IPS\nexus\Shipping\Length( $package->length );
|
||||
$width = new \IPS\nexus\Shipping\Length( $package->width );
|
||||
$height = new \IPS\nexus\Shipping\Length( $package->height );
|
||||
$weight = new \IPS\nexus\Shipping\Weight( $package->weight );
|
||||
|
||||
$easyPost = \IPS\nexus\Shipping\EasyPostRate::getRates( $length->float('in'), $width->float('in'), $height->float('in'), $weight->float('oz'), \IPS\nexus\Customer::loggedIn(), $shipAddress, $memberCurrency );
|
||||
if ( isset( $easyPost['rates'] ) )
|
||||
{
|
||||
foreach ( $easyPost['rates'] as $rate )
|
||||
{
|
||||
if ( $rate['currency'] === $memberCurrency )
|
||||
{
|
||||
$shippingMethods[] = new \IPS\nexus\Shipping\EasyPostRate( $rate );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch ( \IPS\Http\Request\Exception $e ) { }
|
||||
}
|
||||
}
|
||||
|
||||
/* Do we have renewal terms? */
|
||||
$renewalTerm = NULL;
|
||||
$renewOptions = $package->renew_options ? json_decode( $package->renew_options, TRUE ) : array();
|
||||
$initialTerm = NULL;
|
||||
if ( \count( $renewOptions ) )
|
||||
if ( count( $renewOptions ) )
|
||||
{
|
||||
$renewalTerm = TRUE;
|
||||
if ( \count( $renewOptions ) === 1 )
|
||||
if ( count( $renewOptions ) === 1 )
|
||||
{
|
||||
$renewalTerm = array_pop( $renewOptions );
|
||||
$renewalTerm = new \IPS\nexus\Purchase\RenewalTerm( new \IPS\nexus\Money( $renewalTerm['cost'][ $memberCurrency ]['amount'], $memberCurrency ), new \DateInterval( 'P' . $renewalTerm['term'] . mb_strtoupper( $renewalTerm['unit'] ) ), $package->tax ? \IPS\nexus\Tax::load( $package->tax ) : NULL, $renewalTerm['add'] );
|
||||
$renewalTerm = new RenewalTerm( new Money( $renewalTerm['cost'][ $memberCurrency ]['amount'], $memberCurrency ), new DateInterval( 'P' . $renewalTerm['term'] . mb_strtoupper( $renewalTerm['unit'] ) ), $package->tax ? Tax::load( $package->tax ) : NULL, $renewalTerm['add'] );
|
||||
}
|
||||
if ( $package->initial_term )
|
||||
{
|
||||
@@ -192,13 +145,13 @@ class _product extends \IPS\Content\Controller
|
||||
switch( mb_substr( $package->initial_term, -1 ) )
|
||||
{
|
||||
case 'D':
|
||||
$initialTerm = \IPS\Member::loggedIn()->language()->pluralize( \IPS\Member::loggedIn()->language()->get('renew_days'), array( $term ) );
|
||||
$initialTerm = Member::loggedIn()->language()->pluralize( Member::loggedIn()->language()->get('renew_days'), array( $term ) );
|
||||
break;
|
||||
case 'M':
|
||||
$initialTerm = \IPS\Member::loggedIn()->language()->pluralize( \IPS\Member::loggedIn()->language()->get('renew_months'), array( $term ) );
|
||||
$initialTerm = Member::loggedIn()->language()->pluralize( Member::loggedIn()->language()->get('renew_months'), array( $term ) );
|
||||
break;
|
||||
case 'Y':
|
||||
$initialTerm = \IPS\Member::loggedIn()->language()->pluralize( \IPS\Member::loggedIn()->language()->get('renew_years'), array( $term ) );
|
||||
$initialTerm = Member::loggedIn()->language()->pluralize( Member::loggedIn()->language()->get('renew_years'), array( $term ) );
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -206,29 +159,29 @@ class _product extends \IPS\Content\Controller
|
||||
|
||||
/* Display */
|
||||
$formKey = "package_{$package->id}_submitted";
|
||||
if ( \IPS\Request::i()->isAjax() and isset( \IPS\Request::i()->$formKey ) )
|
||||
if ( Request::i()->isAjax() and isset( Request::i()->$formKey ) )
|
||||
{
|
||||
\IPS\Output::i()->sendOutput( $this->_getForm( $package, $inCart, TRUE ), 500 );
|
||||
Output::i()->sendOutput( $this->_getForm( $package, $inCart, TRUE ), 500 );
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Set default search */
|
||||
\IPS\Output::i()->defaultSearchOption = array( 'nexus_package_item', "nexus_package_item_el" );
|
||||
Output::i()->defaultSearchOption = array( 'nexus_package_item', "nexus_package_item_el" );
|
||||
|
||||
\IPS\Output::i()->output = \IPS\Theme::i()->getTemplate('store')->package( $package, $item, $this->_getForm( $package, $inCart, TRUE ), array_sum( $inCart ), $shippingMethods, $itemDataForShipping, $locationType, $renewalTerm, $initialTerm );
|
||||
Output::i()->output = Theme::i()->getTemplate('store')->package( $package, $item, $this->_getForm( $package, $inCart, TRUE ), array_sum( $inCart ), $renewalTerm, $initialTerm );
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
$price = $package->price();
|
||||
}
|
||||
catch( \OutOfBoundsException $e )
|
||||
catch( OutOfBoundsException )
|
||||
{
|
||||
$price = NULL;
|
||||
}
|
||||
|
||||
/* Facebook Pixel */
|
||||
\IPS\core\Facebook\Pixel::i()->ViewContent = array(
|
||||
Pixel::i()->ViewContent = array(
|
||||
'content_ids' => array( $package->id ),
|
||||
'content_type' => 'product'
|
||||
);
|
||||
@@ -236,8 +189,8 @@ class _product extends \IPS\Content\Controller
|
||||
/* A product MUST have an offer, so if there's no price (i.e. due to currency configuration) don't even output */
|
||||
if( $price !== NULL )
|
||||
{
|
||||
\IPS\Output::i()->jsonLd['package'] = array(
|
||||
'@context' => "http://schema.org",
|
||||
Output::i()->jsonLd['package'] = array(
|
||||
'@context' => "https://schema.org",
|
||||
'@type' => "Product",
|
||||
'name' => $package->_title,
|
||||
'description' => $item->truncated( TRUE, NULL ),
|
||||
@@ -250,80 +203,70 @@ class _product extends \IPS\Content\Controller
|
||||
'priceCurrency' => $price->currency,
|
||||
'seller' => array(
|
||||
'@type' => 'Organization',
|
||||
'name' => \IPS\Settings::i()->board_name
|
||||
'name' => Settings::i()->board_name
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
/* Stock status */
|
||||
if( $package->physical )
|
||||
if( $package->stockLevel() === 0 )
|
||||
{
|
||||
if( $package->stockLevel() === 0 )
|
||||
{
|
||||
\IPS\Output::i()->jsonLd['package']['offers']['availability'] = 'http://schema.org/OutOfStock';
|
||||
}
|
||||
else
|
||||
{
|
||||
\IPS\Output::i()->jsonLd['package']['offers']['availability'] = 'http://schema.org/InStock';
|
||||
}
|
||||
Output::i()->jsonLd['package']['offers']['availability'] = 'https://schema.org/OutOfStock';
|
||||
}
|
||||
else
|
||||
{
|
||||
Output::i()->jsonLd['package']['offers']['availability'] = 'https://schema.org/InStock';
|
||||
}
|
||||
|
||||
if( $package->image )
|
||||
{
|
||||
\IPS\Output::i()->jsonLd['package']['image'] = (string) $package->image;
|
||||
\IPS\Output::i()->metaTags['og:image'] = (string)$package->image;
|
||||
Output::i()->jsonLd['package']['image'] = (string) $package->image;
|
||||
Output::i()->metaTags['og:image'] = (string)$package->image;
|
||||
}
|
||||
|
||||
if( $package->reviewable AND $item->averageReviewRating() )
|
||||
{
|
||||
\IPS\Output::i()->jsonLd['package']['aggregateRating'] = array(
|
||||
Output::i()->jsonLd['package']['aggregateRating'] = array(
|
||||
'@type' => 'AggregateRating',
|
||||
'ratingValue' => $item->averageReviewRating(),
|
||||
'ratingCount' => $item->reviews
|
||||
);
|
||||
}
|
||||
|
||||
if( isset( $length ) )
|
||||
{
|
||||
\IPS\Output::i()->jsonLd['package']['depth'] = array( '@type' => 'Distance', 'name' => $length->string() );
|
||||
\IPS\Output::i()->jsonLd['package']['width'] = array( '@type' => 'Distance', 'name' => $width->string() );
|
||||
\IPS\Output::i()->jsonLd['package']['height'] = array( '@type' => 'Distance', 'name' => $height->string() );
|
||||
\IPS\Output::i()->jsonLd['package']['weight'] = array( '@type' => 'QuantitativeValue', 'name' => $weight->string() );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get form
|
||||
*
|
||||
* @param \IPS\nexus\Package $package The package
|
||||
* @param Package $package The package
|
||||
* @param array $inCart The number in the cart already for each of the field combinations
|
||||
* @param bool $verticalForm Whether to output a vertical form (true) or not
|
||||
* @return string
|
||||
*/
|
||||
protected function _getForm( \IPS\nexus\Package $package, $inCart, $verticalForm = FALSE )
|
||||
protected function _getForm( Package $package, array $inCart, bool $verticalForm = FALSE ) : string
|
||||
{
|
||||
/* Is this a subscription package that we've already bought? */
|
||||
if ( $package->subscription )
|
||||
{
|
||||
try
|
||||
{
|
||||
$purchase = \IPS\nexus\Purchase::constructFromData( \IPS\Db::i()->select( '*', 'nexus_purchases', array( 'ps_app=? AND ps_type=? AND ps_item_id=? AND ps_cancelled=0 AND ps_member=?', 'nexus', 'package', $package->id, \IPS\Member::loggedIn()->member_id ) )->first() );
|
||||
return \IPS\Theme::i()->getTemplate( 'store', 'nexus' )->subscriptionPurchase( $purchase );
|
||||
$purchase = Purchase::constructFromData( Db::i()->select( '*', 'nexus_purchases', array( 'ps_app=? AND ps_type=? AND ps_item_id=? AND ps_cancelled=0 AND ps_member=?', 'nexus', 'package', $package->id, Member::loggedIn()->member_id ) )->first() );
|
||||
return Theme::i()->getTemplate( 'store', 'nexus' )->subscriptionPurchase( $purchase );
|
||||
}
|
||||
catch ( \UnderflowException $e ) {}
|
||||
catch ( UnderflowException ) {}
|
||||
}
|
||||
|
||||
/* Get member's currency */
|
||||
$memberCurrency = ( ( isset( \IPS\Request::i()->cookie['currency'] ) and \in_array( \IPS\Request::i()->cookie['currency'], \IPS\nexus\Money::currencies() ) ) ? \IPS\Request::i()->cookie['currency'] : \IPS\nexus\Customer::loggedIn()->defaultCurrency() );
|
||||
$memberCurrency = ( ( isset( Request::i()->cookie['currency'] ) and in_array( Request::i()->cookie['currency'], Money::currencies() ) ) ? Request::i()->cookie['currency'] : Customer::loggedIn()->defaultCurrency() );
|
||||
|
||||
/* Init form */
|
||||
$form = new \IPS\Helpers\Form( "package_{$package->id}", 'add_to_cart' );
|
||||
$form = new Form( "package_{$package->id}", 'add_to_cart' );
|
||||
|
||||
if ( $verticalForm )
|
||||
{
|
||||
$form->class = 'ipsForm_vertical';
|
||||
$form->class = 'ipsForm--vertical ipsForm--add-to-cart';
|
||||
}
|
||||
|
||||
/* Package-dependant fields */
|
||||
@@ -333,7 +276,7 @@ class _product extends \IPS\Content\Controller
|
||||
if ( $package->stock != -1 and $package->stock != -2 and ( $package->stock - array_sum( $inCart ) ) <= 0 )
|
||||
{
|
||||
$form->actionButtons = array();
|
||||
$form->addButton( 'out_of_stock', 'submit', NULL, 'ipsButton ipsButton_primary', array( 'disabled' => 'disabled' ) );
|
||||
$form->addButton( 'out_of_stock', 'submit', NULL, 'ipsButton ipsButton--primary', array( 'disabled' => 'disabled' ) );
|
||||
}
|
||||
|
||||
/* And is it available for our currency */
|
||||
@@ -343,28 +286,28 @@ class _product extends \IPS\Content\Controller
|
||||
{
|
||||
$price = $package->price();
|
||||
}
|
||||
catch ( \OutOfBoundsException $e )
|
||||
catch ( OutOfBoundsException )
|
||||
{
|
||||
$form->actionButtons = array();
|
||||
$form->addButton( 'currently_unavailable', 'submit', NULL, 'ipsButton ipsButton_primary', array( 'disabled' => 'disabled' ) );
|
||||
$form->addButton( 'currently_unavailable', 'submit', NULL, 'ipsButton ipsButton--primary', array( 'disabled' => 'disabled' ) );
|
||||
}
|
||||
}
|
||||
|
||||
/* Associate */
|
||||
if ( \count( $package->associablePackages() ) )
|
||||
if ( count( $package->associablePackages() ) )
|
||||
{
|
||||
$associableIds = array_keys( $package->associablePackages() );
|
||||
$associableOptions = array();
|
||||
foreach ( $_SESSION['cart'] as $k => $item )
|
||||
{
|
||||
if ( \in_array( $item->id, $associableIds ) )
|
||||
if ( in_array( $item->id, $associableIds ) )
|
||||
{
|
||||
for ( $i = 0; $i < $item->quantity; $i++ )
|
||||
{
|
||||
$name = $item->name;
|
||||
if ( \count( $item->details ) )
|
||||
if ( count( $item->details ) )
|
||||
{
|
||||
$customFields = \IPS\nexus\Package\CustomField::roots();
|
||||
$customFields = CustomField::roots();
|
||||
$stickyFields = array();
|
||||
foreach ( $item->details as $_k => $v )
|
||||
{
|
||||
@@ -373,7 +316,7 @@ class _product extends \IPS\Content\Controller
|
||||
$stickyFields[] = $v;
|
||||
}
|
||||
}
|
||||
if ( \count( $stickyFields ) )
|
||||
if ( count( $stickyFields ) )
|
||||
{
|
||||
$name .= ' (' . implode( ' · ', $stickyFields ) . ')';
|
||||
}
|
||||
@@ -382,7 +325,7 @@ class _product extends \IPS\Content\Controller
|
||||
}
|
||||
}
|
||||
}
|
||||
foreach ( new \IPS\Patterns\ActiveRecordIterator( \IPS\Db::i()->select( '*', 'nexus_purchases', array( array( 'ps_member=? AND ps_app=? AND ps_type=?', \IPS\nexus\Customer::loggedIn()->member_id, 'nexus', 'package' ), \IPS\Db::i()->in( 'ps_item_id', $associableIds ) ) ), 'IPS\nexus\Purchase' ) as $purchase )
|
||||
foreach ( new ActiveRecordIterator( Db::i()->select( '*', 'nexus_purchases', array( array( 'ps_member=? AND ps_app=? AND ps_type=?', Customer::loggedIn()->member_id, 'nexus', 'package' ), Db::i()->in( 'ps_item_id', $associableIds ) ) ), 'IPS\nexus\Purchase' ) as $purchase )
|
||||
{
|
||||
$associableOptions['existing_purchases']["1.{$purchase->id}"] = $purchase->name;
|
||||
}
|
||||
@@ -393,24 +336,24 @@ class _product extends \IPS\Content\Controller
|
||||
{
|
||||
array_unshift( $associableOptions, 'do_not_associate' );
|
||||
}
|
||||
$form->add( new \IPS\Helpers\Form\Select( 'associate_with', NULL, $package->force_assoc, array( 'options' => $associableOptions ) ) );
|
||||
$form->add( new Select( 'associate_with', NULL, $package->force_assoc, array( 'options' => $associableOptions ) ) );
|
||||
}
|
||||
elseif ( $package->force_assoc )
|
||||
{
|
||||
return \IPS\Member::loggedIn()->language()->addToStack("nexus_package_{$package->id}_assoc");
|
||||
return Member::loggedIn()->language()->addToStack("nexus_package_{$package->id}_assoc");
|
||||
}
|
||||
}
|
||||
|
||||
/* Renewal options */
|
||||
$renewOptions = $package->renew_options ? json_decode( $package->renew_options, TRUE ) : array();
|
||||
if ( \count( $renewOptions ) > 1 )
|
||||
if ( count( $renewOptions ) > 1 )
|
||||
{
|
||||
$sortedRenewOptions = array();
|
||||
foreach ( $renewOptions as $k => $option )
|
||||
{
|
||||
if ( isset( $renewOptions[ $k ]['cost'][ $memberCurrency ] ) )
|
||||
if ( isset( $option['cost'][ $memberCurrency ] ) )
|
||||
{
|
||||
$sortedRenewOptions[ $k ] = new \IPS\nexus\Purchase\RenewalTerm( new \IPS\nexus\Money( $option['cost'][ $memberCurrency ]['amount'], $memberCurrency ), new \DateInterval( 'P' . $option['term'] . mb_strtoupper( $option['unit'] ) ), $package->tax ? \IPS\nexus\Tax::load( $package->tax ) : NULL, $option['add'], $package->grace_period ? new \DateInterval( 'P' . $package->grace_period . 'D' ) : NULL );
|
||||
$sortedRenewOptions[ $k ] = new RenewalTerm( new Money( $option['cost'][ $memberCurrency ]['amount'], $memberCurrency ), new DateInterval( 'P' . $option['term'] . mb_strtoupper( $option['unit'] ) ), $package->tax ? Tax::load( $package->tax ) : NULL, $option['add'], $package->grace_period ? new DateInterval( 'P' . $package->grace_period . 'D' ) : NULL );
|
||||
}
|
||||
}
|
||||
uasort( $sortedRenewOptions, function( $a, $b ) {
|
||||
@@ -422,7 +365,7 @@ class _product extends \IPS\Content\Controller
|
||||
foreach ( $sortedRenewOptions as $k => $term )
|
||||
{
|
||||
$saving = NULL;
|
||||
if ( \IPS\Settings::i()->nexus_show_renew_option_savings != 'none' )
|
||||
if ( Settings::i()->nexus_show_renew_option_savings != 'none' )
|
||||
{
|
||||
if ( $first === NULL )
|
||||
{
|
||||
@@ -430,19 +373,19 @@ class _product extends \IPS\Content\Controller
|
||||
}
|
||||
else
|
||||
{
|
||||
$saving = $term->diff( $first, \IPS\Settings::i()->nexus_show_renew_option_savings == 'percent' );
|
||||
$saving = $term->diff( $first, Settings::i()->nexus_show_renew_option_savings == 'percent' );
|
||||
}
|
||||
}
|
||||
|
||||
if ( $saving and ( ( \IPS\Settings::i()->nexus_show_renew_option_savings == 'percent' and $saving->isGreaterThanZero() ) or ( \IPS\Settings::i()->nexus_show_renew_option_savings == 'amount' and $saving->amount->isGreaterThanZero() ) ) )
|
||||
if ( $saving and ( ( Settings::i()->nexus_show_renew_option_savings == 'percent' and $saving->isGreaterThanZero() ) or ( Settings::i()->nexus_show_renew_option_savings == 'amount' and $saving->amount->isGreaterThanZero() ) ) )
|
||||
{
|
||||
if ( \IPS\Settings::i()->nexus_show_renew_option_savings == 'percent' )
|
||||
if ( Settings::i()->nexus_show_renew_option_savings == 'percent' )
|
||||
{
|
||||
$options[ $k ] = \IPS\Member::loggedIn()->language()->addToStack( 'renewal_amount_with_pc_saving', FALSE, array( 'sprintf' => array( $term->toDisplay(), $saving->round(1) ) ) );
|
||||
$options[ $k ] = Member::loggedIn()->language()->addToStack( 'renewal_amount_with_pc_saving', FALSE, array( 'sprintf' => array( $term->toDisplay(), $saving->round(1) ) ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
$options[ $k ] = \IPS\Member::loggedIn()->language()->addToStack( 'renewal_amount_with_cost_saving', FALSE, array( 'sprintf' => array( $term->toDisplay(), $saving ) ) );
|
||||
$options[ $k ] = Member::loggedIn()->language()->addToStack( 'renewal_amount_with_cost_saving', FALSE, array( 'sprintf' => array( $term->toDisplay(), $saving ) ) );
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -453,14 +396,15 @@ class _product extends \IPS\Content\Controller
|
||||
|
||||
ksort( $options );
|
||||
|
||||
$form->add( new \IPS\Helpers\Form\Radio( 'renewal_term', NULL, TRUE, array( 'options' => $options ) ) );
|
||||
$form->add( new Radio( 'renewal_term', NULL, TRUE, array( 'options' => $options ) ) );
|
||||
}
|
||||
|
||||
/* Custom Fields */
|
||||
$customFields = \IPS\nexus\Package\CustomField::roots( NULL, NULL, array( array( 'cf_purchase=1' ), array( \IPS\Db::i()->findInSet( 'cf_packages', array( $package->id ) ) ) ) );
|
||||
$customFields = CustomField::roots( NULL, NULL, array( array( 'cf_purchase=1' ), array( Db::i()->findInSet( 'cf_packages', array( $package->id ) ) ) ) );
|
||||
foreach ( $customFields as $field )
|
||||
{
|
||||
if( \IPS\Request::i()->isAjax() && isset( \IPS\Request::i()->stockCheck ) )
|
||||
/* @var CustomField $field */
|
||||
if( Request::i()->isAjax() && isset( Request::i()->stockCheck ) )
|
||||
{
|
||||
$field->required = FALSE; // Otherwise a required text field (for example) can block the price changing when a different radio (for example) value is selected
|
||||
}
|
||||
@@ -469,12 +413,12 @@ class _product extends \IPS\Content\Controller
|
||||
}
|
||||
|
||||
/* Is this the validation for the additional page? */
|
||||
if ( \IPS\Request::i()->isAjax() and isset( \IPS\Request::i()->additionalPageCheck ) )
|
||||
if ( Request::i()->isAjax() and isset( Request::i()->additionalPageCheck ) )
|
||||
{
|
||||
if ( $additionalPage = $package->storeAdditionalPage( $_POST ) )
|
||||
{
|
||||
\IPS\Output::i()->httpHeaders['X-IPS-FormNoSubmit'] = "true";
|
||||
\IPS\Output::i()->json( $additionalPage );
|
||||
Output::i()->httpHeaders['X-IPS-FormNoSubmit'] = "true";
|
||||
Output::i()->json( $additionalPage );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -489,7 +433,7 @@ class _product extends \IPS\Content\Controller
|
||||
if ( isset( $values[ 'nexus_pfield_' . $field->id ] ) )
|
||||
{
|
||||
$class = $field->buildHelper();
|
||||
if ( $class instanceof \IPS\Helpers\Form\Upload )
|
||||
if ( $class instanceof Upload )
|
||||
{
|
||||
$details[ $field->id ] = (string) $values[ 'nexus_pfield_' . $field->id ];
|
||||
}
|
||||
@@ -498,10 +442,10 @@ class _product extends \IPS\Content\Controller
|
||||
$details[ $field->id ] = $class::stringValue( $values[ 'nexus_pfield_' . $field->id ] );
|
||||
}
|
||||
|
||||
if ( !isset( \IPS\Request::i()->stockCheck ) and $field->type === 'Editor' )
|
||||
if ( !isset( Request::i()->stockCheck ) and $field->type === 'Editor' )
|
||||
{
|
||||
$uploadId = \IPS\Db::i()->insert( 'nexus_cart_uploads', array(
|
||||
'session_id' => \IPS\Session::i()->id,
|
||||
$uploadId = Db::i()->insert( 'nexus_cart_uploads', array(
|
||||
'session_id' => Session::i()->id,
|
||||
'time' => time()
|
||||
) );
|
||||
$field->claimAttachments( $uploadId, 'cart' );
|
||||
@@ -512,18 +456,18 @@ class _product extends \IPS\Content\Controller
|
||||
$optionValues = $package->optionValues( $details );
|
||||
|
||||
/* Stock check */
|
||||
$quantity = isset( $values['quantity'] ) ? $values['quantity'] : 1;
|
||||
$quantity = $values['quantity'] ?? 1;
|
||||
try
|
||||
{
|
||||
$data = $package->optionValuesStockAndPrice( $optionValues, TRUE );
|
||||
}
|
||||
catch ( \UnderflowException $e )
|
||||
catch ( UnderflowException )
|
||||
{
|
||||
\IPS\Output::i()->error( 'product_options_price_error', '3X240/2', 500, 'product_options_price_error_admin' );
|
||||
Output::i()->error( 'product_options_price_error', '3X240/2', 500, 'product_options_price_error_admin' );
|
||||
}
|
||||
$inCartForThisFieldCombination = isset( $inCart[ json_encode( $optionValues ) ] ) ? $inCart[ json_encode( $optionValues ) ] : 0;
|
||||
|
||||
if ( \IPS\Request::i()->isAjax() && isset( \IPS\Request::i()->stockCheck ) )
|
||||
if ( Request::i()->isAjax() && isset( Request::i()->stockCheck ) )
|
||||
{
|
||||
/* Stock */
|
||||
if ( $data['stock'] == -1 )
|
||||
@@ -536,8 +480,8 @@ class _product extends \IPS\Content\Controller
|
||||
else
|
||||
{
|
||||
$return = array(
|
||||
'stock' => \IPS\Member::loggedIn()->language()->addToStack( 'x_in_stock', FALSE, array( 'pluralize' => array( $data['stock'] - $inCartForThisFieldCombination ) ) ),
|
||||
'okay' => ( $data['stock'] - $inCartForThisFieldCombination > 0 ) ? true : false,
|
||||
'stock' => Member::loggedIn()->language()->addToStack( 'x_in_stock', FALSE, array( 'pluralize' => array( $data['stock'] - $inCartForThisFieldCombination ) ) ),
|
||||
'okay' => ( $data['stock'] - $inCartForThisFieldCombination > 0 ),
|
||||
);
|
||||
}
|
||||
|
||||
@@ -549,36 +493,36 @@ class _product extends \IPS\Content\Controller
|
||||
$renewOptions = $package->renew_options ? json_decode( $package->renew_options, TRUE ) : array();
|
||||
if ( !empty( $renewOptions ) )
|
||||
{
|
||||
$term = ( isset( \IPS\Request::i()->renewal_term ) and isset( $renewOptions[ \IPS\Request::i()->renewal_term ] ) ) ? $renewOptions[ \IPS\Request::i()->renewal_term ] : array_shift( $renewOptions );
|
||||
$term = ( isset( Request::i()->renewal_term ) and isset( $renewOptions[ Request::i()->renewal_term ] ) ) ? $renewOptions[ Request::i()->renewal_term ] : array_shift( $renewOptions );
|
||||
|
||||
switch( $term['unit'] )
|
||||
{
|
||||
case 'd':
|
||||
$initialTerm = \IPS\Member::loggedIn()->language()->pluralize( \IPS\Member::loggedIn()->language()->get('renew_days'), array( $term['term'] ) );
|
||||
$initialTerm = Member::loggedIn()->language()->pluralize( Member::loggedIn()->language()->get('renew_days'), array( $term['term'] ) );
|
||||
break;
|
||||
case 'm':
|
||||
$initialTerm = \IPS\Member::loggedIn()->language()->pluralize( \IPS\Member::loggedIn()->language()->get('renew_months'), array( $term['term'] ) );
|
||||
$initialTerm = Member::loggedIn()->language()->pluralize( Member::loggedIn()->language()->get('renew_months'), array( $term['term'] ) );
|
||||
break;
|
||||
case 'y':
|
||||
$initialTerm = \IPS\Member::loggedIn()->language()->pluralize( \IPS\Member::loggedIn()->language()->get('renew_years'), array( $term['term'] ) );
|
||||
$initialTerm = Member::loggedIn()->language()->pluralize( Member::loggedIn()->language()->get('renew_years'), array( $term['term'] ) );
|
||||
break;
|
||||
}
|
||||
|
||||
$return['initialTerm'] = sprintf( \IPS\Member::loggedIn()->language()->get('package_initial_term_title'), $initialTerm );
|
||||
$return['initialTerm'] = sprintf( Member::loggedIn()->language()->get('package_initial_term_title'), $initialTerm );
|
||||
|
||||
if ( $term['add'] )
|
||||
{
|
||||
$data['price']->amount = $data['price']->amount->add( new \IPS\Math\Number( number_format( $term['cost'][ $memberCurrency ]['amount'], \IPS\nexus\Money::numberOfDecimalsForCurrency( $memberCurrency ), '.', '' ) ) );
|
||||
$normalPrice->amount = $normalPrice->amount->add( new \IPS\Math\Number( number_format( $term['cost'][ $memberCurrency ]['amount'], \IPS\nexus\Money::numberOfDecimalsForCurrency( $memberCurrency ), '.', '' ) ) );
|
||||
$data['price']->amount = $data['price']->amount->add( new Number( number_format( $term['cost'][ $memberCurrency ]['amount'], Money::numberOfDecimalsForCurrency( $memberCurrency ), '.', '' ) ) );
|
||||
$normalPrice->amount = $normalPrice->amount->add( new Number( number_format( $term['cost'][ $memberCurrency ]['amount'], Money::numberOfDecimalsForCurrency( $memberCurrency ), '.', '' ) ) );
|
||||
}
|
||||
|
||||
$return['renewal'] = ( new \IPS\nexus\Purchase\RenewalTerm(
|
||||
new \IPS\nexus\Money(
|
||||
( new \IPS\Math\Number( number_format( $term['cost'][ $memberCurrency ]['amount'], \IPS\nexus\Money::numberOfDecimalsForCurrency( $memberCurrency ), '.', '' ) ) )
|
||||
->add( ( new \IPS\Math\Number( number_format( $_data['renewalAdjustment'], \IPS\nexus\Money::numberOfDecimalsForCurrency( $memberCurrency ), '.', '' ) ) ) )
|
||||
$return['renewal'] = ( new RenewalTerm(
|
||||
new Money(
|
||||
( new Number( number_format( $term['cost'][ $memberCurrency ]['amount'], Money::numberOfDecimalsForCurrency( $memberCurrency ), '.', '' ) ) )
|
||||
->add( ( new Number( number_format( $_data['renewalAdjustment'], Money::numberOfDecimalsForCurrency( $memberCurrency ), '.', '' ) ) ) )
|
||||
, $memberCurrency ),
|
||||
new \DateInterval( 'P' . $term['term'] . mb_strtoupper( $term['unit'] ) ),
|
||||
$package->tax ? \IPS\nexus\Tax::load( $package->tax ) : NULL, $term['add']
|
||||
new DateInterval( 'P' . $term['term'] . mb_strtoupper( $term['unit'] ) ),
|
||||
$package->tax ? Tax::load( $package->tax ) : NULL, $term['add']
|
||||
) )->toDisplay();
|
||||
}
|
||||
else
|
||||
@@ -587,40 +531,40 @@ class _product extends \IPS\Content\Controller
|
||||
}
|
||||
|
||||
/* Include tax? */
|
||||
if ( \IPS\Settings::i()->nexus_show_tax and $package->tax )
|
||||
if ( Settings::i()->nexus_show_tax and $package->tax )
|
||||
{
|
||||
try
|
||||
{
|
||||
$taxRate = new \IPS\Math\Number( \IPS\nexus\Tax::load( $package->tax )->rate( \IPS\nexus\Customer::loggedIn()->estimatedLocation() ) );
|
||||
$taxRate = new Number( Tax::load( $package->tax )->rate( Customer::loggedIn()->estimatedLocation() ) );
|
||||
|
||||
$data['price']->amount = $data['price']->amount->add( $data['price']->amount->multiply( $taxRate ) );
|
||||
$normalPrice->amount = $normalPrice->amount->add( $normalPrice->amount->multiply( $taxRate ) );
|
||||
}
|
||||
catch ( \OutOfRangeException $e ) { }
|
||||
catch ( OutOfRangeException ) { }
|
||||
}
|
||||
|
||||
/* Format and return */
|
||||
if ( $data['price']->amount->compare( $normalPrice->amount ) !== 0 )
|
||||
{
|
||||
$return['price'] = \IPS\Theme::i()->getTemplate( 'store', 'nexus' )->priceDiscounted( $normalPrice, $data['price'], FALSE, FALSE, NULL );
|
||||
$return['price'] = Theme::i()->getTemplate( 'store', 'nexus' )->priceDiscounted( $normalPrice, $data['price'], FALSE, FALSE, NULL );
|
||||
}
|
||||
else
|
||||
{
|
||||
$return['price'] = \IPS\Theme::i()->getTemplate( 'store', 'nexus' )->price( $data['price'], FALSE, FALSE, NULL );
|
||||
$return['price'] = Theme::i()->getTemplate( 'store', 'nexus' )->price( $data['price'], FALSE, FALSE, NULL );
|
||||
}
|
||||
\IPS\Output::i()->json( $return );
|
||||
Output::i()->json( $return );
|
||||
}
|
||||
elseif ( $data['stock'] != -1 and ( $data['stock'] - $inCartForThisFieldCombination ) < $quantity )
|
||||
{
|
||||
$form->error = \IPS\Member::loggedIn()->language()->addToStack( 'not_enough_in_stock', FALSE, array( 'sprintf' => array( $data['stock'] - $inCartForThisFieldCombination ) ) );
|
||||
$form->error = Member::loggedIn()->language()->addToStack( 'not_enough_in_stock', FALSE, array( 'sprintf' => array( $data['stock'] - $inCartForThisFieldCombination ) ) );
|
||||
return (string) $form;
|
||||
}
|
||||
|
||||
if ( ( !isset( \IPS\Request::i()->additionalPageCheck ) or !\IPS\Request::i()->isAjax() ) and $additionalPage = $package->storeAdditionalPage( $_POST ) )
|
||||
if ( ( !isset( Request::i()->additionalPageCheck ) or !Request::i()->isAjax() ) and $additionalPage = $package->storeAdditionalPage( $_POST ) )
|
||||
{
|
||||
if ( \IPS\Request::i()->isAjax() )
|
||||
if ( Request::i()->isAjax() )
|
||||
{
|
||||
\IPS\Output::i()->json( array( 'dialog' => $additionalPage ) );
|
||||
Output::i()->json( array( 'dialog' => $additionalPage ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -630,9 +574,9 @@ class _product extends \IPS\Content\Controller
|
||||
|
||||
/* Work out renewal term */
|
||||
$renewalTerm = NULL;
|
||||
if ( \count( $renewOptions ) )
|
||||
if ( count( $renewOptions ) )
|
||||
{
|
||||
if ( \count( $renewOptions ) === 1 )
|
||||
if ( count( $renewOptions ) === 1 )
|
||||
{
|
||||
$chosenRenewOption = array_pop( $renewOptions );
|
||||
}
|
||||
@@ -641,7 +585,7 @@ class _product extends \IPS\Content\Controller
|
||||
$chosenRenewOption = $renewOptions[ $values['renewal_term'] ];
|
||||
}
|
||||
|
||||
$renewalTerm = new \IPS\nexus\Purchase\RenewalTerm( new \IPS\nexus\Money( ( new \IPS\Math\Number( number_format( $chosenRenewOption['cost'][ $memberCurrency ]['amount'], 2, '.', '' ) ) )->add( new \IPS\Math\Number( number_format( $data['renewalAdjustment'], 2, '.', '' ) ) ), $memberCurrency ), new \DateInterval( 'P' . $chosenRenewOption['term'] . mb_strtoupper( $chosenRenewOption['unit'] ) ), $package->tax ? \IPS\nexus\Tax::load( $package->tax ) : NULL, $chosenRenewOption['add'], $package->grace_period ? new \DateInterval( 'P' . $package->grace_period . 'D' ) : NULL );
|
||||
$renewalTerm = new RenewalTerm( new Money( ( new Number( number_format( $chosenRenewOption['cost'][ $memberCurrency ]['amount'], 2, '.', '' ) ) )->add( new Number( number_format( $data['renewalAdjustment'], 2, '.', '' ) ) ), $memberCurrency ), new DateInterval( 'P' . $chosenRenewOption['term'] . mb_strtoupper( $chosenRenewOption['unit'] ) ), $package->tax ? Tax::load( $package->tax ) : NULL, $chosenRenewOption['add'], $package->grace_period ? new DateInterval( 'P' . $package->grace_period . 'D' ) : NULL );
|
||||
}
|
||||
|
||||
/* Associations */
|
||||
@@ -651,7 +595,7 @@ class _product extends \IPS\Content\Controller
|
||||
$exploded = explode( '.', $values['associate_with'] );
|
||||
if ( $exploded[0] )
|
||||
{
|
||||
$parent = \IPS\nexus\Purchase::load( $exploded[1] );
|
||||
$parent = Purchase::load( $exploded[1] );
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -661,20 +605,20 @@ class _product extends \IPS\Content\Controller
|
||||
|
||||
/* Actually add to cart */
|
||||
$cartId = $package->addItemsToCartData( $details, $quantity, $renewalTerm, $parent, $values );
|
||||
\IPS\Db::i()->update( 'nexus_cart_uploads', array( 'item_id' => $cartId ), \IPS\Db::i()->in( 'id', $editorUploadIds ) );
|
||||
Db::i()->update( 'nexus_cart_uploads', array( 'item_id' => $cartId ), Db::i()->in( 'id', $editorUploadIds ) );
|
||||
|
||||
/* Redirect or AJAX */
|
||||
if ( \IPS\Request::i()->isAjax() )
|
||||
if ( Request::i()->isAjax() )
|
||||
{
|
||||
/* Upselling? */
|
||||
$upsell = \IPS\nexus\Package\Item::getItemsWithPermission( array( array( 'p_upsell=1' ), array( \IPS\Db::i()->findInSet( 'p_associable', array( $package->id ) ) ) ), 'p_position' );
|
||||
$upsell = Item::getItemsWithPermission( array( array( 'p_upsell=1' ), array( Db::i()->findInSet( 'p_associable', array( $package->id ) ) ) ), 'p_position' );
|
||||
|
||||
/* Send */
|
||||
\IPS\Output::i()->json( array( 'dialog' => \IPS\Theme::i()->getTemplate('store')->cartReview( $package, $quantity, $upsell ), 'cart' => \IPS\Theme::i()->getTemplate('store')->cartHeader(), 'css' => \IPS\Output::i()->cssFiles ) );
|
||||
Output::i()->json( array( 'dialog' => Theme::i()->getTemplate('store')->cartReview( $package, $quantity, $upsell ), 'cart' => Theme::i()->getTemplate('store')->cartHeader(), 'css' => Output::i()->cssFiles ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
\IPS\Output::i()->redirect( \IPS\Http\Url::internal( 'app=nexus&module=store&controller=cart&added=' . $package->id, 'front', 'store_cart' ) );
|
||||
Output::i()->redirect( Url::internal( 'app=nexus&module=store&controller=cart&added=' . $package->id, 'front', 'store_cart' ) );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -12,59 +12,87 @@
|
||||
namespace IPS\nexus\modules\front\store;
|
||||
|
||||
/* To prevent PHP errors (extending class does not exist) revealing path */
|
||||
if ( !\defined( '\IPS\SUITE_UNIQUE_KEY' ) )
|
||||
|
||||
use DateInterval;
|
||||
use IPS\Content\Filter;
|
||||
use IPS\DateTime;
|
||||
use IPS\Db;
|
||||
use IPS\Dispatcher\Controller;
|
||||
use IPS\Helpers\Form;
|
||||
use IPS\Helpers\Form\Number;
|
||||
use IPS\Http\Url;
|
||||
use IPS\Login;
|
||||
use IPS\Member;
|
||||
use IPS\nexus\Customer;
|
||||
use IPS\nexus\Money;
|
||||
use IPS\nexus\Package;
|
||||
use IPS\nexus\Package\Group;
|
||||
use IPS\nexus\Package\Item;
|
||||
use IPS\Output;
|
||||
use IPS\Patterns\ActiveRecordIterator;
|
||||
use IPS\Request;
|
||||
use IPS\Session;
|
||||
use IPS\Settings;
|
||||
use IPS\Theme;
|
||||
use OutOfBoundsException;
|
||||
use OutofRangeException;
|
||||
use function count;
|
||||
use function defined;
|
||||
use function floatval;
|
||||
use function in_array;
|
||||
use function intval;
|
||||
use function is_array;
|
||||
use function is_numeric;
|
||||
|
||||
if ( !defined( '\IPS\SUITE_UNIQUE_KEY' ) )
|
||||
{
|
||||
header( ( isset( $_SERVER['SERVER_PROTOCOL'] ) ? $_SERVER['SERVER_PROTOCOL'] : 'HTTP/1.0' ) . ' 403 Forbidden' );
|
||||
header( ( $_SERVER['SERVER_PROTOCOL'] ?? 'HTTP/1.0' ) . ' 403 Forbidden' );
|
||||
exit;
|
||||
}
|
||||
|
||||
/**
|
||||
* Browse Store
|
||||
*/
|
||||
class _store extends \IPS\Dispatcher\Controller
|
||||
class store extends Controller
|
||||
{
|
||||
/**
|
||||
* @brief Products per page
|
||||
*/
|
||||
protected static $productsPerPage = 50;
|
||||
protected static int $productsPerPage = 50;
|
||||
|
||||
/**
|
||||
* @brief Currency
|
||||
*/
|
||||
protected $currency;
|
||||
protected mixed $currency = NULL;
|
||||
|
||||
/**
|
||||
* Execute
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function execute()
|
||||
public function execute() : void
|
||||
{
|
||||
/* Set CSS */
|
||||
\IPS\Output::i()->cssFiles = array_merge( \IPS\Output::i()->cssFiles, \IPS\Theme::i()->css( 'store.css', 'nexus' ) );
|
||||
if ( \IPS\Theme::i()->settings['responsive'] )
|
||||
{
|
||||
\IPS\Output::i()->cssFiles = array_merge( \IPS\Output::i()->cssFiles, \IPS\Theme::i()->css( 'store_responsive.css', 'nexus', 'front' ) );
|
||||
}
|
||||
Output::i()->cssFiles = array_merge( Output::i()->cssFiles, Theme::i()->css( 'store.css', 'nexus' ) );
|
||||
|
||||
/* Work out currency */
|
||||
if ( isset( \IPS\Request::i()->currency ) and \in_array( \IPS\Request::i()->currency, \IPS\nexus\Money::currencies() ) )
|
||||
if ( isset( Request::i()->currency ) and in_array( Request::i()->currency, Money::currencies() ) )
|
||||
{
|
||||
if ( isset( \IPS\Request::i()->csrfKey ) and \IPS\Login::compareHashes( (string) \IPS\Session::i()->csrfKey, (string) \IPS\Request::i()->csrfKey ) )
|
||||
if ( isset( Request::i()->csrfKey ) and Login::compareHashes( (string) Session::i()->csrfKey, (string) Request::i()->csrfKey ) )
|
||||
{
|
||||
$_SESSION['cart'] = array();
|
||||
\IPS\Request::i()->setCookie( 'currency', \IPS\Request::i()->currency );
|
||||
Request::i()->setCookie( 'currency', Request::i()->currency );
|
||||
|
||||
\IPS\Output::i()->redirect( \IPS\Http\Url::internal( 'app=nexus&module=store&controller=store', 'front', 'store' ) );
|
||||
Output::i()->redirect( Url::internal( 'app=nexus&module=store&controller=store', 'front', 'store' ) );
|
||||
}
|
||||
$this->currency = \IPS\Request::i()->currency;
|
||||
$this->currency = Request::i()->currency;
|
||||
}
|
||||
else
|
||||
{
|
||||
$this->currency = \IPS\nexus\Customer::loggedIn()->defaultCurrency();
|
||||
$this->currency = Customer::loggedIn()->defaultCurrency();
|
||||
}
|
||||
|
||||
\IPS\Output::setCacheTime( false );
|
||||
|
||||
Output::i()->pageCaching = FALSE;
|
||||
|
||||
/* Pass up */
|
||||
parent::execute();
|
||||
@@ -75,12 +103,12 @@ class _store extends \IPS\Dispatcher\Controller
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
protected function manage()
|
||||
protected function manage() : void
|
||||
{
|
||||
/* If we have a category, display it */
|
||||
if ( isset( \IPS\Request::i()->cat ) )
|
||||
if ( isset( Request::i()->cat ) )
|
||||
{
|
||||
return $this->_categoryView();
|
||||
$this->_categoryView();
|
||||
}
|
||||
|
||||
/* Otherwise, display the index */
|
||||
@@ -95,21 +123,21 @@ class _store extends \IPS\Dispatcher\Controller
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
protected function _categoryView()
|
||||
protected function _categoryView() : void
|
||||
{
|
||||
/* Load category */
|
||||
try
|
||||
{
|
||||
$category = \IPS\nexus\Package\Group::loadAndCheckPerms( \IPS\Request::i()->cat );
|
||||
$category = Group::loadAndCheckPerms( Request::i()->cat );
|
||||
}
|
||||
catch ( \OutofRangeException $e )
|
||||
catch ( OutofRangeException )
|
||||
{
|
||||
\IPS\Output::i()->error( 'node_error', '1X241/1', 404, '' );
|
||||
Output::i()->error( 'node_error', '1X241/1', 404, '' );
|
||||
}
|
||||
$url = $category->url();
|
||||
|
||||
/* Set initial stuff for fetching packages */
|
||||
$currentPage = isset( \IPS\Request::i()->page ) ? \intval( \IPS\Request::i()->page ) : 1;
|
||||
$currentPage = isset( Request::i()->page ) ? intval( Request::i()->page ) : 1;
|
||||
if( $currentPage < 1 )
|
||||
{
|
||||
$currentPage = 1;
|
||||
@@ -117,55 +145,55 @@ class _store extends \IPS\Dispatcher\Controller
|
||||
$where = array(
|
||||
array( 'p_group=?', $category->id ),
|
||||
array( 'p_store=1' ),
|
||||
array( "( p_member_groups='*' OR " . \IPS\Db::i()->findInSet( 'p_member_groups', \IPS\Member::loggedIn()->groups ) . ' )' )
|
||||
array( "( p_member_groups='*' OR " . Db::i()->findInSet( 'p_member_groups', Member::loggedIn()->groups ) . ' )' )
|
||||
);
|
||||
$havePackagesWhichAcceptReviews = (bool) \IPS\Db::i()->select( 'COUNT(*)', 'nexus_packages', array_merge( $where, array( array( 'p_reviewable=1' ) ) ) )->first();
|
||||
$havePackagesWhichUseStockLevels = (bool) \IPS\Db::i()->select( 'COUNT(*)', 'nexus_packages', array_merge( $where, array( array( 'p_stock<>-1' ) ) ) )->first();
|
||||
$havePackagesWhichAcceptReviews = (bool) Db::i()->select( 'COUNT(*)', 'nexus_packages', array_merge( $where, array( array( 'p_reviewable=1' ) ) ) )->first();
|
||||
$havePackagesWhichUseStockLevels = (bool) Db::i()->select( 'COUNT(*)', 'nexus_packages', array_merge( $where, array( array( 'p_stock<>-1' ) ) ) )->first();
|
||||
$joins = array();
|
||||
|
||||
/* Apply Filters */
|
||||
if ( isset( \IPS\Request::i()->filter ) and \is_array( \IPS\Request::i()->filter ) )
|
||||
if ( isset( Request::i()->filter ) and is_array( Request::i()->filter ) )
|
||||
{
|
||||
$url = $url->setQueryString( 'filter', \IPS\Request::i()->filter );
|
||||
foreach ( \IPS\Request::i()->filter as $filterId => $allowedValues )
|
||||
$url = $url->setQueryString( 'filter', Request::i()->filter );
|
||||
foreach ( Request::i()->filter as $filterId => $allowedValues )
|
||||
{
|
||||
$filterId = (int) $filterId;
|
||||
$where[] = array( \IPS\Db::i()->findInSet( "filter{$filterId}.pfm_values", array_map( 'intval', explode( ',', $allowedValues ) ) ) );
|
||||
$where[] = array( Db::i()->findInSet( "filter{$filterId}.pfm_values", array_map( 'intval', explode( ',', $allowedValues ) ) ) );
|
||||
$joins[] = array( 'table' => array( 'nexus_package_filters_map', "filter{$filterId}" ), 'on' => array( "filter{$filterId}.pfm_package=p_id AND filter{$filterId}.pfm_filter=?", $filterId ) );
|
||||
}
|
||||
}
|
||||
foreach ( array( 'minPrice' => '>', 'maxPrice' => '<' ) as $k => $op )
|
||||
{
|
||||
if ( isset( \IPS\Request::i()->$k ) and \is_numeric( \IPS\Request::i()->$k ) and \floatval( \IPS\Request::i()->$k ) > 0 )
|
||||
if ( isset( Request::i()->$k ) and is_numeric( Request::i()->$k ) and floatval( Request::i()->$k ) > 0 )
|
||||
{
|
||||
$url = $url->setQueryString( $k, \IPS\Request::i()->$k );
|
||||
$url = $url->setQueryString( $k, Request::i()->$k );
|
||||
$joins['nexus_package_base_prices'] = array( 'table' => 'nexus_package_base_prices', 'on' => array( 'id=p_id' ) );
|
||||
$where[] = array( $this->currency . $op . '=?', \floatval( \IPS\Request::i()->$k ) );
|
||||
$where[] = array( $this->currency . $op . '=?', floatval( Request::i()->$k ) );
|
||||
}
|
||||
}
|
||||
if ( isset( \IPS\Request::i()->minRating ) and \is_numeric( \IPS\Request::i()->minRating ) and \floatval( \IPS\Request::i()->minRating ) > 0 )
|
||||
if ( isset( Request::i()->minRating ) and is_numeric( Request::i()->minRating ) and floatval( Request::i()->minRating ) > 0 )
|
||||
{
|
||||
$url = $url->setQueryString( 'minRating', \IPS\Request::i()->minRating );
|
||||
$where[] = array( 'p_rating>=?', \intval( \IPS\Request::i()->minRating ) );
|
||||
$url = $url->setQueryString( 'minRating', Request::i()->minRating );
|
||||
$where[] = array( 'p_rating>=?', intval( Request::i()->minRating ) );
|
||||
}
|
||||
if ( isset( \IPS\Request::i()->inStock ) )
|
||||
if ( isset( Request::i()->inStock ) )
|
||||
{
|
||||
$url = $url->setQueryString( 'inStock', \IPS\Request::i()->inStock );
|
||||
$where[] = array( '( p_stock>0 OR ( p_stock=-2 AND (?)>0 ) )', \IPS\Db::i()->select( 'MAX(opt_stock)', 'nexus_product_options', 'opt_package=p_id' ) );
|
||||
$url = $url->setQueryString( 'inStock', Request::i()->inStock );
|
||||
$where[] = array( '( p_stock>0 OR ( p_stock=-2 AND (?)>0 ) )', Db::i()->select( 'MAX(opt_stock)', 'nexus_product_options', 'opt_package=p_id' ) );
|
||||
}
|
||||
|
||||
/* Figure out the sorting */
|
||||
switch ( \IPS\Request::i()->sortby )
|
||||
switch ( Request::i()->sortby )
|
||||
{
|
||||
case 'name':
|
||||
$joins['core_sys_lang_words'] = array( 'table' => 'core_sys_lang_words', 'on' => array( "word_app='nexus' AND word_key=CONCAT( 'nexus_package_', p_id ) AND lang_id=?", \IPS\Member::loggedIn()->language()->id ) );
|
||||
$joins['core_sys_lang_words'] = array( 'table' => 'core_sys_lang_words', 'on' => array( "word_app='nexus' AND word_key=CONCAT( 'nexus_package_', p_id ) AND lang_id=?", Member::loggedIn()->language()->id ) );
|
||||
$sortBy = 'word_custom';
|
||||
break;
|
||||
|
||||
case 'price_low':
|
||||
case 'price_high':
|
||||
$joins['nexus_package_base_prices'] = array( 'table' => 'nexus_package_base_prices', 'on' => array( 'id=p_id' ) );
|
||||
$sortBy = \IPS\Request::i()->sortby == 'price_low' ? $this->currency : ( $this->currency . ' DESC' );
|
||||
$sortBy = Request::i()->sortby == 'price_low' ? $this->currency : ( $this->currency . ' DESC' );
|
||||
break;
|
||||
|
||||
case 'rating':
|
||||
@@ -178,15 +206,15 @@ class _store extends \IPS\Dispatcher\Controller
|
||||
}
|
||||
|
||||
/* Fetch the packages */
|
||||
$select = \IPS\Db::i()->select( '*', 'nexus_packages', $where, $sortBy, array( ( $currentPage - 1 ) * static::$productsPerPage, static::$productsPerPage ) );
|
||||
$select = Db::i()->select( '*', 'nexus_packages', $where, $sortBy, array( ( $currentPage - 1 ) * static::$productsPerPage, static::$productsPerPage ) );
|
||||
foreach ( $joins as $join )
|
||||
{
|
||||
$select->join( $join['table'], $join['on'] );
|
||||
}
|
||||
$packages = new \IPS\Patterns\ActiveRecordIterator( $select, 'IPS\nexus\Package' );
|
||||
$packages = new ActiveRecordIterator( $select, 'IPS\nexus\Package' );
|
||||
|
||||
/* Get packages count */
|
||||
$select = \IPS\Db::i()->select( 'COUNT(*)', 'nexus_packages', $where );
|
||||
$select = Db::i()->select( 'COUNT(*)', 'nexus_packages', $where );
|
||||
foreach ( $joins as $join )
|
||||
{
|
||||
$select->join( $join['table'], $join['on'] );
|
||||
@@ -197,50 +225,41 @@ class _store extends \IPS\Dispatcher\Controller
|
||||
$totalPages = ceil( $totalCount / static::$productsPerPage );
|
||||
if ( $totalPages and $currentPage > $totalPages )
|
||||
{
|
||||
\IPS\Output::i()->redirect( $category->url()->setPage( 'page', $totalPages ), NULL, 303 );
|
||||
Output::i()->redirect( $category->url()->setPage( 'page', $totalPages ), NULL, 303 );
|
||||
}
|
||||
$pagination = \IPS\Theme::i()->getTemplate( 'global', 'core', 'global' )->pagination( $category->url(), $totalPages, $currentPage, static::$productsPerPage );
|
||||
$pagination = Theme::i()->getTemplate( 'global', 'core', 'global' )->pagination( $category->url(), $totalPages, $currentPage, static::$productsPerPage );
|
||||
|
||||
/* Other stuff we need for the view */
|
||||
$subcategories = new \IPS\Patterns\ActiveRecordIterator( \IPS\Db::i()->select( '*', 'nexus_package_groups', array( 'pg_parent=?', $category->id ), 'pg_position ASC' ), 'IPS\nexus\Package\Group' );
|
||||
$subcategories = new ActiveRecordIterator( Db::i()->select( '*', 'nexus_package_groups', array( 'pg_parent=?', $category->id ), 'pg_position ASC' ), 'IPS\nexus\Package\Group' );
|
||||
$packagesWithCustomFields = array();
|
||||
foreach ( iterator_to_array( \IPS\Db::i()->select( 'cf_packages', 'nexus_package_fields', 'cf_purchase=1' ) ) as $ids )
|
||||
foreach ( iterator_to_array( Db::i()->select( 'cf_packages', 'nexus_package_fields', 'cf_purchase=1' ) ) as $ids )
|
||||
{
|
||||
$packagesWithCustomFields = array_merge( $packagesWithCustomFields, array_filter( explode( ',', $ids ) ) );
|
||||
}
|
||||
|
||||
/* List or grid? */
|
||||
if ( \IPS\Request::i()->view )
|
||||
{
|
||||
\IPS\Session::i()->csrfCheck();
|
||||
\IPS\Request::i()->setCookie( 'storeView', ( \IPS\Request::i()->view == 'list' ) ? 'list' : 'grid', \IPS\DateTime::ts( time() )->add( new \DateInterval( 'P1Y' ) ) );
|
||||
\IPS\Request::i()->cookie['storeView'] = ( \IPS\Request::i()->view == 'list' ) ? 'list' : 'grid';
|
||||
}
|
||||
|
||||
/* Output */
|
||||
if ( \IPS\Request::i()->isAjax() )
|
||||
if ( Request::i()->isAjax() )
|
||||
{
|
||||
\IPS\Output::i()->json( array(
|
||||
'contents' => \IPS\Theme::i()->getTemplate('store')->categoryContents( $category, $subcategories, $packages, $pagination, $packagesWithCustomFields, $totalCount ),
|
||||
'sidebar' => \IPS\Theme::i()->getTemplate('store')->categorySidebar( $category, $subcategories, $url, \count( $packages ), $this->currency, $havePackagesWhichAcceptReviews, $havePackagesWhichUseStockLevels )
|
||||
Output::i()->json( array(
|
||||
'contents' => Theme::i()->getTemplate('store')->categoryContents( $category, $subcategories, $packages, $pagination, $packagesWithCustomFields, $totalCount ),
|
||||
'sidebar' => Theme::i()->getTemplate('store')->categorySidebar( $category, $subcategories, $url, count( $packages ), $this->currency, $havePackagesWhichAcceptReviews, $havePackagesWhichUseStockLevels )
|
||||
)) ;
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
foreach ( $category->parents() as $parent )
|
||||
{
|
||||
\IPS\Output::i()->breadcrumb[] = array( $parent->url(), $parent->_title );
|
||||
Output::i()->breadcrumb[] = array( $parent->url(), $parent->_title );
|
||||
}
|
||||
\IPS\Output::i()->breadcrumb[] = array( $category->url(), $category->_title );
|
||||
\IPS\Output::i()->title = $category->_title;
|
||||
\IPS\Output::i()->sidebar['contextual'] = \IPS\Theme::i()->getTemplate('store')->categorySidebar( $category, $subcategories, $url, \count( $packages ), $this->currency, $havePackagesWhichAcceptReviews, $havePackagesWhichUseStockLevels );
|
||||
Output::i()->breadcrumb[] = array( $category->url(), $category->_title );
|
||||
Output::i()->title = $category->_title;
|
||||
Output::i()->sidebar['contextual'] = Theme::i()->getTemplate('store')->categorySidebar( $category, $subcategories, $url, count( $packages ), $this->currency, $havePackagesWhichAcceptReviews, $havePackagesWhichUseStockLevels );
|
||||
|
||||
/* Set default search */
|
||||
\IPS\Output::i()->defaultSearchOption = array( 'nexus_package_item', "nexus_package_item_el" );
|
||||
Output::i()->defaultSearchOption = array( 'nexus_package_item', "nexus_package_item_el" );
|
||||
|
||||
\IPS\Output::i()->output = \IPS\Theme::i()->getTemplate('store')->category( $category, $subcategories, $packages, $pagination, $packagesWithCustomFields, $totalCount );
|
||||
\IPS\Output::i()->globalControllers[] = 'nexus.front.store.category';
|
||||
Output::i()->output = Theme::i()->getTemplate('store')->category( $category, $subcategories, $packages, $pagination, $packagesWithCustomFields, $totalCount );
|
||||
Output::i()->globalControllers[] = 'nexus.front.store.category';
|
||||
}
|
||||
|
||||
/* JSON-LD
|
||||
@@ -248,13 +267,14 @@ class _store extends \IPS\Dispatcher\Controller
|
||||
@link https://developers.google.com/search/docs/guides/intro-structured-data#multiple-entities-on-the-same-page */
|
||||
foreach( $packages as $package )
|
||||
{
|
||||
$item = \IPS\nexus\Package\Item::load( $package->id );
|
||||
/* @var Package $package */
|
||||
$item = Item::load( $package->id );
|
||||
|
||||
try
|
||||
{
|
||||
$price = $package->price();
|
||||
}
|
||||
catch( \OutOfBoundsException $e )
|
||||
catch( OutOfBoundsException )
|
||||
{
|
||||
$price = NULL;
|
||||
}
|
||||
@@ -262,8 +282,8 @@ class _store extends \IPS\Dispatcher\Controller
|
||||
/* A product MUST have an offer, so if there's no price (i.e. due to currency configuration) don't even output */
|
||||
if( $price !== NULL )
|
||||
{
|
||||
\IPS\Output::i()->jsonLd['package' . $package->id ] = array(
|
||||
'@context' => "http://schema.org",
|
||||
Output::i()->jsonLd['package' . $package->id ] = array(
|
||||
'@context' => "https://schema.org",
|
||||
'@type' => "Product",
|
||||
'name' => $package->_title,
|
||||
'description' => $item->truncated( TRUE, NULL ),
|
||||
@@ -276,32 +296,29 @@ class _store extends \IPS\Dispatcher\Controller
|
||||
'priceCurrency' => $price->currency,
|
||||
'seller' => array(
|
||||
'@type' => 'Organization',
|
||||
'name' => \IPS\Settings::i()->board_name
|
||||
'name' => Settings::i()->board_name
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
/* Stock levels */
|
||||
if( $package->physical )
|
||||
if( $package->stockLevel() === 0 )
|
||||
{
|
||||
if( $package->stockLevel() === 0 )
|
||||
{
|
||||
\IPS\Output::i()->jsonLd['package' . $package->id ]['offers']['availability'] = 'http://schema.org/OutOfStock';
|
||||
}
|
||||
else
|
||||
{
|
||||
\IPS\Output::i()->jsonLd['package' . $package->id ]['offers']['availability'] = 'http://schema.org/InStock';
|
||||
}
|
||||
Output::i()->jsonLd['package' . $package->id ]['offers']['availability'] = 'https://schema.org/OutOfStock';
|
||||
}
|
||||
else
|
||||
{
|
||||
Output::i()->jsonLd['package' . $package->id ]['offers']['availability'] = 'https://schema.org/InStock';
|
||||
}
|
||||
|
||||
if( $package->image )
|
||||
{
|
||||
\IPS\Output::i()->jsonLd['package' . $package->id ]['image'] = (string) $package->image;
|
||||
Output::i()->jsonLd['package' . $package->id ]['image'] = (string) $package->image;
|
||||
}
|
||||
|
||||
if( $package->reviewable and $item->averageReviewRating() )
|
||||
{
|
||||
\IPS\Output::i()->jsonLd['package' . $package->id ]['aggregateRating'] = array(
|
||||
Output::i()->jsonLd['package' . $package->id ]['aggregateRating'] = array(
|
||||
'@type' => 'AggregateRating',
|
||||
'ratingValue' => $item->averageReviewRating(),
|
||||
'ratingCount' => $item->reviews
|
||||
@@ -316,21 +333,21 @@ class _store extends \IPS\Dispatcher\Controller
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
protected function priceFilter()
|
||||
protected function priceFilter() : void
|
||||
{
|
||||
if ( !isset( \IPS\Request::i()->maxPrice ) )
|
||||
if ( !isset( Request::i()->maxPrice ) )
|
||||
{
|
||||
\IPS\Request::i()->maxPrice = 0;
|
||||
Request::i()->maxPrice = 0;
|
||||
}
|
||||
|
||||
$form = new \IPS\Helpers\Form( 'price_filter', 'filter' );
|
||||
$form->class = 'ipsForm_vertical';
|
||||
$form->add( new \IPS\Helpers\Form\Number( 'minPrice', FALSE, 0, array( 'decimals' => \IPS\nexus\Money::numberOfDecimalsForCurrency( $this->currency ) ), NULL, NULL, $this->currency ) );
|
||||
$form->add( new \IPS\Helpers\Form\Number( 'maxPrice', FALSE, 0, array( 'decimals' => \IPS\nexus\Money::numberOfDecimalsForCurrency( $this->currency ), 'unlimited' => 0 ), NULL, NULL, $this->currency ) );
|
||||
$form = new Form( 'price_filter', 'filter' );
|
||||
$form->class = 'ipsForm--vertical ipsForm--price-filter';
|
||||
$form->add( new Number( 'minPrice', FALSE, 0, array( 'decimals' => Money::numberOfDecimalsForCurrency( $this->currency ) ), NULL, NULL, $this->currency ) );
|
||||
$form->add( new Number( 'maxPrice', FALSE, 0, array( 'decimals' => Money::numberOfDecimalsForCurrency( $this->currency ), 'unlimited' => 0 ), NULL, NULL, $this->currency ) );
|
||||
|
||||
if ( $values = $form->values() )
|
||||
{
|
||||
$url = \IPS\Request::i()->url()->setQueryString( 'do', NULL );
|
||||
$url = Request::i()->url()->setQueryString( 'do', NULL );
|
||||
if ( $values['minPrice'] )
|
||||
{
|
||||
$url = $url->setQueryString( 'minPrice', $values['minPrice'] );
|
||||
@@ -347,11 +364,11 @@ class _store extends \IPS\Dispatcher\Controller
|
||||
{
|
||||
$url = $url->setQueryString( 'maxPrice', NULL );
|
||||
}
|
||||
\IPS\Output::i()->redirect( $url );
|
||||
Output::i()->redirect( $url );
|
||||
}
|
||||
|
||||
\IPS\Output::i()->title = \IPS\Member::loggedIn()->language()->addToStack('price_filter');
|
||||
\IPS\Output::i()->output = $form->customTemplate( array( \IPS\Theme::i()->getTemplate( 'forms', 'core' ), 'popupTemplate' ) );
|
||||
Output::i()->title = Member::loggedIn()->language()->addToStack('price_filter');
|
||||
Output::i()->output = $form->customTemplate( array( Theme::i()->getTemplate( 'forms', 'core' ), 'popupTemplate' ) );
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -359,38 +376,38 @@ class _store extends \IPS\Dispatcher\Controller
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
protected function _indexView()
|
||||
protected function _indexView() : void
|
||||
{
|
||||
/* New Products */
|
||||
$newProducts = array();
|
||||
$nexus_store_new = explode( ',', \IPS\Settings::i()->nexus_store_new );
|
||||
$nexus_store_new = explode( ',', Settings::i()->nexus_store_new );
|
||||
if ( $nexus_store_new[0] )
|
||||
{
|
||||
$newProducts = \IPS\nexus\Package\Item::getItemsWithPermission( array( array( 'p_date_added>?', \IPS\DateTime::create()->sub( new \DateInterval( 'P' . $nexus_store_new[1] . 'D' ) )->getTimestamp() ) ), 'p_date_added DESC', $nexus_store_new[0] );
|
||||
$newProducts = Item::getItemsWithPermission( array( array( 'p_date_added>?', DateTime::create()->sub( new DateInterval( 'P' . $nexus_store_new[1] . 'D' ) )->getTimestamp() ) ), 'p_date_added DESC', $nexus_store_new[0] );
|
||||
}
|
||||
|
||||
/* Popular Products */
|
||||
$popularProducts = array();
|
||||
$nexus_store_popular = explode( ',', \IPS\Settings::i()->nexus_store_popular );
|
||||
$nexus_store_popular = explode( ',', Settings::i()->nexus_store_popular );
|
||||
if ( $nexus_store_popular[0] )
|
||||
{
|
||||
$where = array();
|
||||
$where[] = array( 'ps_app=? AND ps_type=? AND ps_start>?', 'nexus', 'package', \IPS\DateTime::create()->sub( new \DateInterval( 'P' . $nexus_store_popular[1] . 'D' ) )->getTimestamp() );
|
||||
$where[] = "( p_member_groups='*' OR " . \IPS\Db::i()->findInSet( 'p_member_groups', \IPS\Member::loggedIn()->groups ) . ' )';
|
||||
$where[] = array( 'ps_app=? AND ps_type=? AND ps_start>?', 'nexus', 'package', DateTime::create()->sub( new DateInterval( 'P' . $nexus_store_popular[1] . 'D' ) )->getTimestamp() );
|
||||
$where[] = "( p_member_groups='*' OR " . Db::i()->findInSet( 'p_member_groups', Member::loggedIn()->groups ) . ' )';
|
||||
$where[] = array( 'p_store=?', 1 );
|
||||
|
||||
$popularIds = \IPS\Db::i()->select( 'nexus_purchases.ps_item_id', 'nexus_purchases', $where, 'COUNT(ps_item_id) DESC', $nexus_store_popular[0], 'ps_item_id' )->join( 'nexus_packages', 'ps_item_id=p_id' );
|
||||
if( \count( $popularIds ) )
|
||||
$popularIds = Db::i()->select( 'nexus_purchases.ps_item_id', 'nexus_purchases', $where, 'COUNT(ps_item_id) DESC', $nexus_store_popular[0], 'ps_item_id' )->join( 'nexus_packages', 'ps_item_id=p_id' );
|
||||
if( count( $popularIds ) )
|
||||
{
|
||||
$popularProducts = new \IPS\Patterns\ActiveRecordIterator( \IPS\Db::i()->select( 'nexus_packages.*', 'nexus_packages', array( \IPS\Db::i()->in( 'p_id', iterator_to_array( $popularIds ) ) ), 'FIELD(p_id, ' . implode( ',', iterator_to_array($popularIds) ) . ')' ), 'IPS\nexus\Package' );
|
||||
$popularProducts = new ActiveRecordIterator( Db::i()->select( 'nexus_packages.*', 'nexus_packages', array( Db::i()->in( 'p_id', iterator_to_array( $popularIds ) ) ), 'FIELD(p_id, ' . implode( ',', iterator_to_array($popularIds) ) . ')' ), 'IPS\nexus\Package' );
|
||||
}
|
||||
}
|
||||
|
||||
/* Display */
|
||||
\IPS\Output::i()->sidebar['contextual'] = \IPS\Theme::i()->getTemplate('store')->categorySidebar( );
|
||||
\IPS\Output::i()->linkTags['canonical'] = (string) \IPS\Http\Url::internal( 'app=nexus&module=store&controller=store', 'front', 'store' );
|
||||
\IPS\Output::i()->output = \IPS\Theme::i()->getTemplate('store')->index( \IPS\nexus\Customer::loggedIn()->cm_credits[ $this->currency ], $newProducts, $popularProducts );
|
||||
\IPS\Output::i()->title = \IPS\Member::loggedIn()->language()->addToStack('module__nexus_store');
|
||||
Output::i()->sidebar['contextual'] = Theme::i()->getTemplate('store')->categorySidebar( );
|
||||
Output::i()->linkTags['canonical'] = (string) Url::internal( 'app=nexus&module=store&controller=store', 'front', 'store' );
|
||||
Output::i()->output = Theme::i()->getTemplate('store')->index( Customer::loggedIn()->cm_credits[ $this->currency ], $newProducts, $popularProducts );
|
||||
Output::i()->title = Member::loggedIn()->language()->addToStack('module__nexus_store');
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -398,12 +415,12 @@ class _store extends \IPS\Dispatcher\Controller
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function register()
|
||||
public function register() : void
|
||||
{
|
||||
\IPS\Output::i()->bodyClasses[] = 'ipsLayout_minimal';
|
||||
\IPS\Output::i()->sidebar['enabled'] = FALSE;
|
||||
\IPS\Output::i()->output = \IPS\Theme::i()->getTemplate('store')->register( \IPS\nexus\Package\Item::getItemsWithPermission( array( array( 'p_reg=1' ) ), 'pg_position, p_position', 10, 'read', \IPS\Content\Hideable::FILTER_AUTOMATIC, 0, NULL, TRUE ) );
|
||||
\IPS\Output::i()->title = \IPS\Member::loggedIn()->language()->addToStack('sign_up');
|
||||
Output::i()->bodyClasses[] = 'ipsLayout_minimal';
|
||||
Output::i()->sidebar['enabled'] = FALSE;
|
||||
Output::i()->output = Theme::i()->getTemplate('store')->register( Item::getItemsWithPermission( array( array( 'p_reg=1' ) ), 'pg_position, p_position', 10, 'read', Filter::FILTER_AUTOMATIC, 0, NULL, TRUE ) );
|
||||
Output::i()->title = Member::loggedIn()->language()->addToStack('sign_up');
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -411,8 +428,8 @@ class _store extends \IPS\Dispatcher\Controller
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
protected function cart()
|
||||
protected function cart() : void
|
||||
{
|
||||
\IPS\Output::i()->output = \IPS\Theme::i()->getTemplate('store')->cart();
|
||||
Output::i()->output = Theme::i()->getTemplate('store')->cart();
|
||||
}
|
||||
}
|
||||
@@ -12,40 +12,65 @@
|
||||
namespace IPS\nexus\modules\front\subscriptions;
|
||||
|
||||
/* To prevent PHP errors (extending class does not exist) revealing path */
|
||||
if ( !\defined( '\IPS\SUITE_UNIQUE_KEY' ) )
|
||||
|
||||
use DateInterval;
|
||||
use Exception;
|
||||
use IPS\core\Facebook\Pixel;
|
||||
use IPS\Dispatcher\Controller;
|
||||
use IPS\Http\Url;
|
||||
use IPS\Login;
|
||||
use IPS\Member;
|
||||
use IPS\nexus\Customer;
|
||||
use IPS\nexus\extensions\nexus\Item\Subscription;
|
||||
use IPS\nexus\Invoice;
|
||||
use IPS\nexus\Money;
|
||||
use IPS\nexus\Purchase;
|
||||
use IPS\nexus\Subscription\Package;
|
||||
use IPS\nexus\Subscription\Table;
|
||||
use IPS\nexus\Tax;
|
||||
use IPS\Output;
|
||||
use IPS\Request;
|
||||
use IPS\Session;
|
||||
use IPS\Settings;
|
||||
use IPS\Theme;
|
||||
use OutOfRangeException;
|
||||
use function defined;
|
||||
use function in_array;
|
||||
|
||||
if ( !defined( '\IPS\SUITE_UNIQUE_KEY' ) )
|
||||
{
|
||||
header( ( isset( $_SERVER['SERVER_PROTOCOL'] ) ? $_SERVER['SERVER_PROTOCOL'] : 'HTTP/1.0' ) . ' 403 Forbidden' );
|
||||
header( ( $_SERVER['SERVER_PROTOCOL'] ?? 'HTTP/1.0' ) . ' 403 Forbidden' );
|
||||
exit;
|
||||
}
|
||||
|
||||
/**
|
||||
* subscriptions
|
||||
*/
|
||||
class _subscriptions extends \IPS\Dispatcher\Controller
|
||||
class subscriptions extends Controller
|
||||
{
|
||||
/**
|
||||
* Execute
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function execute()
|
||||
public function execute() : void
|
||||
{
|
||||
/* Work out currency */
|
||||
if ( isset( \IPS\Request::i()->currency ) and \in_array( \IPS\Request::i()->currency, \IPS\nexus\Money::currencies() ) )
|
||||
if ( isset( Request::i()->currency ) and in_array( Request::i()->currency, Money::currencies() ) )
|
||||
{
|
||||
if ( isset( \IPS\Request::i()->csrfKey ) and \IPS\Login::compareHashes( (string) \IPS\Session::i()->csrfKey, (string) \IPS\Request::i()->csrfKey ) )
|
||||
if ( isset( Request::i()->csrfKey ) and Login::compareHashes( (string) Session::i()->csrfKey, (string) Request::i()->csrfKey ) )
|
||||
{
|
||||
$_SESSION['cart'] = array();
|
||||
\IPS\Request::i()->setCookie( 'currency', \IPS\Request::i()->currency );
|
||||
Request::i()->setCookie( 'currency', Request::i()->currency );
|
||||
|
||||
$url = \IPS\Http\Url::internal( 'app=nexus&module=subscriptions&controller=subscriptions', 'front', 'nexus_subscriptions' );
|
||||
$url = Url::internal( 'app=nexus&module=subscriptions&controller=subscriptions', 'front', 'nexus_subscriptions' );
|
||||
|
||||
if( isset( \IPS\Request::i()->register ) )
|
||||
if( isset( Request::i()->register ) )
|
||||
{
|
||||
$url = $url->setQueryString( 'register', (int) \IPS\Request::i()->register );
|
||||
$url = $url->setQueryString( 'register', (int) Request::i()->register );
|
||||
}
|
||||
|
||||
\IPS\Output::i()->redirect( $url );
|
||||
Output::i()->redirect( $url );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -57,46 +82,45 @@ class _subscriptions extends \IPS\Dispatcher\Controller
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
protected function manage()
|
||||
protected function manage() : void
|
||||
{
|
||||
if ( ! \IPS\Settings::i()->nexus_subs_enabled )
|
||||
if ( ! Settings::i()->nexus_subs_enabled )
|
||||
{
|
||||
\IPS\Output::i()->error( 'nexus_no_subs', '2X379/1', 404, '' );
|
||||
Output::i()->error( 'nexus_no_subs', '2X379/1', 404, '' );
|
||||
}
|
||||
|
||||
/* Send no-cache headers for this page, required for guest sign-ups */
|
||||
\IPS\Output::setCacheTime( false );
|
||||
Output::i()->pageCaching = FALSE;
|
||||
|
||||
/* 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 );
|
||||
$table = new Table( Url::internal( 'app=nexus&module=subscriptions&controller=subscriptions', 'front', 'nexus_subscriptions' ) );
|
||||
$current = \IPS\nexus\Subscription::loadByMember( Member::loggedIn(), FALSE );
|
||||
|
||||
if ( $current )
|
||||
{
|
||||
$table->activeSubscription = $current;
|
||||
}
|
||||
|
||||
if ( isset( \IPS\Request::i()->purchased ) and $table->activeSubscription )
|
||||
if ( isset( Request::i()->purchased ) and $table->activeSubscription )
|
||||
{
|
||||
try
|
||||
{
|
||||
$invoice = \IPS\nexus\Invoice::load( $table->activeSubscription->invoice_id );
|
||||
$invoice = 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');
|
||||
Pixel::i()->Purchase = array( 'value' => $invoice->total->amount, 'currency' => $invoice->total->currency );
|
||||
Output::i()->inlineMessage = Member::loggedIn()->language()->addToStack( 'nexus_subs_paid_flash_msg');
|
||||
}
|
||||
catch( \Exception $e ) { }
|
||||
catch( Exception ) { }
|
||||
}
|
||||
|
||||
\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' ) );
|
||||
Output::i()->jsFiles = array_merge( Output::i()->jsFiles, Output::i()->js( 'front_subscriptions.js', 'nexus', 'front' ) );
|
||||
|
||||
\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') );
|
||||
Output::i()->breadcrumb['module'] = array( Url::internal( 'app=nexus&module=subscriptions&controller=subscriptions', 'front', 'nexus_subscriptions' ), Member::loggedIn()->language()->addToStack('nexus_front_subscriptions') );
|
||||
|
||||
\IPS\Output::i()->linkTags['canonical'] = (string) \IPS\Http\Url::internal( 'app=nexus&module=subscriptions&controller=subscriptions', 'front', 'nexus_subscriptions' );
|
||||
\IPS\Output::i()->title = \IPS\Member::loggedIn()->language()->addToStack('nexus_front_subscriptions');
|
||||
\IPS\Output::i()->output = $table;
|
||||
Output::i()->linkTags['canonical'] = (string) Url::internal( 'app=nexus&module=subscriptions&controller=subscriptions', 'front', 'nexus_subscriptions' );
|
||||
Output::i()->title = Member::loggedIn()->language()->addToStack('nexus_front_subscriptions');
|
||||
Output::i()->output = $table;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -104,40 +128,40 @@ class _subscriptions extends \IPS\Dispatcher\Controller
|
||||
*
|
||||
* @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()
|
||||
protected function change() : void
|
||||
{
|
||||
/* CSRF Check */
|
||||
\IPS\Session::i()->csrfCheck();
|
||||
Session::i()->csrfCheck();
|
||||
|
||||
try
|
||||
{
|
||||
$newPackage = \IPS\nexus\Subscription\Package::load( \IPS\Request::i()->id );
|
||||
$newPackage = Package::load( Request::i()->id );
|
||||
}
|
||||
catch( \OutOfRangeException $e )
|
||||
catch( OutOfRangeException )
|
||||
{
|
||||
\IPS\Output::i()->error( 'nexus_no_subs_package', '2X379/2', 404, '' );
|
||||
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, '' );
|
||||
Output::i()->error( 'node_error', '2X379/7', 403, '' );
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
$subscription = \IPS\nexus\Subscription::loadByMember( \IPS\Member::loggedIn(), FALSE );
|
||||
$subscription = \IPS\nexus\Subscription::loadByMember( Member::loggedIn(), FALSE );
|
||||
}
|
||||
catch( \OutOfRangeException $e )
|
||||
catch( OutOfRangeException )
|
||||
{
|
||||
\IPS\Output::i()->error( 'nexus_no_subs_subs', '2X379/3', 404, '' );
|
||||
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, TRUE, TRUE ) as $row )
|
||||
foreach ( Subscription::getPurchases( Customer::loggedIn(), $subscription->package->id, TRUE, TRUE ) as $row )
|
||||
{
|
||||
if ( !$row->cancelled OR ( $row->cancelled AND $row->can_reactivate ) )
|
||||
{
|
||||
@@ -149,33 +173,34 @@ class _subscriptions extends \IPS\Dispatcher\Controller
|
||||
|
||||
if ( $purchase === NULL )
|
||||
{
|
||||
\IPS\Output::i()->error( 'nexus_sub_no_purchase', '2X379/4', 404, '' );
|
||||
Output::i()->error( 'nexus_sub_no_purchase', '2X379/4', 404, '' );
|
||||
}
|
||||
|
||||
/* @var Purchase $purchase */
|
||||
/* We cannot process changes if an active Billing Agreement is in place */
|
||||
if( $purchase->billing_agreement and !$purchase->billing_agreement->canceled )
|
||||
{
|
||||
\IPS\Output::i()->error( 'nexus_sub_no_change_ba', '2X379/B', 404, '' );
|
||||
Output::i()->error( 'nexus_sub_no_change_ba', '2X379/B', 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() );
|
||||
$upgradeCost = $newPackage->costToUpgrade( $subscription->package, Customer::loggedIn() );
|
||||
|
||||
if ( $upgradeCost === NULL )
|
||||
{
|
||||
\IPS\Output::i()->error( 'nexus_no_subs_nocost', '2X379/5', 404, '' );
|
||||
Output::i()->error( 'nexus_no_subs_nocost', '2X379/5', 404, '' );
|
||||
}
|
||||
|
||||
$invoice = $subscription->package->upgradeDowngrade( $purchase, $newPackage );
|
||||
|
||||
if ( $invoice )
|
||||
{
|
||||
\IPS\Output::i()->redirect( $invoice->checkoutUrl() );
|
||||
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' ) );
|
||||
Output::i()->redirect( Url::internal( 'app=nexus&module=subscriptions&controller=subscriptions', 'front', 'nexus_subscriptions' ) );
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -183,37 +208,37 @@ class _subscriptions extends \IPS\Dispatcher\Controller
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
protected function purchase()
|
||||
protected function purchase() : void
|
||||
{
|
||||
/* CSRF Check */
|
||||
\IPS\Session::i()->csrfCheck();
|
||||
Session::i()->csrfCheck();
|
||||
|
||||
/* Send no-cache headers for this page, required for guest sign-ups */
|
||||
\IPS\Output::setCacheTime( false );
|
||||
Output::i()->pageCaching = FALSE;
|
||||
|
||||
/* Already purchased a subscription */
|
||||
if ( $current = \IPS\nexus\Subscription::loadByMember( \IPS\nexus\Customer::loggedIn(), FALSE ) AND ( $current->purchase AND ( !$current->purchase->cancelled OR $current->purchase->can_reactivate ) ) )
|
||||
if ( $current = \IPS\nexus\Subscription::loadByMember( Customer::loggedIn(), FALSE ) AND ( $current->purchase AND ( !$current->purchase->cancelled OR $current->purchase->can_reactivate ) ) )
|
||||
{
|
||||
\IPS\Output::i()->error( 'nexus_subs_already_got_package', '2X379/6', 403, '' );
|
||||
Output::i()->error( 'nexus_subs_already_got_package', '2X379/6', 403, '' );
|
||||
}
|
||||
|
||||
$package = \IPS\nexus\Subscription\Package::load( \IPS\Request::i()->id );
|
||||
$package = Package::load( Request::i()->id );
|
||||
|
||||
/* Is the subscription purchasable ? */
|
||||
if ( !$package->enabled )
|
||||
{
|
||||
\IPS\Output::i()->error( 'node_error', '2X379/7', 403, '' );
|
||||
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 = new Subscription( Customer::loggedIn()->language()->get( $package->_titleLanguageKey ), $price );
|
||||
$item->id = $package->id;
|
||||
try
|
||||
{
|
||||
$item->tax = \IPS\nexus\Tax::load( $package->tax );
|
||||
$item->tax = Tax::load( $package->tax );
|
||||
}
|
||||
catch ( \OutOfRangeException $e ) { }
|
||||
catch ( OutOfRangeException ) { }
|
||||
if ( $package->gateways !== '*' )
|
||||
{
|
||||
$item->paymentMethodIds = explode( ',', $package->gateways );
|
||||
@@ -221,19 +246,19 @@ class _subscriptions extends \IPS\Dispatcher\Controller
|
||||
$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'] ) );
|
||||
$item->initialInterval = new DateInterval( 'P' . $costs['term'] . mb_strtoupper( $costs['unit'] ) );
|
||||
}
|
||||
|
||||
/* Generate the invoice */
|
||||
$invoice = new \IPS\nexus\Invoice;
|
||||
$invoice = new Invoice;
|
||||
$invoice->currency = $price->currency;
|
||||
$invoice->member = \IPS\nexus\Customer::loggedIn();
|
||||
$invoice->member = 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() );
|
||||
Output::i()->redirect( $invoice->checkoutUrl() );
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -241,30 +266,30 @@ class _subscriptions extends \IPS\Dispatcher\Controller
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
protected function reactivate()
|
||||
protected function reactivate() : void
|
||||
{
|
||||
/* CSRF Check */
|
||||
\IPS\Session::i()->csrfCheck();
|
||||
Session::i()->csrfCheck();
|
||||
|
||||
/* Get subscription and purchase */
|
||||
try
|
||||
{
|
||||
$package = \IPS\nexus\Subscription\Package::load( \IPS\Request::i()->id );
|
||||
$package = Package::load( Request::i()->id );
|
||||
}
|
||||
catch( \OutOfRangeException $e )
|
||||
catch( OutOfRangeException )
|
||||
{
|
||||
\IPS\Output::i()->error( 'nexus_no_subs_package', '2X379/2', 404, '' );
|
||||
Output::i()->error( 'nexus_no_subs_package', '2X379/2', 404, '' );
|
||||
}
|
||||
try
|
||||
{
|
||||
$subscription = \IPS\nexus\Subscription::loadByMemberAndPackage( \IPS\Member::loggedIn(), $package, FALSE );
|
||||
$subscription = \IPS\nexus\Subscription::loadByMemberAndPackage( Member::loggedIn(), $package, FALSE );
|
||||
}
|
||||
catch( \OutOfRangeException $e )
|
||||
catch( OutOfRangeException )
|
||||
{
|
||||
\IPS\Output::i()->error( 'nexus_no_subs_subs', '2X379/8', 404, '' );
|
||||
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 )
|
||||
foreach ( Subscription::getPurchases( Customer::loggedIn(), $subscription->package->id, TRUE, TRUE ) as $row )
|
||||
{
|
||||
if ( $row->can_reactivate )
|
||||
{
|
||||
@@ -274,15 +299,16 @@ class _subscriptions extends \IPS\Dispatcher\Controller
|
||||
}
|
||||
if ( $purchase === NULL )
|
||||
{
|
||||
\IPS\Output::i()->error( 'nexus_sub_no_purchase', '2X379/9', 404, '' );
|
||||
Output::i()->error( 'nexus_sub_no_purchase', '2X379/9', 404, '' );
|
||||
}
|
||||
|
||||
|
||||
/* @var Purchase $purchase */
|
||||
/* Set renewal terms */
|
||||
try
|
||||
{
|
||||
$currency = $purchase->original_invoice->currency;
|
||||
}
|
||||
catch ( \Exception $e )
|
||||
catch ( Exception )
|
||||
{
|
||||
$currency = $purchase->member->defaultCurrency();
|
||||
}
|
||||
@@ -296,11 +322,11 @@ class _subscriptions extends \IPS\Dispatcher\Controller
|
||||
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 );
|
||||
Output::i()->redirect( $url );
|
||||
}
|
||||
else
|
||||
{
|
||||
\IPS\Output::i()->redirect( \IPS\Http\Url::internal( 'app=nexus&module=subscriptions&controller=subscriptions', 'front', 'nexus_subscriptions' ) );
|
||||
Output::i()->redirect( Url::internal( 'app=nexus&module=subscriptions&controller=subscriptions', 'front', 'nexus_subscriptions' ) );
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,63 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* @brief Handle actions from emails
|
||||
* @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 Nexus
|
||||
* @since 17 Nov 2020
|
||||
*/
|
||||
|
||||
namespace IPS\nexus\modules\front\support;
|
||||
|
||||
/* 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;
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle actions from emails
|
||||
*/
|
||||
class _email extends \IPS\Dispatcher\Controller
|
||||
{
|
||||
/**
|
||||
* Send or discard reply
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function sendDiscard()
|
||||
{
|
||||
try
|
||||
{
|
||||
$reply = \IPS\nexus\Support\Reply::load( \IPS\Request::i()->id );
|
||||
if ( !\IPS\Login::compareHashes( md5( $reply->item()->email_key . $reply->date ), (string) \IPS\Request::i()->key ) )
|
||||
{
|
||||
throw new \OutOfRangeException;
|
||||
}
|
||||
}
|
||||
catch ( \OutOfRangeException $e )
|
||||
{
|
||||
\IPS\Output::i()->error( 'node_error', '2X206/1', 404, '' );
|
||||
}
|
||||
|
||||
if ( $reply->type !== \IPS\nexus\Support\Reply::REPLY_PENDING )
|
||||
{
|
||||
\IPS\Output::i()->error( 'support_reply_not_pending', '1X206/2', 403, '' );
|
||||
}
|
||||
|
||||
if ( \IPS\Request::i()->send )
|
||||
{
|
||||
$reply->sendPending();
|
||||
}
|
||||
else
|
||||
{
|
||||
$reply->delete();
|
||||
}
|
||||
|
||||
\IPS\Output::i()->title = \IPS\Member::loggedIn()->language()->addToStack( \IPS\Request::i()->send ? 'support_pending_sent' : 'support_pending_discarded' );
|
||||
\IPS\Output::i()->output = \IPS\Theme::i()->getTemplate( 'support', 'nexus', 'front' )->pendingDone( \IPS\Request::i()->send ? 'support_pending_sent' : 'support_pending_discarded' );
|
||||
}
|
||||
}
|
||||
@@ -1,90 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* @brief Support Index
|
||||
* @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 Nexus
|
||||
* @since 08 Apr 2014
|
||||
*/
|
||||
|
||||
namespace IPS\nexus\modules\front\support;
|
||||
|
||||
/* 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;
|
||||
}
|
||||
|
||||
/**
|
||||
* Support Index
|
||||
*/
|
||||
class _home extends \IPS\Dispatcher\Controller
|
||||
{
|
||||
/**
|
||||
* Execute
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function execute()
|
||||
{
|
||||
if ( !\IPS\Member::loggedIn()->member_id )
|
||||
{
|
||||
\IPS\Output::i()->error( 'no_module_permission_guest', '2X265/1', 403, '' );
|
||||
}
|
||||
|
||||
parent::execute();
|
||||
}
|
||||
|
||||
/**
|
||||
* Index
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
protected function manage()
|
||||
{
|
||||
$table = new \IPS\Helpers\Table\Content( 'IPS\nexus\Support\Request', \IPS\Http\Url::internal( 'app=nexus&module=support&controller=home', 'front', 'support' ) );
|
||||
$table->rowsTemplate = array( \IPS\Theme::i()->getTemplate( 'support' ), 'tableRows' );
|
||||
$table->classes[] = 'ipsDataList_large';
|
||||
$table->showFilters = FALSE;
|
||||
\IPS\Output::i()->title = \IPS\Member::loggedIn()->language()->addToStack('support');
|
||||
\IPS\Output::i()->output = \IPS\Theme::i()->getTemplate('support')->requestList( (string) $table );
|
||||
}
|
||||
|
||||
/**
|
||||
* Create
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
protected function create()
|
||||
{
|
||||
\IPS\Output::i()->title = \IPS\Member::loggedIn()->language()->addToStack('new_request');
|
||||
\IPS\Output::i()->breadcrumb[] = array( NULL, \IPS\Member::loggedIn()->language()->addToStack( 'new_request' ) );
|
||||
|
||||
$accounts = \IPS\nexus\Customer::loggedIn()->parentContacts( array( 'support=1' ) );
|
||||
if ( \count( $accounts ) and !isset( \IPS\Request::i()->account ) )
|
||||
{
|
||||
$options = array();
|
||||
$options[ \IPS\nexus\Customer::loggedIn()->member_id ] = \IPS\nexus\Customer::loggedIn()->language()->addToStack( 'my_account', FALSE, array( 'sprintf' => array( \IPS\nexus\Customer::loggedIn()->cm_name ) ) );
|
||||
foreach ( $accounts as $contact )
|
||||
{
|
||||
$options[ $contact->main_id->member_id ] = $contact->main_id->cm_name;
|
||||
}
|
||||
|
||||
$form = new \IPS\Helpers\Form( 'account', 'continue' );
|
||||
$form->class = 'ipsForm_vertical';
|
||||
$form->add( new \IPS\Helpers\Form\Radio( 'support_account', \IPS\nexus\Customer::loggedIn()->member_id, TRUE, array( 'options' => $options, 'parse' => 'normal' ) ) );
|
||||
if ( $values = $form->values() )
|
||||
{
|
||||
\IPS\Output::i()->redirect( \IPS\Http\Url::internal( "app=nexus&module=support&controller=home&do=create&account={$values['support_account']}", 'front', 'support_create' ) );
|
||||
}
|
||||
\IPS\Output::i()->output = $form->customTemplate( array( \IPS\Theme::i()->getTemplate( 'forms', 'core' ), 'popupTemplate' ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
\IPS\Output::i()->output = \IPS\Theme::i()->getTemplate('support')->create( \IPS\nexus\Support\Request::create() );
|
||||
}
|
||||
}
|
||||
}
|
||||
Whitespace-only changes.
@@ -1,41 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* @brief Legacy Redirector
|
||||
* @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 07 Sep 2016
|
||||
*/
|
||||
|
||||
namespace IPS\nexus\modules\front\support;
|
||||
|
||||
/* 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;
|
||||
}
|
||||
|
||||
/**
|
||||
* Legacy Redirector
|
||||
*/
|
||||
class _redirect extends \IPS\Dispatcher\Controller
|
||||
{
|
||||
/**
|
||||
* Redirect
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
protected function manage()
|
||||
{
|
||||
$url = \IPS\Http\Url::internal( "app=core&module=system&controller=redirect" )->setQueryString( array(
|
||||
'url' => \IPS\Request::i()->url,
|
||||
'resource' => ( \IPS\Request::i()->resource ) ? 1 : NULL,
|
||||
'key' => hash_hmac( "sha256", \IPS\Request::i()->url, \IPS\Settings::i()->site_secret_key . 'r' ),
|
||||
) );
|
||||
|
||||
\IPS\Output::i()->redirect( $url );
|
||||
}
|
||||
}
|
||||
@@ -1,182 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* @brief Support Request View
|
||||
* @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 Nexus
|
||||
* @since 09 Apr 2014
|
||||
*/
|
||||
|
||||
namespace IPS\nexus\modules\front\support;
|
||||
|
||||
/* 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;
|
||||
}
|
||||
|
||||
/**
|
||||
* Support Request View
|
||||
*/
|
||||
class _view extends \IPS\Content\Controller
|
||||
{
|
||||
/**
|
||||
* [Content\Controller] Class
|
||||
*/
|
||||
protected static $contentModel = 'IPS\nexus\Support\Request';
|
||||
|
||||
/**
|
||||
* Execute
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function execute()
|
||||
{
|
||||
if ( !\IPS\Member::loggedIn()->member_id )
|
||||
{
|
||||
\IPS\Output::i()->error( 'no_module_permission_guest', '2X264/1', 403, '' );
|
||||
}
|
||||
|
||||
\IPS\Output::i()->jsFiles = array_merge( \IPS\Output::i()->jsFiles, \IPS\Output::i()->js( 'front_support.js', 'nexus', 'front' ) );
|
||||
parent::execute();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief The current support request (instance of \IPS\nexus\Support\Request)
|
||||
*/
|
||||
protected $request;
|
||||
|
||||
/**
|
||||
* View Item
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
protected function manage()
|
||||
{
|
||||
$this->request = parent::manage();
|
||||
if ( !$this->request )
|
||||
{
|
||||
\IPS\Output::i()->error( 'node_error', '2X204/1', 404, '' );
|
||||
}
|
||||
|
||||
$allowedStatuses = \IPS\nexus\Support\Status::publicSetStatuses( $this->request );
|
||||
if ( isset( \IPS\Request::i()->setStatus ) and !empty( $allowedStatuses ) and \in_array( \IPS\Request::i()->setStatus, array_keys( $allowedStatuses ) ) )
|
||||
{
|
||||
\IPS\Session::i()->csrfCheck();
|
||||
$newStatus = \IPS\nexus\Support\Status::load( \IPS\Request::i()->setStatus );
|
||||
$this->request->log( 'status', $this->request->status, $newStatus );
|
||||
$this->request->status = $newStatus;
|
||||
$this->request->save();
|
||||
\IPS\Output::i()->redirect( $this->request->url() );
|
||||
}
|
||||
|
||||
if ( !isset( \IPS\Request::i()->root ) and $purchase = $this->request->purchase and $purchase->childrenCount( NULL ) )
|
||||
{
|
||||
\IPS\Request::i()->root = $purchase->id;
|
||||
\IPS\Request::i()->noshowroot = TRUE;
|
||||
}
|
||||
|
||||
\IPS\Output::i()->output = \IPS\Theme::i()->getTemplate( 'support' )->request( $this->request );
|
||||
}
|
||||
|
||||
/**
|
||||
* Rate Staff Response
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
protected function rate()
|
||||
{
|
||||
try
|
||||
{
|
||||
$reply = \IPS\nexus\Support\Reply::loadAndCheckPerms( \IPS\Request::i()->response );
|
||||
}
|
||||
catch ( \OutOfRangeException $e )
|
||||
{
|
||||
\IPS\Output::i()->error( 'node_error', '2X209/1', 404, '' );
|
||||
}
|
||||
|
||||
/* If we've rated, do not allow us to rate again */
|
||||
try
|
||||
{
|
||||
\IPS\Db::i()->select( '*', 'nexus_support_ratings', array( 'rating_reply=?', $reply->id ) )->first();
|
||||
|
||||
\IPS\Output::i()->error( 'already_rated', '2X204/2', 403, '' );
|
||||
}
|
||||
catch ( \UnderflowException $e ) {}
|
||||
|
||||
$form = new \IPS\Helpers\Form( 'feedback', 'send_feedback' );
|
||||
$form->class = 'ipsForm_vertical';
|
||||
$form->add( new \IPS\Helpers\Form\Rating( 'support_rating_rating', \IPS\Request::i()->rating, TRUE ) );
|
||||
$form->add( new \IPS\Helpers\Form\TextArea( 'support_rating_feedback', NULL, FALSE ) );
|
||||
if ( $values = $form->values() )
|
||||
{
|
||||
$save = array(
|
||||
'rating_reply' => $reply->id,
|
||||
'rating_rating' => $values['support_rating_rating'],
|
||||
'rating_from' => \IPS\Member::loggedIn()->member_id,
|
||||
'rating_staff' => $reply->member,
|
||||
'rating_note' => $values['support_rating_feedback'],
|
||||
'rating_date' => time()
|
||||
);
|
||||
|
||||
\IPS\Db::i()->insert( 'nexus_support_ratings', $save );
|
||||
|
||||
if ( \IPS\Request::i()->isAjax() )
|
||||
{
|
||||
$reply->ratingData = $save;
|
||||
\IPS\Output::i()->json( \IPS\Theme::i()->getTemplate('support')->ratingValue( $reply ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
\IPS\Output::i()->redirect( $reply->url(), 'thanks_for_your_feedback' );
|
||||
}
|
||||
}
|
||||
|
||||
\IPS\Output::i()->output = $form->customTemplate( array( \IPS\Theme::i()->getTemplate( 'forms', 'core' ), 'popupTemplate' ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Change Severity
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
protected function severity()
|
||||
{
|
||||
try
|
||||
{
|
||||
$request = \IPS\nexus\Support\Request::loadAndCheckPerms( \IPS\Request::i()->id );
|
||||
}
|
||||
catch ( \OutOfRangeException $e )
|
||||
{
|
||||
\IPS\Output::i()->error( 'node_error', '2X209/1', 404, '' );
|
||||
}
|
||||
|
||||
if ( !\IPS\Settings::i()->nexus_severities or \IPS\Member::loggedIn()->cm_no_sev )
|
||||
{
|
||||
\IPS\Output::i()->error( 'node_error', '2X209/3', 404, '' );
|
||||
}
|
||||
|
||||
$options = array();
|
||||
foreach ( \IPS\nexus\Support\Severity::roots( NULL, NULL, array( array( 'sev_public=1' ), array( "sev_departments='*' OR " . \IPS\Db::i()->findInSet( 'sev_departments', array( $request->department->id ) ) ) ) ) as $severity )
|
||||
{
|
||||
$options[ $severity->id ] = $severity->_title;
|
||||
}
|
||||
|
||||
$form = new \IPS\Helpers\Form;
|
||||
$form->class = 'ipsForm_vertical';
|
||||
$form->add( new \IPS\Helpers\Form\Radio( 'support_severity', $request->severity->id, FALSE, array(
|
||||
'options' => $options
|
||||
) ) );
|
||||
if ( $values = $form->values() )
|
||||
{
|
||||
$request->severity = \IPS\nexus\Support\Severity::load( $values['support_severity'] );
|
||||
$request->save();
|
||||
\IPS\Output::i()->redirect( $request->url() );
|
||||
}
|
||||
|
||||
\IPS\Output::i()->output = $form->customTemplate( array( \IPS\Theme::i()->getTemplate( 'forms', 'core' ), 'popupTemplate' ) );
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user