Version 4.5.0

This commit is contained in:
Neo committed 2025-12-19 05:51:58 -08:00
1 parent 1a0c7fd3c2
commit f79dcf067a
3791 files changed
+248032 -76372

No files matched your search

@@ -12,7 +12,7 @@
namespace IPS\nexus\modules\admin\customers;
/* To prevent PHP errors (extending class does not exist) revealing path */
if ( !defined( '\IPS\SUITE_UNIQUE_KEY' ) )
if ( !\defined( '\IPS\SUITE_UNIQUE_KEY' ) )
{
header( ( isset( $_SERVER['SERVER_PROTOCOL'] ) ? $_SERVER['SERVER_PROTOCOL'] : 'HTTP/1.0' ) . ' 403 Forbidden' );
exit;
@@ -23,6 +23,11 @@ if ( !defined( '\IPS\SUITE_UNIQUE_KEY' ) )
*/
class _fields extends \IPS\Node\Controller
{
/**
* @brief Has been CSRF-protected
*/
public static $csrfProtected = TRUE;
/**
* Node Class
*/
@@ -12,7 +12,7 @@
namespace IPS\nexus\modules\admin\customers;
/* To prevent PHP errors (extending class does not exist) revealing path */
if ( !defined( '\IPS\SUITE_UNIQUE_KEY' ) )
if ( !\defined( '\IPS\SUITE_UNIQUE_KEY' ) )
{
header( ( isset( $_SERVER['SERVER_PROTOCOL'] ) ? $_SERVER['SERVER_PROTOCOL'] : 'HTTP/1.0' ) . ' 403 Forbidden' );
exit;
@@ -23,6 +23,11 @@ if ( !defined( '\IPS\SUITE_UNIQUE_KEY' ) )
*/
class _purchases extends \IPS\Dispatcher\Controller
{
/**
* @brief Has been CSRF-protected
*/
public static $csrfProtected = TRUE;
/**
* View
*
@@ -152,9 +157,22 @@ class _purchases extends \IPS\Dispatcher\Controller
{
$groupedChildren[] = $child;
$childGroupedRenewals = $child->grouped_renewals;
/* Figure out tax */
$tax = NULL;
try
{
$childGroupedRenewalTerm = new \IPS\nexus\Purchase\RenewalTerm( new \IPS\nexus\Money( $childGroupedRenewals['price'], $this->purchase->renewals->cost->currency ), new \DateInterval( 'P' . $childGroupedRenewals['term'] . mb_strtoupper( $childGroupedRenewals['unit'] ) ) );
if( $this->purchase->tax )
{
$tax = \IPS\nexus\Tax::load( $this->purchase->tax );
}
}
catch( \OutOfRangeException $e ){}
try
{
$childGroupedRenewalTerm = new \IPS\nexus\Purchase\RenewalTerm( new \IPS\nexus\Money( $childGroupedRenewals['price'], $this->purchase->renewals->cost->currency ), new \DateInterval( 'P' . $childGroupedRenewals['term'] . mb_strtoupper( $childGroupedRenewals['unit'] ) ), $tax );
$renewals = new \IPS\nexus\Purchase\RenewalTerm( $renewals->subtract( $childGroupedRenewalTerm ), $renewals->interval );
}
catch ( \Exception $e ) { }
@@ -278,6 +296,7 @@ class _purchases extends \IPS\Dispatcher\Controller
$invoice = new \IPS\nexus\Invoice;
$invoice->currency = $this->purchase->renewal_currency;
$invoice->member = $this->purchase->member;
$invoice->billaddress = $this->purchase->member->primaryBillingAddress();
$invoice->addItem( \IPS\nexus\Invoice\Item\Renewal::create( $this->purchase, $values['renew_cycles'] ) );
$invoice->save();
$invoice->sendNotification();
@@ -393,6 +412,7 @@ class _purchases extends \IPS\Dispatcher\Controller
protected function reactivate()
{
\IPS\Dispatcher::i()->checkAcpPermission( 'purchases_cancel' );
\IPS\Session::i()->csrfCheck();
$parent = $this->purchase->parent();
@@ -486,6 +506,8 @@ class _purchases extends \IPS\Dispatcher\Controller
protected function group()
{
\IPS\Dispatcher::i()->checkAcpPermission( 'purchases_edit' );
\IPS\Session::i()->csrfCheck();
if ( $this->purchase->billing_agreement and !$this->purchase->billing_agreement->canceled )
{
\IPS\Output::i()->error( 'not_with_billing_agreement', '2X195/E', 403, '' );
@@ -511,6 +533,8 @@ class _purchases extends \IPS\Dispatcher\Controller
protected function ungroup()
{
\IPS\Dispatcher::i()->checkAcpPermission( 'purchases_edit' );
\IPS\Session::i()->csrfCheck();
if ( $this->purchase->billing_agreement and !$this->purchase->billing_agreement->canceled )
{
\IPS\Output::i()->error( 'not_with_billing_agreement', '2X195/F', 403, '' );
@@ -1,68 +0,0 @@
<?php
/**
* @brief referralbanners
* @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 18 Aug 2014
*/
namespace IPS\nexus\modules\admin\customers;
/* 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;
}
/**
* referralbanners
*/
class _referralbanners extends \IPS\Node\Controller
{
/**
* Node Class
*/
protected $nodeClass = 'IPS\nexus\ReferralBanner';
/**
* Title can contain HTML?
*/
public $_titleHtml = TRUE;
/**
* Execute
*
* @return void
*/
public function execute()
{
\IPS\Dispatcher::i()->checkAcpPermission( 'referralbanners_manage' );
parent::execute();
}
/**
* Manage
*
* @return void
*/
public function manage()
{
\IPS\Output::i()->output .= \IPS\Theme::i()->getTemplate( 'forms', 'core' )->blurb( 'referral_banners_blurb', TRUE, TRUE );
return parent::manage();
}
/**
* Form
*
* @return void
*/
public function form()
{
parent::form();
\IPS\Output::i()->title = \IPS\Member::loggedIn()->language()->addToStack('referral_banners');
}
}
@@ -1,69 +0,0 @@
<?php
/**
* @brief Referrals
* @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 15 Aug 2014
*/
namespace IPS\nexus\modules\admin\customers;
/* 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;
}
/**
* Referrals
*/
class _referrals extends \IPS\Dispatcher\Controller
{
/**
* Call
*
* @return void
*/
public function __call( $method, $args )
{
$tabs = array();
if( \IPS\Member::loggedIn()->hasAcpRestriction( 'nexus', 'customers', 'referrals_manage' ) )
{
$tabs['refersettings'] = 'settings';
}
if( \IPS\Settings::i()->cm_ref_on and \IPS\Member::loggedIn()->hasAcpRestriction( 'nexus', 'customers', 'referrals_commission_rules' ) )
{
$tabs['commissionrules'] = 'commission_rules';
}
if( \IPS\Settings::i()->cm_ref_on and \IPS\Member::loggedIn()->hasAcpRestriction( 'nexus', 'customers', 'referrals_banners' ) )
{
$tabs['referralbanners'] = 'referral_banners';
}
if ( isset( \IPS\Request::i()->tab ) and isset( $tabs[ \IPS\Request::i()->tab ] ) )
{
$activeTab = \IPS\Request::i()->tab;
}
else
{
$_tabs = array_keys( $tabs ) ;
$activeTab = array_shift( $_tabs );
}
$classname = 'IPS\nexus\modules\admin\customers\\' . $activeTab;
$class = new $classname;
$class->url = \IPS\Http\Url::internal("app=nexus&module=customers&controller=referrals&tab={$activeTab}");
$class->execute();
if ( $method !== 'manage' or \IPS\Request::i()->isAjax() )
{
return;
}
\IPS\Output::i()->title = \IPS\Member::loggedIn()->language()->addToStack('menu__nexus_customers_referrals');
\IPS\Output::i()->output = \IPS\Theme::i()->getTemplate( 'global', 'core' )->tabs( $tabs, $activeTab, \IPS\Output::i()->output, \IPS\Http\Url::internal( "app=nexus&module=customers&controller=referrals" ) );
}
}
@@ -1,55 +0,0 @@
<?php
/**
* @brief Referral Settings
* @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 15 Aug 2014
*/
namespace IPS\nexus\modules\admin\customers;
/* 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;
}
/**
* Referral Settings
*/
class _refersettings extends \IPS\Dispatcher\Controller
{
/**
* Manage
*
* @return void
*/
public function execute()
{
$tabsKey = md5( \IPS\Http\Url::internal("app=nexus&module=customers&controller=referrals") );
$form = new \IPS\Helpers\Form;
$form->add( new \IPS\Helpers\Form\YesNo( 'cm_ref_on', \IPS\Settings::i()->cm_ref_on, FALSE, array( 'togglesOn' => array( 'nexus_com_rules' ) ) ) );
$form->add( new \IPS\Helpers\Form\YesNo( 'nexus_com_rules', \IPS\Settings::i()->nexus_com_rules, FALSE, array( 'togglesOff' => array( 'nexus_com_rules_alt' ) ), NULL, NULL, NULL, 'nexus_com_rules' ) );
$form->add( new \IPS\Helpers\Form\Translatable( 'nexus_com_rules_alt', NULL, FALSE, array( 'app' => 'nexus', 'key' => 'nexus_com_rules_val', 'editor' => array( 'app' => 'core', 'key' => 'Admin', 'autoSaveKey' => 'nexus_com_rules_alt', 'attachIds' => array( NULL, NULL, 'nexus_com_rules_alt' ) ) ), NULL, NULL, NULL, 'nexus_com_rules_alt' ) );
if ( $values = $form->values() )
{
\IPS\Lang::saveCustom( 'nexus', 'nexus_com_rules_val', $values['nexus_com_rules_alt'] );
unset( $values['nexus_com_rules_alt'] );
$form->saveAsSettings( $values );
/* Clear guest page caches */
\IPS\Data\Cache::i()->clearAll();
\IPS\Output::i()->redirect( \IPS\Http\Url::internal('app=nexus&module=customers&controller=referrals') );
}
\IPS\Output::i()->output = $form;
}
}
@@ -12,7 +12,7 @@
namespace IPS\nexus\modules\admin\customers;
/* To prevent PHP errors (extending class does not exist) revealing path */
if ( !defined( '\IPS\SUITE_UNIQUE_KEY' ) )
if ( !\defined( '\IPS\SUITE_UNIQUE_KEY' ) )
{
header( ( isset( $_SERVER['SERVER_PROTOCOL'] ) ? $_SERVER['SERVER_PROTOCOL'] : 'HTTP/1.0' ) . ' 403 Forbidden' );
exit;
@@ -23,6 +23,11 @@ if ( !defined( '\IPS\SUITE_UNIQUE_KEY' ) )
*/
class _search extends \IPS\Dispatcher\Controller
{
/**
* @brief Has been CSRF-protected
*/
public static $csrfProtected = TRUE;
/**
* Execute
*
@@ -52,7 +57,7 @@ class _search extends \IPS\Dispatcher\Controller
array(
'select' => 'address',
'from' => 'nexus_customer_addresses',
'where' => 'nexus_customer_addresses.member=nexus_customers.member_id AND primary_billing=1'
'where' => 'nexus_customer_addresses.`member`=nexus_customers.member_id AND primary_billing=1'
)
);
$table->include = array( 'photo', 'name', 'cm_last_name', 'cm_first_name', 'email', 'address' );
@@ -12,7 +12,7 @@
namespace IPS\nexus\modules\admin\customers;
/* To prevent PHP errors (extending class does not exist) revealing path */
if ( !defined( '\IPS\SUITE_UNIQUE_KEY' ) )
if ( !\defined( '\IPS\SUITE_UNIQUE_KEY' ) )
{
header( ( isset( $_SERVER['SERVER_PROTOCOL'] ) ? $_SERVER['SERVER_PROTOCOL'] : 'HTTP/1.0' ) . ' 403 Forbidden' );
exit;
@@ -23,6 +23,11 @@ if ( !defined( '\IPS\SUITE_UNIQUE_KEY' ) )
*/
class _view extends \IPS\Dispatcher\Controller
{
/**
* @brief Has been CSRF-protected
*/
public static $csrfProtected = TRUE;
/**
* @brief Member
*/
@@ -82,12 +87,13 @@ class _view extends \IPS\Dispatcher\Controller
*/
protected function addresses()
{
$addresses = new \IPS\Helpers\Table\Db( 'nexus_customer_addresses', \IPS\Http\Url::internal("app=nexus&module=customers&controller=view&id={$this->member->member_id}")->setQueryString( 'view', 'addresses' ), array( 'member=?', $this->member->member_id ) );
$addresses = new \IPS\Helpers\Table\Db( 'nexus_customer_addresses', \IPS\Http\Url::internal("app=nexus&module=customers&controller=view&id={$this->member->member_id}")->setQueryString( 'view', 'addresses' ), array( '`member`=?', $this->member->member_id ) );
$addresses->sortBy = 'primary_billing, primary_shipping, added';
$addresses->include = array( 'address', 'primary_billing', 'primary_shipping' );
$addresses->parsers = array( 'address' => function( $val )
{
return \IPS\GeoLocation::buildFromJson( $val )->toString( '<br>' );
$address = \IPS\GeoLocation::buildFromJson( $val );
return $address->toString( '<br>' ) . ( ( isset( $address->business ) and $address->business and isset( $address->vat ) and $address->vat ) ? ( '<br>' . \IPS\Member::loggedIn()->language()->addToStack('cm_checkout_vat_number') . ': ' .\IPS\Theme::i()->getTemplate( 'global', 'nexus' )->vatNumber( $address->vat ) ) : '' );
} );
if ( \IPS\Member::loggedIn()->hasAcpRestriction( 'nexus', 'customers', 'customers_edit_details' ) )
{
@@ -122,23 +128,6 @@ class _view extends \IPS\Dispatcher\Controller
$addresses->rowsTemplate = array( \IPS\Theme::i()->getTemplate('customers'), 'addressTableRows' );
\IPS\Output::i()->output = \IPS\Theme::i()->getTemplate('customers')->customerPopup( $addresses );
}
/**
* View Purchase List
*
* @return void
*/
protected function purchaseList()
{
$purchases = \IPS\nexus\Purchase::tree( \IPS\Http\Url::internal("app=nexus&module=customers&controller=view&id={$this->member->member_id}")->setQueryString( 'do', 'purchaseList' ), array( array( 'ps_member=?', $this->member->member_id ) ) );
$purchases->rootsPerPage = 25;
$purchases->getTotalRoots = function()
{
return \IPS\Db::i()->select( 'COUNT(*)', 'nexus_purchases', array( 'ps_member=? AND ps_show=1 AND ps_parent=0', $this->member->member_id ) )->first();
};
\IPS\Output::i()->output = $purchases;
\IPS\Output::i()->title = \IPS\Member::loggedIn()->language()->addToStack( 'members_purchases', FALSE, array( 'sprintf' => array( $this->member->cm_name ) ) );
}
/**
* Edit Customer Fields
@@ -157,6 +146,10 @@ class _view extends \IPS\Dispatcher\Controller
foreach ( \IPS\nexus\Customer\CustomField::roots() as $field )
{
$column = $field->column;
if ( $field->type === 'Editor' )
{
$field::$editorOptions = array_merge( $field::$editorOptions, array( 'attachIds' => array( $this->member->member_id ) ) );
}
$form->add( $field->buildHelper( $this->member->$column ) );
}
@@ -249,7 +242,7 @@ class _view extends \IPS\Dispatcher\Controller
if ( \IPS\Request::i()->note_id )
{
\IPS\Dispatcher::i()->checkAcpPermission( 'customer_notes_edit' );
$noteId = intval( \IPS\Request::i()->note_id );
$noteId = \intval( \IPS\Request::i()->note_id );
try
{
$note = \IPS\Db::i()->select( 'note_text', 'nexus_notes', array( 'note_id=?', \IPS\Request::i()->note_id ) )->first();
@@ -363,12 +356,28 @@ class _view extends \IPS\Dispatcher\Controller
{
$address = new \IPS\nexus\Customer\Address;
$address->member = $this->member;
$address->primary_billing = ( \IPS\Db::i()->select( 'COUNT(*)', 'nexus_customer_addresses', array( 'member=? AND primary_billing=1', $this->member->member_id ) )->first() == 0 );
$address->primary_shipping = ( \IPS\Db::i()->select( 'COUNT(*)', 'nexus_customer_addresses', array( 'member=? AND primary_shipping=1', $this->member->member_id ) )->first() == 0 );
$address->primary_billing = ( \IPS\Db::i()->select( 'COUNT(*)', 'nexus_customer_addresses', array( '`member`=? AND primary_billing=1', $this->member->member_id ) )->first() == 0 );
$address->primary_shipping = ( \IPS\Db::i()->select( 'COUNT(*)', 'nexus_customer_addresses', array( '`member`=? AND primary_shipping=1', $this->member->member_id ) )->first() == 0 );
}
$needTaxStatus = NULL;
foreach ( \IPS\nexus\Tax::roots() as $tax )
{
if ( $tax->type === 'eu' )
{
$needTaxStatus = 'eu';
break;
}
if ( $tax->type === 'business' )
{
$needTaxStatus = 'business';
}
}
$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 \IPS\Helpers\Form\Address( 'address', $address->address, TRUE ) );
$form->add( new $addressHelperClass( 'address', $address->address, TRUE, $addressHelperOptions ) );
$form->add( new \IPS\Helpers\Form\YesNo( 'primary_billing', $address->primary_billing ) );
$form->add( new \IPS\Helpers\Form\YesNo( 'primary_shipping', $address->primary_shipping ) );
if ( $values = $form->values() )
@@ -381,12 +390,12 @@ class _view extends \IPS\Dispatcher\Controller
}
if ( $values['primary_billing'] and !$address->primary_billing )
{
\IPS\Db::i()->update( 'nexus_customer_addresses', array( 'primary_billing' => 0 ), array( 'member=?', $this->member->member_id ) );
\IPS\Db::i()->update( 'nexus_customer_addresses', array( 'primary_billing' => 0 ), array( '`member`=?', $this->member->member_id ) );
$this->member->log( 'address', array( 'type' => 'primary_billing', 'details' => json_encode( $values['address'] ) ) );
}
if ( $values['primary_shipping'] and !$address->primary_shipping )
{
\IPS\Db::i()->update( 'nexus_customer_addresses', array( 'primary_shipping' => 0 ), array( 'member=?', $this->member->member_id ) );
\IPS\Db::i()->update( 'nexus_customer_addresses', array( 'primary_shipping' => 0 ), array( '`member`=?', $this->member->member_id ) );
$this->member->log( 'address', array( 'type' => 'primary_shipping', 'details' => json_encode( $values['address'] ) ) );
}
}
@@ -430,12 +439,13 @@ class _view extends \IPS\Dispatcher\Controller
/**
* Add Card
*
* @csrfChecked Uses Form helper in Gateway classes 7 Oct 2019
* @return void
*/
public function addCard()
{
\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( $this->member );
$form = \IPS\nexus\Customer\CreditCard::create( $this->member, TRUE );
if ( $form instanceof \IPS\nexus\Customer\CreditCard )
{
$this->member->log( 'card', array( 'type' => 'add', 'number' => $form->card->lastFour ) );
@@ -444,8 +454,7 @@ class _view extends \IPS\Dispatcher\Controller
else
{
\IPS\Output::i()->output = $form;
}
}
}
/**
@@ -488,7 +497,13 @@ class _view extends \IPS\Dispatcher\Controller
$form = new \IPS\Helpers\Form;
if ( !$existing )
{
$form->add( new \IPS\Helpers\Form\Member( 'altcontact_member_admin', NULL, TRUE ) );
$form->add( new \IPS\Helpers\Form\Member( 'altcontact_member_admin', NULL, TRUE, array(), function( $val )
{
if( $this->member->member_id === $val->member_id )
{
throw new \DomainException('altcontact_member_admin_self');
}
} ) );
}
$form->add( new \IPS\Helpers\Form\Node( 'altcontact_purchases_admin', $existing ? iterator_to_array( $existing->purchases ) : NULL, FALSE, array( 'class' => 'IPS\nexus\Purchase', 'forceOwner' => $this->member, 'multiple' => TRUE ) ) );
$form->add( new \IPS\Helpers\Form\YesNo( 'altcontact_support_admin', $existing ? $existing->support : FALSE ) );
@@ -548,6 +563,7 @@ class _view extends \IPS\Dispatcher\Controller
if ( isset( \IPS\Request::i()->process ) )
{
\IPS\Session::i()->csrfCheck();
$values = array(
'void_refund_transactions' => \IPS\Request::i()->trans,
'void_cancel_billing_agreements' => \IPS\Request::i()->ba,
@@ -617,14 +633,14 @@ class _view extends \IPS\Dispatcher\Controller
$member = $this->member;
\IPS\Output::i()->output = new \IPS\Helpers\MultipleRedirect( \IPS\Http\Url::internal("app=nexus&module=customers&controller=view&id={$this->member->member_id}")->setQueryString( array(
'do' => 'void',
'do' => 'void',
'process' => 1,
'trans' => $values['void_refund_transactions'],
'ba' => isset( $values['void_cancel_billing_agreements'] ) ? $values['void_cancel_billing_agreements'] : FALSE ,
'purch' => $values['void_cancel_purchases'],
) ), function( $data ) use ( $member )
) )->csrf(), function( $data ) use ( $member )
{
if ( !is_array( $data ) )
if ( !\is_array( $data ) )
{
$data = array( 'trans' => 0, 'ba' => 0, 'purch' => 0, 'fail' => array() );
}
@@ -635,16 +651,16 @@ class _view extends \IPS\Dispatcher\Controller
{
foreach ( new \IPS\Patterns\ActiveRecordIterator( \IPS\Db::i()->select( '*', 'nexus_transactions', array( 't_member=?', $member->member_id ), 't_id', array( $data['trans'], 10 ) ), 'IPS\nexus\Transaction' ) as $transaction )
{
if ( in_array( $transaction->status, array( $transaction::STATUS_PENDING, $transaction::STATUS_WAITING, $transaction::STATUS_GATEWAY_PENDING ) ) )
if ( \in_array( $transaction->status, array( $transaction::STATUS_PENDING, $transaction::STATUS_WAITING, $transaction::STATUS_GATEWAY_PENDING ) ) )
{
$transaction->status = $transaction::STATUS_REVIEW;
$transaction->save();
}
elseif ( in_array( $transaction->status, array( $transaction::STATUS_PAID, $transaction::STATUS_HELD, $transaction::STATUS_REVIEW, $transaction::STATUS_PART_REFUNDED ) ) )
elseif ( \in_array( $transaction->status, array( $transaction::STATUS_PAID, $transaction::STATUS_HELD, $transaction::STATUS_REVIEW, $transaction::STATUS_PART_REFUNDED ) ) )
{
try
{
if ( $this->auth and in_array( $this->status, array( static::STATUS_HELD, static::STATUS_REVIEW ) ) )
if ( $this->auth and \in_array( $this->status, array( static::STATUS_HELD, static::STATUS_REVIEW ) ) )
{
$transaction->void();
}
@@ -710,7 +726,7 @@ class _view extends \IPS\Dispatcher\Controller
return NULL;
}, function() use ( $member )
{
if ( count( $_SESSION['voidAccountFails'] ) )
if ( \count( $_SESSION['voidAccountFails'] ) )
{
\IPS\Output::i()->redirect( $member->acpUrl()->setQueryString( 'do', 'voidFails' ) );
}
@@ -12,7 +12,7 @@
namespace IPS\nexus\modules\admin\hosting;
/* To prevent PHP errors (extending class does not exist) revealing path */
if ( !defined( '\IPS\SUITE_UNIQUE_KEY' ) )
if ( !\defined( '\IPS\SUITE_UNIQUE_KEY' ) )
{
header( ( isset( $_SERVER['SERVER_PROTOCOL'] ) ? $_SERVER['SERVER_PROTOCOL'] : 'HTTP/1.0' ) . ' 403 Forbidden' );
exit;
@@ -23,6 +23,11 @@ if ( !defined( '\IPS\SUITE_UNIQUE_KEY' ) )
*/
class _errors extends \IPS\Dispatcher\Controller
{
/**
* @brief Has been CSRF-protected
*/
public static $csrfProtected = TRUE;
/**
* Execute
*
@@ -35,14 +40,15 @@ class _errors extends \IPS\Dispatcher\Controller
}
/**
* Manage
* Table
*
* @param \IPS\Http\Url $url The URL the table will be shown on
* @return void
*/
protected function manage()
{
public static function table( $url )
{
/* Create the table */
$table = new \IPS\Helpers\Table\Db( 'nexus_hosting_errors', \IPS\Http\Url::internal( 'app=nexus&module=hosting&controller=errors' ) );
$table = new \IPS\Helpers\Table\Db( 'nexus_hosting_errors', $url );
$table->include = array( 'e_time', 'e_server', 'e_account', 'e_function', 'e_message' );
$table->langPrefix = 'hosting_';
$table->rowClasses = array( 'e_message' => array( 'ipsTable_wrap' ) );
@@ -93,7 +99,7 @@ class _errors extends \IPS\Dispatcher\Controller
}
if ( $username )
{
return \IPS\Theme::i()->getTemplate('hosting')->accountLink( $username );
return \IPS\Theme::i()->getTemplate('hosting', 'nexus')->accountLink( $username );
}
return '';
},
@@ -123,7 +129,7 @@ class _errors extends \IPS\Dispatcher\Controller
'retry' => array(
'icon' => 'refresh',
'title' => 'retry',
'link' => \IPS\Http\Url::internal( 'app=nexus&module=hosting&controller=errors&do=retry&id=' . $row['e_id'] )
'link' => \IPS\Http\Url::internal( 'app=nexus&module=hosting&controller=errors&do=retry&id=' . $row['e_id'] )->csrf()
),
'delete'=> array(
'icon' => 'times-circle',
@@ -134,15 +140,19 @@ class _errors extends \IPS\Dispatcher\Controller
);
};
/* Display */
\IPS\Output::i()->sidebar['actions'][] = array(
'icon' => 'envelope',
'title' => 'notifications',
'link' => \IPS\Http\Url::internal( "app=nexus&module=hosting&controller=errors&do=settings" ),
'data' => array( 'ipsDialog' => '', 'ipsDialog-title' => \IPS\Member::loggedIn()->language()->addToStack('notifications') )
);
/* Return */
return $table;
}
/**
* Manage
*
* @return void
*/
protected function manage()
{
\IPS\Output::i()->title = \IPS\Member::loggedIn()->language()->addToStack('menu__nexus_hosting_errors');
\IPS\Output::i()->output = \IPS\Theme::i()->getTemplate( 'forms', 'core' )->blurb( 'hosting_errors_blurb' ) . (string) $table;
\IPS\Output::i()->output = \IPS\Theme::i()->getTemplate( 'forms', 'core' )->blurb( 'hosting_errors_blurb' ) . (string) static::table( \IPS\Http\Url::internal( 'app=nexus&module=hosting&controller=errors' ) );
}
/**
@@ -172,6 +182,8 @@ class _errors extends \IPS\Dispatcher\Controller
*/
public function retry()
{
\IPS\Session::i()->csrfCheck();
try
{
$log = \IPS\Db::i()->select( '*', 'nexus_hosting_errors', array( 'e_id=?', \IPS\Request::i()->id ) )->first();
@@ -216,24 +228,4 @@ class _errors extends \IPS\Dispatcher\Controller
\IPS\Db::i()->delete( 'nexus_hosting_errors', array( 'e_id=?', \IPS\Request::i()->id ) );
\IPS\Output::i()->redirect( \IPS\Http\Url::internal('app=nexus&module=hosting&controller=errors'), 'deleted' );
}
/**
* Settings
*
* @return void
*/
public function settings()
{
$form = new \IPS\Helpers\Form;
$form->add( new \IPS\Helpers\Form\Stack( 'nexus_hosting_error_emails', explode( ',', \IPS\Settings::i()->nexus_hosting_error_emails ), FALSE, array( 'stackFieldType' => 'Email' ) ) );
if ( $values = $form->values() )
{
$values['nexus_hosting_error_emails'] = implode( ',', $values['nexus_hosting_error_emails'] );
$form->saveAsSettings( $values );
\IPS\Session::i()->log( 'acplogs__host_err_settings' );
\IPS\Output::i()->redirect( \IPS\Http\Url::internal('app=nexus&module=hosting&controller=errors'), 'saved' );
}
\IPS\Output::i()->title = \IPS\Member::loggedIn()->language()->addToStack('menu__nexus_hosting_errors');
\IPS\Output::i()->output = $form;
}
}
@@ -12,7 +12,7 @@
namespace IPS\nexus\modules\admin\hosting;
/* To prevent PHP errors (extending class does not exist) revealing path */
if ( !defined( '\IPS\SUITE_UNIQUE_KEY' ) )
if ( !\defined( '\IPS\SUITE_UNIQUE_KEY' ) )
{
header( ( isset( $_SERVER['SERVER_PROTOCOL'] ) ? $_SERVER['SERVER_PROTOCOL'] : 'HTTP/1.0' ) . ' 403 Forbidden' );
exit;
@@ -23,6 +23,11 @@ if ( !defined( '\IPS\SUITE_UNIQUE_KEY' ) )
*/
class _monitoring extends \IPS\Node\Controller
{
/**
* @brief Has been CSRF-protected
*/
public static $csrfProtected = TRUE;
/**
* Node Class
*/
@@ -12,7 +12,7 @@
namespace IPS\nexus\modules\admin\hosting;
/* To prevent PHP errors (extending class does not exist) revealing path */
if ( !defined( '\IPS\SUITE_UNIQUE_KEY' ) )
if ( !\defined( '\IPS\SUITE_UNIQUE_KEY' ) )
{
header( ( isset( $_SERVER['SERVER_PROTOCOL'] ) ? $_SERVER['SERVER_PROTOCOL'] : 'HTTP/1.0' ) . ' 403 Forbidden' );
exit;
@@ -23,6 +23,11 @@ if ( !defined( '\IPS\SUITE_UNIQUE_KEY' ) )
*/
class _queues extends \IPS\Node\Controller
{
/**
* @brief Has been CSRF-protected
*/
public static $csrfProtected = TRUE;
/**
* Node Class
*/
@@ -12,7 +12,7 @@
namespace IPS\nexus\modules\admin\hosting;
/* To prevent PHP errors (extending class does not exist) revealing path */
if ( !defined( '\IPS\SUITE_UNIQUE_KEY' ) )
if ( !\defined( '\IPS\SUITE_UNIQUE_KEY' ) )
{
header( ( isset( $_SERVER['SERVER_PROTOCOL'] ) ? $_SERVER['SERVER_PROTOCOL'] : 'HTTP/1.0' ) . ' 403 Forbidden' );
exit;
@@ -23,6 +23,11 @@ if ( !defined( '\IPS\SUITE_UNIQUE_KEY' ) )
*/
class _servers extends \IPS\Node\Controller
{
/**
* @brief Has been CSRF-protected
*/
public static $csrfProtected = TRUE;
/**
* Node Class
*/
@@ -98,7 +103,7 @@ class _servers extends \IPS\Node\Controller
$return['reboot'] = array(
'title' => 'reboot',
'icon' => 'refresh',
'link' => \IPS\Http\Url::internal( 'app=nexus&module=hosting&controller=servers&do=reboot&id=' . $row['server_id'] )
'link' => \IPS\Http\Url::internal( 'app=nexus&module=hosting&controller=servers&do=reboot&id=' . $row['server_id'] )->csrf()
);
}
@@ -248,7 +253,7 @@ class _servers extends \IPS\Node\Controller
}
\IPS\Output::i()->title = $server->hostname;
\IPS\Output::i()->output = call_user_func_array( array( \IPS\Theme::i()->getTemplate( 'hosting' ), 'viewAccounts' ), $this->_audit( $server ) );
\IPS\Output::i()->output = \IPS\Theme::i()->getTemplate( 'hosting' )->viewAccounts( ...$this->_audit( $server ) );
}
/**
@@ -259,6 +264,7 @@ class _servers extends \IPS\Node\Controller
protected function reboot()
{
\IPS\Dispatcher::i()->checkAcpPermission( 'servers_reboot' );
\IPS\Session::i()->csrfCheck();
try
{
@@ -299,7 +305,7 @@ class _servers extends \IPS\Node\Controller
\IPS\Http\Url::internal('app=nexus&module=hosting&controller=servers&do=audit'),
function( $data ) use ( $self )
{
if ( !is_array( $data ) )
if ( !\is_array( $data ) )
{
$_SESSION['serverAudit'] = array();
$data = array( 'offset' => 0, 'bad' => array() );
@@ -307,7 +313,7 @@ class _servers extends \IPS\Node\Controller
try
{
$select = \IPS\Db::i()->select( '*', 'nexus_hosting_servers', array(), 'server_hostname', array( $data['offset'], 1 ), NULL, NULL, \IPS\Db::SELECT_SQL_CALC_FOUND_ROWS );
$select = \IPS\Db::i()->select( '*', 'nexus_hosting_servers', array(), 'server_hostname', array( $data['offset'], 1 ) );
$server = \IPS\nexus\Hosting\Server::constructFromData( $select->first() );
$results = $self->_audit( $server );
@@ -321,7 +327,7 @@ class _servers extends \IPS\Node\Controller
}
$data['offset']++;
return array( $data, \IPS\Member::loggedIn()->language()->get('hserv_audit_running'), 100 / $select->count(TRUE) * $data['offset'] );
return array( $data, \IPS\Member::loggedIn()->language()->get('hserv_audit_running'), 100 / \IPS\Db::i()->select( '*', 'nexus_hosting_servers' )->first() * $data['offset'] );
}
catch ( \UnderflowException $e )
{
@@ -466,19 +472,10 @@ class _servers extends \IPS\Node\Controller
*/
protected function form()
{
$availableTypes = array();
foreach ( new \DirectoryIterator( \IPS\ROOT_PATH . '/applications/nexus/sources/Hosting' ) as $file )
$availableTypes = \IPS\nexus\Hosting\Server::serverTypes();
if( isset( \IPS\Request::i()->server_type ) and \array_key_exists( \IPS\Request::i()->server_type, $availableTypes ) )
{
if (!$file->isDot() and mb_substr($file, 0, 1) !== '.' and $file->isDir())
{
$availableTypes[] = (string) $file;
}
}
if( isset( \IPS\Request::i()->server_type ) and in_array( \IPS\Request::i()->server_type, $availableTypes ) )
{
$this->nodeClass = "IPS\\nexus\\Hosting\\" . mb_ucfirst( \IPS\Request::i()->server_type ) . "\\Server";
$this->nodeClass = $availableTypes[ mb_ucfirst( \IPS\Request::i()->server_type ) ];
}
parent::form();
@@ -12,7 +12,7 @@
namespace IPS\nexus\modules\admin\hosting;
/* To prevent PHP errors (extending class does not exist) revealing path */
if ( !defined( '\IPS\SUITE_UNIQUE_KEY' ) )
if ( !\defined( '\IPS\SUITE_UNIQUE_KEY' ) )
{
header( ( isset( $_SERVER['SERVER_PROTOCOL'] ) ? $_SERVER['SERVER_PROTOCOL'] : 'HTTP/1.0' ) . ' 403 Forbidden' );
exit;
@@ -23,6 +23,11 @@ if ( !defined( '\IPS\SUITE_UNIQUE_KEY' ) )
*/
class _settings extends \IPS\Dispatcher\Controller
{
/**
* @brief Has been CSRF-protected
*/
public static $csrfProtected = TRUE;
/**
* Execute
*
@@ -46,7 +51,7 @@ class _settings extends \IPS\Dispatcher\Controller
/* Account Management */
$form->addTab('hosting_account_management');
$form->add( new \IPS\Helpers\Form\Number( 'nexus_hosting_terminate', \IPS\Settings::i()->nexus_hosting_terminate, TRUE, array( 'unlimited' => -1, 'unlimitedLang' => 'forever' ), NULL, NULL, \IPS\Member::loggedIn()->language()->addToStack('days') ) );
$form->add( new \IPS\Helpers\Form\Interval( 'nexus_hosting_terminate', \IPS\Settings::i()->nexus_hosting_terminate, TRUE, array( 'valueAs' => \IPS\Helpers\Form\Interval::DAYS, 'unlimited' => -1, 'unlimitedLang' => 'forever' ), NULL, NULL, NULL ) );
/* Domains */
$form->addTab('hosting_settings_domains');
@@ -54,7 +59,7 @@ class _settings extends \IPS\Dispatcher\Controller
$optionsVal = array();
$domainPrices = array();
if ( \IPS\Settings::i()->nexus_enom_un and $domainPrices = json_decode( \IPS\Settings::i()->nexus_domain_prices, TRUE ) and count( $domainPrices ) )
if ( \IPS\Settings::i()->nexus_enom_un and $domainPrices = json_decode( \IPS\Settings::i()->nexus_domain_prices, TRUE ) and \count( $domainPrices ) )
{
$optionsVal[] = 'enom';
}
@@ -113,7 +118,7 @@ class _settings extends \IPS\Dispatcher\Controller
return new \IPS\nexus\Form\Money( $key, $value, FALSE, array() );
},
);
if ( count( $domainPrices ) )
if ( \count( $domainPrices ) )
{
foreach ( $domainPrices as $tld => $prices )
{
@@ -140,7 +145,7 @@ class _settings extends \IPS\Dispatcher\Controller
},
);
$bandwidthPrices = json_decode( \IPS\Settings::i()->nexus_hosting_bandwidth, TRUE );
if ( count( $bandwidthPrices ) )
if ( \count( $bandwidthPrices ) )
{
foreach ( $bandwidthPrices as $amount => $prices )
{
@@ -157,7 +162,7 @@ class _settings extends \IPS\Dispatcher\Controller
if ( $values = $form->values() )
{
$domainPrices = array();
if ( in_array( 'enom', $values['domain_options'] ) )
if ( \in_array( 'enom', $values['domain_options'] ) )
{
foreach ( $values['nexus_domain_prices'] as $option )
{
@@ -168,11 +173,11 @@ class _settings extends \IPS\Dispatcher\Controller
}
}
$values['nexus_domain_prices'] = json_encode( $domainPrices );
$values['nexus_hosting_allow_own_domain'] = in_array( 'own', $values['domain_options'] );
$values['nexus_hosting_allow_own_domain'] = \in_array( 'own', $values['domain_options'] );
$values['nexus_hosting_nameservers'] = implode( ',', $values['nexus_hosting_nameservers'] );
$values['nexus_hosting_subdomains'] = in_array( 'sub', $values['domain_options'] ) ? implode( ',', $values['nexus_hosting_subdomains'] ) : '';
$values['nexus_hosting_own_domains'] = in_array( 'own', $values['domain_options'] ) ? implode( ',', $values['nexus_hosting_own_domains'] ) : '';
$values['nexus_hosting_subdomains'] = \in_array( 'sub', $values['domain_options'] ) ? implode( ',', $values['nexus_hosting_subdomains'] ) : '';
$values['nexus_hosting_own_domains'] = \in_array( 'own', $values['domain_options'] ) ? implode( ',', $values['nexus_hosting_own_domains'] ) : '';
\IPS\Db::i()->update( 'core_tasks', array( 'enabled' => (bool) $values['nexus_hosting_terminate'] ), "`key`='terminateHosting'" );
@@ -12,7 +12,7 @@
namespace IPS\nexus\modules\admin\payments;
/* To prevent PHP errors (extending class does not exist) revealing path */
if ( !defined( '\IPS\SUITE_UNIQUE_KEY' ) )
if ( !\defined( '\IPS\SUITE_UNIQUE_KEY' ) )
{
header( ( isset( $_SERVER['SERVER_PROTOCOL'] ) ? $_SERVER['SERVER_PROTOCOL'] : 'HTTP/1.0' ) . ' 403 Forbidden' );
exit;
@@ -23,6 +23,11 @@ if ( !defined( '\IPS\SUITE_UNIQUE_KEY' ) )
*/
class _billingagreements extends \IPS\Dispatcher\Controller
{
/**
* @brief Has been CSRF-protected
*/
public static $csrfProtected = TRUE;
/**
* Execute
*
@@ -79,7 +84,7 @@ class _billingagreements extends \IPS\Dispatcher\Controller
$transactions->limit = 50;
foreach ( $transactions->include as $k => $v )
{
if ( in_array( $v, array( 't_method', 't_member' ) ) )
if ( \in_array( $v, array( 't_method', 't_member' ) ) )
{
unset( $transactions->include[ $k ] );
}
@@ -94,7 +99,7 @@ class _billingagreements extends \IPS\Dispatcher\Controller
\IPS\Output::i()->sidebar['actions']['suspend'] = array(
'icon' => 'times',
'title' => 'billing_agreement_suspend',
'link' => $billingAgreement->acpUrl()->setQueryString( array( 'do' => 'act', 'act' => 'suspend' ) ),
'link' => $billingAgreement->acpUrl()->setQueryString( array( 'do' => 'act', 'act' => 'suspend' ) )->csrf(),
'data' => array( 'confirm' => '', 'confirmSubMessage' => \IPS\Member::loggedIn()->language()->addToStack('billing_agreement_suspend_confirm') )
);
}
@@ -103,7 +108,7 @@ class _billingagreements extends \IPS\Dispatcher\Controller
\IPS\Output::i()->sidebar['actions']['reactivate'] = array(
'icon' => 'check',
'title' => 'billing_agreement_reactivate',
'link' => $billingAgreement->acpUrl()->setQueryString( array( 'do' => 'act', 'act' => 'reactivate' ) ),
'link' => $billingAgreement->acpUrl()->setQueryString( array( 'do' => 'act', 'act' => 'reactivate' ) )->csrf(),
'data' => array( 'confirm' => '' )
);
}
@@ -112,13 +117,13 @@ class _billingagreements extends \IPS\Dispatcher\Controller
\IPS\Output::i()->sidebar['actions']['cancel'] = array(
'icon' => 'times-circle',
'title' => 'billing_agreement_cancel',
'link' => $billingAgreement->acpUrl()->setQueryString( array( 'do' => 'act', 'act' => 'cancel' ) ),
'link' => $billingAgreement->acpUrl()->setQueryString( array( 'do' => 'act', 'act' => 'cancel' ) )->csrf(),
);
}
}
/* Display */
\IPS\Output::i()->title = \IPS\Member::loggedIn()->language()->addToStack( 'billing_agreement_id', FALSE, array( 'sprintf' => array( $billingAgreement->id ) ) );
\IPS\Output::i()->title = \IPS\Member::loggedIn()->language()->addToStack( 'billing_agreement_id', FALSE, array( 'sprintf' => array( $billingAgreement->gw_id ) ) );
\IPS\Output::i()->output = \IPS\Theme::i()->getTemplate( 'billingagreements' )->view( $billingAgreement, $purchases, $transactions );
}
catch ( \IPS\nexus\Gateway\PayPal\Exception $e )
@@ -138,6 +143,8 @@ class _billingagreements extends \IPS\Dispatcher\Controller
*/
public function reconcile()
{
\IPS\Session::i()->csrfCheck();
/* Load */
try
{
@@ -173,9 +180,11 @@ class _billingagreements extends \IPS\Dispatcher\Controller
*/
public function act()
{
\IPS\Session::i()->csrfCheck();
/* Check act */
$act = \IPS\Request::i()->act;
if ( !in_array( $act, array( 'suspend', 'reactivate', 'cancel' ) ) )
if ( !\in_array( $act, array( 'suspend', 'reactivate', 'cancel' ) ) )
{
\IPS\Output::i()->error( 'node_error', '3X320/8', 403, '' );
}
@@ -12,7 +12,7 @@
namespace IPS\nexus\modules\admin\payments;
/* To prevent PHP errors (extending class does not exist) revealing path */
if ( !defined( '\IPS\SUITE_UNIQUE_KEY' ) )
if ( !\defined( '\IPS\SUITE_UNIQUE_KEY' ) )
{
header( ( isset( $_SERVER['SERVER_PROTOCOL'] ) ? $_SERVER['SERVER_PROTOCOL'] : 'HTTP/1.0' ) . ' 403 Forbidden' );
exit;
@@ -23,6 +23,11 @@ if ( !defined( '\IPS\SUITE_UNIQUE_KEY' ) )
*/
class _checkoutsettings extends \IPS\Dispatcher\Controller
{
/**
* @brief Has been CSRF-protected
*/
public static $csrfProtected = TRUE;
/**
* Execute
*
@@ -43,7 +48,7 @@ class _checkoutsettings extends \IPS\Dispatcher\Controller
{
$requireBillingOptions = array();
$requireBillingOptions['product'] = 'nexus_require_billing_package';
if ( ( $giftVouchers = json_decode( \IPS\Settings::i()->nexus_gift_vouchers, TRUE ) and count( $giftVouchers ) ) or \IPS\Settings::i()->nexus_gift_vouchers_free )
if ( ( $giftVouchers = json_decode( \IPS\Settings::i()->nexus_gift_vouchers, TRUE ) and \count( $giftVouchers ) ) or \IPS\Settings::i()->nexus_gift_vouchers_free )
{
$requireBillingOptions['giftvoucher'] = 'nexus_require_billing_gift';
}
@@ -51,7 +56,7 @@ class _checkoutsettings extends \IPS\Dispatcher\Controller
{
$requireBillingOptions['donation'] = 'nexus_require_billing_donation';
}
if ( \IPS\Settings::i()->nexus_enom_un and $domainPrices = json_decode( \IPS\Settings::i()->nexus_domain_prices, TRUE ) and count( $domainPrices ) )
if ( \IPS\Settings::i()->nexus_enom_un and $domainPrices = json_decode( \IPS\Settings::i()->nexus_domain_prices, TRUE ) and \count( $domainPrices ) )
{
$requireBillingOptions['domain'] = 'nexus_require_billing_domain';
}
@@ -86,7 +91,8 @@ class _checkoutsettings extends \IPS\Dispatcher\Controller
if ( $values = $form->values() )
{
$values['nexus_split_payments'] = $values['nexus_split_payments_on'] ? ( $values['nexus_split_payments'] == '*' ? 0 : json_encode( $values['nexus_split_payments'] ) ) : -1;
$values['nexus_require_billing'] = count( $values['nexus_require_billing'] ) ? implode( ',', $values['nexus_require_billing'] ) : 'none';
unset( $values['nexus_split_payments_on'] );
$values['nexus_require_billing'] = \count( $values['nexus_require_billing'] ) ? implode( ',', $values['nexus_require_billing'] ) : 'none';
$form->saveAsSettings( $values );
\IPS\Session::i()->log( 'acplogs__checkout_settings' );
@@ -12,7 +12,7 @@
namespace IPS\nexus\modules\admin\payments;
/* To prevent PHP errors (extending class does not exist) revealing path */
if ( !defined( '\IPS\SUITE_UNIQUE_KEY' ) )
if ( !\defined( '\IPS\SUITE_UNIQUE_KEY' ) )
{
header( ( isset( $_SERVER['SERVER_PROTOCOL'] ) ? $_SERVER['SERVER_PROTOCOL'] : 'HTTP/1.0' ) . ' 403 Forbidden' );
exit;
@@ -23,6 +23,11 @@ if ( !defined( '\IPS\SUITE_UNIQUE_KEY' ) )
*/
class _currencies extends \IPS\Dispatcher\Controller
{
/**
* @brief Has been CSRF-protected
*/
public static $csrfProtected = TRUE;
/**
* Execute
*
@@ -53,7 +58,7 @@ class _currencies extends \IPS\Dispatcher\Controller
},
'default' => function( $key, $value, $data ) use ( $languages )
{
if ( count( $languages ) === 1 )
if ( \count( $languages ) === 1 )
{
return new \IPS\Helpers\Form\Checkbox( $key, $value );
}
@@ -80,7 +85,7 @@ class _currencies extends \IPS\Dispatcher\Controller
'default' => $defaults
);
if ( !in_array( $code, array( 'AED', 'AFN', 'ALL', 'AMD', 'ANG', 'AOA', 'ARS', 'AUD', 'AWG', 'AZN', 'BAM', 'BBD', 'BDT', 'BGN', 'BHD', 'BIF', 'BMD', 'BND', 'BOB', 'BRL', 'BSD', 'BTN', 'BWP', 'BYN', 'BYR', 'BZD', 'CAD', 'CDF', 'CHF', 'CLF', 'CLP', 'CNY', 'COP', 'CRC', 'CUC', 'CUP', 'CVE', 'CZK', 'DJF', 'DKK', 'DOP', 'DZD', 'EGP', 'ERN', 'ETB', 'EUR', 'FJD', 'FKP', 'GBP', 'GEL', 'GGP', 'GHS', 'GIP', 'GMD', 'GNF', 'GTQ', 'GYD', 'HKD', 'HNL', 'HRK', 'HTG', 'HUF', 'IDR', 'ILS', 'IMP', 'INR', 'IQD', 'IRR', 'ISK', 'JEP', 'JMD', 'JOD', 'JPY', 'KES', 'KGS', 'KHR', 'KMF', 'KPW', 'KRW', 'KWD', 'KYD', 'KZT', 'LAK', 'LBP', 'LKR', 'LRD', 'LSL', 'LYD', 'MAD', 'MDL', 'MGA', 'MKD', 'MMK', 'MNT', 'MOP', 'MRO', 'MUR', 'MVR', 'MWK', 'MXN', 'MYR', 'MZN', 'NAD', 'NGN', 'NIO', 'NOK', 'NPR', 'NZD', 'OMR', 'PAB', 'PEN', 'PGK', 'PHP', 'PKR', 'PLN', 'PYG', 'QAR', 'RON', 'RSD', 'RUB', 'RWF', 'SAR', 'SBD', 'SCR', 'SDG', 'SEK', 'SGD', 'SHP', 'SLL', 'SOS', 'SPL*', 'SRD', 'STD', 'SVC', 'SYP', 'SZL', 'THB', 'TJS', 'TMT', 'TND', 'TOP', 'TRY', 'TTD', 'TVD', 'TWD', 'TZS', 'UAH', 'UGX', 'USD', 'UYU', 'UZS', 'VEF', 'VND', 'VUV', 'WST', 'XAF', 'XCD', 'XDR', 'XOF', 'XPF', 'YER', 'ZAR', 'ZMW', 'ZWD' ) ) )
if ( !\in_array( $code, array( 'AED', 'AFN', 'ALL', 'AMD', 'ANG', 'AOA', 'ARS', 'AUD', 'AWG', 'AZN', 'BAM', 'BBD', 'BDT', 'BGN', 'BHD', 'BIF', 'BMD', 'BND', 'BOB', 'BRL', 'BSD', 'BTN', 'BWP', 'BYN', 'BYR', 'BZD', 'CAD', 'CDF', 'CHF', 'CLF', 'CLP', 'CNY', 'COP', 'CRC', 'CUC', 'CUP', 'CVE', 'CZK', 'DJF', 'DKK', 'DOP', 'DZD', 'EGP', 'ERN', 'ETB', 'EUR', 'FJD', 'FKP', 'GBP', 'GEL', 'GGP', 'GHS', 'GIP', 'GMD', 'GNF', 'GTQ', 'GYD', 'HKD', 'HNL', 'HRK', 'HTG', 'HUF', 'IDR', 'ILS', 'IMP', 'INR', 'IQD', 'IRR', 'ISK', 'JEP', 'JMD', 'JOD', 'JPY', 'KES', 'KGS', 'KHR', 'KMF', 'KPW', 'KRW', 'KWD', 'KYD', 'KZT', 'LAK', 'LBP', 'LKR', 'LRD', 'LSL', 'LYD', 'MAD', 'MDL', 'MGA', 'MKD', 'MMK', 'MNT', 'MOP', 'MRO', 'MUR', 'MVR', 'MWK', 'MXN', 'MYR', 'MZN', 'NAD', 'NGN', 'NIO', 'NOK', 'NPR', 'NZD', 'OMR', 'PAB', 'PEN', 'PGK', 'PHP', 'PKR', 'PLN', 'PYG', 'QAR', 'RON', 'RSD', 'RUB', 'RWF', 'SAR', 'SBD', 'SCR', 'SDG', 'SEK', 'SGD', 'SHP', 'SLL', 'SOS', 'SPL*', 'SRD', 'STD', 'SVC', 'SYP', 'SZL', 'THB', 'TJS', 'TMT', 'TND', 'TOP', 'TRY', 'TTD', 'TVD', 'TWD', 'TZS', 'UAH', 'UGX', 'USD', 'UYU', 'UZS', 'VEF', 'VND', 'VUV', 'WST', 'XAF', 'XCD', 'XDR', 'XOF', 'XPF', 'YER', 'ZAR', 'ZMW', 'ZWD' ) ) )
{
$warnings .= \IPS\Theme::i()->getTemplate( 'global', 'core', 'global' )->message( \IPS\Member::loggedIn()->language()->addToStack( 'currency_code_invalid', FALSE, array( 'sprintf' => array( $code ) ) ), 'warning' );
}
@@ -90,26 +95,35 @@ class _currencies extends \IPS\Dispatcher\Controller
{
$matrix->rows[] = array(
'code' => \IPS\Settings::i()->nexus_currency,
'default' => count( $languages ) === 1 ? TRUE : array_keys( $languages )
'default' => \count( $languages ) === 1 ? TRUE : array_keys( $languages )
);
}
if ( $values = $matrix->values() )
{
$save = array();
$definition = \IPS\Db::i()->getTableDefinition( 'nexus_package_base_prices' );
foreach ( $values as $data )
{
if ( $data['code'] )
{
$save[ $data['code'] ] = ( count( $languages ) === 1 ) ? ( $data['default'] ? array_keys( $languages ) : array() ) : $data['default'];
$save[ $data['code'] ] = ( \count( $languages ) === 1 ) ? ( $data['default'] ? array_keys( $languages ) : array() ) : $data['default'];
/* Add the column if it doesn't exist */
if ( !isset( $definition['columns'][ $data['code'] ] ) )
{
\IPS\Db::i()->addColumn( 'nexus_package_base_prices', array(
'name' => $data['code'],
'type' => 'FLOAT'
) );
}
}
}
\IPS\Settings::i()->changeValues( array( 'nexus_currency' => json_encode( $save ) ) );
$definition = \IPS\Db::i()->getTableDefinition( 'nexus_package_base_prices' );
foreach ( $definition['columns'] AS $key => $value )
{
if ( $key === 'id' )
@@ -12,7 +12,7 @@
namespace IPS\nexus\modules\admin\payments;
/* To prevent PHP errors (extending class does not exist) revealing path */
if ( !defined( '\IPS\SUITE_UNIQUE_KEY' ) )
if ( !\defined( '\IPS\SUITE_UNIQUE_KEY' ) )
{
header( ( isset( $_SERVER['SERVER_PROTOCOL'] ) ? $_SERVER['SERVER_PROTOCOL'] : 'HTTP/1.0' ) . ' 403 Forbidden' );
exit;
@@ -23,6 +23,11 @@ if ( !defined( '\IPS\SUITE_UNIQUE_KEY' ) )
*/
class _donationgoals extends \IPS\Node\Controller
{
/**
* @brief Has been CSRF-protected
*/
public static $csrfProtected = TRUE;
/**
* Node Class
*/
@@ -12,7 +12,7 @@
namespace IPS\nexus\modules\admin\payments;
/* To prevent PHP errors (extending class does not exist) revealing path */
if ( !defined( '\IPS\SUITE_UNIQUE_KEY' ) )
if ( !\defined( '\IPS\SUITE_UNIQUE_KEY' ) )
{
header( ( isset( $_SERVER['SERVER_PROTOCOL'] ) ? $_SERVER['SERVER_PROTOCOL'] : 'HTTP/1.0' ) . ' 403 Forbidden' );
exit;
@@ -23,6 +23,11 @@ if ( !defined( '\IPS\SUITE_UNIQUE_KEY' ) )
*/
class _donations extends \IPS\Dispatcher\Controller
{
/**
* @brief Has been CSRF-protected
*/
public static $csrfProtected = TRUE;
/**
* Execute
*
@@ -12,7 +12,7 @@
namespace IPS\nexus\modules\admin\payments;
/* To prevent PHP errors (extending class does not exist) revealing path */
if ( !defined( '\IPS\SUITE_UNIQUE_KEY' ) )
if ( !\defined( '\IPS\SUITE_UNIQUE_KEY' ) )
{
header( ( isset( $_SERVER['SERVER_PROTOCOL'] ) ? $_SERVER['SERVER_PROTOCOL'] : 'HTTP/1.0' ) . ' 403 Forbidden' );
exit;
@@ -23,6 +23,11 @@ if ( !defined( '\IPS\SUITE_UNIQUE_KEY' ) )
*/
class _emails extends \IPS\Dispatcher\Controller
{
/**
* @brief Has been CSRF-protected
*/
public static $csrfProtected = TRUE;
/**
* Execute
*
@@ -30,7 +35,7 @@ class _emails extends \IPS\Dispatcher\Controller
*/
public function execute()
{
\IPS\Dispatcher::i()->checkAcpPermission( 'email_copies_setting' );
\IPS\Dispatcher::i()->checkAcpPermission( 'email_copies_settings' );
parent::execute();
}
@@ -12,7 +12,7 @@
namespace IPS\nexus\modules\admin\payments;
/* To prevent PHP errors (extending class does not exist) revealing path */
if ( !defined( '\IPS\SUITE_UNIQUE_KEY' ) )
if ( !\defined( '\IPS\SUITE_UNIQUE_KEY' ) )
{
header( ( isset( $_SERVER['SERVER_PROTOCOL'] ) ? $_SERVER['SERVER_PROTOCOL'] : 'HTTP/1.0' ) . ' 403 Forbidden' );
exit;
@@ -23,6 +23,11 @@ if ( !defined( '\IPS\SUITE_UNIQUE_KEY' ) )
*/
class _fraud extends \IPS\Node\Controller
{
/**
* @brief Has been CSRF-protected
*/
public static $csrfProtected = TRUE;
/**
* Node Class
*/
@@ -12,7 +12,7 @@
namespace IPS\nexus\modules\admin\payments;
/* To prevent PHP errors (extending class does not exist) revealing path */
if ( !defined( '\IPS\SUITE_UNIQUE_KEY' ) )
if ( !\defined( '\IPS\SUITE_UNIQUE_KEY' ) )
{
header( ( isset( $_SERVER['SERVER_PROTOCOL'] ) ? $_SERVER['SERVER_PROTOCOL'] : 'HTTP/1.0' ) . ' 403 Forbidden' );
exit;
@@ -23,6 +23,11 @@ if ( !defined( '\IPS\SUITE_UNIQUE_KEY' ) )
*/
class _gateways extends \IPS\Node\Controller
{
/**
* @brief Has been CSRF-protected
*/
public static $csrfProtected = TRUE;
/**
* Node Class
*/
@@ -78,22 +83,20 @@ class _gateways extends \IPS\Node\Controller
{
\IPS\Output::i()->jsFiles = array_merge( \IPS\Output::i()->jsFiles, \IPS\Output::i()->js( 'plupload/plupload.full.min.js', 'core', 'interface' ) );
}
\IPS\Output::i()->output = new \IPS\Helpers\Wizard( array(
\IPS\Output::i()->output = (string) new \IPS\Helpers\Wizard( array(
'gateways_gateway' => function( $data )
{
$options = array();
foreach ( new \DirectoryIterator( \IPS\ROOT_PATH . '/applications/nexus/sources/Gateway' ) as $file )
foreach ( \IPS\nexus\Gateway::gateways() as $key => $class )
{
if ( $file->isDir() and !$file->isDot() )
/* Deprecate Authorize.net, don't allow it to be used for new gateways */
if( $key === 'AuthorizeNet' )
{
if ( ( (string) $file === 'Test' and !\IPS\NEXUS_TEST_GATEWAYS ) or (string) $file === 'SagePay' )
{
continue;
}
$options[ (string) $file ] = 'gateway__' . $file;
continue;
}
$options[ $key ] = 'gateway__' . $key;
}
$form = new \IPS\Helpers\Form;
$form->add( new \IPS\Helpers\Form\Radio( 'gateways_gateway', TRUE, NULL, array( 'options' => $options ) ) );
if ( $values = $form->values() )
@@ -105,19 +108,18 @@ class _gateways extends \IPS\Node\Controller
'gateways_details' => function( $data )
{
$form = new \IPS\Helpers\Form('gw');
$form->add( new \IPS\Helpers\Form\Translatable( 'paymethod_name', \IPS\Member::loggedIn()->language()->addToStack( 'gateway__' . $data['gateway'] ), TRUE ) );
$class = 'IPS\nexus\Gateway\\' . $data['gateway'];
$class = \IPS\nexus\Gateway::gateways()[ $data['gateway'] ];
$obj = new $class;
$obj->gateway = $data['gateway'];
$obj->active = TRUE;
$obj->settings( $form );
$obj->form( $form );
if ( $values = $form->values() )
{
$settings = array();
foreach ( $values as $k => $v )
{
if ( $k !== 'paymethod_name' )
if ( $k !== 'paymethod_name' AND $k !== 'paymethod_countries' )
{
$settings[ mb_substr( $k, mb_strlen( $data['gateway'] ) + 1 ) ] = $v;
}
@@ -131,11 +133,13 @@ class _gateways extends \IPS\Node\Controller
$form->error = $e->getMessage();
return $form;
}
$obj->settings = json_encode( $settings );
$obj->save();
\IPS\Lang::saveCustom( 'nexus', "nexus_paymethod_{$obj->id}", $values['paymethod_name'] );
$name = $values['paymethod_name'];
$values = $obj->formatFormValues( $values );
$obj->settings = json_encode( $settings );
$obj->countries = $values['countries'];
$obj->save();
\IPS\Lang::saveCustom( 'nexus', "nexus_paymethod_{$obj->id}", $name );
\IPS\Output::i()->redirect( \IPS\Http\Url::internal('app=nexus&module=payments&controller=paymentsettings&tab=gateways') );
}
@@ -144,4 +148,48 @@ class _gateways extends \IPS\Node\Controller
), \IPS\Http\Url::internal('app=nexus&module=payments&controller=paymentsettings&tab=gateways&do=form') );
}
}
/**
* Delete
*
* @return void
*/
protected function delete()
{
/* Get node */
$nodeClass = $this->nodeClass;
if ( \IPS\Request::i()->subnode )
{
$nodeClass = $nodeClass::$subnodeClass;
}
try
{
$node = $nodeClass::load( \IPS\Request::i()->id );
}
catch ( \OutOfRangeException $e )
{
\IPS\Output::i()->error( 'node_error', '2X411/1', 404, '' );
}
/* Permission check */
if( !$node->canDelete() )
{
\IPS\Output::i()->error( 'node_noperm_delete', '2X411/2', 403, '' );
}
if( $node->hasActiveBillingAgreements() )
{
/* Make sure the user confirmed the deletion */
\IPS\Request::i()->confirmedDelete();
\IPS\Task::queue( 'nexus', 'DeletePaymentMethod', array( 'id' => $node->id ), 3, array( 'id' ) );
\IPS\Session::i()->log( 'acplog__node_deleted_c', array( $this->title => TRUE, $node->titleForLog() => FALSE ) );
\IPS\Output::i()->redirect( $this->url->setQueryString( array( 'root' => ( $node->parent() ? $node->parent()->_id : '' ) ) ), 'deleted' );
}
else
{
return parent::delete();
}
}
}
@@ -12,7 +12,7 @@
namespace IPS\nexus\modules\admin\payments;
/* To prevent PHP errors (extending class does not exist) revealing path */
if ( !defined( '\IPS\SUITE_UNIQUE_KEY' ) )
if ( !\defined( '\IPS\SUITE_UNIQUE_KEY' ) )
{
header( ( isset( $_SERVER['SERVER_PROTOCOL'] ) ? $_SERVER['SERVER_PROTOCOL'] : 'HTTP/1.0' ) . ' 403 Forbidden' );
exit;
@@ -23,6 +23,11 @@ if ( !defined( '\IPS\SUITE_UNIQUE_KEY' ) )
*/
class _invoiceTimeline extends \IPS\Dispatcher\Controller
{
/**
* @brief Has been CSRF-protected
*/
public static $csrfProtected = TRUE;
/**
* Manage
*
@@ -12,7 +12,7 @@
namespace IPS\nexus\modules\admin\payments;
/* To prevent PHP errors (extending class does not exist) revealing path */
if ( !defined( '\IPS\SUITE_UNIQUE_KEY' ) )
if ( !\defined( '\IPS\SUITE_UNIQUE_KEY' ) )
{
header( ( isset( $_SERVER['SERVER_PROTOCOL'] ) ? $_SERVER['SERVER_PROTOCOL'] : 'HTTP/1.0' ) . ' 403 Forbidden' );
exit;
@@ -22,7 +22,12 @@ if ( !defined( '\IPS\SUITE_UNIQUE_KEY' ) )
* Invoices
*/
class _invoices extends \IPS\Dispatcher\Controller
{
{
/**
* @brief Has been CSRF-protected
*/
public static $csrfProtected = TRUE;
/**
* Execute
*
@@ -66,6 +71,12 @@ class _invoices extends \IPS\Dispatcher\Controller
'i_date' => \IPS\Helpers\Table\SEARCH_DATE_RANGE,
);
$table->quickSearch = 'i_id';
$table->filters = array(
'istatus_paid' => array( 'i_status=?', \IPS\nexus\Invoice::STATUS_PAID ),
'istatus_pend' => array( 'i_status=?', \IPS\nexus\Invoice::STATUS_PENDING ),
'istatus_expd' => array( 'i_status=?', \IPS\nexus\Invoice::STATUS_EXPIRED ),
'istatus_canc' => array( 'i_status=?' , \IPS\nexus\Invoice::STATUS_CANCELED )
);
$table->mainColumn = 'i_title';
if ( $customer )
{
@@ -130,7 +141,7 @@ class _invoices extends \IPS\Dispatcher\Controller
foreach ( $transactions->include as $k => $v )
{
if ( in_array( $v, array( 't_member', 't_invoice' ) ) )
if ( \in_array( $v, array( 't_member', 't_invoice' ) ) )
{
unset( $transactions->include[ $k ] );
}
@@ -205,7 +216,8 @@ class _invoices extends \IPS\Dispatcher\Controller
public function paid()
{
\IPS\Dispatcher::i()->checkAcpPermission( 'invoices_edit' );
\IPS\Session::i()->csrfCheck();
/* Load Invoice */
try
{
@@ -216,14 +228,20 @@ class _invoices extends \IPS\Dispatcher\Controller
\IPS\Output::i()->error( 'node_error', '2X190/6', 404, '' );
}
/* Do we have a billing address? */
if ( !$invoice->billaddress AND $invoice->hasItemsRequiringBillingAddress() )
{
\IPS\Output::i()->error( 'err_no_billaddress', '2X190/I', 403 );
}
/* Any pending transactions? */
if ( !isset( \IPS\Request::i()->override ) and \IPS\Member::loggedIn()->hasAcpRestriction( 'nexus', 'payments', 'transactions_manage' ) )
{
$pendingTransactions = $invoice->transactions( array( \IPS\nexus\Transaction::STATUS_WAITING, \IPS\nexus\Transaction::STATUS_HELD, \IPS\nexus\Transaction::STATUS_REVIEW, \IPS\nexus\Transaction::STATUS_GATEWAY_PENDING ) );
if ( count( $pendingTransactions ) )
if ( \count( $pendingTransactions ) )
{
$transUrl = $invoice->acpUrl();
if ( count( $pendingTransactions ) === 1 )
if ( \count( $pendingTransactions ) === 1 )
{
foreach ( $pendingTransactions as $transaction )
{
@@ -233,7 +251,7 @@ class _invoices extends \IPS\Dispatcher\Controller
\IPS\Output::i()->output = \IPS\Theme::i()->getTemplate('global', 'core')->decision( 'invoice_paid_trans', array(
'invoice_paid_trans_view' => $transUrl,
'invoice_paid_trans_ovrd' => $invoice->acpUrl()->setQueryString( array( 'do' => 'paid', 'override' => 1 ) )
'invoice_paid_trans_ovrd' => $invoice->acpUrl()->setQueryString( array( 'do' => 'paid', 'override' => 1 ) )->csrf()
) );
return;
}
@@ -248,7 +266,7 @@ class _invoices extends \IPS\Dispatcher\Controller
) );
/* Send Email */
\IPS\Email::buildFromTemplate( 'nexus', 'invoiceMarkedPaid', array( $invoice, $invoice->summary() ), \IPS\Email::TYPE_TRANSACTIONAL )
\IPS\Email::buildFromTemplate( 'nexus', 'invoiceMarkedPaid', array( $invoice, $invoice->summary( $invoice->member->language() ) ), \IPS\Email::TYPE_TRANSACTIONAL )
->send(
$invoice->member,
array_map(
@@ -258,7 +276,7 @@ class _invoices extends \IPS\Dispatcher\Controller
},
iterator_to_array( $invoice->member->alternativeContacts( array( 'billing=1' ) ) )
),
( ( in_array( 'new_invoice', explode( ',', \IPS\Settings::i()->nexus_notify_copy_types ) ) AND \IPS\Settings::i()->nexus_notify_copy_email ) ? explode( ',', \IPS\Settings::i()->nexus_notify_copy_email ) : array() )
( ( \in_array( 'new_invoice', explode( ',', \IPS\Settings::i()->nexus_notify_copy_types ) ) AND \IPS\Settings::i()->nexus_notify_copy_email ) ? explode( ',', \IPS\Settings::i()->nexus_notify_copy_email ) : array() )
);
/* Do it */
@@ -289,10 +307,10 @@ class _invoices extends \IPS\Dispatcher\Controller
}
/* Get gateways */
$gateways = \IPS\nexus\Gateway::manualChargeGateways();
$gateways = \IPS\nexus\Gateway::manualChargeGateways( $invoice->member );
/* Can we do this? */
if ( $invoice->status !== \IPS\nexus\Invoice::STATUS_PENDING or !count( $gateways ) )
if ( $invoice->status !== \IPS\nexus\Invoice::STATUS_PENDING or !\count( $gateways ) )
{
\IPS\Output::i()->error( 'invoice_status_err', '2X190/9', 403, '' );
}
@@ -300,7 +318,7 @@ class _invoices extends \IPS\Dispatcher\Controller
$self = $this;
/* Wizard */
\IPS\Output::i()->title = \IPS\Member::loggedIn()->language()->addToStack( 'invoice_charge_to_card' );
\IPS\Output::i()->output = new \IPS\Helpers\Wizard(
\IPS\Output::i()->output = (string) new \IPS\Helpers\Wizard(
array(
't_amount' => function( $data ) use ( $invoice )
{
@@ -322,7 +340,7 @@ class _invoices extends \IPS\Dispatcher\Controller
$paymentMethodsToggles = array();
foreach ( $gateways as $gateway )
{
foreach ( $gateway->paymentScreen( $invoice, $amountToPay, $invoice->member ) as $element )
foreach ( $gateway->paymentScreen( $invoice, $amountToPay, $invoice->member, array(), 'admin' ) as $element )
{
if ( !$element->htmlId )
{
@@ -340,7 +358,23 @@ class _invoices extends \IPS\Dispatcher\Controller
/* Build form */
$form = new \IPS\Helpers\Form( 'charge', 'invoice_charge_to_card' );
if ( count( $gateways ) > 1 )
if ( isset( \IPS\Request::i()->previousTransactions ) )
{
$form->hiddenValues['previousTransactions'] = \IPS\Request::i()->previousTransactions;
}
else
{
if ( $previousTransactions = $invoice->transactions() and \count( $previousTransactions ) )
{
$previousTransactionIds = array();
foreach ( $previousTransactions as $previousTransaction )
{
$previousTransactionIds[] = $previousTransaction->id;
}
$form->hiddenValues['previousTransactions'] = implode( ',', $previousTransactionIds );
}
}
if ( \count( $gateways ) > 1 )
{
$form->add( new \IPS\Helpers\Form\Radio( 'payment_method', NULL, TRUE, array( 'options' => $paymentMethodOptions, 'toggles' => $paymentMethodsToggles ) ) );
}
@@ -352,7 +386,7 @@ class _invoices extends \IPS\Dispatcher\Controller
/* Handle submissions */
if ( $values = $form->values() )
{
if ( count( $gateways ) === 1 )
if ( \count( $gateways ) === 1 )
{
$gateway = array_pop( $gateways );
}
@@ -372,7 +406,15 @@ class _invoices extends \IPS\Dispatcher\Controller
try
{
$transaction->auth = $gateway->auth( $transaction, $values );
$auth = $gateway->auth( $transaction, $values, NULL, array(), 'manual' );
if ( \is_array( $auth ) )
{
return $this->_webhookRedirector( $invoice, $auth );
}
else
{
$transaction->auth = $auth;
}
$transaction->capture();
$transaction->member->log( 'transaction', array(
@@ -482,6 +524,7 @@ class _invoices extends \IPS\Dispatcher\Controller
public function resend()
{
\IPS\Dispatcher::i()->checkAcpPermission( 'invoices_resend' );
\IPS\Session::i()->csrfCheck();
/* Load Invoice */
try
@@ -529,24 +572,9 @@ class _invoices extends \IPS\Dispatcher\Controller
{
\IPS\Output::i()->error( 'node_error', '2X190/D', 404, '' );
}
/* Get the address */
$address = NULL;
if ( $invoice->billaddress )
{
$address = $invoice->billaddress;
}
else
{
try
{
$address = \IPS\nexus\Customer\Address::constructFromData( \IPS\Db::i()->select( '*', 'nexus_customer_addresses', array( "member=? AND primary_billing=?", $invoice->member->member_id, 1 ) )->first() )->address;
}
catch( \UnderflowException $e ) {}
}
/* Get output */
$output = \IPS\Theme::i()->getTemplate( 'invoices', 'nexus', 'global' )->printInvoice( $invoice, $invoice->summary(), $address );
$output = \IPS\Theme::i()->getTemplate( 'invoices', 'nexus', 'global' )->printInvoice( $invoice, $invoice->summary(), $invoice->billaddress ?: $invoice->member->primaryBillingAddress() );
\IPS\Output::i()->title = 'I' . $invoice->id;
\IPS\Output::i()->sendOutput( \IPS\Theme::i()->getTemplate( 'global', 'core', 'front' )->blankTemplate( $output ) );
}
@@ -608,12 +636,12 @@ class _invoices extends \IPS\Dispatcher\Controller
/* How do we want to refund? */
$field = new \IPS\Helpers\Form\Radio( $transaction->id . '_refund_method', 'none', TRUE, array( 'options' => $refundMethods, 'toggles' => $refundMethodToggles ) );
$field->label = count( $transactions ) === 1 ? \IPS\Member::loggedIn()->language()->addToStack( 'refund_method' ) : \IPS\Member::loggedIn()->language()->addToStack( 'trans_refund_method', FALSE, array( 'sprintf' => array( $transaction->id ) ) );
$field->label = \count( $transactions ) === 1 ? \IPS\Member::loggedIn()->language()->addToStack( 'refund_method' ) : \IPS\Member::loggedIn()->language()->addToStack( 'trans_refund_method', FALSE, array( 'sprintf' => array( $transaction->id ) ) );
$form->add( $field );
if ( $refundReasons )
{
$field = new \IPS\Helpers\Form\Radio( $transaction->id . '_refund_reason', NULL, FALSE, array( 'options' => $refundReasons ), NULL, NULL, NULL, $transaction->id . '_refund_reason' );
$field->label = count( $transactions ) === 1 ? \IPS\Member::loggedIn()->language()->addToStack( 'refund_reason' ) : \IPS\Member::loggedIn()->language()->addToStack( 'trans_refund_reason', FALSE, array( 'sprintf' => array( $transaction->id ) ) );
$field->label = \count( $transactions ) === 1 ? \IPS\Member::loggedIn()->language()->addToStack( 'refund_reason' ) : \IPS\Member::loggedIn()->language()->addToStack( 'trans_refund_reason', FALSE, array( 'sprintf' => array( $transaction->id ) ) );
$form->add( $field );
}
@@ -678,7 +706,7 @@ class _invoices extends \IPS\Dispatcher\Controller
}
/* Billing Agreement? */
if ( $billingAgreement = $transaction->billing_agreement )
if ( $billingAgreement = $transaction->billing_agreement AND $billingAgreement->status() !== $billingAgreement::STATUS_CANCELED )
{
$field = new \IPS\Helpers\Form\YesNo( $transaction->id . '_refund_cancel_billing_agreement', TRUE, NULL, array( 'togglesOff' => array( "form_{$transaction->id}_refund_cancel_billing_agreement_warning" ) ) );
$field->label = \IPS\Member::loggedIn()->language()->addToStack( 'refund_cancel_billing_agreement' );
@@ -922,7 +950,7 @@ class _invoices extends \IPS\Dispatcher\Controller
/* Select Customer */
$steps = array();
if ( !isset( \IPS\Request::i()->member ) and !$invoice )
if ( !isset( \IPS\Request::i()->member ) and ( !$invoice or !$invoice->member->member_id ) )
{
$steps['invoice_generate_member'] = function( $data )
{
@@ -945,7 +973,7 @@ class _invoices extends \IPS\Dispatcher\Controller
$form->addHeader( 'invoice_settings' );
$currencies = \IPS\nexus\Money::currencies();
if ( count( $currencies ) > 1 )
if ( \count( $currencies ) > 1 )
{
$form->add( new \IPS\Helpers\Form\Radio( 'currency', $invoice ? $invoice->currency : $customer->defaultCurrency(), TRUE, array( 'options' => array_combine( $currencies, $currencies ) ) ) );
}
@@ -962,9 +990,25 @@ class _invoices extends \IPS\Dispatcher\Controller
$form->add( new \IPS\Helpers\Form\Text( 'invoice_po_number', $invoice ? $invoice->po_number : NULL, FALSE, array( 'maxLength' => 255 ) ) );
$form->add( new \IPS\Helpers\Form\TextArea( 'invoice_notes', $invoice ? $invoice->notes : NULL ) );
$needTaxStatus = NULL;
foreach ( \IPS\nexus\Tax::roots() as $tax )
{
if ( $tax->type === 'eu' )
{
$needTaxStatus = 'eu';
break;
}
if ( $tax->type === 'business' )
{
$needTaxStatus = 'business';
}
}
$addressHelperClass = $needTaxStatus ? 'IPS\nexus\Form\BusinessAddress' : 'IPS\Helpers\Form\Address';
$addressHelperOptions = ( $needTaxStatus === 'eu' ) ? array( 'vat' => TRUE ) : array();
$form->addHeader( 'invoice_generate_addresses' );
$addresses = \IPS\Db::i()->select( '*', 'nexus_customer_addresses', array( 'member=?', $customer->member_id ) );
if ( count( $addresses ) )
$addresses = \IPS\Db::i()->select( '*', 'nexus_customer_addresses', array( '`member`=?', $customer->member_id ) );
if ( \count( $addresses ) )
{
$primaryBillingAddressId = NULL;
$chosenBillingAddressId = 0;
@@ -973,7 +1017,7 @@ class _invoices extends \IPS\Dispatcher\Controller
$options = array();
foreach ( new \IPS\Patterns\ActiveRecordIterator( $addresses, 'IPS\nexus\Customer\Address' ) as $address )
{
$options[ $address->id ] = (string) $address->address;
$options[ $address->id ] = $address->address->toString('<br>') . ( ( isset( $address->address->business ) and $address->address->business and isset( $address->address->vat ) and $address->address->vat ) ? ( '<br>' . \IPS\Member::loggedIn()->language()->addToStack('cm_checkout_vat_number') . ': ' . \IPS\Theme::i()->getTemplate( 'global', 'nexus' )->vatNumber( $address->address->vat ) ) : '' );
if ( $address->primary_billing )
{
$primaryBillingAddressId = $address->id;
@@ -992,28 +1036,33 @@ class _invoices extends \IPS\Dispatcher\Controller
$chosenShippingAddressid = $address->id;
}
}
$options[0] = 'other';
$options[0] = \IPS\Member::loggedIn()->language()->addToStack('other');
$form->add( new \IPS\Helpers\Form\Radio( 'billing_address', ( $invoice and $invoice->billaddress ) ? $chosenBillingAddressId : $primaryBillingAddressId, TRUE, array( 'options' => $options, 'toggles' => array( 0 => array( 'new_billing_address' ) ) ) ) );
$newAddress = new \IPS\Helpers\Form\Address( 'new_billing_address', $invoice ? $invoice->billaddress : NULL, FALSE, array(), NULL, NULL, NULL, 'new_billing_address' );
$form->add( new \IPS\Helpers\Form\Radio( 'billing_address', ( $invoice and $invoice->billaddress ) ? $chosenBillingAddressId : $primaryBillingAddressId, TRUE, array( 'options' => $options, 'toggles' => array( 0 => array( 'new_billing_address' ) ), 'parse' => 'raw' ) ) );
$newAddress = new $addressHelperClass( 'new_billing_address', $invoice ? $invoice->billaddress : NULL, FALSE, $addressHelperOptions, NULL, NULL, NULL, 'new_billing_address' );
$newAddress->label = ' ';
$form->add( $newAddress );
$form->add( new \IPS\Helpers\Form\Radio( 'shipping_address', ( $invoice and $invoice->shipaddress ) ? $chosenShippingAddressid : ( ( $primaryShippingAddressId == $primaryBillingAddressId ) ? 'x' : $primaryShippingAddressId ), TRUE, array( 'options' => array( 'x' => 'same_as_billing_address' ) + $options, 'toggles' => array( 0 => array( 'new_shipping_address' ) ) ) ) );
$newAddress = new \IPS\Helpers\Form\Address( 'new_shipping_address', $invoice ? $invoice->shipaddress : NULL, FALSE, array(), NULL, NULL, NULL, 'new_shipping_address' );
$form->add( new \IPS\Helpers\Form\Radio( 'shipping_address', ( $invoice and $invoice->shipaddress ) ? $chosenShippingAddressid : ( ( $primaryShippingAddressId == $primaryBillingAddressId ) ? 'x' : $primaryShippingAddressId ), TRUE, array( 'options' => array( 'x' => \IPS\Member::loggedIn()->language()->addToStack('same_as_billing_address') ) + $options, 'toggles' => array( 0 => array( 'new_shipping_address' ) ), 'parse' => 'raw' ) ) );
$newAddress = new $addressHelperClass( 'new_shipping_address', $invoice ? $invoice->shipaddress : NULL, FALSE, array(), NULL, NULL, NULL, 'new_shipping_address' );
$newAddress->label = ' ';
$form->add( $newAddress );
}
else
{
$form->add( new \IPS\Helpers\Form\Address( 'new_billing_address', $invoice ? $invoice->billaddress : NULL, FALSE ) );
$form->add( new $addressHelperClass( 'new_billing_address', $invoice ? $invoice->billaddress : NULL, FALSE, $addressHelperOptions, function( $val ) {
if ( \IPS\Request::i()->invoice_status === \IPS\nexus\Invoice::STATUS_PAID and !$val )
{
throw new \DomainException('billing_address_req');
}
} ) );
$form->add( new \IPS\Helpers\Form\Radio( 'shipping_address', ( $invoice and $invoice->shipaddress and $invoice->shipaddress != $invoice->billaddress ) ? '1' : 'x', FALSE, array( 'options' => array( 'x' => 'same_as_billing_address', '1' => 'other' ), 'toggles' => array( '1' => array( 'new_shipping_address' ) ) ) ) );
$form->add( new \IPS\Helpers\Form\Address( 'new_shipping_address', $invoice ? $invoice->billaddress : NULL, FALSE, array(), NULL, NULL, NULL, 'new_shipping_address' ) );
$form->add( new $addressHelperClass( 'new_shipping_address', $invoice ? $invoice->billaddress : NULL, FALSE, array(), NULL, NULL, NULL, 'new_shipping_address' ) );
}
if ( $values = $form->values() )
{
if ( count( $addresses ) and $values['billing_address'] )
if ( \count( $addresses ) and $values['billing_address'] )
{
$data['billaddress'] = \IPS\nexus\Customer\Address::load( $values['billing_address'] )->address;
}
@@ -1029,7 +1078,7 @@ class _invoices extends \IPS\Dispatcher\Controller
}
}
if ( count( $addresses ) and $values['shipping_address'] and $values['shipping_address'] !== 'x' )
if ( \count( $addresses ) and $values['shipping_address'] and $values['shipping_address'] !== 'x' )
{
$data['shipaddress'] = \IPS\nexus\Customer\Address::load( $values['shipping_address'] )->address;
}
@@ -1120,6 +1169,21 @@ class _invoices extends \IPS\Dispatcher\Controller
$invoice->status = $data['status'];
$invoice->save();
}
/* Now that we have an ID, do we need to update purchase rows? */
if ( isset( $data['update_purchase_invoice_pending'] ) and \is_array( $data['update_purchase_invoice_pending'] ) )
{
foreach( $data['update_purchase_invoice_pending'] as $id )
{
try
{
$purchase = \IPS\nexus\Purchase::load( $id );
$purchase->invoice_pending = $invoice;
$purchase->save();
}
catch( \Exception $e ) {}
}
}
$invoice->sendNotification();
@@ -1144,6 +1208,7 @@ class _invoices extends \IPS\Dispatcher\Controller
foreach ( $values['purchases_to_renew'] as $purchase )
{
$invoice->addItem( \IPS\nexus\Invoice\Item\Renewal::create( $purchase, $values['renew_cycles'] ) );
$data['update_purchase_invoice_pending'][] = $purchase->id;
}
$data['items'] = $invoice->items->getArrayCopy();
$_SESSION[ 'wizard-' . md5( $url ) . '-data' ] = $data;
@@ -1180,7 +1245,7 @@ class _invoices extends \IPS\Dispatcher\Controller
if ( $secondStepValues = $secondStepForm->values() )
{
$item = $class::createFromForm( $secondStepValues, $invoice );
if( is_array( $item ) )
if( \is_array( $item ) )
{
foreach ( $item as $i )
{
@@ -1196,12 +1261,20 @@ class _invoices extends \IPS\Dispatcher\Controller
\IPS\Output::i()->redirect( $url );
return;
}
return $secondStepForm;
if ( \IPS\Request::i()->isAjax() )
{
\IPS\Output::i()->sendOutput( \IPS\Theme::i()->getTemplate( 'global', 'core' )->blankTemplate( $secondStepForm ), 200, 'text/html' );
}
else
{
\IPS\Output::i()->sendOutput( \IPS\Theme::i()->getTemplate( 'global', 'core' )->globalTemplate( \IPS\Output::i()->title, $secondStepForm, array( 'app' => \IPS\Dispatcher::i()->application->directory, 'module' => \IPS\Dispatcher::i()->module->key, 'controller' => \IPS\Dispatcher::i()->controller ) ), 200, 'text/html' );
}
}
}
$item = $class::createFromForm( $values, $invoice );
if( is_array( $item ) )
if( \is_array( $item ) )
{
foreach ( $item as $i )
{
@@ -1220,11 +1293,11 @@ class _invoices extends \IPS\Dispatcher\Controller
if ( \IPS\Request::i()->isAjax() )
{
\IPS\Output::i()->sendOutput( \IPS\Theme::i()->getTemplate( 'global', 'core' )->blankTemplate( $form ), 200, 'text/html', \IPS\Output::i()->httpHeaders );
\IPS\Output::i()->sendOutput( \IPS\Theme::i()->getTemplate( 'global', 'core' )->blankTemplate( $form ), 200, 'text/html' );
}
else
{
\IPS\Output::i()->sendOutput( \IPS\Theme::i()->getTemplate( 'global', 'core' )->globalTemplate( \IPS\Output::i()->title, $form, array( 'app' => \IPS\Dispatcher::i()->application->directory, 'module' => \IPS\Dispatcher::i()->module->key, 'controller' => \IPS\Dispatcher::i()->controller ) ), 200, 'text/html', \IPS\Output::i()->httpHeaders );
\IPS\Output::i()->sendOutput( \IPS\Theme::i()->getTemplate( 'global', 'core' )->globalTemplate( \IPS\Output::i()->title, $form, array( 'app' => \IPS\Dispatcher::i()->application->directory, 'module' => \IPS\Dispatcher::i()->module->key, 'controller' => \IPS\Dispatcher::i()->controller ) ), 200, 'text/html' );
}
return;
}
@@ -1270,13 +1343,13 @@ class _invoices extends \IPS\Dispatcher\Controller
protected function settings()
{
\IPS\Dispatcher::i()->checkAcpPermission( 'invoices_settings' );
$form = new \IPS\Helpers\Form;
$form->addheader('invoice_flow');
$form->addMessage('invoice_flow_visualise');
$form->add( new \IPS\Helpers\Form\Number( 'cm_invoice_generate', \IPS\Settings::i()->cm_invoice_generate, FALSE, array( 'min' => 1 ), NULL, NULL, \IPS\Member::loggedIn()->language()->addToStack('cm_invoice_generate_suffix') ) );
$form->add( new \IPS\Helpers\Form\Number( 'cm_invoice_warning', \IPS\Settings::i()->cm_invoice_warning, FALSE, array( 'unlimited' => 0, 'unlimitedLang' => 'never' ), NULL, NULL, \IPS\Member::loggedIn()->language()->addToStack('cm_invoice_warning_suffix') ) );
$form->add( new \IPS\Helpers\Form\Number( 'cm_invoice_expireafter', \IPS\Settings::i()->cm_invoice_expireafter, FALSE, array( 'unlimited' => 0 ), NULL, NULL, \IPS\Member::loggedIn()->language()->addToStack('days') ) );
$form->add( new \IPS\Helpers\Form\Interval( 'cm_invoice_generate', \IPS\Settings::i()->cm_invoice_generate, FALSE, array( 'valueAs' => \IPS\Helpers\Form\Interval::HOURS, 'min' => 1 ), NULL, NULL, \IPS\Member::loggedIn()->language()->addToStack('cm_invoice_generate_suffix') ) );
$form->add( new \IPS\Helpers\Form\Interval( 'cm_invoice_warning', \IPS\Settings::i()->cm_invoice_warning, FALSE, array( 'valueAs' => \IPS\Helpers\Form\Interval::HOURS, 'unlimited' => 0, 'unlimitedLang' => 'never' ), NULL, NULL, \IPS\Member::loggedIn()->language()->addToStack('cm_invoice_warning_suffix') ) );
$form->add( new \IPS\Helpers\Form\Interval( 'cm_invoice_expireafter', \IPS\Settings::i()->cm_invoice_expireafter, FALSE, array( 'valueAs' => \IPS\Helpers\Form\Interval::DAYS, 'unlimited' => 0 ), NULL, NULL, NULL ) );
$form->addHeader('invoice_layout');
$form->addMessage('invoice_layout_blurb');
$form->add( new \IPS\Helpers\Form\Editor( 'nexus_invoice_header', \IPS\Settings::i()->nexus_invoice_header, FALSE, array( 'app' => 'nexus', 'key' => 'Admin', 'autoSaveKey' => 'nexus-invoice-header', 'attachIds' => array( NULL, NULL, 'invoice-header' ), 'minimize' => 'nexus_invoice_header_placeholder' ) ) );
@@ -1332,4 +1405,74 @@ class _invoices extends \IPS\Dispatcher\Controller
\IPS\Output::i()->redirect( $invoice->acpUrl() );
}
/**
* Wait for the webhook for a transaction to come through before it has been created
*
* @return void
*/
public function webhook()
{
/* Load the invoice */
try
{
$invoice = \IPS\nexus\Invoice::load( \IPS\Request::i()->invoice );
}
catch ( \OutOfRangeException $e )
{
\IPS\Output::i()->error( 'node_error', '2X190/J', 404, '' );
}
/* Have we decided to give up waiting and just show a pending screen? */
if ( isset( \IPS\Request::i()->pending ) )
{
\IPS\Output::i()->error( 'webhook_not_received', '2X190/K', 404 );
}
/* Nope - show a redirector */
\IPS\Output::i()->output = $this->_webhookRedirector( $invoice, isset( \IPS\Request::i()->exclude ) ? explode( ',', \IPS\Request::i()->exclude ) : array() );
}
/**
* Get a redirector that points to do=webhook
*
* @param \IPS\nexus\Invoice $invoice The invoice
* @param array $exclude Transaction IDs to exclude
* @return \IPS\Helpers\MultipleRedirect
*/
protected function _webhookRedirector( \IPS\nexus\Invoice $invoice, $exclude )
{
$self = $this;
return new \IPS\Helpers\MultipleRedirect(
\IPS\Http\Url::internal('app=nexus&module=payments&controller=invoices')->setQueryString( array( 'do' => 'webhook', 'invoice' => $invoice->id, 'exclude' => implode( ',', $exclude ) ) ),
function( $data ) use ( $self, $invoice, $exclude ) {
if ( $data === NULL )
{
return array( time(), \IPS\Member::loggedIn()->language()->addToStack('processing_the_payment') );
}
else
{
/* Do we have any transactions yet? */
foreach ( $invoice->transactions( array( \IPS\nexus\Transaction::STATUS_PAID, \IPS\nexus\Transaction::STATUS_HELD, \IPS\nexus\Transaction::STATUS_REFUSED ), $exclude ? array( array( \IPS\Db::i()->in( 't_id', $exclude, TRUE ) ) ) : array() ) as $transaction )
{
$self->_redirect( $invoice );
}
$giveUpTime = ( $data + 60 );
if ( time() > $giveUpTime )
{
return NULL;
}
else
{
sleep(5);
return array( $data, \IPS\Member::loggedIn()->language()->addToStack('processing_the_payment') );
}
}
},
function() use( $invoice ) {
\IPS\Output::i()->redirect( \IPS\Http\Url::internal('app=nexus&module=payments&controller=invoices')->setQueryString( array( 'do' => 'webhook', 'invoice' => $invoice->id, 'pending' => 1 ) ) );
}
);
}
}
@@ -12,7 +12,7 @@
namespace IPS\nexus\modules\admin\payments;
/* To prevent PHP errors (extending class does not exist) revealing path */
if ( !defined( '\IPS\SUITE_UNIQUE_KEY' ) )
if ( !\defined( '\IPS\SUITE_UNIQUE_KEY' ) )
{
header( ( isset( $_SERVER['SERVER_PROTOCOL'] ) ? $_SERVER['SERVER_PROTOCOL'] : 'HTTP/1.0' ) . ' 403 Forbidden' );
exit;
@@ -23,6 +23,11 @@ if ( !defined( '\IPS\SUITE_UNIQUE_KEY' ) )
*/
class _paymentsettings extends \IPS\Dispatcher\Controller
{
/**
* @brief Has been CSRF-protected
*/
public static $csrfProtected = TRUE;
/**
* Call
*
@@ -55,7 +60,7 @@ class _paymentsettings extends \IPS\Dispatcher\Controller
{
$tabs['review'] = 'transaction_review';
}
if( \IPS\Member::loggedIn()->hasAcpRestriction( 'nexus', 'payments', 'email_copies_setting' ) )
if( \IPS\Member::loggedIn()->hasAcpRestriction( 'nexus', 'payments', 'email_copies_settings' ) )
{
$tabs['emails'] = 'notification_copies';
}
@@ -12,7 +12,7 @@
namespace IPS\nexus\modules\admin\payments;
/* To prevent PHP errors (extending class does not exist) revealing path */
if ( !defined( '\IPS\SUITE_UNIQUE_KEY' ) )
if ( !\defined( '\IPS\SUITE_UNIQUE_KEY' ) )
{
header( ( isset( $_SERVER['SERVER_PROTOCOL'] ) ? $_SERVER['SERVER_PROTOCOL'] : 'HTTP/1.0' ) . ' 403 Forbidden' );
exit;
@@ -23,6 +23,11 @@ if ( !defined( '\IPS\SUITE_UNIQUE_KEY' ) )
*/
class _payouts extends \IPS\Dispatcher\Controller
{
/**
* @brief Has been CSRF-protected
*/
public static $csrfProtected = TRUE;
/**
* Execute
*
@@ -64,13 +69,13 @@ class _payouts extends \IPS\Dispatcher\Controller
foreach ( \IPS\Db::i()->select( 'po_gateway', 'nexus_payouts', array( 'po_status=?', \IPS\nexus\Payout::STATUS_PENDING ), NULL, NULL, 'po_gateway' ) as $gateway )
{
$classname = 'IPS\nexus\Gateway\\' . $gateway . '\Payout';
$classname = \IPS\nexus\Gateway::payoutGateways()[ $gateway ];
if ( class_exists( $classname ) and method_exists( $classname, 'massProcess' ) )
{
\IPS\Output::i()->sidebar['actions'][] = array(
'icon' => 'check',
'title' => \IPS\Member::loggedIn()->language()->addToStack( 'account_credit_mass_payout', TRUE, array( 'sprintf' => array( \IPS\Member::loggedIn()->language()->addToStack( 'payout__admin_' . $gateway ) ) ) ),
'link' => \IPS\Http\Url::internal( 'app=nexus&module=payments&controller=payouts&do=massprocess&gateway=' . $gateway )
'link' => \IPS\Http\Url::internal( 'app=nexus&module=payments&controller=payouts&do=massprocess&gateway=' . $gateway )->csrf()
);
}
}
@@ -107,6 +112,7 @@ class _payouts extends \IPS\Dispatcher\Controller
protected function process()
{
\IPS\Dispatcher::i()->checkAcpPermission( 'payouts_process' );
\IPS\Session::i()->csrfCheck();
try
{
@@ -150,8 +156,9 @@ class _payouts extends \IPS\Dispatcher\Controller
protected function massprocess()
{
\IPS\Dispatcher::i()->checkAcpPermission( 'payouts_process' );
\IPS\Session::i()->csrfCheck();
$classname = 'IPS\nexus\Gateway\\' . \IPS\Request::i()->gateway . '\Payout';
$classname = \IPS\nexus\Gateway::payoutGateways()[ \IPS\Request::i()->gateway ];
if ( !class_exists( $classname ) or !method_exists( $classname, 'massProcess' ) )
{
\IPS\Output::i()->error( 'generic_error', '2X200/8', 403, '' );
@@ -191,6 +198,7 @@ class _payouts extends \IPS\Dispatcher\Controller
protected function cancel()
{
\IPS\Dispatcher::i()->checkAcpPermission( 'payouts_cancel' );
\IPS\Session::i()->csrfCheck();
try
{
@@ -264,24 +272,20 @@ class _payouts extends \IPS\Dispatcher\Controller
$options = array();
$toggles = array();
$fields = array();
foreach ( new \DirectoryIterator( \IPS\ROOT_PATH . '/applications/nexus/sources/Gateway' ) as $file )
foreach ( \IPS\nexus\Gateway::payoutGateways() as $key => $class )
{
if ( $file->isDir() and !$file->isDot() and $file != 'Stripe' and file_exists( \IPS\ROOT_PATH . '/applications/nexus/sources/Gateway/' . $file . '/Payout.php' ) )
$options[ $key ] = 'payout__admin_' . $key;
$toggles[ $key ] = array( 'form_header_payout_settings' );
foreach ( $class::settings() as $field )
{
$options[ (string) $file ] = 'payout__admin_' . $file;
$toggles[ (string) $file ] = array( 'form_header_payout_settings' );
$class = 'IPS\nexus\Gateway\\' . (string) $file . '\\Payout';
foreach ( $class::settings() as $field )
if ( !$field->htmlId )
{
if ( !$field->htmlId )
{
$field->htmlId = md5(mt_rand());
}
$fields[] = $field;
$toggles[ (string) $file ][] = $field->htmlId;
$field->htmlId = md5(mt_rand());
}
$fields[] = $field;
$toggles[ $key ][] = $field->htmlId;
}
}
@@ -292,7 +296,7 @@ class _payouts extends \IPS\Dispatcher\Controller
}
$settings = \IPS\Settings::i()->nexus_payout ? json_decode( \IPS\Settings::i()->nexus_payout, TRUE ) : array();
$settings = is_array( $settings ) ? array_keys( $settings ) : array();
$settings = \is_array( $settings ) ? array_keys( $settings ) : array();
$form = new \IPS\Helpers\Form;
$form->addMessage('payout_description');
@@ -305,10 +309,10 @@ class _payouts extends \IPS\Dispatcher\Controller
$form->add( $field );
}
$form->addHeader('payout_settings');
$form->add( new \IPS\nexus\Form\Money( 'nexus_payout_min', \IPS\Settings::i()->nexus_payout_min ? json_decode( \IPS\Settings::i()->nexus_payout_min, TRUE ) : '*', FALSE, array( 'unlimitedLang' => 'no_restriction' ), NULL, NULL, NULL, 'nexus_payout_min' ) );
$form->add( new \IPS\nexus\Form\Money( 'nexus_payout_min', ( \IPS\Settings::i()->nexus_payout_min AND \IPS\Settings::i()->nexus_payout_min != '*' ) ? json_decode( \IPS\Settings::i()->nexus_payout_min, TRUE ) : '*', FALSE, array( 'unlimitedLang' => 'no_restriction' ), NULL, NULL, NULL, 'nexus_payout_min' ) );
$form->add( new \IPS\Helpers\Form\Custom( 'nexus_payout_maximum', NULL, FALSE, array( 'getHtml' => function( $element ) {
$amount = new \IPS\nexus\Form\Money( 'nexus_payout_maximum[2]', \IPS\Settings::i()->nexus_payout_max ? json_decode( \IPS\Settings::i()->nexus_payout_max, TRUE ) : '*', FALSE, array( 'unlimitedLang' => 'no_restriction', 'unlimitedTogglesOff' => array( 'payout_max_limited' ) ), NULL, NULL, NULL, 'nexus_payout_max' );
$amount = new \IPS\nexus\Form\Money( 'nexus_payout_maximum[2]', ( \IPS\Settings::i()->nexus_payout_max AND \IPS\Settings::i()->nexus_payout_max != '*' ) ? json_decode( \IPS\Settings::i()->nexus_payout_max, TRUE ) : '*', FALSE, array( 'unlimitedLang' => 'no_restriction', 'unlimitedTogglesOff' => array( 'payout_max_limited' ) ), NULL, NULL, NULL, 'nexus_payout_max' );
$period = \IPS\Settings::i()->nexus_payout_max_period ? json_decode( \IPS\Settings::i()->nexus_payout_max_period, TRUE ) : array( 1, 'day' );
return \IPS\Theme::i()->getTemplate( 'payouts' )->maximumLimits( $amount->html(), (int) $period[0], $period[1] );
@@ -334,12 +338,18 @@ class _payouts extends \IPS\Dispatcher\Controller
}
}
}
/* Clear out gateway fields that aren't real settings */
foreach( $fields as $field )
{
unset( $values[ $field->name ] );
}
$values['nexus_payout'] = json_encode( $payoutSettings );
$values['nexus_payout_min'] = is_array( $values['nexus_payout_min'] ) ? json_encode( $values['nexus_payout_min'] ) : '*';
$values['nexus_payout_max'] = is_array( $values['nexus_payout_maximum'][2] ) ? json_encode( $values['nexus_payout_maximum'][2] ) : '*';
$values['nexus_payout_max_period'] = json_encode( array( $values['nexus_payout_maximum'][0], $values['nexus_payout_maximum'][1] ) );
$values['nexus_payout_min'] = \is_array( $values['nexus_payout_min'] ) ? json_encode( $values['nexus_payout_min'] ) : '*';
$values['nexus_payout_max'] = ( \is_array( $values['nexus_payout_maximum'][2] ) AND ( !isset( $values['nexus_payout_maximum'][2]['__unlimited'] ) OR !$values['nexus_payout_maximum'][2]['__unlimited'] ) ) ? json_encode( $values['nexus_payout_maximum'][2] ) : '*';
$values['nexus_payout_max_period'] = ( $values['nexus_payout_max'] == '*' ) ? NULL : json_encode( array( $values['nexus_payout_maximum'][0], $values['nexus_payout_maximum'][1] ) );
if ( $values['allow_topups'] )
{
$values['nexus_min_topup'] = $values['nexus_min_topup'] == '*' ? '*' : json_encode( $values['nexus_min_topup'] );
@@ -350,10 +360,10 @@ class _payouts extends \IPS\Dispatcher\Controller
$values['nexus_min_topup'] = '';
$values['nexus_max_credit'] = '';
}
unset( $values['allow_topups'] );
unset( $values['allow_topups'], $values['nexus_payout_maximum'] );
$values['nexus_no_commission'] = implode( ',', $values['nexus_no_commission'] );
$form->saveAsSettings( $values );
\IPS\Session::i()->log( 'acplogs__payout_settings' );
@@ -387,7 +397,10 @@ class _payouts extends \IPS\Dispatcher\Controller
case 't':
\IPS\Output::i()->redirect( \IPS\Http\Url::internal('app=nexus&module=payments&controller=payouts')->setQueryString( 'filter', \IPS\Request::i()->filter ) );
break;
case 'n':
\IPS\Output::i()->redirect( \IPS\Http\Url::internal('app=core&module=overview&controller=notifications') );
break;
}
}
@@ -12,7 +12,7 @@
namespace IPS\nexus\modules\admin\payments;
/* To prevent PHP errors (extending class does not exist) revealing path */
if ( !defined( '\IPS\SUITE_UNIQUE_KEY' ) )
if ( !\defined( '\IPS\SUITE_UNIQUE_KEY' ) )
{
header( ( isset( $_SERVER['SERVER_PROTOCOL'] ) ? $_SERVER['SERVER_PROTOCOL'] : 'HTTP/1.0' ) . ' 403 Forbidden' );
exit;
@@ -23,6 +23,11 @@ if ( !defined( '\IPS\SUITE_UNIQUE_KEY' ) )
*/
class _review extends \IPS\Dispatcher\Controller
{
/**
* @brief Has been CSRF-protected
*/
public static $csrfProtected = TRUE;
/**
* Execute
*
@@ -12,7 +12,7 @@
namespace IPS\nexus\modules\admin\payments;
/* To prevent PHP errors (extending class does not exist) revealing path */
if ( !defined( '\IPS\SUITE_UNIQUE_KEY' ) )
if ( !\defined( '\IPS\SUITE_UNIQUE_KEY' ) )
{
header( ( isset( $_SERVER['SERVER_PROTOCOL'] ) ? $_SERVER['SERVER_PROTOCOL'] : 'HTTP/1.0' ) . ' 403 Forbidden' );
exit;
@@ -23,6 +23,11 @@ if ( !defined( '\IPS\SUITE_UNIQUE_KEY' ) )
*/
class _shipping extends \IPS\Dispatcher\Controller
{
/**
* @brief Has been CSRF-protected
*/
public static $csrfProtected = TRUE;
/**
* Execute
*
@@ -41,87 +46,6 @@ class _shipping extends \IPS\Dispatcher\Controller
*/
protected function manage()
{
/* Create the table */
$table = new \IPS\Helpers\Table\Db( 'nexus_ship_orders', \IPS\Http\Url::internal( 'app=nexus&module=payments&controller=shipping' ) );
$table->sortBy = $table->sortBy ?: 'o_date';
/* Format Columns */
$table->include = array( 'o_status', 'o_method', 'o_invoice', 'o_date' );
$table->parsers = array(
'o_status' => function( $val )
{
return \IPS\Theme::i()->getTemplate('shiporders')->status( $val );
},
'o_method' => function( $val, $row )
{
if ( $row['o_api_service'] )
{
return $row['o_api_service'];
}
try
{
return \IPS\nexus\Shipping\FlatRate::load( $val )->_title;
}
catch ( \Exception $e )
{
return '';
}
},
'o_invoice' => function( $val )
{
try
{
return \IPS\Theme::i()->getTemplate('invoices')->link( \IPS\nexus\Invoice::load( $val ) );
}
catch ( \Exception $e )
{
return '';
}
},
'o_date' => function( $val )
{
return (string) \IPS\DateTime::ts( $val );
}
);
/* Filters */
$table->filters = array(
'sstatus_pend' => array( 'o_status=?', 'pend' ),
);
/* Search */
$methods = array();
foreach( \IPS\nexus\Shipping\FlatRate::roots() as $method )
{
$methods[ $method->id ] = $method->_title;
}
$table->advancedSearch = array(
'o_status' => array( \IPS\Helpers\Table\SEARCH_SELECT, array( 'options' => array(
\IPS\nexus\Shipping\Order::STATUS_SHIPPED => 'sstatus_done',
\IPS\nexus\Shipping\Order::STATUS_PENDING => 'sstatus_pend',
\IPS\nexus\Shipping\Order::STATUS_CANCELED => 'sstatus_canc',
), 'multiple' => TRUE ) ),
'o_method' => array( \IPS\Helpers\Table\SEARCH_SELECT, array( 'options' => $methods, 'multiple' => TRUE ) ),
'o_date' => \IPS\Helpers\Table\SEARCH_DATE_RANGE,
'o_shipped_date'=> \IPS\Helpers\Table\SEARCH_DATE_RANGE,
'o_tracknumber' => \IPS\Helpers\Table\SEARCH_CONTAINS_TEXT,
);
$table->quickSearch = 'o_tracknumber';
/* Buttons */
$table->rowButtons = function( $row )
{
return array_merge( array(
'view' => array(
'icon' => 'search',
'title' => 'shipment_view',
'link' => \IPS\Http\Url::internal( "app=nexus&module=payments&controller=shipping&do=view&id={$row['o_id']}" )
)
), \IPS\nexus\Shipping\Order::constructFromData( $row )->buttons( 't' ) );
};
/* Settings Button */
if ( \IPS\Member::loggedIn()->hasAcpRestriction( 'nexus', 'payments', 'shipmethods_manage' ) )
{
\IPS\Output::i()->sidebar['actions']['settings'] = array(
@@ -133,7 +57,7 @@ class _shipping extends \IPS\Dispatcher\Controller
/* Display */
\IPS\Output::i()->title = \IPS\Member::loggedIn()->language()->addToStack('shipping');
\IPS\Output::i()->output = (string) $table;
\IPS\Output::i()->output = (string) \IPS\nexus\Shipping\Order::table( \IPS\Http\Url::internal( 'app=nexus&module=payments&controller=shipping' ) );
}
/**
@@ -421,7 +345,7 @@ class _shipping extends \IPS\Dispatcher\Controller
$easyPost = \IPS\Http\Url::external( 'https://api.easypost.com/v2/shipments' )->request()->login( \IPS\Settings::i()->easypost_api_key, '' )->post( array( 'shipment' => array(
'to_address' => array(
'street1' => array_shift( $toAddress['addressLines'] ),
'street2' => count( $toAddress['addressLines'] ) ? implode( ', ', $toAddress['addressLines'] ) : NULL,
'street2' => \count( $toAddress['addressLines'] ) ? implode( ', ', $toAddress['addressLines'] ) : NULL,
'city' => $toAddress['city'],
'state' => $toAddress['region'],
'zip' => $toAddress['postalCode'],
@@ -432,7 +356,7 @@ class _shipping extends \IPS\Dispatcher\Controller
),
'from_address' => array(
'street1' => array_shift( $fromAddress->addressLines ),
'street2' => count( $fromAddress->addressLines ) ? implode( ', ', $fromAddress->addressLines ) : NULL,
'street2' => \count( $fromAddress->addressLines ) ? implode( ', ', $fromAddress->addressLines ) : NULL,
'city' => $fromAddress->city,
'state' => $fromAddress->region,
'zip' => $fromAddress->postalCode,
@@ -445,7 +369,7 @@ class _shipping extends \IPS\Dispatcher\Controller
'customs_info' => $customsInfo
) ) )->decodeJson();
if ( !count( $easyPost['rates'] ) )
if ( !\count( $easyPost['rates'] ) )
{
\IPS\Output::i()->error( 'err_no_easypost', '1X193/6', 403, '' );
}
@@ -570,7 +494,7 @@ class _shipping extends \IPS\Dispatcher\Controller
/* How much did the customer pay for shipping? */
$invoiceSummary = $shipment->invoice->summary();
$otherShipments = count( $shipment->invoice->shipments() ) - 1;
$otherShipments = \count( $shipment->invoice->shipments() ) - 1;
$message = $otherShipments ? \IPS\Member::loggedIn()->language()->addToStack( 'shipment_cost_others', FALSE, array( 'sprintf' => array( $invoiceSummary['shippingTotal'], $shipment->invoice->id, $otherShipments ) ) ) : \IPS\Member::loggedIn()->language()->addToStack( 'shipment_cost_noothers', FALSE, array( 'sprintf' => array( $invoiceSummary['shippingTotal'] ) ) );
\IPS\Member::loggedIn()->language()->words['easypost_rate_desc'] = $message;
@@ -587,6 +511,7 @@ class _shipping extends \IPS\Dispatcher\Controller
public function cancel()
{
\IPS\Dispatcher::i()->checkAcpPermission( 'shiporders_edit' );
\IPS\Session::i()->csrfCheck();
/* Load */
try
@@ -675,7 +600,7 @@ class _shipping extends \IPS\Dispatcher\Controller
\IPS\Output::i()->cssFiles = array_merge( \IPS\Output::i()->cssFiles, \IPS\Theme::i()->css( 'shipping.css', 'nexus' ) );
}
\IPS\Output::i()->sendOutput( \IPS\Theme::i()->getTemplate( 'global', 'core', 'front' )->blankTemplate( $output ), 200, 'text/html', \IPS\Output::i()->httpHeaders );
\IPS\Output::i()->sendOutput( \IPS\Theme::i()->getTemplate( 'global', 'core', 'front' )->blankTemplate( $output ), 200, 'text/html' );
}
/**
@@ -12,7 +12,7 @@
namespace IPS\nexus\modules\admin\payments;
/* To prevent PHP errors (extending class does not exist) revealing path */
if ( !defined( '\IPS\SUITE_UNIQUE_KEY' ) )
if ( !\defined( '\IPS\SUITE_UNIQUE_KEY' ) )
{
header( ( isset( $_SERVER['SERVER_PROTOCOL'] ) ? $_SERVER['SERVER_PROTOCOL'] : 'HTTP/1.0' ) . ' 403 Forbidden' );
exit;
@@ -23,6 +23,11 @@ if ( !defined( '\IPS\SUITE_UNIQUE_KEY' ) )
*/
class _shippingrates extends \IPS\Node\Controller
{
/**
* @brief Has been CSRF-protected
*/
public static $csrfProtected = TRUE;
/**
* Node Class
*/
@@ -75,7 +80,7 @@ class _shippingrates extends \IPS\Node\Controller
{
$haveNoLowerLimit = TRUE;
}
elseif ( is_array( $rate['min'] ) )
elseif ( \is_array( $rate['min'] ) )
{
$allAreZero = TRUE;
foreach ( $rate['min'] as $val )
@@ -104,17 +109,17 @@ class _shippingrates extends \IPS\Node\Controller
if ( $lastUpper !== NULL )
{
if ( is_array( $lastUpper ) )
if ( \is_array( $lastUpper ) )
{
foreach ( $lastUpper as $k => $v )
{
if ( strval( $rate['min'][ $k ] - $v ) > 0.01 ) # @note: We use strval() here to prevent PHP from applying a precision to the float, inadvertently causing this to return TRUE
if ( \strval( $rate['min'][ $k ] - $v ) > 0.01 ) # @note: We use strval() here to prevent PHP from applying a precision to the float, inadvertently causing this to return TRUE
{
$consecutive = FALSE;
}
}
}
elseif ( strval( $rate['min'] - $lastUpper ) > 0.01 ) # @note: We use strval() here to prevent PHP from applying a precision to the float, inadvertently causing this to return TRUE
elseif ( \strval( $rate['min'] - $lastUpper ) > 0.01 ) # @note: We use strval() here to prevent PHP from applying a precision to the float, inadvertently causing this to return TRUE
{
$consecutive = FALSE;
}
@@ -12,7 +12,7 @@
namespace IPS\nexus\modules\admin\payments;
/* To prevent PHP errors (extending class does not exist) revealing path */
if ( !defined( '\IPS\SUITE_UNIQUE_KEY' ) )
if ( !\defined( '\IPS\SUITE_UNIQUE_KEY' ) )
{
header( ( isset( $_SERVER['SERVER_PROTOCOL'] ) ? $_SERVER['SERVER_PROTOCOL'] : 'HTTP/1.0' ) . ' 403 Forbidden' );
exit;
@@ -23,6 +23,11 @@ if ( !defined( '\IPS\SUITE_UNIQUE_KEY' ) )
*/
class _tax extends \IPS\Node\Controller
{
/**
* @brief Has been CSRF-protected
*/
public static $csrfProtected = TRUE;
/**
* Node Class
*/
@@ -12,7 +12,7 @@
namespace IPS\nexus\modules\admin\payments;
/* To prevent PHP errors (extending class does not exist) revealing path */
if ( !defined( '\IPS\SUITE_UNIQUE_KEY' ) )
if ( !\defined( '\IPS\SUITE_UNIQUE_KEY' ) )
{
header( ( isset( $_SERVER['SERVER_PROTOCOL'] ) ? $_SERVER['SERVER_PROTOCOL'] : 'HTTP/1.0' ) . ' 403 Forbidden' );
exit;
@@ -23,6 +23,11 @@ if ( !defined( '\IPS\SUITE_UNIQUE_KEY' ) )
*/
class _transactions extends \IPS\Dispatcher\Controller
{
/**
* @brief Has been CSRF-protected
*/
public static $csrfProtected = TRUE;
/**
* Execute
*
@@ -45,7 +50,7 @@ class _transactions extends \IPS\Dispatcher\Controller
/* Create Table */
$table = \IPS\nexus\Transaction::table( array( array( 't_status<>?', \IPS\nexus\Transaction::STATUS_PENDING ) ), \IPS\Http\Url::internal( 'app=nexus&module=payments&controller=transactions' ), 't' );
$table->filters = array(
'trans_attention_required' => array( '( t_status=? OR t_status=? OR t_status=? )', \IPS\nexus\Transaction::STATUS_HELD, \IPS\nexus\Transaction::STATUS_REVIEW, \IPS\nexus\Transaction::STATUS_DISPUTED ),
'trans_attention_required' => array( \IPS\Db::i()->in( 't_status', array( \IPS\nexus\Transaction::STATUS_HELD, \IPS\nexus\Transaction::STATUS_WAITING, \IPS\nexus\Transaction::STATUS_REVIEW, \IPS\nexus\Transaction::STATUS_DISPUTED ) ) ),
);
$table->advancedSearch = array(
't_id' => \IPS\Helpers\Table\SEARCH_CONTAINS_TEXT,
@@ -96,6 +101,7 @@ class _transactions extends \IPS\Dispatcher\Controller
public function approve()
{
\IPS\Dispatcher::i()->checkAcpPermission( 'transactions_edit' );
\IPS\Session::i()->csrfCheck();
/* Load Transaction */
try
@@ -109,7 +115,7 @@ class _transactions extends \IPS\Dispatcher\Controller
$method = $transaction->method;
/* Can we approve it? */
if ( !in_array( $transaction->status, array( \IPS\nexus\Transaction::STATUS_WAITING, \IPS\nexus\Transaction::STATUS_HELD, \IPS\nexus\Transaction::STATUS_REVIEW, \IPS\nexus\Transaction::STATUS_GATEWAY_PENDING ) ) )
if ( !\in_array( $transaction->status, array( \IPS\nexus\Transaction::STATUS_WAITING, \IPS\nexus\Transaction::STATUS_HELD, \IPS\nexus\Transaction::STATUS_REVIEW, \IPS\nexus\Transaction::STATUS_GATEWAY_PENDING, \IPS\nexus\Transaction::STATUS_DISPUTED ) ) )
{
\IPS\Output::i()->error( 'transaction_status_err', '2X186/A', 403, '' );
}
@@ -127,7 +133,10 @@ class _transactions extends \IPS\Dispatcher\Controller
/* Do it */
try
{
$transaction->capture();
if ( $transaction->status !== \IPS\nexus\Transaction::STATUS_DISPUTED )
{
$transaction->capture();
}
$transaction->approve( \IPS\Member::loggedIn() );
}
catch ( \LogicException $e )
@@ -141,9 +150,16 @@ class _transactions extends \IPS\Dispatcher\Controller
/* Send Email */
$transaction->sendNotification();
/* Redirect */
$this->_redirect( $transaction );
if ( \IPS\Request::i()->isAjax() and \IPS\Request::i()->queueStatus )
{
\IPS\Output::i()->json( array( 'message' => \IPS\Member::loggedIn()->language()->addToStack('tstatus_okay_set'), 'queue' => \IPS\nexus\extensions\core\AdminNotifications\Transaction::queueHtml( \IPS\Request::i()->queueStatus ) ) );
}
else
{
$this->_redirect( $transaction );
}
}
/**
@@ -154,6 +170,7 @@ class _transactions extends \IPS\Dispatcher\Controller
public function review()
{
\IPS\Dispatcher::i()->checkAcpPermission( 'transactions_edit' );
\IPS\Session::i()->csrfCheck();
/* Load Transaction */
try
@@ -167,7 +184,7 @@ class _transactions extends \IPS\Dispatcher\Controller
$method = $transaction->method;
/* Can we flag it? */
if ( !in_array( $transaction->status, array( \IPS\nexus\Transaction::STATUS_WAITING, \IPS\nexus\Transaction::STATUS_HELD ) ) )
if ( !\in_array( $transaction->status, array( \IPS\nexus\Transaction::STATUS_WAITING, \IPS\nexus\Transaction::STATUS_HELD ) ) )
{
\IPS\Output::i()->error( 'transaction_status_err', '2X186/B', 403, '' );
}
@@ -189,6 +206,9 @@ class _transactions extends \IPS\Dispatcher\Controller
) );
}
/* Notification */
\IPS\core\AdminNotification::send( 'nexus', 'Transaction', \IPS\nexus\Transaction::STATUS_REVIEW, TRUE, $transaction );
/* Create a support request? */
if ( \IPS\Settings::i()->nexus_revw_sa != -1 )
{
@@ -214,7 +234,7 @@ class _transactions extends \IPS\Dispatcher\Controller
else
{
$_SESSION["wizard-{$key}-data"] = $extraData;
if ( count( \IPS\nexus\Support\StockAction::roots() ) )
if ( \count( \IPS\nexus\Support\StockAction::roots() ) )
{
$_SESSION["wizard-{$key}-step"] = 'stock_action';
}
@@ -231,7 +251,14 @@ class _transactions extends \IPS\Dispatcher\Controller
}
/* Redirect */
$this->_redirect( $transaction );
if ( \IPS\Request::i()->isAjax() and \IPS\Request::i()->queueStatus )
{
\IPS\Output::i()->json( array( 'message' => \IPS\Member::loggedIn()->language()->addToStack('tstatus_revw_set'), 'queue' => \IPS\nexus\extensions\core\AdminNotifications\Transaction::queueHtml( \IPS\Request::i()->queueStatus ) ) );
}
else
{
$this->_redirect( $transaction );
}
}
/**
@@ -242,6 +269,7 @@ class _transactions extends \IPS\Dispatcher\Controller
public function void()
{
\IPS\Dispatcher::i()->checkAcpPermission( 'transactions_edit' );
\IPS\Session::i()->csrfCheck();
/* Load Transaction */
try
@@ -255,7 +283,7 @@ class _transactions extends \IPS\Dispatcher\Controller
$method = $transaction->method;
/* Can we void it? */
if ( !in_array( $transaction->status, array( \IPS\nexus\Transaction::STATUS_WAITING, \IPS\nexus\Transaction::STATUS_GATEWAY_PENDING ) ) and ( !$transaction->auth or !in_array( $transaction->status, array( \IPS\nexus\Transaction::STATUS_HELD, \IPS\nexus\Transaction::STATUS_REVIEW ) ) ) )
if ( !\in_array( $transaction->status, array( \IPS\nexus\Transaction::STATUS_WAITING, \IPS\nexus\Transaction::STATUS_GATEWAY_PENDING ) ) and ( !$transaction->auth or !\in_array( $transaction->status, array( \IPS\nexus\Transaction::STATUS_HELD, \IPS\nexus\Transaction::STATUS_REVIEW ) ) ) )
{
\IPS\Output::i()->error( 'transaction_status_err', '2X186/5', 403, '' );
}
@@ -277,7 +305,14 @@ class _transactions extends \IPS\Dispatcher\Controller
$transaction->sendNotification();
/* Redirect */
$this->_redirect( $transaction );
if ( \IPS\Request::i()->isAjax() and \IPS\Request::i()->queueStatus )
{
\IPS\Output::i()->json( array( 'message' => \IPS\Member::loggedIn()->language()->addToStack('tstatus_fail_set'), 'queue' => \IPS\nexus\extensions\core\AdminNotifications\Transaction::queueHtml( \IPS\Request::i()->queueStatus ) ) );
}
else
{
$this->_redirect( $transaction );
}
}
/**
@@ -301,7 +336,7 @@ class _transactions extends \IPS\Dispatcher\Controller
$method = $transaction->method;
/* Can we refund it? */
if ( !in_array( $transaction->status, array( \IPS\nexus\Transaction::STATUS_PAID, \IPS\nexus\Transaction::STATUS_HELD, \IPS\nexus\Transaction::STATUS_REVIEW, \IPS\nexus\Transaction::STATUS_PART_REFUNDED ) ) )
if ( !\in_array( $transaction->status, array( \IPS\nexus\Transaction::STATUS_PAID, \IPS\nexus\Transaction::STATUS_HELD, \IPS\nexus\Transaction::STATUS_REVIEW, \IPS\nexus\Transaction::STATUS_PART_REFUNDED, \IPS\nexus\Transaction::STATUS_DISPUTED ) ) )
{
\IPS\Output::i()->error( 'transaction_status_err', '2X186/E', 403, '' );
}
@@ -567,6 +602,10 @@ class _transactions extends \IPS\Dispatcher\Controller
case 't':
\IPS\Output::i()->redirect( \IPS\Http\Url::internal('app=nexus&module=payments&controller=transactions') );
break;
case 'n':
\IPS\Output::i()->redirect( \IPS\Http\Url::internal('app=core&module=overview&controller=notifications') );
break;
}
}
@@ -12,7 +12,7 @@
namespace IPS\nexus\modules\admin\reports;
/* To prevent PHP errors (extending class does not exist) revealing path */
if ( !defined( '\IPS\SUITE_UNIQUE_KEY' ) )
if ( !\defined( '\IPS\SUITE_UNIQUE_KEY' ) )
{
header( ( isset( $_SERVER['SERVER_PROTOCOL'] ) ? $_SERVER['SERVER_PROTOCOL'] : 'HTTP/1.0' ) . ' 403 Forbidden' );
exit;
@@ -23,6 +23,11 @@ if ( !defined( '\IPS\SUITE_UNIQUE_KEY' ) )
*/
class _income extends \IPS\Dispatcher\Controller
{
/**
* @brief Has been CSRF-protected
*/
public static $csrfProtected = TRUE;
/**
* Execute
*
@@ -45,7 +50,7 @@ class _income extends \IPS\Dispatcher\Controller
$tabs = array( 'totals' => 'nexus_report_income_totals' );
if( count( $currencies ) == 1 )
if( \count( $currencies ) == 1 )
{
$tabs['members'] = 'nexus_report_income_members';
}
@@ -74,7 +79,7 @@ class _income extends \IPS\Dispatcher\Controller
'colors' => array( '#10967e', '#ea7963', '#de6470', '#6b9dde', '#b09be4', '#eec766', '#9fc973', '#e291bf', '#55c1a6', '#5fb9da' ),
'hAxis' => array( 'gridlines' => array( 'color' => '#f5f5f5' ) ),
'lineWidth' => 1,
'areaOpacity' => 0.4,
'areaOpacity' => 0.4
),
( \IPS\Request::i()->tab == 'members' ) ? 'PieChart' : 'AreaChart',
'monthly',
@@ -97,7 +102,7 @@ class _income extends \IPS\Dispatcher\Controller
{
$chart->groupBy = 't_member';
if( count( $currencies ) === 1 )
if( \count( $currencies ) === 1 )
{
$chart->format = array_pop( $currencies );
}
@@ -12,7 +12,7 @@
namespace IPS\nexus\modules\admin\reports;
/* To prevent PHP errors (extending class does not exist) revealing path */
if ( !defined( '\IPS\SUITE_UNIQUE_KEY' ) )
if ( !\defined( '\IPS\SUITE_UNIQUE_KEY' ) )
{
header( ( isset( $_SERVER['SERVER_PROTOCOL'] ) ? $_SERVER['SERVER_PROTOCOL'] : 'HTTP/1.0' ) . ' 403 Forbidden' );
exit;
@@ -23,6 +23,11 @@ if ( !defined( '\IPS\SUITE_UNIQUE_KEY' ) )
*/
class _markets extends \IPS\Dispatcher\Controller
{
/**
* @brief Has been CSRF-protected
*/
public static $csrfProtected = TRUE;
/**
* Execute
*
@@ -59,7 +64,7 @@ class _markets extends \IPS\Dispatcher\Controller
'colors' => array( '#c9e2de', '#10967e' ),
'hAxis' => array( 'gridlines' => array( 'color' => '#f5f5f5' ) ),
'lineWidth' => 1,
'areaOpacity' => 0.4,
'areaOpacity' => 0.4
),
'GeoChart',
'monthly',
@@ -12,7 +12,7 @@
namespace IPS\nexus\modules\admin\reports;
/* To prevent PHP errors (extending class does not exist) revealing path */
if ( !defined( '\IPS\SUITE_UNIQUE_KEY' ) )
if ( !\defined( '\IPS\SUITE_UNIQUE_KEY' ) )
{
header( ( isset( $_SERVER['SERVER_PROTOCOL'] ) ? $_SERVER['SERVER_PROTOCOL'] : 'HTTP/1.0' ) . ' 403 Forbidden' );
exit;
@@ -23,6 +23,11 @@ if ( !defined( '\IPS\SUITE_UNIQUE_KEY' ) )
*/
class _purchases extends \IPS\Dispatcher\Controller
{
/**
* @brief Has been CSRF-protected
*/
public static $csrfProtected = TRUE;
/**
* Execute
*
@@ -51,7 +56,7 @@ class _purchases extends \IPS\Dispatcher\Controller
'colors' => array( '#10967e', '#ea7963', '#de6470', '#6b9dde', '#b09be4', '#eec766', '#9fc973', '#e291bf', '#55c1a6', '#5fb9da' ),
'hAxis' => array( 'gridlines' => array( 'color' => '#f5f5f5' ) ),
'lineWidth' => 1,
'areaOpacity' => 0.4,
'areaOpacity' => 0.4
)
);
$chart->where[] = array( 'ps_app=? AND ps_type=?', 'nexus', 'package' );
@@ -12,7 +12,7 @@
namespace IPS\nexus\modules\admin\store;
/* To prevent PHP errors (extending class does not exist) revealing path */
if ( !defined( '\IPS\SUITE_UNIQUE_KEY' ) )
if ( !\defined( '\IPS\SUITE_UNIQUE_KEY' ) )
{
header( ( isset( $_SERVER['SERVER_PROTOCOL'] ) ? $_SERVER['SERVER_PROTOCOL'] : 'HTTP/1.0' ) . ' 403 Forbidden' );
exit;
@@ -23,6 +23,11 @@ if ( !defined( '\IPS\SUITE_UNIQUE_KEY' ) )
*/
class _coupons extends \IPS\Node\Controller
{
/**
* @brief Has been CSRF-protected
*/
public static $csrfProtected = TRUE;
/**
* Node Class
*/
@@ -70,7 +75,7 @@ class _coupons extends \IPS\Node\Controller
$table->parsers = array(
'coupon_customer' => function ( $val )
{
return is_numeric( $val ) ? \IPS\Theme::i()->getTemplate('global')->userLink( \IPS\Member::load( $val ) ) : $val;
return \is_numeric( $val ) ? \IPS\Theme::i()->getTemplate('global')->userLink( \IPS\Member::load( $val ) ) : $val;
}
);
$table->sortBy = 'coupon_uses';
@@ -12,7 +12,7 @@
namespace IPS\nexus\modules\admin\store;
/* To prevent PHP errors (extending class does not exist) revealing path */
if ( !defined( '\IPS\SUITE_UNIQUE_KEY' ) )
if ( !\defined( '\IPS\SUITE_UNIQUE_KEY' ) )
{
header( ( isset( $_SERVER['SERVER_PROTOCOL'] ) ? $_SERVER['SERVER_PROTOCOL'] : 'HTTP/1.0' ) . ' 403 Forbidden' );
exit;
@@ -23,6 +23,11 @@ if ( !defined( '\IPS\SUITE_UNIQUE_KEY' ) )
*/
class _fields extends \IPS\Node\Controller
{
/**
* @brief Has been CSRF-protected
*/
public static $csrfProtected = TRUE;
/**
* Node Class
*/
@@ -77,7 +82,7 @@ class _fields extends \IPS\Node\Controller
if ( $old AND $old->extra != $new->extra )
{
$products = \IPS\Db::i()->select( 'DISTINCT(opt_package)', 'nexus_product_options', "opt_values LIKE '%\"{$new->_id}\":%'" );
if ( count( $products ) )
if ( \count( $products ) )
{
\IPS\Output::i()->redirect( $this->url->setQueryString( array( 'do' => 'warning', 'ids' => implode( ',', iterator_to_array( $products ) ) ) ) );
}
@@ -1,32 +1,48 @@
<?php
/**
* @brief Comission Rules
* @brief filters
* @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 15 Aug 2014
* @subpackage Commerce
* @since 22 Aug 2018
*/
namespace IPS\nexus\modules\admin\customers;
namespace IPS\nexus\modules\admin\store;
/* To prevent PHP errors (extending class does not exist) revealing path */
if ( !defined( '\IPS\SUITE_UNIQUE_KEY' ) )
if ( !\defined( '\IPS\SUITE_UNIQUE_KEY' ) )
{
header( ( isset( $_SERVER['SERVER_PROTOCOL'] ) ? $_SERVER['SERVER_PROTOCOL'] : 'HTTP/1.0' ) . ' 403 Forbidden' );
exit;
}
/**
* Comission Rules
* filters
*/
class _commissionrules extends \IPS\Node\Controller
class _filters extends \IPS\Node\Controller
{
/**
* @brief Has been CSRF-protected
*/
public static $csrfProtected = TRUE;
/**
* Node Class
*/
protected $nodeClass = 'IPS\nexus\CommissionRule';
protected $nodeClass = 'IPS\nexus\Package\Filter';
/**
* Manage
*
* @return void
*/
protected function manage()
{
\IPS\Output::i()->output .= \IPS\Theme::i()->getTemplate( 'forms', 'core' )->blurb( 'product_filters_blurb' );
parent::manage();
}
/**
* Execute
@@ -35,18 +51,7 @@ class _commissionrules extends \IPS\Node\Controller
*/
public function execute()
{
\IPS\Dispatcher::i()->checkAcpPermission( 'commission_rules_manage' );
\IPS\Dispatcher::i()->checkAcpPermission( 'filters_manage' );
parent::execute();
}
/**
* Manage
*
* @return void
*/
public function manage()
{
\IPS\Output::i()->output .= \IPS\Theme::i()->getTemplate( 'forms', 'core' )->blurb( 'commission_rules_blurb', TRUE, TRUE );
return parent::manage();
}
}
@@ -12,7 +12,7 @@
namespace IPS\nexus\modules\admin\store;
/* To prevent PHP errors (extending class does not exist) revealing path */
if ( !defined( '\IPS\SUITE_UNIQUE_KEY' ) )
if ( !\defined( '\IPS\SUITE_UNIQUE_KEY' ) )
{
header( ( isset( $_SERVER['SERVER_PROTOCOL'] ) ? $_SERVER['SERVER_PROTOCOL'] : 'HTTP/1.0' ) . ' 403 Forbidden' );
exit;
@@ -23,6 +23,11 @@ if ( !defined( '\IPS\SUITE_UNIQUE_KEY' ) )
*/
class _packages extends \IPS\Node\Controller
{
/**
* @brief Has been CSRF-protected
*/
public static $csrfProtected = TRUE;
/**
* Node Class
*/
@@ -37,8 +42,8 @@ class _packages extends \IPS\Node\Controller
{
\IPS\Dispatcher::i()->checkAcpPermission( 'packages_manage' );
\IPS\Output::i()->jsFiles = array_merge( \IPS\Output::i()->jsFiles, \IPS\Output::i()->js( 'admin_store.js', 'nexus', 'admin' ) );
parent::execute();
\IPS\Output::i()->title = \IPS\Member::loggedIn()->language()->addToStack('menu__nexus_store_packages');
parent::execute();
}
/**
@@ -58,6 +63,24 @@ class _packages extends \IPS\Node\Controller
return $buttons;
}
/**
* Fetch any additional HTML for this row
*
* @param object $node Node returned from $nodeClass::load()
* @return NULL|string
*/
public function _getRowHtml( $node )
{
if ( $node instanceof \IPS\nexus\Package and \IPS\Member::loggedIn()->hasAcpRestriction( 'nexus', 'customers', 'purchases_view' ) )
{
$active = \IPS\Db::i()->select( 'COUNT(*)', 'nexus_purchases', array( 'ps_app=? AND ps_type=? AND ps_item_id=? AND ps_active=1', 'nexus', 'package', $node->_id ) )->first();
$expired = \IPS\Db::i()->select( 'COUNT(*)', 'nexus_purchases', array( 'ps_app=? AND ps_type=? AND ps_item_id=? AND ps_active=0 AND ps_cancelled=0', 'nexus', 'package', $node->_id ) )->first();
$canceled = \IPS\Db::i()->select( 'COUNT(*)', 'nexus_purchases', array( 'ps_app=? AND ps_type=? AND ps_item_id=? AND ps_active=0 AND ps_cancelled=1', 'nexus', 'package', $node->_id ) )->first();
return \IPS\Theme::i()->getTemplate( 'store', 'nexus' )->productRowHtml( $node, $active, $expired, $canceled );
}
}
/**
* Redirect after save
*
@@ -72,7 +95,7 @@ class _packages extends \IPS\Node\Controller
{
return parent::_afterSave( $old, $new, $lastUsedTab );
}
$changes = array();
if ( $old )
{
@@ -91,7 +114,7 @@ class _packages extends \IPS\Node\Controller
/* If something has changed, see if anyone has purchased */
$purchases = 0;
if( count( $changes ) )
if( \count( $changes ) )
{
$purchases = \IPS\Db::i()->select( 'COUNT(*)', 'nexus_purchases', array( 'ps_app=? AND ps_type=? AND ps_item_id=?', 'nexus', 'package', $new->id ) )->first();
}
@@ -101,7 +124,7 @@ class _packages extends \IPS\Node\Controller
if ( !empty( $changes ) AND $purchases )
{
\IPS\Output::i()->output = \IPS\Theme::i()->getTemplate( 'global', 'core' )->decision( 'product_change_blurb', array(
'product_change_blurb_existing' => \IPS\Http\Url::internal( "app=nexus&module=store&controller=packages&do=updateExisting&id={$new->_id}" )->setQueryString( 'changes', json_encode( $changes ) ),
'product_change_blurb_existing' => \IPS\Http\Url::internal( "app=nexus&module=store&controller=packages&do=updateExisting&id={$new->_id}" )->setQueryString( 'changes', json_encode( $changes ) )->csrf(),
'product_change_blurb_new' => $this->url->setQueryString( array( 'root' => ( $new->parent() ? $new->parent()->_id : '' ) ) ),
) );
}
@@ -111,13 +134,134 @@ class _packages extends \IPS\Node\Controller
}
}
/**
* Delete
*
* @return void
*/
public function delete()
{
/* If &subnode=1 is not in the URL, we are deleting a group and not a package, so we don't need to check the package */
if( !\IPS\Request::i()->subnode )
{
return parent::delete();
}
/* Load package */
try
{
$package = \IPS\nexus\Package::load( \IPS\Request::i()->id );
}
catch ( \OutOfRangeException $e )
{
return parent::delete();
}
/* Are there any purchases of this product? */
$active = \IPS\Db::i()->select( 'COUNT(*)', 'nexus_purchases', array( 'ps_app=? AND ps_type=? AND ps_item_id=? AND ps_active=1', 'nexus', 'package', $package->_id ) )->first();
$expiredRenewable = \IPS\Db::i()->select( 'COUNT(*)', 'nexus_purchases', array( 'ps_app=? AND ps_type=? AND ps_item_id=? AND ps_active=0 AND ps_cancelled=0 AND ps_renewals>0', 'nexus', 'package', $package->_id ) )->first();
$expredNonRenewable = \IPS\Db::i()->select( 'COUNT(*)', 'nexus_purchases', array( 'ps_app=? AND ps_type=? AND ps_item_id=? AND ps_active=0 AND ps_cancelled=0 AND ps_renewals=0', 'nexus', 'package', $package->_id ) )->first();
$canceledCanBeReactivated = \IPS\Db::i()->select( 'COUNT(*)', 'nexus_purchases', array( 'ps_app=? AND ps_type=? AND ps_item_id=? AND ps_active=0 AND ps_cancelled=1 AND ps_can_reactivate=1', 'nexus', 'package', $package->_id ) )->first();
$canceledCannotBeReactivated = \IPS\Db::i()->select( 'COUNT(*)', 'nexus_purchases', array( 'ps_app=? AND ps_type=? AND ps_item_id=? AND ps_active=0 AND ps_cancelled=1 AND ps_can_reactivate=0', 'nexus', 'package', $package->_id ) )->first();
if ( $active or $expiredRenewable or $canceledCanBeReactivated )
{
$upgradeTo = FALSE;
$prices = json_decode( $package->base_price, TRUE );
if ( $package->renew_options )
{
$renewalOptions = json_decode( $package->renew_options, TRUE );
if ( !empty( $renewalOptions ) )
{
$option = array_shift( $renewalOptions );
if ( $option['add'] )
{
foreach ( $prices as $currency => $_price )
{
$prices[ $currency ]['amount'] += ( $option['cost'][ $currency ]['amount'] );
}
}
}
}
foreach ( $package->parent()->children() as $_package )
{
if ( $_package->id === $package->id )
{
continue;
}
$_prices = json_decode( $_package->base_price, TRUE );
if ( $_package->renew_options )
{
$renewalOptions = json_decode( $_package->renew_options, TRUE );
if ( !empty( $renewalOptions ) )
{
$option = array_shift( $renewalOptions );
if ( $option['add'] )
{
foreach ( $_prices as $currency => $_price )
{
$_prices[ $currency ]['amount'] += ( $option['cost'][ $currency ]['amount'] );
}
}
}
}
foreach ( $_prices as $currency => $_price )
{
if ( ( $_price['amount'] <= $prices[ $currency ]['amount'] and $_package->allow_upgrading ) or ( $_price['amount'] > $prices[ $currency ]['amount'] and $_package->allow_downgrading ) )
{
$upgradeTo = TRUE;
break 2;
}
}
}
\IPS\Output::i()->title = $package->_title;
\IPS\Output::i()->output = \IPS\Theme::i()->getTemplate( 'store' )->productDeleteWarning( $package, $active, $expiredRenewable, $expredNonRenewable, $canceledCanBeReactivated, $canceledCannotBeReactivated, $upgradeTo );
return;
}
/* If not, just handle the delete as normal */
return parent::delete();
}
/**
* Hide from store
*
* @return void
*/
public function hide()
{
\IPS\Session::i()->csrfCheck();
/* Load package */
try
{
$package = \IPS\nexus\Package::load( \IPS\Request::i()->id );
}
catch ( \OutOfRangeException $e )
{
\IPS\Output::i()->error( 'node_error', '2X249/3', 404, '' );
}
/* Do it */
$package->store = FALSE;
$package->reg = FALSE;
$package->save();
/* Redirect */
\IPS\Output::i()->redirect( \IPS\Http\Url::internal( "app=nexus&module=store&controller=packages" )->setQueryString( array( 'root' => ( $package->parent() ? $package->parent()->_id : '' ) ) ) );
}
/**
* Update Existing Purchases
*
* @return void
*/
public function updateExisting()
{
{
\IPS\Session::i()->csrfCheck();
try
{
$package = \IPS\nexus\Package::load( \IPS\Request::i()->id );
@@ -139,7 +283,7 @@ class _packages extends \IPS\Node\Controller
$newOptions = array( '-' => \IPS\Member::loggedIn()->language()->addToStack('do_not_change') );
$existingRenewOptions = json_decode( $package->renew_options, TRUE );
if( !is_array( $existingRenewOptions ) )
if( !\is_array( $existingRenewOptions ) )
{
$existingRenewOptions = array();
}
@@ -231,38 +375,52 @@ class _packages extends \IPS\Node\Controller
}
}
if ( isset( $changes['renew_options'] ) and !isset( \IPS\Request::i()->ba ) )
if ( ( isset( $changes['tax'] ) or isset( $changes['renew_options'] ) ) and !isset( \IPS\Request::i()->ba ) )
{
$needBaPrompt = FALSE;
foreach ( $changes['renew_options'] as $ro )
$canChangeOptions = FALSE;
if ( isset( $changes['renew_options'] ) )
{
if ( !in_array( $ro['new'], array( '-', 'x', 'y', 'z' ) ) )
foreach ( $changes['renew_options'] as $ro )
{
$needBaPrompt = TRUE;
break;
if ( !\in_array( $ro['new'], array( '-', 'x', 'y', 'z' ) ) )
{
$canChangeOptions = TRUE;
$needBaPrompt = TRUE;
break;
}
}
}
if ( isset( $changes['tax'] ) )
{
$needBaPrompt = TRUE;
}
if ( $needBaPrompt and $withBillingAgreement = \IPS\Db::i()->select( 'COUNT(*)', 'nexus_purchases', array( 'ps_app=? AND ps_type=? AND ps_item_id=? AND ps_billing_agreement>0 AND ba_canceled=0', 'nexus', 'package', $package->id ) )->join( 'nexus_billing_agreements', 'ba_id=ps_billing_agreement' )->first() )
{
\IPS\Output::i()->output = \IPS\Theme::i()->getTemplate( 'global', 'core' )->decision( 'change_renew_ba_blurb', array(
$options = array(
'change_renew_ba_skip' => \IPS\Http\Url::internal( "app=nexus&module=store&controller=packages&do=updateExisting" )->setQueryString( array(
'id' => \IPS\Request::i()->id,
'changes' => json_encode( $changes ),
'processing'=> 1,
'ba' => 0
) ),
) )->csrf(),
'change_renew_ba_cancel' => \IPS\Http\Url::internal( "app=nexus&module=store&controller=packages&do=updateExisting" )->setQueryString( array(
'id' => \IPS\Request::i()->id,
'changes' => json_encode( $changes ),
'processing'=> 1,
'ba' => 1
) ),
'change_renew_ba_go_back' => \IPS\Http\Url::internal( "app=nexus&module=store&controller=packages&do=updateExisting" )->setQueryString( array(
) )->csrf()
);
if ( $canChangeOptions )
{
$options['change_renew_ba_go_back'] = \IPS\Http\Url::internal( "app=nexus&module=store&controller=packages&do=updateExisting" )->setQueryString( array(
'id' => \IPS\Request::i()->id,
'changes' => \IPS\Request::i()->changes,
) ),
) );
) )->csrf();
}
\IPS\Output::i()->output = \IPS\Theme::i()->getTemplate( 'global', 'core' )->decision( 'change_renew_ba_blurb', $options );
return;
}
}
@@ -273,16 +431,16 @@ class _packages extends \IPS\Node\Controller
'changes' => json_encode( $changes ),
'processing'=> 1,
'ba' => isset( \IPS\Request::i()->ba ) ? \IPS\Request::i()->ba : 0
) ),
) )->csrf(),
function( $offset ) use ( $package, $changes )
{
$offset = intval( $offset );
$select = \IPS\Db::i()->select( '*', 'nexus_purchases', array( "ps_app=? and ps_type=? and ps_item_id=?", 'nexus', 'package', $package->id ), 'ps_id', array( $offset, 1 ), NULL, NULL, \IPS\Db::SELECT_SQL_CALC_FOUND_ROWS );
$offset = \intval( $offset );
$select = \IPS\Db::i()->select( '*', 'nexus_purchases', array( "ps_app=? and ps_type=? and ps_item_id=?", 'nexus', 'package', $package->id ), 'ps_id', array( $offset, 1 ) );
try
{
$purchase = \IPS\nexus\Purchase::constructFromData( $select->first() );
$total = $select->count( TRUE );
$total = \IPS\Db::i()->select( 'COUNT(*)', 'nexus_purchases', array( "ps_app=? and ps_type=? and ps_item_id=?", 'nexus', 'package', $package->id ) )->first();
$package->updatePurchase( $purchase, $changes, \IPS\Request::i()->ba );
@@ -358,10 +516,11 @@ class _packages extends \IPS\Node\Controller
/**
* Little function from the PHP manual comments
*
* @param array $_ Array
* @return array
*/
protected function arraycartesian($_) {
if(count($_) == 0)
if(\count($_) == 0)
return array(array());
foreach($_ as $k=>$a) {
unset($_[$k]);
@@ -402,7 +561,16 @@ class _packages extends \IPS\Node\Controller
'ps_expire' => \IPS\Helpers\Table\SEARCH_DATE_RANGE,
);
$table->noSort = array( 'purchase_status' );
$table->filters = array( 'active' => 'ps_active=1' );
if ( $package->renew_options or \IPS\Db::i()->select( 'COUNT(*)', 'nexus_purchases', array( 'ps_app=? AND ps_type=? AND ps_item_id=? AND ps_active=0 AND ps_cancelled=0', 'nexus', 'package', $package->_id ) )->first() )
{
$table->filters = array( 'purchase_tab_active' => 'ps_active=1', 'purchase_tab_expired' => 'ps_active=0 AND ps_cancelled=0', 'purchase_tab_canceled' => 'ps_active=0 AND ps_cancelled=1' );
}
else
{
$table->filters = array( 'purchase_tab_active' => 'ps_active=1', 'purchase_tab_canceled' => 'ps_active=0' );
}
$table->parsers = array(
'ps_member' => function( $val ) {
try
@@ -457,6 +625,132 @@ class _packages extends \IPS\Node\Controller
\IPS\Output::i()->title = $package->_title;
\IPS\Output::i()->output = $table;
\IPS\Output::i()->sidebar['actions'] = array(
'cancel_purchases' => array(
'icon' => 'arrow-right',
'title' => 'mass_change_all_purchases',
'link' => \IPS\Http\Url::internal( "app=nexus&module=store&controller=packages" )->setQueryString( array( 'do' => 'massManagePurchases', 'id' => $package->_id ) ),
'data' => array(
'ipsDialog' => TRUE,
'ipsDialog-title' => $package->_title
)
),
);
}
/**
* Mass Change/Cancel Purchases
*
* @return void
*/
protected function massManagePurchases()
{
try
{
$package = \IPS\nexus\Package::load( \IPS\Request::i()->id );
if ( $package->deleteOrMoveQueued() )
{
throw new \OutOfRangeException;
}
}
catch ( \OutOfRangeException $e )
{
\IPS\Output::i()->error( 'node_error', '2X249/4', 404, '' );
}
$form = new \IPS\Helpers\Form( 'form', 'go' );
$form->addMessage('mass_change_purchases_explain');
$options = array();
if ( \IPS\Member::loggedIn()->hasAcpRestriction( 'nexus', 'customers', 'purchases_edit' ) )
{
$options['change'] = 'mass_change_purchases_change';
$options['expire'] = 'mass_change_purchases_expire';
}
if ( \IPS\Member::loggedIn()->hasAcpRestriction( 'nexus', 'customers', 'purchases_cancel' ) )
{
$options['cancel'] = 'mass_change_purchases_cancel';
}
$upgradeDowngradeOptions = array();
$toggles = array();
$renewFields = array();
$desciptions = [];
foreach ( $package->parent()->children() as $siblingPackage )
{
if ( $package->id === $siblingPackage->id )
{
continue;
}
$upgradeDowngradeOptions[ $siblingPackage->id ] = $siblingPackage->_title;
$renewOptions = json_decode( $siblingPackage->renew_options, TRUE ) ?: array();
$renewalOptions = array();
$renewFieldsDescriptions = array();
foreach ( $renewOptions as $k => $option )
{
$renewTermObject = new \IPS\nexus\Purchase\RenewalTerm( new \IPS\nexus\Money( 0, '' ), new \DateInterval( 'P' . $option['term'] . mb_strtoupper( $option['unit'] ) ) );
$costs = array();
foreach ( $option['cost'] as $cost )
{
$costs[] = new \IPS\nexus\Money( $cost['amount'], $cost['currency'] );
}
$renewalOptions[ $k ] = sprintf( \IPS\Member::loggedIn()->language()->get( 'renew_option'), implode( ' / ', $costs ), $renewTermObject->getTermUnit() );
}
if ( $renewalOptions )
{
$desciptions[ $siblingPackage->id ] = \IPS\Member::loggedIn()->language()->formatList( $renewalOptions, \IPS\Member::loggedIn()->language()->get('or_list_format') );
$renewFields[] = new \IPS\Helpers\Form\Radio( 'renew_option_' . $siblingPackage->id, NULL, NULL, array( 'options' => $renewalOptions, 'descriptions' => $renewFieldsDescriptions, 'parse' => 'normal' ), NULL, NULL, NULL, 'renew_option_' . $siblingPackage->id );
\IPS\Member::loggedIn()->language()->words['renew_option_' . $siblingPackage->id] = \IPS\Member::loggedIn()->language()->addToStack( 'renewal_term', FALSE );
$toggles[ $siblingPackage->id ] = array( 'renew_option_' . $siblingPackage->id );
}
else
{
$desciptions[ $siblingPackage->id ] = \IPS\Member::loggedIn()->language()->addToStack('mass_change_purchases_no_renewals');
}
}
$form->add( new \IPS\Helpers\Form\Radio( 'cancel_type', NULL, TRUE, array(
'options' => $options,
'toggles' => array(
'change' => array( 'mass_change_purchases_to', 'mass_change_purchases_override' ),
'expire' => array( 'ps_can_reactivate' ),
'cancel' => array( 'ps_can_reactivate' ),
),
'disabled' => $upgradeDowngradeOptions ? [] : ['change']
) ) );
if ( !$upgradeDowngradeOptions )
{
\IPS\Member::loggedIn()->language()->words['mass_change_purchases_change_desc'] = \IPS\Member::loggedIn()->language()->addToStack('cancel_type_change_no_siblings');
}
$form->add( new \IPS\Helpers\Form\Radio( 'mass_change_purchases_to', NULL, NULL, array( 'options' => $upgradeDowngradeOptions, 'descriptions' => $desciptions, 'toggles' => $toggles, 'parse' => 'normal' ), NULL, NULL, NULL, 'mass_change_purchases_to' ) );
foreach ( $renewFields as $field )
{
$form->add( $field );
}
$form->add( new \IPS\Helpers\Form\YesNo( 'mass_change_purchases_override', TRUE, NULL, array(), NULL, NULL, NULL, 'mass_change_purchases_override' ) );
$form->add( new \IPS\Helpers\Form\YesNo( 'ps_can_reactivate', NULL, FALSE, array(), NULL, NULL, NULL, 'ps_can_reactivate' ) );
if ( $values = $form->values() )
{
// Note: Maybe we cannot upgrade/downgrade cancelled purchases? Reflect that in the form if so
// Note: Must cancel billing agreements when upgrading/downgrading purchases. Reflect that in the form
$values['id'] = $package->_id;
$values['admin'] = \IPS\Member::loggedIn()->member_id;
\IPS\Task::queue( 'nexus', 'MassChangePurchases', $values );
\IPS\Output::i()->redirect( \IPS\Http\Url::internal( "app=nexus&module=store&controller=packages" )->setQueryString( array( 'root' => ( $package->parent() ? $package->parent()->_id : '' ) ) ), 'mass_change_purchases_confirm' );
}
\IPS\Output::i()->title = $package->_title;
\IPS\Output::i()->output = $form;
}
/**
@@ -466,6 +760,8 @@ class _packages extends \IPS\Node\Controller
*/
public function emailPreview()
{
\IPS\Session::i()->csrfCheck();
$functionName = 'emailPreview_' . mt_rand();
\IPS\Theme::makeProcessFunction( \IPS\Request::i()->value, $functionName, '$purchase' );
@@ -480,7 +776,8 @@ class _packages extends \IPS\Node\Controller
try
{
$output = \IPS\Email::buildFromContent( 'Test', call_user_func( 'IPS\\Theme\\'.$functionName, $dummyPurchase ) )->compileContent( 'html', \IPS\Member::loggedIn() );
$themeFunction = 'IPS\\Theme\\'. $functionName;
$output = \IPS\Email::buildFromContent( 'Test', $themeFunction( $dummyPurchase ) )->compileContent( 'html', \IPS\Member::loggedIn() );
}
catch ( \Exception $e )
{
@@ -488,4 +785,53 @@ class _packages extends \IPS\Node\Controller
}
\IPS\Output::i()->sendOutput( $output );
}
/**
* Build the form to mass move content
*
* @param \IPS\Helpers\Form $form The form helper object
* @param mixed $data Data from the wizard helper
* @param string $nodeClass Node class
* @param \IPS\Node\Mode $node Node we are working with
* @param string $contentItemClass Content item class (if there is one)
* @return \IPS\Helpers\Form
*/
protected function _buildMassMoveForm( $form, $data, $nodeClass, $node, $contentItemClass )
{
$form->addHeader('node_mass_move_delete_then');
$moveToClass = isset( $data['moveToClass'] ) ? $data['moveToClass'] : $nodeClass;
$form->add( new \IPS\Helpers\Form\Node( 'node_move_products', isset( $data['moveTo'] ) ? $moveToClass::load( $data['moveTo'] ) : 0, TRUE, array( 'class' => $nodeClass, 'disabledIds' => array( $node->_id ), 'disabledLang' => 'node_move_delete', 'zeroVal' => 'products_delete_content', 'subnodes' => FALSE ) ) );
return $form;
}
/**
* Process the mass move form submission
*
* @param array $values Values from form submission
* @param mixed $data Data from the wizard helper
* @param string $nodeClass Node class
* @param \IPS\Node\Mode $node Node we are working with
* @param string $contentItemClass Content item class (if there is one)
* @return array Wizard helper data
*/
protected function _processMassMoveForm( $values, $data, $nodeClass, $node, $contentItemClass )
{
$data['deleteWhenDone'] = FALSE;
$data['class'] = \get_class( $node );
$data['id'] = $node->_id;
if ( \is_object( $values['node_move_products'] ) )
{
$data['moveToClass'] = \get_class( $values['node_move_products'] );
$data['moveTo'] = $values['node_move_products']->_id;
}
else
{
unset( $data['moveToClass'] );
unset( $data['moveTo'] );
}
return $data;
}
}
@@ -12,7 +12,7 @@
namespace IPS\nexus\modules\admin\store;
/* To prevent PHP errors (extending class does not exist) revealing path */
if ( !defined( '\IPS\SUITE_UNIQUE_KEY' ) )
if ( !\defined( '\IPS\SUITE_UNIQUE_KEY' ) )
{
header( ( isset( $_SERVER['SERVER_PROTOCOL'] ) ? $_SERVER['SERVER_PROTOCOL'] : 'HTTP/1.0' ) . ' 403 Forbidden' );
exit;
@@ -23,6 +23,11 @@ if ( !defined( '\IPS\SUITE_UNIQUE_KEY' ) )
*/
class _settings extends \IPS\Dispatcher\Controller
{
/**
* @brief Has been CSRF-protected
*/
public static $csrfProtected = TRUE;
/**
* Execute
*
Whitespace-only changes.
@@ -12,7 +12,7 @@
namespace IPS\nexus\modules\admin\subscriptions;
/* To prevent PHP errors (extending class does not exist) revealing path */
if ( !defined( '\IPS\SUITE_UNIQUE_KEY' ) )
if ( !\defined( '\IPS\SUITE_UNIQUE_KEY' ) )
{
header( ( isset( $_SERVER['SERVER_PROTOCOL'] ) ? $_SERVER['SERVER_PROTOCOL'] : 'HTTP/1.0' ) . ' 403 Forbidden' );
exit;
@@ -23,6 +23,11 @@ if ( !defined( '\IPS\SUITE_UNIQUE_KEY' ) )
*/
class _subscribers extends \IPS\Dispatcher\Controller
{
/**
* @brief Has been CSRF-protected
*/
public static $csrfProtected = TRUE;
/**
* Execute
*
@@ -82,8 +87,8 @@ class _subscribers extends \IPS\Dispatcher\Controller
'sub_start' => function( $val ) {
return \IPS\DateTime::ts( $val );
},
'sub_expire' => function( $val ) {
return $val ? \IPS\DateTime::ts( $val ) : '';
'sub_expire' => function( $val, $row ) {
return $val ? \IPS\nexus\Subscription::constructFromData( $row )->_expire : '';
},
'sub_active' => function( $val ) {
return \IPS\Theme::i()->getTemplate('subscription', 'nexus')->status( $val );
@@ -147,6 +152,8 @@ class _subscribers extends \IPS\Dispatcher\Controller
*/
protected function remove()
{
\IPS\Session::i()->csrfCheck();
try
{
$sub = \IPS\nexus\Subscription::load( \IPS\Request::i()->id );
@@ -12,7 +12,7 @@
namespace IPS\nexus\modules\admin\subscriptions;
/* To prevent PHP errors (extending class does not exist) revealing path */
if ( !defined( '\IPS\SUITE_UNIQUE_KEY' ) )
if ( !\defined( '\IPS\SUITE_UNIQUE_KEY' ) )
{
header( ( isset( $_SERVER['SERVER_PROTOCOL'] ) ? $_SERVER['SERVER_PROTOCOL'] : 'HTTP/1.0' ) . ' 403 Forbidden' );
exit;
@@ -23,6 +23,11 @@ if ( !defined( '\IPS\SUITE_UNIQUE_KEY' ) )
*/
class _subscriptions extends \IPS\Node\Controller
{
/**
* @brief Has been CSRF-protected
*/
public static $csrfProtected = TRUE;
/**
* Node Class
*/
@@ -85,17 +90,23 @@ class _subscriptions extends \IPS\Node\Controller
*/
public function convertToSubscription()
{
\IPS\Session::i()->csrfCheck();
try
{
$package = \IPS\nexus\Package::load( \IPS\Request::i()->id );
if ( $package->deleteOrMoveQueued() )
{
throw new \OutOfRangeException;
}
}
catch( \OutOfRangeException $ex )
{
\IPS\Output::i()->error( 'node_error', '2X393/2', 404, '' );
}
$renewOptions = array();
if ( $package->renew_options and $_renewOptions = json_decode( $package->renew_options, TRUE ) and is_array( $_renewOptions ) )
if ( $package->renew_options and $_renewOptions = json_decode( $package->renew_options, TRUE ) and \is_array( $_renewOptions ) )
{
foreach ( $_renewOptions as $option )
{
@@ -104,11 +115,23 @@ class _subscriptions extends \IPS\Node\Controller
{
$costs[ $cost['currency'] ] = new \IPS\nexus\Money( $cost['amount'], $cost['currency'] );
}
/* Figure out tax */
$tax = NULL;
try
{
if( $package->tax )
{
$tax = \IPS\nexus\Tax::load( $package->tax );
}
}
catch( \OutOfRangeException $e ){}
/* Catch any invalid renewal terms, these can occasionally appear from legacy IP.Subscriptions */
try
{
$renewOptions[] = new \IPS\nexus\Purchase\RenewalTerm( $costs, new \DateInterval( "P{$option['term']}" . mb_strtoupper( $option['unit'] ) ), NULL, $option['add'] );
$renewOptions[] = new \IPS\nexus\Purchase\RenewalTerm( $costs, new \DateInterval( "P{$option['term']}" . mb_strtoupper( $option['unit'] ) ), $tax, $option['add'] );
}
catch( \Exception $ex) {}
}
@@ -129,8 +152,8 @@ class _subscriptions extends \IPS\Node\Controller
{
$sub = new \IPS\nexus\Subscription\Package;
$sub->enabled = 1;
$sub->tax = $values['sp_tax'] ? $values['p_tax']->id : 0;
$sub->gateways = ( isset( $values['sp_gateways'] ) and is_array( $values['sp_gateways'] ) ) ? implode( ',', array_keys( $values['sp_gateways'] ) ) : '*';
$sub->tax = $values['sp_tax'] ? $values['sp_tax']->id : 0;
$sub->gateways = ( isset( $values['sp_gateways'] ) and \is_array( $values['sp_gateways'] ) ) ? implode( ',', array_keys( $values['sp_gateways'] ) ) : '*';
$sub->price = json_encode( $values['sp_price'] );
foreach( array( 'primary_group', 'secondary_group') as $thingsWotAreTheSame )
@@ -201,6 +224,8 @@ class _subscriptions extends \IPS\Node\Controller
*/
public function enable()
{
\IPS\Session::i()->csrfCheck();
\IPS\Settings::i()->changeValues( array( 'nexus_subs_enabled' => true ) );
\IPS\Session::i()->log( 'acplog__subscription_settings' );
@@ -208,6 +233,70 @@ class _subscriptions extends \IPS\Node\Controller
\IPS\Output::i()->redirect( \IPS\Http\Url::internal('app=nexus&module=subscriptions&controller=subscriptions') );
}
/**
* Delete
*
* @return void
*/
public function delete()
{
/* Load package */
try
{
$package = \IPS\nexus\Subscription\Package::load( \IPS\Request::i()->id );
}
catch ( \OutOfRangeException $e )
{
return parent::delete();
}
/* Are there any purchases of this product? */
if ( !isset( \IPS\Request::i()->confirmImplications ) and \IPS\Db::i()->select( 'COUNT(*)', 'nexus_purchases', array( 'ps_app=? AND ps_type=? AND ps_item_id=?', 'nexus', 'subscription', $package->id ) )->first() )
{
$options = array(
'product_delete_confirm' => \IPS\Http\Url::internal( "app=nexus&module=subscriptions&controller=subscriptions&do=delete&wasConfirmed=1&id={$package->_id}&confirmImplications=1" )->csrf(),
);
if ( $package->enabled )
{
$options['product_delete_hide'] = \IPS\Http\Url::internal( "app=nexus&module=subscriptions&controller=subscriptions&do=hide&id={$package->_id}" )->csrf();
}
$options['cancel'] = \IPS\Http\Url::internal( "app=nexus&module=subscriptions&controller=subscriptions" );
\IPS\Output::i()->output = \IPS\Theme::i()->getTemplate( 'global', 'core' )->decision( 'subscription_delete_blurb', $options );
return;
}
/* If not, just handle the delete as normal */
return parent::delete();
}
/**
* Hide from store
*
* @return void
*/
public function hide()
{
\IPS\Session::i()->csrfCheck();
/* Load package */
try
{
$package = \IPS\nexus\Subscription\Package::load( \IPS\Request::i()->id );
}
catch ( \OutOfRangeException $e )
{
\IPS\Output::i()->error( 'node_error', '1X393/2', 404, '' );
}
/* Do it */
$package->enabled = FALSE;
$package->save();
/* Redirect */
\IPS\Output::i()->redirect( \IPS\Http\Url::internal( "app=nexus&module=subscriptions&controller=subscriptions" ) );
}
/**
* Add a member for free!
*
@@ -267,7 +356,7 @@ class _subscriptions extends \IPS\Node\Controller
$form->add( new \IPS\Helpers\Form\YesNo( 'nexus_subs_enabled', \IPS\Settings::i()->nexus_subs_enabled, FALSE, array(), NULL, NULL, NULL, 'nexus_subs_enabled' ) );
$form->add( new \IPS\Helpers\Form\YesNo( 'nexus_subs_register', \IPS\Settings::i()->nexus_subs_register, FALSE, array(), NULL, NULL, NULL, 'nexus_subs_register' ) );
$form->add( new \IPS\Helpers\Form\YesNo( 'nexus_subs_show_public', \IPS\Settings::i()->nexus_subs_show_public, FALSE, array(), NULL, NULL, NULL, 'nexus_subs_show_public' ) );
$form->add( new \IPS\Helpers\Form\Number( 'nexus_subs_invoice_grace', \IPS\Settings::i()->nexus_subs_invoice_grace, FALSE, array( ), NULL, NULL, \IPS\Member::loggedIn()->language()->addToStack('days'), 'nexus_subs_invoice_grace' ) );
$form->add( new \IPS\Helpers\Form\Interval( 'nexus_subs_invoice_grace', \IPS\Settings::i()->nexus_subs_invoice_grace, FALSE, array( 'valueAs' => \IPS\Helpers\Form\Interval::DAYS ), NULL, NULL, NULL, 'nexus_subs_invoice_grace' ) );
$form->add( new \IPS\Helpers\Form\Select( 'nexus_subs_exclude_groups', explode( ',', \IPS\Settings::i()->nexus_subs_exclude_groups ), FALSE, array( 'options' => $groups, 'multiple' => TRUE ) ) );
@@ -313,5 +402,235 @@ class _subscriptions extends \IPS\Node\Controller
\IPS\Output::i()->title = \IPS\Member::loggedIn()->language()->addToStack('settings');
\IPS\Output::i()->output = $form;
}
/**
* Redirect after save
*
* @param \IPS\Node\Model $old A clone of the node as it was before or NULL if this is a creation
* @param \IPS\Node\Model $new The node now
* @param string $lastUsedTab The tab last used in the form
* @return void
*/
protected function _afterSave( \IPS\Node\Model $old = NULL, \IPS\Node\Model $new, $lastUsedTab = FALSE )
{
$changes = array();
if ( $old )
{
foreach ( array( 'tax', 'renew_options', 'primary_group', 'secondary_group' ) as $k )
{
if ( $old->$k != $new->$k )
{
$changes[ $k ] = $old->$k;
}
}
}
/* If something has changed, see if anyone has purchased */
$purchases = 0;
if( \count( $changes ) )
{
$purchases = \IPS\Db::i()->select( 'COUNT(*)', 'nexus_member_subscriptions', array( 'sub_package_id=? AND sub_active=1 and sub_added_manually=0', $new->id ) )->first();
}
/* Only show this screen if the package has been purchased. Otherwise even just copying a package and saving asks if you want to update
existing purchases unnecessarily */
if ( !empty( $changes ) AND $purchases )
{
\IPS\Output::i()->output = \IPS\Theme::i()->getTemplate( 'global', 'core' )->decision( 'product_change_blurb', array(
'product_change_blurb_existing' => \IPS\Http\Url::internal( "app=nexus&module=subscriptions&controller=subscriptions&do=updateExisting&id={$new->_id}" )->setQueryString( 'changes', json_encode( $changes ) )->csrf(),
'product_change_blurb_new' => $this->url->setQueryString( array( 'root' => ( $new->parent() ? $new->parent()->_id : '' ) ) ),
) );
}
else
{
return parent::_afterSave( $old, $new, $lastUsedTab );
}
}
/**
* Update Existing Purchases
*
* @return void
*/
public function updateExisting()
{
\IPS\Session::i()->csrfCheck();
try
{
$package = \IPS\nexus\Subscription\Package::load( \IPS\Request::i()->id );
}
catch ( \OutOfRangeException $e )
{
\IPS\Output::i()->error( 'node_error', '1X393/1', 404, '' );
}
$changes = json_decode( \IPS\Request::i()->changes, TRUE );
if ( !isset( \IPS\Request::i()->processing ) )
{
if ( isset( $changes['renew_options'] ) )
{
$matrix = new \IPS\Helpers\Form\Matrix( 'matrix', 'continue' );
$matrix->manageable = FALSE;
$newOptions = array( '-' => \IPS\Member::loggedIn()->language()->addToStack('do_not_change') );
$newOption = json_decode( $package->renew_options, TRUE );
$costs = array();
foreach ( $newOption['cost'] as $data )
{
$costs[] = new \IPS\nexus\Money( $data['amount'], $data['currency'] );
}
switch ( $newOption['unit'] )
{
case 'd':
$term = \IPS\Member::loggedIn()->language()->addToStack('renew_days', FALSE, array( 'pluralize' => array( $newOption['term'] ) ) );
break;
case 'm':
$term = \IPS\Member::loggedIn()->language()->addToStack('renew_months', FALSE, array( 'pluralize' => array( $newOption['term'] ) ) );
break;
case 'y':
$term = \IPS\Member::loggedIn()->language()->addToStack('renew_years', FALSE, array( 'pluralize' => array( $newOption['term'] ) ) );
break;
}
$newOptions['o'] = \IPS\Member::loggedIn()->language()->addToStack( 'renew_option', FALSE, array( 'sprintf' => array( \IPS\Member::loggedIn()->language()->formatList( $costs, \IPS\Member::loggedIn()->language()->get('or_list_format') ), $term ) ) );
$newOptions['z'] = \IPS\Member::loggedIn()->language()->addToStack('remove_renewal_no_expire_leave');
$newOptions['y'] = \IPS\Member::loggedIn()->language()->addToStack('remove_renewal_no_expire_reactivate');
$newOptions['x'] = \IPS\Member::loggedIn()->language()->addToStack('remove_renewal_expire');
$matrix->columns = array(
'customers_currently_paying' => function( $key, $value, $data )
{
return $data[0];
},
'now_pay' => function( $key, $value, $data ) use ( $newOptions )
{
return new \IPS\Helpers\Form\Select( $key, $data[1], TRUE, array( 'options' => $newOptions, 'noDefault' => TRUE ) );
},
);
if ( $changes['renew_options'] )
{
$oldOption = json_decode( $changes['renew_options'], TRUE );
$costs = array();
foreach ( $oldOption['cost'] as $data )
{
$costs[] = new \IPS\nexus\Money( $data['amount'], $data['currency'] );
}
switch ( $oldOption['unit'] )
{
case 'd':
$term = \IPS\Member::loggedIn()->language()->addToStack('renew_days', FALSE, array( 'pluralize' => array( $oldOption['term'] ) ) );
break;
case 'm':
$term = \IPS\Member::loggedIn()->language()->addToStack('renew_months', FALSE, array( 'pluralize' => array( $oldOption['term'] ) ) );
break;
case 'y':
$term = \IPS\Member::loggedIn()->language()->addToStack('renew_years', FALSE, array( 'pluralize' => array( $oldOption['term'] ) ) );
break;
}
$matrix->rows[ 1 ] = array( \IPS\Member::loggedIn()->language()->addToStack( 'renew_option', FALSE, array( 'sprintf' => array( \IPS\Member::loggedIn()->language()->formatList( $costs, \IPS\Member::loggedIn()->language()->get('or_list_format') ), $term ) ) ), "o" );
}
if ( $values = $matrix->values() )
{
$data = json_decode( $changes['renew_options'], TRUE );
$changes['renew_options'] = array();
if( !empty( $data ) )
{
$changes['renew_options'] = array( 'old' => $data, 'new' => $values[1]['now_pay'] );
}
}
else
{
\IPS\Output::i()->output .= $matrix;
return;
}
}
}
if ( ( isset( $changes['renew_options'] ) or isset( $changes['tax'] ) ) and !isset( \IPS\Request::i()->ba ) )
{
$needBaPrompt = FALSE;
$canChangeOptions = FALSE;
if ( isset( $changes['renew_options'] ) and !\in_array( $changes['renew_options']['new'], array( '-', 'x', 'y', 'z' ) ) )
{
$needBaPrompt = TRUE;
$canChangeOptions = TRUE;
}
if ( isset( $changes['tax'] ) )
{
$needBaPrompt = TRUE;
}
if ( $needBaPrompt and $withBillingAgreement = \IPS\Db::i()->select( 'COUNT(*)', 'nexus_purchases', array( 'ps_app=? AND ps_type=? AND ps_item_id=? AND ps_billing_agreement>0 AND ba_canceled=0', 'nexus', 'subscription', $package->id ) )->join( 'nexus_billing_agreements', 'ba_id=ps_billing_agreement' )->first() )
{
$options = array(
'change_renew_ba_skip' => \IPS\Http\Url::internal( "app=nexus&module=subscriptions&controller=subscriptions&do=updateExisting" )->setQueryString( array(
'id' => \IPS\Request::i()->id,
'changes' => json_encode( $changes ),
'processing'=> 1,
'ba' => 0
) )->csrf(),
'change_renew_ba_cancel' => \IPS\Http\Url::internal( "app=nexus&module=subscriptions&controller=subscriptions&do=updateExisting" )->setQueryString( array(
'id' => \IPS\Request::i()->id,
'changes' => json_encode( $changes ),
'processing'=> 1,
'ba' => 1
) )->csrf()
);
if ( $canChangeOptions )
{
$options['change_renew_ba_go_back'] = \IPS\Http\Url::internal( "app=nexus&module=subscriptions&controller=subscriptions&do=updateExisting" )->setQueryString( array(
'id' => \IPS\Request::i()->id,
'changes' => \IPS\Request::i()->changes,
) )->csrf();
}
\IPS\Output::i()->output = \IPS\Theme::i()->getTemplate( 'global', 'core' )->decision( 'change_renew_ba_blurb', $options );
return;
}
}
\IPS\Output::i()->output = new \IPS\Helpers\MultipleRedirect(
\IPS\Http\Url::internal( "app=nexus&module=subscriptions&controller=subscriptions&do=updateExisting&id=1&changes=secondary_group" )->setQueryString( array(
'id' => \IPS\Request::i()->id,
'changes' => json_encode( $changes ),
'processing'=> 1,
'ba' => isset( \IPS\Request::i()->ba ) ? \IPS\Request::i()->ba : 0
) )->csrf(),
function( $offset ) use ( $package, $changes )
{
$offset = \intval( $offset );
$select = \IPS\Db::i()->select( '*', 'nexus_purchases', array( "ps_app=? and ps_type=? and ps_item_id=?", 'nexus', 'subscription', $package->id ), 'ps_id', array( $offset, 1 ) );
try
{
$purchase = \IPS\nexus\Purchase::constructFromData( $select->first() );
$total = \IPS\Db::i()->select( 'COUNT(*)', 'nexus_purchases', array( "ps_app=? and ps_type=? and ps_item_id=?", 'nexus', 'subscription', $package->id ) )->first();
$package->updatePurchase( $purchase, $changes, \IPS\Request::i()->ba );
return array( ++$offset, \IPS\Member::loggedIn()->language()->get('processing'), 100 / $total * $offset );
}
catch ( \UnderflowException $e )
{
return NULL;
}
},
function() use ( $package )
{
\IPS\Output::i()->redirect( \IPS\Http\Url::internal( "app=nexus&module=subscriptions&controller=subscriptions" )->setQueryString( array( 'root' => ( $package->parent() ? $package->parent()->_id : '' ) ) ) );
}
);
}
}
@@ -12,7 +12,7 @@
namespace IPS\nexus\modules\admin\support;
/* To prevent PHP errors (extending class does not exist) revealing path */
if ( !defined( '\IPS\SUITE_UNIQUE_KEY' ) )
if ( !\defined( '\IPS\SUITE_UNIQUE_KEY' ) )
{
header( ( isset( $_SERVER['SERVER_PROTOCOL'] ) ? $_SERVER['SERVER_PROTOCOL'] : 'HTTP/1.0' ) . ' 403 Forbidden' );
exit;
@@ -23,6 +23,11 @@ if ( !defined( '\IPS\SUITE_UNIQUE_KEY' ) )
*/
class _autoresolve extends \IPS\Dispatcher\Controller
{
/**
* @brief Has been CSRF-protected
*/
public static $csrfProtected = TRUE;
/**
* Manage
*
@@ -48,7 +53,7 @@ class _autoresolve extends \IPS\Dispatcher\Controller
$form->addSeparator();
$form->add( new \IPS\Helpers\Form\Node( 'nexus_autoresolve_departments', \IPS\Settings::i()->nexus_autoresolve_departments === '*' ? 0 : explode( ',', \IPS\Settings::i()->nexus_autoresolve_departments ), FALSE, array( 'class' => 'IPS\nexus\Support\Department', 'multiple' => TRUE, 'zeroVal' => 'any' ), NULL, NULL, NULL, 'nexus_autoresolve_departments' ) );
$form->add( new \IPS\Helpers\Form\Node( 'nexus_autoresolve_applicable', \IPS\Settings::i()->nexus_autoresolve_applicable, FALSE, array( 'class' => 'IPS\nexus\Support\Status', 'multiple' => TRUE ), NULL, NULL, NULL, 'nexus_autoresolve_applicable' ) );
$form->add( new \IPS\Helpers\Form\Number( 'nexus_autoresolve_days', \IPS\Settings::i()->nexus_autoresolve_days, FALSE, array(), NULL, NULL, \IPS\Member::loggedIn()->language()->addToStack('days'), 'nexus_autoresolve_days' ) );
$form->add( new \IPS\Helpers\Form\Interval( 'nexus_autoresolve_days', \IPS\Settings::i()->nexus_autoresolve_days, FALSE, array( 'valueAs' => \IPS\Helpers\Form\Interval::DAYS ), NULL, NULL, NULL, 'nexus_autoresolve_days' ) );
$form->add( new \IPS\Helpers\Form\Node( 'nexus_autoresolve_status', \IPS\Settings::i()->nexus_autoresolve_status, FALSE, array( 'class' => 'IPS\nexus\Support\Status' ), NULL, NULL, NULL, 'nexus_autoresolve_status' ) );
$form->add( new \IPS\Helpers\Form\Number( 'nexus_autoresolve_notify', \IPS\Settings::i()->nexus_autoresolve_notify, FALSE, array( 'unlimited' => 0, 'unlimitedLang' => 'never' ), NULL, NULL, \IPS\Member::loggedIn()->language()->addToStack('hours_before_resolving'), 'nexus_autoresolve_notify' ) );
@@ -63,7 +68,7 @@ class _autoresolve extends \IPS\Dispatcher\Controller
unset( $values['nexus_autoresolve_on'] );
$values['nexus_autoresolve_departments'] = $values['nexus_autoresolve_departments'] ? implode( ',' , array_keys( $values['nexus_autoresolve_departments'] ) ) : '*';
$values['nexus_autoresolve_applicable'] = is_array( $values['nexus_autoresolve_applicable'] ) ? implode( ',', array_keys( $values['nexus_autoresolve_applicable'] ) ) : $values['nexus_autoresolve_applicable'];
$values['nexus_autoresolve_applicable'] = \is_array( $values['nexus_autoresolve_applicable'] ) ? implode( ',', array_keys( $values['nexus_autoresolve_applicable'] ) ) : $values['nexus_autoresolve_applicable'];
$values['nexus_autoresolve_status'] = $values['nexus_autoresolve_status']->id;
$form->saveAsSettings( $values );
@@ -12,7 +12,7 @@
namespace IPS\nexus\modules\admin\support;
/* To prevent PHP errors (extending class does not exist) revealing path */
if ( !defined( '\IPS\SUITE_UNIQUE_KEY' ) )
if ( !\defined( '\IPS\SUITE_UNIQUE_KEY' ) )
{
header( ( isset( $_SERVER['SERVER_PROTOCOL'] ) ? $_SERVER['SERVER_PROTOCOL'] : 'HTTP/1.0' ) . ' 403 Forbidden' );
exit;
@@ -23,6 +23,11 @@ if ( !defined( '\IPS\SUITE_UNIQUE_KEY' ) )
*/
class _customerfeedback extends \IPS\Dispatcher\Controller
{
/**
* @brief Has been CSRF-protected
*/
public static $csrfProtected = TRUE;
/**
* Manage
*
@@ -12,7 +12,7 @@
namespace IPS\nexus\modules\admin\support;
/* To prevent PHP errors (extending class does not exist) revealing path */
if ( !defined( '\IPS\SUITE_UNIQUE_KEY' ) )
if ( !\defined( '\IPS\SUITE_UNIQUE_KEY' ) )
{
header( ( isset( $_SERVER['SERVER_PROTOCOL'] ) ? $_SERVER['SERVER_PROTOCOL'] : 'HTTP/1.0' ) . ' 403 Forbidden' );
exit;
@@ -23,6 +23,11 @@ if ( !defined( '\IPS\SUITE_UNIQUE_KEY' ) )
*/
class _departments extends \IPS\Node\Controller
{
/**
* @brief Has been CSRF-protected
*/
public static $csrfProtected = TRUE;
/**
* Node Class
*/
@@ -12,7 +12,7 @@
namespace IPS\nexus\modules\admin\support;
/* To prevent PHP errors (extending class does not exist) revealing path */
if ( !defined( '\IPS\SUITE_UNIQUE_KEY' ) )
if ( !\defined( '\IPS\SUITE_UNIQUE_KEY' ) )
{
header( ( isset( $_SERVER['SERVER_PROTOCOL'] ) ? $_SERVER['SERVER_PROTOCOL'] : 'HTTP/1.0' ) . ' 403 Forbidden' );
exit;
@@ -23,6 +23,11 @@ if ( !defined( '\IPS\SUITE_UNIQUE_KEY' ) )
*/
class _fields extends \IPS\Node\Controller
{
/**
* @brief Has been CSRF-protected
*/
public static $csrfProtected = TRUE;
/**
* Node Class
*/
@@ -12,7 +12,7 @@
namespace IPS\nexus\modules\admin\support;
/* To prevent PHP errors (extending class does not exist) revealing path */
if ( !defined( '\IPS\SUITE_UNIQUE_KEY' ) )
if ( !\defined( '\IPS\SUITE_UNIQUE_KEY' ) )
{
header( ( isset( $_SERVER['SERVER_PROTOCOL'] ) ? $_SERVER['SERVER_PROTOCOL'] : 'HTTP/1.0' ) . ' 403 Forbidden' );
exit;
@@ -23,6 +23,11 @@ if ( !defined( '\IPS\SUITE_UNIQUE_KEY' ) )
*/
class _incomingemail extends \IPS\Dispatcher\Controller
{
/**
* @brief Has been CSRF-protected
*/
public static $csrfProtected = TRUE;
/**
* Execute
*
@@ -110,7 +115,7 @@ class _incomingemail extends \IPS\Dispatcher\Controller
{
$task = \IPS\Db::i()->select( '*', 'core_tasks', array( 'app=? AND `key`=? AND enabled=1', 'core', 'pop' ) )->first();
$pop3Form = $this->_pop3();
$pop3Form->addButton( 'disable_pop3', 'link', \IPS\Http\Url::internal( 'app=nexus&module=support&controller=incomingemail&do=disablePop3' ), '', array( 'data-confirm' => '' ) );
$pop3Form->addButton( 'disable_pop3', 'link', \IPS\Http\Url::internal( 'app=nexus&module=support&controller=incomingemail&do=disablePop3' )->csrf(), '', array( 'data-confirm' => '' ) );
$content = \IPS\Theme::i()->getTemplate('incomingemailsetup')->usingpop3( $pop3Form, (string) $table );
}
catch ( \UnderflowException $e ) { }
@@ -130,6 +135,7 @@ class _incomingemail extends \IPS\Dispatcher\Controller
*/
protected function disablePop3()
{
\IPS\Session::i()->csrfCheck();
\IPS\Settings::i()->changeValues( array( 'pop3_server' => '', 'pop3_port' => '', 'pop3_user' => '', 'pop3_password' => '' ) );
\IPS\Session::i()->log( 'acplogs__pop3_settings' );
\IPS\Db::i()->update( 'core_tasks', array( 'enabled' => 0 ), array( 'app=? AND `key`=?', 'core', 'pop' ) );
@@ -12,7 +12,7 @@
namespace IPS\nexus\modules\admin\support;
/* To prevent PHP errors (extending class does not exist) revealing path */
if ( !defined( '\IPS\SUITE_UNIQUE_KEY' ) )
if ( !\defined( '\IPS\SUITE_UNIQUE_KEY' ) )
{
header( ( isset( $_SERVER['SERVER_PROTOCOL'] ) ? $_SERVER['SERVER_PROTOCOL'] : 'HTTP/1.0' ) . ' 403 Forbidden' );
exit;
@@ -23,6 +23,11 @@ if ( !defined( '\IPS\SUITE_UNIQUE_KEY' ) )
*/
class _outgoingemail extends \IPS\Dispatcher\Controller
{
/**
* @brief Has been CSRF-protected
*/
public static $csrfProtected = TRUE;
/**
* Manage
*
@@ -12,7 +12,7 @@
namespace IPS\nexus\modules\admin\support;
/* To prevent PHP errors (extending class does not exist) revealing path */
if ( !defined( '\IPS\SUITE_UNIQUE_KEY' ) )
if ( !\defined( '\IPS\SUITE_UNIQUE_KEY' ) )
{
header( ( isset( $_SERVER['SERVER_PROTOCOL'] ) ? $_SERVER['SERVER_PROTOCOL'] : 'HTTP/1.0' ) . ' 403 Forbidden' );
exit;
@@ -23,6 +23,11 @@ if ( !defined( '\IPS\SUITE_UNIQUE_KEY' ) )
*/
class _reports extends \IPS\Dispatcher\Controller
{
/**
* @brief Has been CSRF-protected
*/
public static $csrfProtected = TRUE;
/**
* Execute
*
@@ -13,7 +13,7 @@ namespace IPS\nexus\modules\admin\support;
use \IPS\nexus\Support;
/* To prevent PHP errors (extending class does not exist) revealing path */
if ( !defined( '\IPS\SUITE_UNIQUE_KEY' ) )
if ( !\defined( '\IPS\SUITE_UNIQUE_KEY' ) )
{
header( ( isset( $_SERVER['SERVER_PROTOCOL'] ) ? $_SERVER['SERVER_PROTOCOL'] : 'HTTP/1.0' ) . ' 403 Forbidden' );
exit;
@@ -24,6 +24,11 @@ if ( !defined( '\IPS\SUITE_UNIQUE_KEY' ) )
*/
class _request extends \IPS\nexus\modules\front\support\view
{
/**
* @brief Has been CSRF-protected
*/
public static $csrfProtected = TRUE;
/**
* Execute
*
@@ -92,7 +97,35 @@ class _request extends \IPS\nexus\modules\front\support\view
if ( $action->message )
{
$data['message'] = $action->message;
/* Do we have default content? */
try
{
$defaultContent = \IPS\Db::i()->select( 'content', 'nexus_support_staff_preferences', array( 'staff_id=?', \IPS\Member::loggedIn()->member_id ) )->first();
/* If we aren't using the {default_content} tag then we just want the stock reply returned */
if( mb_strpos( $defaultContent, '{default_content}' ) === FALSE )
{
throw new \UnderflowException;
}
$data['message'] = str_replace(
array( '{customer_first_name}', '{customer_last_name}', '{customer_full_name}', '{department_name}', '{department_email}', '{default_content}' ),
array(
( $this->request->supportAuthor() instanceof \IPS\nexus\Support\Author\Member ) ? \IPS\nexus\Customer::load( $this->request->author()->member_id )->cm_first_name : '',
( $this->request->supportAuthor() instanceof \IPS\nexus\Support\Author\Member ) ? \IPS\nexus\Customer::load( $this->request->author()->member_id )->cm_last_name : '',
$this->request->supportAuthor()->name(),
$action->department ? $action->department->_title : $this->request->department->_title,
$action->department ? $action->department->email : $this->request->department->email,
/* We want to strip the wrapping <p></p> because where we insert it into our default content will already be wrapped, so we will have double line breaks otherwise */
preg_replace( "/^<p>(.+?)<\/p>$/is", "$1", trim( $action->message ) )
),
$defaultContent
);
}
catch ( \UnderflowException $e )
{
$data['message'] = $action->message;
}
}
\IPS\Output::i()->json( $data );
@@ -122,7 +155,9 @@ class _request extends \IPS\nexus\modules\front\support\view
/* Setting Order? */
if ( isset( \IPS\Request::i()->order ) )
{
\IPS\Session::i()->csrfCheck();
\IPS\Request::i()->setCookie( 'support_replies_order', \IPS\Request::i()->order, \IPS\DateTime::create()->add( new \DateInterval('P1Y') ) );
\IPS\Output::i()->redirect( $this->request->acpUrl() );
}
/* Views */
@@ -144,7 +179,7 @@ class _request extends \IPS\nexus\modules\front\support\view
'icon' => 'tag',
'title' => $this->request->status->_title,
'menu' => array(),
'menuClass' => 'ipsMenu_selectable ipsMenu_narrow',
'menuClass' => 'ipsMenu_selectable ipsMenu_narrow',
'data' => array( 'role' => 'statusMenu', 'controller' => 'nexus.admin.support.metamenu' ),
'tooltip' => \IPS\Member::loggedIn()->language()->addToStack('keyboard_shortcut_status')
),
@@ -152,7 +187,7 @@ class _request extends \IPS\nexus\modules\front\support\view
'icon' => 'exclamation',
'title' => $this->request->severity->_title,
'menu' => array(),
'menuClass' => 'ipsMenu_selectable',
'menuClass' => 'ipsMenu_selectable',
'data' => array( 'role' => 'severityMenu', 'controller' => 'nexus.admin.support.metamenu' ),
'tooltip' => \IPS\Member::loggedIn()->language()->addToStack('keyboard_shortcut_severity')
),
@@ -160,7 +195,7 @@ class _request extends \IPS\nexus\modules\front\support\view
'icon' => 'folder',
'title' => $this->request->department->_title,
'menu' => array(),
'menuClass' => 'ipsMenu_selectable ipsMenu_narrow',
'menuClass' => 'ipsMenu_selectable ipsMenu_narrow',
'data' => array( 'role' => 'departmentMenu', 'controller' => 'nexus.admin.support.metamenu' ),
'tooltip' => \IPS\Member::loggedIn()->language()->addToStack('keyboard_shortcut_department')
),
@@ -171,17 +206,17 @@ class _request extends \IPS\nexus\modules\front\support\view
array(
'class' => $trackLang === 'not_tracking' ? 'ipsMenu_itemChecked' : '',
'title' => 'not_tracking',
'link' => $this->request->acpUrl()->setQueryString( array( 'do' => 'track', 'track' => 0 ) )
'link' => $this->request->acpUrl()->setQueryString( array( 'do' => 'track', 'track' => 0 ) )->csrf()
),
array(
'class' => $trackLang === 'tracking_no_notify' ? 'ipsMenu_itemChecked' : '',
'title' => 'tracking_no_notify',
'link' => $this->request->acpUrl()->setQueryString( array( 'do' => 'track', 'track' => 1, 'notify' => 0 ) )
'link' => $this->request->acpUrl()->setQueryString( array( 'do' => 'track', 'track' => 1, 'notify' => 0 ) )->csrf()
),
array(
'class' => $trackLang === 'tracking_notify' ? 'ipsMenu_itemChecked' : '',
'title' => 'tracking_notify',
'link' => $this->request->acpUrl()->setQueryString( array( 'do' => 'track', 'track' => 1, 'notify' => 1 ) )
'link' => $this->request->acpUrl()->setQueryString( array( 'do' => 'track', 'track' => 1, 'notify' => 1 ) )->csrf()
)
),
'menuClass' => 'ipsMenu_selectable',
@@ -204,12 +239,12 @@ class _request extends \IPS\nexus\modules\front\support\view
$requestActions['status']['menu'][] = array(
'class' => $status->id === $this->request->status->id ? 'ipsMenu_itemChecked' : '',
'title' => $status->_title,
'link' => $this->request->acpUrl()->setQueryString( array( 'do' => 'status', 'status' => $status->id ) )
'link' => $this->request->acpUrl()->setQueryString( array( 'do' => 'status', 'status' => $status->id ) )->csrf()
);
}
/* Populate severities */
if ( count( Support\Severity::roots() ) < 2 )
if ( \count( Support\Severity::roots() ) < 2 )
{
unset( \IPS\Output::i()->sidebar['actions']['severity'] );
}
@@ -220,7 +255,7 @@ class _request extends \IPS\nexus\modules\front\support\view
$requestActions['severity']['menu'][] = array(
'class' => $severity->id === $this->request->severity->id ? 'ipsMenu_itemChecked' : '',
'title' => $severity->_title,
'link' => $this->request->acpUrl()->setQueryString( array( 'do' => 'severity', 'severity' => $severity->id ) ),
'link' => $this->request->acpUrl()->setQueryString( array( 'do' => 'severity', 'severity' => $severity->id ) )->csrf(),
'data' => array( 'group' => 'severities' ),
);
}
@@ -231,13 +266,13 @@ class _request extends \IPS\nexus\modules\front\support\view
$requestActions['severity']['menu'][] = array(
'class' => !$this->request->author()->cm_no_sev ? 'ipsMenu_itemChecked' : '',
'title' => \IPS\Member::loggedIn()->language()->addToStack( 'cm_no_sev_off', FALSE, array( 'sprintf' => array( $this->request->supportAuthor()->name() ) ) ),
'link' => $this->request->acpUrl()->setQueryString( array( 'do' => 'noSev', 'no_sev' => 0 ) ),
'link' => $this->request->acpUrl()->setQueryString( array( 'do' => 'noSev', 'no_sev' => 0 ) )->csrf(),
'data' => array( 'group' => 'no_sev', 'noSet' => 'true' ),
);
$requestActions['severity']['menu'][] = array(
'class' => $this->request->author()->cm_no_sev ? 'ipsMenu_itemChecked' : '',
'title' => \IPS\Member::loggedIn()->language()->addToStack( 'cm_no_sev_on', FALSE, array( 'sprintf' => array( $this->request->supportAuthor()->name() ) ) ),
'link' => $this->request->acpUrl()->setQueryString( array( 'do' => 'noSev', 'no_sev' => 1 ) ),
'link' => $this->request->acpUrl()->setQueryString( array( 'do' => 'noSev', 'no_sev' => 1 ) )->csrf(),
'data' => array( 'group' => 'no_sev', 'noSet' => 'true' ),
);
}
@@ -249,7 +284,7 @@ class _request extends \IPS\nexus\modules\front\support\view
$requestActions['department']['menu'][] = array(
'class' => $department->id === $this->request->department->id ? 'ipsMenu_itemChecked' : '',
'title' => $department->_title,
'link' => $this->request->acpUrl()->setQueryString( array( 'do' => 'department', 'department' => $department->id ) )
'link' => $this->request->acpUrl()->setQueryString( array( 'do' => 'department', 'department' => $department->id ) )->csrf()
);
}
@@ -259,27 +294,27 @@ class _request extends \IPS\nexus\modules\front\support\view
$requestActions['staff']['menu'][] = array(
'class' => ( $this->request->staff and $id === $this->request->staff->member_id ) ? 'ipsMenu_itemChecked' : '',
'title' => $name,
'link' => $this->request->acpUrl()->setQueryString( array( 'do' => 'staff', 'staff' => $id ) ),
'link' => $this->request->acpUrl()->setQueryString( array( 'do' => 'staff', 'staff' => $id ) )->csrf(),
'data' => array( 'group' => 'staff', 'id' => $id ),
);
}
$requestActions['staff']['menu'][] = array(
'class' => !$this->request->staff ? 'ipsMenu_itemChecked' : '',
'title' => 'unassigned',
'link' => $this->request->acpUrl()->setQueryString( array( 'do' => 'staff', 'staff' => 0 ) ),
'link' => $this->request->acpUrl()->setQueryString( array( 'do' => 'staff', 'staff' => 0 ) )->csrf(),
'data' => array( 'group' => 'staff', 'id' => 0 ),
);
$requestActions['staff']['menu'][] = array( 'hr' => TRUE );
$requestActions['staff']['menu'][] = array(
'class' => $this->request->staff_lock ? 'ipsMenu_itemChecked' : '',
'title' => \IPS\Member::loggedIn()->language()->addToStack( 'request_staff_lock_on' ),
'link' => $this->request->acpUrl()->setQueryString( array( 'do' => 'staffLock', 'lock' => 1 ) ),
'link' => $this->request->acpUrl()->setQueryString( array( 'do' => 'staffLock', 'lock' => 1 ) )->csrf(),
'data' => array( 'group' => 'staff_lock', 'noSet' => 'true' ),
);
$requestActions['staff']['menu'][] = array(
'class' => !$this->request->staff_lock ? 'ipsMenu_itemChecked' : '',
'title' =>\IPS\Member::loggedIn()->language()->addToStack( 'request_staff_lock_off' ),
'link' => $this->request->acpUrl()->setQueryString( array( 'do' => 'staffLock', 'lock' => 0 ) ),
'link' => $this->request->acpUrl()->setQueryString( array( 'do' => 'staffLock', 'lock' => 0 ) )->csrf(),
'data' => array( 'group' => 'staff_lock', 'noSet' => 'true' ),
);
@@ -289,18 +324,21 @@ class _request extends \IPS\nexus\modules\front\support\view
\IPS\Output::i()->sidebar['actions']['delete'] = array(
'icon' => 'times-circle',
'title' => 'delete',
'link' => $this->request->acpUrl()->setQueryString( 'do', 'delete' ),
'link' => $this->request->acpUrl()->setQueryString( 'do', 'delete' )->csrf(),
'data' => array( 'confirm' => '' )
);
}
\IPS\Output::i()->sidebar['actions']['purchase'] = array(
'icon' => 'cube',
'title' => 'associate_purchase',
'link' => $this->request->acpUrl()->setQueryString( 'do', 'associate' ),
'data' => array( 'ipsDialog' => '', 'ipsDialog-title' => \IPS\Member::loggedIn()->language()->addToStack('associate'), 'ipsDialog-size' => 'narrow', 'role' => 'associatePurchaseMenu' ),
'tooltip' => \IPS\Member::loggedIn()->language()->addToStack('keyboard_shortcut_purchase')
);
if( \IPS\Member::loggedIn()->hasAcpRestriction( \IPS\Application::load('nexus'), \IPS\Application\Module::get( 'nexus', 'customers' ), 'purchases_view' ) )
{
\IPS\Output::i()->sidebar['actions']['purchase'] = array(
'icon' => 'cube',
'title' => 'associate_purchase',
'link' => $this->request->acpUrl()->setQueryString( 'do', 'associate' ),
'data' => array( 'ipsDialog' => '', 'ipsDialog-title' => \IPS\Member::loggedIn()->language()->addToStack('associate'), 'ipsDialog-size' => 'narrow', 'role' => 'associatePurchaseMenu' ),
'tooltip' => \IPS\Member::loggedIn()->language()->addToStack('keyboard_shortcut_purchase')
);
}
\IPS\Output::i()->output = \IPS\Theme::i()->getTemplate( 'support' )->request( $this->request, $requestActions );
@@ -408,7 +446,7 @@ class _request extends \IPS\nexus\modules\front\support\view
$page = ceil( $commentPosition / \IPS\nexus\Support\Request::getCommentsPerPage() );
if ( $page != 1 )
{
$url = $url->setQueryString( 'page', $page );
$url = $url->setPage( 'page', $page );
}
$url = $url->setFragment( "reply-{$unreadComment->id}" );
@@ -429,7 +467,7 @@ class _request extends \IPS\nexus\modules\front\support\view
$lastPage = $request->commentPageCount();
if ( $lastPage != 1 )
{
$url = $url->setQueryString( 'page', $lastPage );
$url = $url->setPage( 'page', $lastPage );
}
}
@@ -480,7 +518,7 @@ class _request extends \IPS\nexus\modules\front\support\view
$page = ceil( $commentPosition / \IPS\nexus\Support\Request::getCommentsPerPage() );
if ( $page != 1 )
{
$url = $url->setQueryString( 'page', $page );
$url = $url->setPage( 'page', $page );
}
$url = $url->setFragment( "reply-{$comment->id}" );
\IPS\Output::i()->redirect( $url );
@@ -492,7 +530,9 @@ class _request extends \IPS\nexus\modules\front\support\view
* @return void
*/
protected function pending()
{
{
\IPS\Session::i()->csrfCheck();
try
{
$message = Support\Reply::loadAndCheckPerms( \IPS\Request::i()->response );
@@ -589,7 +629,12 @@ class _request extends \IPS\nexus\modules\front\support\view
$form = new \IPS\Helpers\Form;
foreach ( $request->department->customFields() as $field )
{
$form->add( $field->buildHelper( isset( $customFieldValues[ $field->id ] ) ? $customFieldValues[ $field->id ] : NULL ) );
if ( $field->type === 'Editor' )
{
$field::$editorOptions = array_merge( $field::$editorOptions, array( 'attachIds' => array( $request->id, $field->id, 'fields' ) ) );
}
$helper = $field->buildHelper( isset( $customFieldValues[ $field->id ] ) ? $customFieldValues[ $field->id ] : NULL );
$form->add( $helper );
}
if ( $values = $form->values( TRUE ) )
@@ -619,6 +664,8 @@ class _request extends \IPS\nexus\modules\front\support\view
*/
protected function status()
{
\IPS\Session::i()->csrfCheck();
try
{
/* Init */
@@ -680,6 +727,8 @@ class _request extends \IPS\nexus\modules\front\support\view
*/
protected function severity()
{
\IPS\Session::i()->csrfCheck();
try
{
$request = Support\Request::loadAndCheckPerms( \IPS\Request::i()->id );
@@ -709,6 +758,7 @@ class _request extends \IPS\nexus\modules\front\support\view
protected function noSev()
{
\IPS\Dispatcher::i()->checkAcpPermission( 'requests_block_sev' );
\IPS\Session::i()->csrfCheck();
try
{
@@ -734,6 +784,8 @@ class _request extends \IPS\nexus\modules\front\support\view
*/
protected function staffLock()
{
\IPS\Session::i()->csrfCheck();
try
{
$request = Support\Request::loadAndCheckPerms( \IPS\Request::i()->id );
@@ -758,6 +810,8 @@ class _request extends \IPS\nexus\modules\front\support\view
*/
protected function department()
{
\IPS\Session::i()->csrfCheck();
try
{
$request = Support\Request::loadAndCheckPerms( \IPS\Request::i()->id );
@@ -809,6 +863,8 @@ class _request extends \IPS\nexus\modules\front\support\view
*/
protected function staff()
{
\IPS\Session::i()->csrfCheck();
try
{
$request = Support\Request::loadAndCheckPerms( \IPS\Request::i()->id );
@@ -839,6 +895,8 @@ class _request extends \IPS\nexus\modules\front\support\view
*/
protected function track()
{
\IPS\Session::i()->csrfCheck();
try
{
$request = Support\Request::loadAndCheckPerms( \IPS\Request::i()->id );
@@ -884,7 +942,7 @@ class _request extends \IPS\nexus\modules\front\support\view
$form = new \IPS\Helpers\Form;
$parentContacts = \IPS\nexus\Customer::load( $request->author()->member_id )->parentContacts();
if ( count( $parentContacts ) )
if ( \count( $parentContacts ) )
{
$form->class = 'ipsForm_vertical';
$options = array();
@@ -932,7 +990,7 @@ class _request extends \IPS\nexus\modules\front\support\view
\IPS\Output::i()->redirect( $request->acpUrl() );
}
\IPS\Output::i()->output = $form->customTemplate( array( call_user_func_array( array( \IPS\Theme::i(), 'getTemplate' ), array( 'forms', 'core', 'front' ) ), 'popupTemplate' ) );
\IPS\Output::i()->output = $form->customTemplate( array( \IPS\Theme::i()->getTemplate( 'forms', 'core', 'front' ), 'popupTemplate' ) );
}
catch ( \OutOfRangeException $e )
{
@@ -948,6 +1006,7 @@ class _request extends \IPS\nexus\modules\front\support\view
protected function merge()
{
\IPS\Dispatcher::i()->checkAcpPermission( 'requests_merge' );
\IPS\Session::i()->csrfCheck();
try
{
@@ -1171,4 +1230,4 @@ class _request extends \IPS\nexus\modules\front\support\view
}
return $defaultAction;
}
}
}
@@ -12,7 +12,7 @@
namespace IPS\nexus\modules\admin\support;
/* To prevent PHP errors (extending class does not exist) revealing path */
if ( !defined( '\IPS\SUITE_UNIQUE_KEY' ) )
if ( !\defined( '\IPS\SUITE_UNIQUE_KEY' ) )
{
header( ( isset( $_SERVER['SERVER_PROTOCOL'] ) ? $_SERVER['SERVER_PROTOCOL'] : 'HTTP/1.0' ) . ' 403 Forbidden' );
exit;
@@ -23,6 +23,11 @@ if ( !defined( '\IPS\SUITE_UNIQUE_KEY' ) )
*/
class _requests extends \IPS\Dispatcher\Controller
{
/**
* @brief Has been CSRF-protected
*/
public static $csrfProtected = TRUE;
/**
* Execute
*
@@ -51,7 +56,7 @@ class _requests extends \IPS\Dispatcher\Controller
protected function manage()
{
/* Can we access anything? */
if ( !count( \IPS\nexus\Support\Department::departmentsWithPermission() ) )
if ( !\count( \IPS\nexus\Support\Department::departmentsWithPermission() ) )
{
if ( \IPS\Member::loggedIn()->hasAcpRestriction( 'nexus', 'support', 'departments_manage' ) )
{
@@ -62,55 +67,83 @@ class _requests extends \IPS\Dispatcher\Controller
\IPS\Output::i()->error( 'err_no_departments_with_perm2', '1X261/2', 403, '' );
}
}
/* Permissions */
$where = array();
$where[] = array( "( dpt_staff='*' OR " . \IPS\Db::i()->findInSet( 'dpt_staff', \IPS\nexus\Support\Department::staffDepartmentPerms() ) . ')' );
/* Get my stream */
$stream = NULL;
if ( isset( \IPS\Request::i()->cookie['support_stream'] ) or isset( \IPS\Request::i()->stream ) or isset( \IPS\Request::i()->member ) )
/* Get stream - can set new... */
if ( ( isset( \IPS\Request::i()->stream ) and \IPS\Request::i()->stream !== 'custom' ) or isset( \IPS\Request::i()->member ) or isset( \IPS\Request::i()->email ) )
{
if ( isset( \IPS\Request::i()->member ) )
\IPS\Session::i()->csrfCheck();
/* Specific stream */
if ( isset( \IPS\Request::i()->stream ) )
{
try
{
$customer = \IPS\nexus\Customer::load( \IPS\Request::i()->member );
$stream = \IPS\nexus\Support\Stream::customer( $customer );
$stream->temporary = TRUE;
$stream->owner = \IPS\Member::loggedIn()->member_id;
$stream->save();
\IPS\Request::i()->setCookie( 'support_stream', $stream->id, \IPS\DateTime::create()->add( new \DateInterval( 'P1Y') ), FALSE );
\IPS\Db::i()->delete( 'nexus_support_streams', array( 'stream_owner=? AND stream_temporary=1 AND stream_id<>?', \IPS\Member::loggedIn()->member_id, $stream->id ) );
$stream = \IPS\nexus\Support\Stream::load( \IPS\Request::i()->stream );
}
catch ( \OutOfRangeException $e )
{
\IPS\Output::i()->error( 'node_error', '2X261/4', 404, '' );
}
}
/* Temporary stream */
else
{
$streamId = isset( \IPS\Request::i()->stream ) ? \IPS\Request::i()->stream : \IPS\Request::i()->cookie['support_stream'];
try
if( isset( \IPS\Request::i()->member ) )
{
$stream = \IPS\nexus\Support\Stream::load( $streamId );
if ( isset( \IPS\Request::i()->stream ) )
{
\IPS\Request::i()->setCookie( 'support_stream', $streamId, \IPS\DateTime::create()->add( new \DateInterval( 'P1Y') ), FALSE );
\IPS\Db::i()->delete( 'nexus_support_streams', array( 'stream_owner=? AND stream_temporary=1 AND stream_id<>?', \IPS\Member::loggedIn()->member_id, $streamId ) );
}
$customer = \IPS\nexus\Customer::load( \IPS\Request::i()->member );
}
catch ( \OutOfRangeException $e ) { }
else
{
$customer = \IPS\nexus\Customer::constructFromData( array( 'email' => \IPS\Request::i()->email ) );
}
$stream = \IPS\nexus\Support\Stream::customer( $customer );
$stream->temporary = TRUE;
$stream->owner = \IPS\Member::loggedIn()->member_id;
$stream->save();
}
/* Set the cookie */
\IPS\Request::i()->setCookie( 'support_stream', $stream->id, \IPS\DateTime::create()->add( new \DateInterval( 'P1Y') ), FALSE );
/* Delete previously stored temporary streams */
$where = array(
array( 'stream_owner=?', \IPS\Member::loggedIn()->member_id ),
array( 'stream_temporary=?', 1 )
);
if ( !\in_array( $stream->id, array( 'open', 'assigned', 'tracked' ) ) )
{
$where[] = array( 'stream_id<>?', $stream->id );
}
\IPS\Db::i()->delete( 'nexus_support_streams', $where );
/* If this isn't an AJAX request, redirect to it to stop the CSRF key hanging around in the address bar */
if ( !\IPS\Request::i()->isAjax() )
{
\IPS\Output::i()->redirect( \IPS\Http\Url::internal('app=nexus&module=support&controller=requests' ) );
}
}
$stream = $stream ?: \IPS\nexus\Support\Stream::load('open');
/* ... or use preferred stream */
elseif ( isset( \IPS\Request::i()->cookie['support_stream'] ) )
{
try
{
$stream = \IPS\nexus\Support\Stream::load( \IPS\Request::i()->cookie['support_stream'] );
}
catch ( \OutOfRangeException $e )
{
$stream = \IPS\nexus\Support\Stream::load('open');
}
}
/* ... or just use the default */
else
{
$stream = \IPS\nexus\Support\Stream::load('open');
}
/* Are we grouping by department? */
if ( isset( \IPS\Request::i()->groupByDepartment ) )
{
\IPS\Session::i()->csrfCheck();
if ( \IPS\Request::i()->groupByDepartment )
{
\IPS\Request::i()->setCookie( 'support_dpt_group', 1, \IPS\DateTime::create()->add( new \DateInterval( 'P1Y') ), FALSE );
@@ -119,21 +152,40 @@ class _requests extends \IPS\Dispatcher\Controller
{
\IPS\Request::i()->setCookie( 'support_dpt_group', 0, \IPS\DateTime::create()->add( new \DateInterval( 'P1Y') ), FALSE );
}
if ( !\IPS\Request::i()->isAjax() )
{
\IPS\Output::i()->redirect( \IPS\Http\Url::internal('app=nexus&module=support&controller=requests' ) );
}
}
$groupByDepartment = ( isset( \IPS\Request::i()->cookie['support_dpt_group'] ) and \IPS\Request::i()->cookie['support_dpt_group'] );
/* What's our order? */
if ( \IPS\Request::i()->sortBy )
{
\IPS\Session::i()->csrfCheck();
\IPS\Request::i()->setCookie( 'support_sort', \IPS\Request::i()->sortBy, \IPS\DateTime::create()->add( new \DateInterval( 'P1Y') ), FALSE );
if ( !\IPS\Request::i()->isAjax() )
{
\IPS\Output::i()->redirect( \IPS\Http\Url::internal('app=nexus&module=support&controller=requests' ) );
}
}
if ( \IPS\Request::i()->sortDir )
{
\IPS\Session::i()->csrfCheck();
\IPS\Request::i()->setCookie( 'support_order', \IPS\Request::i()->sortDir, \IPS\DateTime::create()->add( new \DateInterval( 'P1Y') ), FALSE );
if ( !\IPS\Request::i()->isAjax() )
{
\IPS\Output::i()->redirect( \IPS\Http\Url::internal('app=nexus&module=support&controller=requests' ) );
}
}
if ( isset( \IPS\Request::i()->honorSeverities ) )
{
\IPS\Session::i()->csrfCheck();
\IPS\Request::i()->setCookie( 'support_honor_severities', \IPS\Request::i()->honorSeverities, \IPS\DateTime::create()->add( new \DateInterval( 'P1Y') ), FALSE );
if ( !\IPS\Request::i()->isAjax() )
{
\IPS\Output::i()->redirect( \IPS\Http\Url::internal('app=nexus&module=support&controller=requests' ) );
}
}
$order = array();
if ( $groupByDepartment )
@@ -146,8 +198,8 @@ class _requests extends \IPS\Dispatcher\Controller
{
$order[] = 'sev_position ASC';
}
$sortBy = ( isset( \IPS\Request::i()->cookie['support_sort'] ) and in_array( \IPS\Request::i()->cookie['support_sort'], array( 'r_started', 'r_last_new_reply', 'r_last_reply', 'r_last_staff_reply' ) ) ) ? \IPS\Request::i()->cookie['support_sort'] : 'r_last_new_reply';
$sortDir = ( isset( \IPS\Request::i()->cookie['support_order'] ) and in_array( \IPS\Request::i()->cookie['support_order'], array( 'ASC', 'DESC' ) ) ) ? \IPS\Request::i()->cookie['support_order'] : 'ASC';
$sortBy = ( isset( \IPS\Request::i()->cookie['support_sort'] ) and \in_array( \IPS\Request::i()->cookie['support_sort'], array( 'r_started', 'r_last_new_reply', 'r_last_reply', 'r_last_staff_reply' ) ) ) ? \IPS\Request::i()->cookie['support_sort'] : 'r_last_new_reply';
$sortDir = ( isset( \IPS\Request::i()->cookie['support_order'] ) and \in_array( \IPS\Request::i()->cookie['support_order'], array( 'ASC', 'DESC' ) ) ) ? \IPS\Request::i()->cookie['support_order'] : 'ASC';
$order[] = $sortBy . ' ' . $sortDir;
$order = implode( ', ', $order );
@@ -155,7 +207,7 @@ class _requests extends \IPS\Dispatcher\Controller
$perPage = 25;
$count = $stream->count( \IPS\Member::loggedIn() );
$numberOfPages = ceil( $count / $perPage );
$page = ( isset( \IPS\Request::i()->page ) and \IPS\Request::i()->page <= $numberOfPages ) ? intval( \IPS\Request::i()->page ) : 1;
$page = ( isset( \IPS\Request::i()->page ) and \IPS\Request::i()->page <= $numberOfPages ) ? \intval( \IPS\Request::i()->page ) : 1;
$results = $stream->results( \IPS\Member::loggedIn(), $order, $page, $perPage );
$pagination = \IPS\Theme::i()->getTemplate( 'global', 'core', 'global' )->pagination( \IPS\Http\Url::internal('app=nexus&module=support&controller=requests'), $numberOfPages, $page, $perPage );
@@ -172,14 +224,14 @@ class _requests extends \IPS\Dispatcher\Controller
{
\IPS\Db::i()->delete( 'nexus_support_streams', array( 'stream_owner=? AND stream_temporary=1', \IPS\Member::loggedIn()->member_id ) );
$stream = \IPS\nexus\Support\Stream::createFromForm( $values );
\IPS\Output::i()->redirect( \IPS\Http\Url::internal('app=nexus&module=support&controller=requests&stream=') . $stream->id );
\IPS\Output::i()->redirect( \IPS\Http\Url::internal( 'app=nexus&module=support&controller=requests&stream=' . $stream->id )->csrf() );
}
else
{
\IPS\Request::i()->setCookie( 'support_stream', $values['stream'], \IPS\DateTime::create()->add( new \DateInterval( 'P1Y') ), FALSE );
}
}
$form = $form->customTemplate( array( call_user_func_array( array( \IPS\Theme::i(), 'getTemplate' ), array( 'support' ) ), 'filterForm' ) );
$form = $form->customTemplate( array( \IPS\Theme::i()->getTemplate( 'support' ), 'filterForm' ) );
/* Display */
if ( \IPS\Request::i()->isAjax() )
@@ -230,7 +282,7 @@ class _requests extends \IPS\Dispatcher\Controller
protected function filters()
{
\IPS\Output::i()->title = \IPS\Member::loggedIn()->language()->addToStack('menu__nexus_support_requests');
\IPS\Output::i()->output = \IPS\nexus\Support\Stream::load('open')->form( NULL, \IPS\Http\Url::internal('app=nexus&module=support&controller=requests') )->customTemplate( array( call_user_func_array( array( \IPS\Theme::i(), 'getTemplate' ), array( 'support' ) ), 'filterForm' ) );
\IPS\Output::i()->output = \IPS\nexus\Support\Stream::load('open')->form( NULL, \IPS\Http\Url::internal('app=nexus&module=support&controller=requests') )->customTemplate( array( \IPS\Theme::i()->getTemplate( 'support' ), 'filterForm' ) );
}
/**
@@ -242,6 +294,7 @@ class _requests extends \IPS\Dispatcher\Controller
{
if ( isset( \IPS\Request::i()->stream_title ) )
{
\IPS\Session::i()->csrfCheck();
\IPS\Db::i()->update( 'nexus_support_streams', array(
'stream_title' => \IPS\Request::i()->stream_title,
'stream_temporary' => 0
@@ -293,11 +346,11 @@ class _requests extends \IPS\Dispatcher\Controller
$stream->title = $values['stream_title'];
$stream->updateFromForm( $values );
$stream->save();
\IPS\Output::i()->redirect( \IPS\Http\Url::internal( 'app=nexus&module=support&controller=requests&stream=' . $stream->id ) );
\IPS\Output::i()->redirect( \IPS\Http\Url::internal( 'app=nexus&module=support&controller=requests&stream=' . $stream->id )->csrf() );
}
}
\IPS\Output::i()->output = $form->customTemplate( array( call_user_func_array( array( \IPS\Theme::i(), 'getTemplate' ), array( 'support' ) ), 'filterForm' ) );
\IPS\Output::i()->output = $form->customTemplate( array( \IPS\Theme::i()->getTemplate( 'support' ), 'filterForm' ) );
}
/**
@@ -437,10 +490,11 @@ class _requests extends \IPS\Dispatcher\Controller
}
$form->add( new \IPS\Helpers\Form\Editor( 'nexus_default_support_content', $preferences ? $preferences['content'] : NULL, FALSE, array( 'app' => 'nexus', 'key' => 'Support', 'autoSaveKey' => 'default_content', 'tags' => array(
'{customer_first_name}' => \IPS\Member::loggedIn()->language()->addToStack('customer_first_name'),
'{customer_last_name}' => \IPS\Member::loggedIn()->language()->addToStack('customer_first_name'),
'{customer_last_name}' => \IPS\Member::loggedIn()->language()->addToStack('customer_last_name'),
'{customer_full_name}' => \IPS\Member::loggedIn()->language()->addToStack('customer_full_name'),
'{department_name}' => \IPS\Member::loggedIn()->language()->addToStack('department_name'),
'{department_email}' => \IPS\Member::loggedIn()->language()->addToStack('department_email'),
'{default_content}' => \IPS\Member::loggedIn()->language()->addToStack('default_content'),
) ) ) );
$form->add( new \IPS\Helpers\Form\Select( 'nexus_default_support_action', $preferences ? $preferences['action'] : '', FALSE, array( 'options' => array(
'' => 'reply_remember_last',
@@ -499,7 +553,7 @@ class _requests extends \IPS\Dispatcher\Controller
foreach ( $types as $k => $t )
{
if ( $values[ $k ] === 0 or count( $values[ $k ] ) )
if ( $values[ $k ] === 0 or \count( $values[ $k ] ) )
{
\IPS\Db::i()->insert( 'nexus_support_notify', array(
'staff_id' => \IPS\Member::loggedIn()->member_id,
@@ -585,7 +639,7 @@ class _requests extends \IPS\Dispatcher\Controller
/* Stock Actions */
$stockActions = \IPS\nexus\Support\StockAction::roots();
if ( count( $stockActions ) )
if ( \count( $stockActions ) )
{
$steps['stock_action'] = function( $data ) use ( $stockActions, $url )
{
@@ -651,12 +705,12 @@ class _requests extends \IPS\Dispatcher\Controller
/* Custom Fields */
$customFields = \IPS\nexus\Support\CustomField::roots();
if ( count( $customFields ) )
if ( \count( $customFields ) )
{
$steps['custom_support_fields'] = function( $data ) use ( $url )
{
$customFields = \IPS\nexus\Support\CustomField::roots( NULL, NULL, array( "sf_departments='*' OR " . \IPS\Db::i()->findInSet( 'sf_departments', array( $data['department'] ) ) ) );
if ( count( $customFields ) )
if ( \count( $customFields ) )
{
$form = new \IPS\Helpers\Form( 'custom_fields', 'continue', $url->setQueryString( '_step', 'custom_support_fields' ) );
foreach ( $customFields as $field )
@@ -692,21 +746,22 @@ class _requests extends \IPS\Dispatcher\Controller
$owner = isset( $data['member'] ) ? \IPS\nexus\Customer::load( $data['member'] ) : NULL;
$defaultContent = \IPS\Db::i()->select( 'content', 'nexus_support_staff_preferences', array( 'staff_id=?', \IPS\Member::loggedIn()->member_id ) )->first();
$defaultContent = str_replace(
array( '{customer_first_name}', '{customer_last_name}', '{customer_full_name}', '{department_name}', '{department_email}' ),
$defaultContent = $defaultContent ? str_replace(
array( '{customer_first_name}', '{customer_last_name}', '{customer_full_name}', '{department_name}', '{department_email}', '{default_content}' ),
array(
$owner ? $owner->cm_first_name : '',
$owner ? $owner->cm_last_name : '',
$owner ? $owner->cm_name : $data['email'],
$department->_title,
$department->email
$department->email,
$stockAction ? $stockAction->message : ''
),
$defaultContent
);
) : ( $stockAction ? $stockAction->message : '' );
}
catch ( \UnderflowException $e )
{
$defaultContent = NULL;
$defaultContent = $stockAction ? $stockAction->message : NULL;
}
$form = new \IPS\Helpers\Form( 'your_message', 'save', $url->setQueryString( '_step', 'your_message' ) );
@@ -714,7 +769,7 @@ class _requests extends \IPS\Dispatcher\Controller
$form->add( new \IPS\Helpers\Form\Email( 'to', isset( $data['member'] ) ? \IPS\Member::load( $data['member'] )->email : $data['email'], NULL, array(), NULL, NULL, NULL, 'support_create_to' ) );
$form->add( new \IPS\Helpers\Form\Text( 'cc', array(), FALSE, array( 'autocomplete' => array( 'unique' => TRUE, 'forceLower' => TRUE ) ), array( 'IPS\nexus\Support\Request', '_validateEmail' ), NULL, NULL, 'support_create_cc' ) );
$form->add( new \IPS\Helpers\Form\Text( 'bcc', array(), FALSE, array( 'autocomplete' => array( 'unique' => TRUE, 'forceLower' => TRUE ) ), array( 'IPS\nexus\Support\Request', '_validateEmail' ), NULL, NULL, 'support_create_bcc' ) );
$form->add( new \IPS\Helpers\Form\Editor( 'message', $stockAction ? $stockAction->message : $defaultContent, TRUE, array( 'app' => 'nexus', 'key' => 'Support', 'autoSaveKey' => "new-req-message", 'defaultIfNoAutoSave' => TRUE ) ) );
$form->add( new \IPS\Helpers\Form\Editor( 'message', $defaultContent, TRUE, array( 'app' => 'nexus', 'key' => 'Support', 'autoSaveKey' => "new-req-message", 'defaultIfNoAutoSave' => TRUE ) ) );
if ( $values = $form->values() )
{
$request = new \IPS\nexus\Support\Request;
@@ -856,7 +911,7 @@ class _requests extends \IPS\Dispatcher\Controller
/* Display */
\IPS\Output::i()->title = \IPS\Member::loggedIn()->language()->addToStack('create_support_request');
\IPS\Output::i()->output = new \IPS\Helpers\Wizard( $steps, $url, TRUE, $initialData );
\IPS\Output::i()->output = (string) new \IPS\Helpers\Wizard( $steps, $url, TRUE, $initialData );
}
/**
@@ -891,7 +946,7 @@ class _requests extends \IPS\Dispatcher\Controller
$yesterday = $yesterday->sub( new \DateInterval('P1D') );
/* What page are we on? */
$page = isset( \IPS\Request::i()->page ) ? intval( \IPS\Request::i()->page ) : 1;
$page = isset( \IPS\Request::i()->page ) ? \intval( \IPS\Request::i()->page ) : 1;
$perPage = 25;
/* Get our replies */
@@ -906,7 +961,7 @@ class _requests extends \IPS\Dispatcher\Controller
array( ( $page - 1 ) * $perPage, $perPage ),
NULL,
NULL,
\IPS\Db::SELECT_SQL_CALC_FOUND_ROWS + \IPS\Db::SELECT_MULTIDIMENSIONAL_JOINS
\IPS\Db::SELECT_MULTIDIMENSIONAL_JOINS
)
->join( 'nexus_support_requests', 'r_id=reply_request' )
->join( 'nexus_support_departments', 'dpt_id=r_department' )
@@ -915,7 +970,11 @@ class _requests extends \IPS\Dispatcher\Controller
);
/* Work out pagination */
$count = $replies->count( TRUE );
$count = \IPS\Db::i()->select( 'COUNT(*)', 'nexus_support_replies', $replyWhere )
->join( 'nexus_support_requests', 'r_id=reply_request' )
->join( 'nexus_support_departments', 'dpt_id=r_department' )
->join( 'nexus_support_ratings', 'reply_id=rating_reply' )
->first();
$numberOfPages = ceil( $count / $perPage );
$pagination = \IPS\Theme::i()->getTemplate( 'global', 'core', 'global' )->pagination( \IPS\Http\Url::internal( 'app=nexus&module=support&controller=requests&do=history&date=' . $date->getTimestamp() ), $numberOfPages, $page, $perPage );
@@ -12,7 +12,7 @@
namespace IPS\nexus\modules\admin\support;
/* To prevent PHP errors (extending class does not exist) revealing path */
if ( !defined( '\IPS\SUITE_UNIQUE_KEY' ) )
if ( !\defined( '\IPS\SUITE_UNIQUE_KEY' ) )
{
header( ( isset( $_SERVER['SERVER_PROTOCOL'] ) ? $_SERVER['SERVER_PROTOCOL'] : 'HTTP/1.0' ) . ' 403 Forbidden' );
exit;
@@ -23,9 +23,16 @@ if ( !defined( '\IPS\SUITE_UNIQUE_KEY' ) )
*/
class _settings extends \IPS\Dispatcher\Controller
{
/**
* @brief Has been CSRF-protected
*/
public static $csrfProtected = TRUE;
/**
* Call
*
* @param string $method Method called
* @param array $args Arguments
* @return void
*/
public function __call( $method, $args )
@@ -12,7 +12,7 @@
namespace IPS\nexus\modules\admin\support;
/* To prevent PHP errors (extending class does not exist) revealing path */
if ( !defined( '\IPS\SUITE_UNIQUE_KEY' ) )
if ( !\defined( '\IPS\SUITE_UNIQUE_KEY' ) )
{
header( ( isset( $_SERVER['SERVER_PROTOCOL'] ) ? $_SERVER['SERVER_PROTOCOL'] : 'HTTP/1.0' ) . ' 403 Forbidden' );
exit;
@@ -23,6 +23,11 @@ if ( !defined( '\IPS\SUITE_UNIQUE_KEY' ) )
*/
class _severities extends \IPS\Node\Controller
{
/**
* @brief Has been CSRF-protected
*/
public static $csrfProtected = TRUE;
/**
* Node Class
*/
@@ -50,6 +55,7 @@ class _severities extends \IPS\Node\Controller
if ( isset( \IPS\Request::i()->nexus_severities ) )
{
\IPS\Session::i()->csrfCheck();
\IPS\Settings::i()->changeValues( array( 'nexus_severities' => \IPS\Request::i()->nexus_severities ) );
\IPS\Session::i()->log( 'acplogs__severity_settings' );
\IPS\Output::i()->redirect( \IPS\Http\Url::internal('app=nexus&module=support&controller=settings&tab=severities') );
@@ -12,7 +12,7 @@
namespace IPS\nexus\modules\admin\support;
/* To prevent PHP errors (extending class does not exist) revealing path */
if ( !defined( '\IPS\SUITE_UNIQUE_KEY' ) )
if ( !\defined( '\IPS\SUITE_UNIQUE_KEY' ) )
{
header( ( isset( $_SERVER['SERVER_PROTOCOL'] ) ? $_SERVER['SERVER_PROTOCOL'] : 'HTTP/1.0' ) . ' 403 Forbidden' );
exit;
@@ -12,7 +12,7 @@
namespace IPS\nexus\modules\admin\support;
/* To prevent PHP errors (extending class does not exist) revealing path */
if ( !defined( '\IPS\SUITE_UNIQUE_KEY' ) )
if ( !\defined( '\IPS\SUITE_UNIQUE_KEY' ) )
{
header( ( isset( $_SERVER['SERVER_PROTOCOL'] ) ? $_SERVER['SERVER_PROTOCOL'] : 'HTTP/1.0' ) . ' 403 Forbidden' );
exit;
@@ -12,7 +12,7 @@
namespace IPS\nexus\modules\admin\support;
/* To prevent PHP errors (extending class does not exist) revealing path */
if ( !defined( '\IPS\SUITE_UNIQUE_KEY' ) )
if ( !\defined( '\IPS\SUITE_UNIQUE_KEY' ) )
{
header( ( isset( $_SERVER['SERVER_PROTOCOL'] ) ? $_SERVER['SERVER_PROTOCOL'] : 'HTTP/1.0' ) . ' 403 Forbidden' );
exit;
@@ -23,6 +23,11 @@ if ( !defined( '\IPS\SUITE_UNIQUE_KEY' ) )
*/
class _volume extends \IPS\Dispatcher\Controller
{
/**
* @brief Has been CSRF-protected
*/
public static $csrfProtected = TRUE;
/**
* Execute
*
@@ -48,7 +53,7 @@ class _volume extends \IPS\Dispatcher\Controller
'colors' => array( '#10967e', '#ea7963', '#de6470', '#6b9dde', '#b09be4', '#eec766', '#9fc973', '#e291bf', '#55c1a6', '#5fb9da' ),
'hAxis' => array( 'gridlines' => array( 'color' => '#f5f5f5' ) ),
'lineWidth' => 1,
'areaOpacity' => 0.4,
'areaOpacity' => 0.4
),
'AreaChart'
);