Version 5.0.0 beta 1
This commit is contained in:
1 parent
25ddeb65d6
commit
15c7beabc5
6736 files changed
+627902
-497943
No files matched your search
@@ -12,89 +12,168 @@
|
||||
namespace IPS\nexus\Package;
|
||||
|
||||
/* To prevent PHP errors (extending class does not exist) revealing path */
|
||||
if ( !\defined( '\IPS\SUITE_UNIQUE_KEY' ) )
|
||||
|
||||
use IPS\Application;
|
||||
use IPS\core\AdminNotification;
|
||||
use IPS\core\Advertisement;
|
||||
use IPS\Db;
|
||||
use IPS\Extensions\AdvertisementLocationsAbstract;
|
||||
use IPS\Helpers\Form;
|
||||
use IPS\Helpers\Form\CheckboxSet;
|
||||
use IPS\Helpers\Form\Custom;
|
||||
use IPS\Helpers\Form\Node;
|
||||
use IPS\Helpers\Form\Number;
|
||||
use IPS\Helpers\Form\Upload;
|
||||
use IPS\Helpers\Form\WidthHeight;
|
||||
use IPS\Helpers\Form\YesNo;
|
||||
use IPS\Http\Url;
|
||||
use IPS\Member;
|
||||
use IPS\Member\Group;
|
||||
use IPS\nexus\Invoice;
|
||||
use IPS\nexus\Package;
|
||||
use IPS\nexus\Purchase;
|
||||
use IPS\nexus\Purchase\RenewalTerm;
|
||||
use IPS\Request;
|
||||
use IPS\Theme;
|
||||
use OutOfRangeException;
|
||||
use UnderflowException;
|
||||
use function defined;
|
||||
use function intval;
|
||||
use function is_array;
|
||||
|
||||
if ( !defined( '\IPS\SUITE_UNIQUE_KEY' ) )
|
||||
{
|
||||
header( ( isset( $_SERVER['SERVER_PROTOCOL'] ) ? $_SERVER['SERVER_PROTOCOL'] : 'HTTP/1.0' ) . ' 403 Forbidden' );
|
||||
header( ( $_SERVER['SERVER_PROTOCOL'] ?? 'HTTP/1.0' ) . ' 403 Forbidden' );
|
||||
exit;
|
||||
}
|
||||
|
||||
/**
|
||||
* Advertisement Package
|
||||
*/
|
||||
class _Ad extends \IPS\nexus\Package
|
||||
class Ad extends Package
|
||||
{
|
||||
/**
|
||||
* @brief Database Table
|
||||
*/
|
||||
protected static $packageDatabaseTable = 'nexus_packages_ads';
|
||||
protected static string $packageDatabaseTable = 'nexus_packages_ads';
|
||||
|
||||
/**
|
||||
* @brief Which columns belong to the local table
|
||||
*/
|
||||
protected static $packageDatabaseColumns = array( 'p_locations', 'p_exempt', 'p_expire', 'p_expire_unit', 'p_max_height', 'p_max_width' );
|
||||
protected static array $packageDatabaseColumns = array( 'p_locations', 'p_exempt', 'p_expire', 'p_expire_unit', 'p_max_height', 'p_max_width', 'p_settings' );
|
||||
|
||||
/**
|
||||
* @brief Icon
|
||||
*/
|
||||
public static $icon = 'newspaper-o';
|
||||
public static string $icon = 'newspaper';
|
||||
|
||||
/**
|
||||
* @brief Title
|
||||
*/
|
||||
public static $title = 'advertisement';
|
||||
public static string $title = 'advertisement';
|
||||
|
||||
/* !ACP Package Form */
|
||||
|
||||
/**
|
||||
* ACP Fields
|
||||
*
|
||||
* @param \IPS\nexus\Package $package The package
|
||||
* @param bool $custom If TRUE, is for a custom package
|
||||
* @param bool $customEdit If TRUE, is editing a custom package
|
||||
* @return array
|
||||
* @param Package $package The package
|
||||
* @param bool $custom If TRUE, is for a custom package
|
||||
* @param bool $customEdit If TRUE, is editing a custom package
|
||||
* @return array
|
||||
*/
|
||||
public static function acpFormFields( \IPS\nexus\Package $package, $custom=FALSE, $customEdit=FALSE )
|
||||
public static function acpFormFields( Package $package, bool $custom=FALSE, bool $customEdit=FALSE ): array
|
||||
{
|
||||
$return = array();
|
||||
|
||||
if ( !$customEdit ) // If we're editing a custom package, they can get to this by editing the advertisement
|
||||
{
|
||||
$locations = array(
|
||||
'ad_global_header' => array(),
|
||||
'ad_global_footer' => array(),
|
||||
'ad_sidebar' => array(),
|
||||
$currentValues = ( $package->id AND $package->settings ) ? json_decode( $package->settings, true ) : array();
|
||||
|
||||
/* Add the location fields, remember to call extensions for additional locations.
|
||||
Array format: location => array of toggle fields to show */
|
||||
$defaultLocations = array(
|
||||
'ad_global_header' => array( 'ad_apps' ),
|
||||
'ad_global_footer' => array( 'ad_apps' ),
|
||||
'ad_sidebar' => array( 'ad_apps' ),
|
||||
);
|
||||
foreach ( \IPS\Application::allExtensions( 'core', 'AdvertisementLocations', FALSE, 'core' ) as $key => $extension )
|
||||
|
||||
$settingFields = [];
|
||||
|
||||
/* Add a field to restrict by app */
|
||||
$settingFields[] = new Node( 'ad_apps', $currentValues['ad_apps'] ?? 0, false, array(
|
||||
'class' => Application::class,
|
||||
'multiple' => true,
|
||||
'zeroVal' => 'all',
|
||||
'subnodes' => false
|
||||
), null, null, null, 'ad_apps' );
|
||||
|
||||
/* Now grab ad location extensions */
|
||||
foreach ( Application::allExtensions( 'core', 'AdvertisementLocations', FALSE, 'core' ) as $key => $extension )
|
||||
{
|
||||
$result = $extension->getSettings( array() );
|
||||
$locations = array_merge( $locations, $result['locations'] );
|
||||
/* @var AdvertisementLocationsAbstract $extension */
|
||||
$result = $extension->getSettings( $currentValues );
|
||||
|
||||
$defaultLocations = array_merge( $defaultLocations, $result['locations'] );
|
||||
|
||||
/* If this is a list view, add setting fields for interaval and repeat */
|
||||
if( $extension::$listView )
|
||||
{
|
||||
$settingFields[] = new Number( 'ad_view_number', ( isset( $currentValues['ad_view_number'] ) AND $currentValues['ad_view_number'] ) ? $currentValues['ad_view_number'] : 1, FALSE, array( 'min' => 1 ), NULL, NULL, Member::loggedIn()->language()->addToStack('ad_view_number_suffix'), 'ad_view_number' );
|
||||
|
||||
$settingFields[] = new Number( 'ad_view_repeat', $currentValues['ad_view_repeat'] ?? 1, FALSE, array( 'unlimited' => -1 ), NULL, NULL, Member::loggedIn()->language()->addToStack('ad_view_repeat_suffix'), 'ad_view_repeat' );
|
||||
|
||||
foreach( $result['locations'] as $location => $toggles )
|
||||
{
|
||||
$defaultLocations[$location][] = 'ad_view_number';
|
||||
$defaultLocations[$location][] = 'ad_view_repeat';
|
||||
}
|
||||
}
|
||||
|
||||
if( isset( $result['settings'] ) )
|
||||
{
|
||||
$settingFields = $settingFields + $result['settings'];
|
||||
}
|
||||
}
|
||||
$locations['_ad_custom_'] = array('p_locations_custom');
|
||||
$locationValues = array();
|
||||
$customLocations = array();
|
||||
|
||||
/* Add the locations to the form, and make sure the toggles get set properly */
|
||||
$locations = array();
|
||||
if ( $package->id )
|
||||
{
|
||||
$locationValues = explode( ',', $package->locations );
|
||||
$customLocations = array_diff( $locationValues, array_keys( $locations ) );
|
||||
if ( !empty( $customLocations ) )
|
||||
{
|
||||
$locationValues[] = '_ad_custom_';
|
||||
}
|
||||
$locationValues = array_intersect( $locationValues, array_keys( $locations ) );
|
||||
$locations = $package->locations ? explode( ',', $package->locations ) : [];
|
||||
$locations = array_intersect( $locations, array_keys( $defaultLocations ) );
|
||||
}
|
||||
$return['package_settings']['p_locations'] = new \IPS\Helpers\Form\CheckboxSet( 'p_locations', $locationValues, TRUE, array( 'options' => array_combine( array_keys( $locations ), array_keys( $locations ) ), 'toggles' => $locations, 'userSuppliedInput' => '_ad_custom_' ) );
|
||||
$return['package_settings']['p_locations_custom'] = new \IPS\Helpers\Form\Stack( 'p_locations_custom', $customLocations, FALSE, array(), NULL, NULL, NULL, 'p_locations_custom' );
|
||||
|
||||
$return['package_settings']['p_exempt'] = new \IPS\Helpers\Form\CheckboxSet( 'p_exempt', $package->id ? ( $package->exempt == '*' ? '*' : explode( ',', $package->exempt ) ) : '*', FALSE, array( 'options' => \IPS\Member\Group::groups(), 'parse' => 'normal', 'multiple' => TRUE, 'unlimited' => '*', 'unlimitedLang' => 'everyone', 'impliedUnlimited' => TRUE ) );
|
||||
|
||||
/* Make locations optional so that we can have ads for widgets only */
|
||||
$return['package_settings']['p_locations'] = new CheckboxSet( 'p_locations',
|
||||
$locations,
|
||||
false,
|
||||
array(
|
||||
'options' => array_combine( array_keys( $defaultLocations ), array_keys( $defaultLocations ) ),
|
||||
'toggles' => $defaultLocations,
|
||||
'noDefault' => true
|
||||
),
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
'p_locations'
|
||||
);
|
||||
|
||||
foreach( $settingFields as $settingField )
|
||||
{
|
||||
$return['package_settings'][ $settingField->name ] = $settingField;
|
||||
}
|
||||
|
||||
$return['package_settings']['p_exempt'] = new CheckboxSet( 'p_exempt', ( $package->id and $package->exempt ) ? ( $package->exempt == '*' ? '*' : explode( ',', $package->exempt ) ) : '*', FALSE, array( 'options' => Group::groups(), 'parse' => 'normal', 'multiple' => TRUE, 'unlimited' => '*', 'unlimitedLang' => 'everyone', 'impliedUnlimited' => TRUE ) );
|
||||
|
||||
$return['package_settings']['p_expire'] = new \IPS\Helpers\Form\Custom( 'p_expire', array( 'value' => ( $package->id ) ? $package->expire : -1, 'type' => ( $package->id ) ? $package->expire_unit : 'i' ), FALSE, array(
|
||||
$return['package_settings']['p_expire'] = new Custom( 'p_expire', array( 'value' => ( $package->id and $package->expire ) ? $package->expire : -1, 'type' => ( $package->id ) ? $package->expire_unit : 'i' ), FALSE, array(
|
||||
'getHtml' => function( $element )
|
||||
{
|
||||
return \IPS\Theme::i()->getTemplate( 'promotion', 'core' )->imageMaximums( $element->name, $element->value['value'], $element->value['type'] );
|
||||
return Theme::i()->getTemplate( 'promotion', 'core' )->imageMaximums( $element->name, $element->value['value'], $element->value['type'] );
|
||||
},
|
||||
'formatValue' => function( $element )
|
||||
{
|
||||
if( !\is_array( $element->value ) AND $element->value == -1 )
|
||||
if( !is_array( $element->value ) AND $element->value == -1 )
|
||||
{
|
||||
return array( 'value' => -1, 'type' => 'i' );
|
||||
}
|
||||
@@ -105,7 +184,7 @@ class _Ad extends \IPS\nexus\Package
|
||||
|
||||
if ( !$custom )
|
||||
{
|
||||
$return['package_settings']['p_max_dims'] = new \IPS\Helpers\Form\WidthHeight( 'p_max_dims', array( $package->max_width, $package->max_height ), FALSE, array( 'unlimited' => array( 0, 0 ), 'resizableDiv' => FALSE ) );
|
||||
$return['package_settings']['p_max_dims'] = new WidthHeight( 'p_max_dims', ( $package->id and $package->width ) ? array( $package->max_width, $package->max_height ) : null, FALSE, array( 'unlimited' => array( 0, 0 ), 'resizableDiv' => FALSE ) );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -118,16 +197,16 @@ class _Ad extends \IPS\nexus\Package
|
||||
* @param array $values Values from the form
|
||||
* @return array
|
||||
*/
|
||||
public function formatFormValues( $values )
|
||||
public function formatFormValues( array $values ): array
|
||||
{
|
||||
if( isset( $values['p_exempt'] ) )
|
||||
{
|
||||
$values['p_exempt'] = \is_array( $values['p_exempt'] ) ? implode( ',', $values['p_exempt'] ) : $values['p_exempt'];
|
||||
$values['p_exempt'] = is_array( $values['p_exempt'] ) ? implode( ',', $values['p_exempt'] ) : $values['p_exempt'];
|
||||
}
|
||||
|
||||
if ( isset( $values['p_expire'] ) and \is_array( $values['p_expire'] ) )
|
||||
if ( isset( $values['p_expire'] ) and is_array( $values['p_expire'] ) )
|
||||
{
|
||||
$values['expire'] = \intval( $values['p_expire']['value'] );
|
||||
$values['expire'] = intval( $values['p_expire']['value'] );
|
||||
$values['expire_unit'] = $values['p_expire']['type'];
|
||||
unset( $values['p_expire'] );
|
||||
}
|
||||
@@ -141,16 +220,49 @@ class _Ad extends \IPS\nexus\Package
|
||||
|
||||
if ( isset( $values['p_locations'] ) )
|
||||
{
|
||||
$locations = $values['p_locations'];
|
||||
$customKey = array_search( '_ad_custom_', $locations );
|
||||
if ( $customKey !== FALSE )
|
||||
$values['p_locations'] = is_array( $values['p_locations'] ) ? implode( ',', $values['p_locations'] ) : '';
|
||||
}
|
||||
|
||||
$additionalSettings = array(
|
||||
'ad_apps' => ( isset( $values['ad_apps'] ) AND $values['ad_apps'] != 0 ) ? array_keys( $values['ad_apps'] ) : 0
|
||||
);
|
||||
|
||||
foreach ( Application::allExtensions( 'core', 'AdvertisementLocations', FALSE, 'core' ) as $key => $extension )
|
||||
{
|
||||
/* @var AdvertisementLocationsAbstract $extension */
|
||||
if( $extension::$listView )
|
||||
{
|
||||
unset( $locations[ $customKey ] );
|
||||
$locations = array_merge( $locations, $values['p_locations_custom'] );
|
||||
$additionalSettings['ad_view_number'] = $values['ad_view_number'] ?? 1;
|
||||
$additionalSettings['ad_view_repeat'] = $values['ad_view_repeat'] ?? 0;
|
||||
}
|
||||
$values['p_locations'] = implode( ',', $locations );
|
||||
|
||||
$settings = $extension->parseSettings( $values );
|
||||
|
||||
$additionalSettings = array_merge( $additionalSettings, $settings );
|
||||
|
||||
/* Unset any elements that were added */
|
||||
$result = $extension->getSettings( $values );
|
||||
if( isset( $result['settings'] ) )
|
||||
{
|
||||
foreach( $result['settings'] as $settingField )
|
||||
{
|
||||
if( isset( $values[ $settingField->name ] ) )
|
||||
{
|
||||
unset( $values[ $settingField->name ] );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$values['p_settings'] = json_encode( $additionalSettings );
|
||||
|
||||
foreach( array( 'ad_apps', 'ad_view_number', 'ad_view_repeat' ) as $field )
|
||||
{
|
||||
if( isset( $values[ $field ] ) )
|
||||
{
|
||||
unset( $values[ $field ] );
|
||||
}
|
||||
}
|
||||
unset( $values['p_locations_custom'] );
|
||||
|
||||
return parent::formatFormValues( $values );
|
||||
}
|
||||
@@ -160,7 +272,7 @@ class _Ad extends \IPS\nexus\Package
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public static function updateableFields()
|
||||
public static function updateableFields() : array
|
||||
{
|
||||
return array_merge( parent::updateableFields(), array(
|
||||
'locations',
|
||||
@@ -173,22 +285,23 @@ class _Ad extends \IPS\nexus\Package
|
||||
/**
|
||||
* Update existing purchases
|
||||
*
|
||||
* @param \IPS\nexus\Purchase $purchase The purchase
|
||||
* @param array $changes The old values
|
||||
* @param bool $cancelBillingAgreementIfNecessary If making changes to renewal terms, TRUE will cancel associated billing agreements. FALSE will skip that change
|
||||
* @return void
|
||||
* @param Purchase $purchase The purchase
|
||||
* @param array $changes The old values
|
||||
* @param bool $cancelBillingAgreementIfNecessary If making changes to renewal terms, TRUE will cancel associated billing agreements. FALSE will skip that change
|
||||
* @return void
|
||||
*/
|
||||
public function updatePurchase( \IPS\nexus\Purchase $purchase, $changes, $cancelBillingAgreementIfNecessary=FALSE )
|
||||
public function updatePurchase(Purchase $purchase, array $changes, bool $cancelBillingAgreementIfNecessary=FALSE ): void
|
||||
{
|
||||
if ( $purchase->extra['ad'] )
|
||||
{
|
||||
try
|
||||
{
|
||||
$ad = \IPS\Db::i()->select( '*','core_advertisements', array( 'ad_id=?', $purchase->extra['ad'] ) )->first();
|
||||
$ad = Db::i()->select( '*','core_advertisements', array( 'ad_id=?', $purchase->extra['ad'] ) )->first();
|
||||
}
|
||||
catch ( \UnderflowException $e )
|
||||
catch ( UnderflowException )
|
||||
{
|
||||
return parent::updatePurchase( $purchase, $changes, $cancelBillingAgreementIfNecessary );
|
||||
parent::updatePurchase( $purchase, $changes, $cancelBillingAgreementIfNecessary );
|
||||
return;
|
||||
}
|
||||
|
||||
$update = array();
|
||||
@@ -212,7 +325,7 @@ class _Ad extends \IPS\nexus\Package
|
||||
break;
|
||||
}
|
||||
|
||||
if ( $ad[ $i ] == $changes[ $k ] )
|
||||
if ( isset( $i ) AND $ad[ $i ] == $changes[ $k ] )
|
||||
{
|
||||
$update[ $i ] = $this->$k;
|
||||
}
|
||||
@@ -220,11 +333,11 @@ class _Ad extends \IPS\nexus\Package
|
||||
}
|
||||
if ( !empty( $update ) )
|
||||
{
|
||||
\IPS\Db::i()->update( 'core_advertisements', $update, array( 'ad_id=?', $purchase->extra['ad'] ) );
|
||||
Db::i()->update( 'core_advertisements', $update, array( 'ad_id=?', $purchase->extra['ad'] ) );
|
||||
}
|
||||
}
|
||||
|
||||
return parent::updatePurchase( $purchase, $changes, $cancelBillingAgreementIfNecessary );
|
||||
parent::updatePurchase( $purchase, $changes, $cancelBillingAgreementIfNecessary );
|
||||
}
|
||||
|
||||
/* !Store */
|
||||
@@ -232,13 +345,13 @@ class _Ad extends \IPS\nexus\Package
|
||||
/**
|
||||
* Store Form
|
||||
*
|
||||
* @param \IPS\Helpers\Form $form The form
|
||||
* @param string $memberCurrency The currency being used
|
||||
* @return void
|
||||
* @param Form $form The form
|
||||
* @param string $memberCurrency The currency being used
|
||||
* @return void
|
||||
*/
|
||||
public function storeForm( \IPS\Helpers\Form $form, $memberCurrency )
|
||||
public function storeForm(Form $form, string $memberCurrency ): void
|
||||
{
|
||||
$form->add( new \IPS\Helpers\Form\Url( 'advertisement_url', NULL, TRUE ) );
|
||||
$form->add( new Form\Url( 'advertisement_url', NULL, TRUE ) );
|
||||
|
||||
$maxDims = TRUE;
|
||||
if ( $this->max_height or $this->max_width )
|
||||
@@ -254,41 +367,42 @@ class _Ad extends \IPS\nexus\Package
|
||||
}
|
||||
}
|
||||
|
||||
if ( !isset( \IPS\Request::i()->stockCheck ) ) // The stock check will attempt to save the upload which we don't want to do until the form is actually submitted
|
||||
if ( !isset( Request::i()->stockCheck ) ) // The stock check will attempt to save the upload which we don't want to do until the form is actually submitted
|
||||
{
|
||||
$form->add( new \IPS\Helpers\Form\Upload( 'advertisement_image', NULL, TRUE, array( 'storageExtension' => 'nexus_Ads', 'image' => $maxDims ) ) );
|
||||
$form->add( new Upload( 'advertisement_image', NULL, TRUE, array( 'storageExtension' => 'nexus_Ads', 'image' => $maxDims ) ) );
|
||||
}
|
||||
|
||||
if ( $this->max_height and $this->max_width )
|
||||
{
|
||||
\IPS\Member::loggedIn()->language()->words['advertisement_image_desc'] = \IPS\Member::loggedIn()->language()->addToStack( 'advertisement_image_max_wh', FALSE, array( 'sprintf' => array( $this->max_width, $this->max_height ) ) );
|
||||
Member::loggedIn()->language()->words['advertisement_image_desc'] = Member::loggedIn()->language()->addToStack( 'advertisement_image_max_wh', FALSE, array( 'sprintf' => array( $this->max_width, $this->max_height ) ) );
|
||||
}
|
||||
elseif ( $this->max_height )
|
||||
{
|
||||
\IPS\Member::loggedIn()->language()->words['advertisement_image_desc'] = \IPS\Member::loggedIn()->language()->addToStack( 'advertisement_image_max_h', FALSE, array( 'sprintf' => array( $this->max_height ) ) );
|
||||
Member::loggedIn()->language()->words['advertisement_image_desc'] = Member::loggedIn()->language()->addToStack( 'advertisement_image_max_h', FALSE, array( 'sprintf' => array( $this->max_height ) ) );
|
||||
}
|
||||
elseif ( $this->max_width )
|
||||
{
|
||||
\IPS\Member::loggedIn()->language()->words['advertisement_image_desc'] = \IPS\Member::loggedIn()->language()->addToStack( 'advertisement_image_max_w', FALSE, array( 'sprintf' => array( $this->max_width ) ) );
|
||||
Member::loggedIn()->language()->words['advertisement_image_desc'] = Member::loggedIn()->language()->addToStack( 'advertisement_image_max_w', FALSE, array( 'sprintf' => array( $this->max_width ) ) );
|
||||
}
|
||||
|
||||
$form->add( new \IPS\Helpers\Form\YesNo( 'ad_image_more', FALSE, FALSE, array( 'togglesOn' => array( 'ad_image_small', 'ad_image_medium' ) ), NULL, NULL, NULL, 'ad_image_more' ) );
|
||||
$form->add( new \IPS\Helpers\Form\Upload( 'ad_image_small', NULL, FALSE, array( 'image' => TRUE, 'storageExtension' => 'nexus_Ads' ), NULL, NULL, NULL, 'ad_image_small' ) );
|
||||
$form->add( new \IPS\Helpers\Form\Upload( 'ad_image_medium', NULL, FALSE, array( 'image' => TRUE, 'storageExtension' => 'nexus_Ads' ), NULL, NULL, NULL, 'ad_image_medium' ) );
|
||||
$form->add( new YesNo( 'ad_image_more', FALSE, FALSE, array( 'togglesOn' => array( 'ad_image_small', 'ad_image_medium' ) ), NULL, NULL, NULL, 'ad_image_more' ) );
|
||||
$form->add( new Upload( 'ad_image_small', NULL, FALSE, array( 'image' => TRUE, 'storageExtension' => 'nexus_Ads' ), NULL, NULL, NULL, 'ad_image_small' ) );
|
||||
$form->add( new Upload( 'ad_image_medium', NULL, FALSE, array( 'image' => TRUE, 'storageExtension' => 'nexus_Ads' ), NULL, NULL, NULL, 'ad_image_medium' ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Add To Cart
|
||||
*
|
||||
* @param \IPS\nexus\extensions\nexus\Item\Package $item The item
|
||||
* @param \IPS\nexus\Invoice\Item $item The item
|
||||
* @param array $values Values from form
|
||||
* @param string $memberCurrency The currency being used
|
||||
* @return array Additional items to add
|
||||
* @param string $memberCurrency The currency being used
|
||||
* @return array Additional items to add
|
||||
*/
|
||||
public function addToCart( \IPS\nexus\extensions\nexus\Item\Package $item, array $values, $memberCurrency )
|
||||
public function addToCart(\IPS\nexus\Invoice\Item $item, array $values, string $memberCurrency ): array
|
||||
{
|
||||
$item->extra['image'] = json_encode( array( 'large' => (string) $values['advertisement_image'], 'medium' => (string) $values['ad_image_medium'], 'small' => (string) $values['ad_image_small'] ) );
|
||||
$item->extra['link'] = (string) $values['advertisement_url'];
|
||||
return parent::addToCart( $item, $values, $memberCurrency );
|
||||
}
|
||||
|
||||
/* !Client Area */
|
||||
@@ -298,7 +412,7 @@ class _Ad extends \IPS\nexus\Package
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function showPurchaseRecord()
|
||||
public function showPurchaseRecord(): bool
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
@@ -306,23 +420,23 @@ class _Ad extends \IPS\nexus\Package
|
||||
/**
|
||||
* Get Client Area Page HTML
|
||||
*
|
||||
* @param \IPS\nexus\Purchase $purchase The purchase
|
||||
* @param Purchase $purchase The purchase
|
||||
* @return array( 'packageInfo' => '...', 'purchaseInfo' => '...' )
|
||||
*/
|
||||
public function clientAreaPage( \IPS\nexus\Purchase $purchase )
|
||||
public function clientAreaPage( Purchase $purchase ) : array
|
||||
{
|
||||
$parent = parent::clientAreaPage( $purchase );
|
||||
|
||||
try
|
||||
{
|
||||
$advertisement = \IPS\core\Advertisement::load( $purchase->extra['ad'] );
|
||||
$advertisement = Advertisement::load( $purchase->extra['ad'] );
|
||||
|
||||
return array(
|
||||
'packageInfo' => $parent['packageInfo'],
|
||||
'purchaseInfo' => $parent['purchaseInfo'] . \IPS\Theme::i()->getTemplate('purchases')->advertisement( $purchase, $advertisement ),
|
||||
'purchaseInfo' => $parent['purchaseInfo'] . Theme::i()->getTemplate('purchases')->advertisement( $purchase, $advertisement ),
|
||||
);
|
||||
}
|
||||
catch ( \OutOfRangeException $e )
|
||||
catch ( OutOfRangeException )
|
||||
{
|
||||
return $parent;
|
||||
}
|
||||
@@ -333,44 +447,44 @@ class _Ad extends \IPS\nexus\Package
|
||||
/**
|
||||
* ACP Generate Invoice Form
|
||||
*
|
||||
* @param \IPS\Helpers\Form $form The form
|
||||
* @param string $k The key to add to the field names
|
||||
* @return void
|
||||
* @param Form $form The form
|
||||
* @param string $k The key to add to the field names
|
||||
* @return void
|
||||
*/
|
||||
public function generateInvoiceForm( \IPS\Helpers\Form $form, $k )
|
||||
public function generateInvoiceForm(Form $form, string $k ): void
|
||||
{
|
||||
$form->attributes['data-bypassValidation'] = true;
|
||||
$field = new \IPS\Helpers\Form\Url( 'advertisement_url' . $k, NULL, TRUE );
|
||||
$field->label = \IPS\Member::loggedIn()->language()->addToStack('advertisement_url');
|
||||
$field = new Form\Url( 'advertisement_url' . $k, NULL, TRUE );
|
||||
$field->label = Member::loggedIn()->language()->addToStack('advertisement_url');
|
||||
$form->add( $field );
|
||||
|
||||
$field = new \IPS\Helpers\Form\Upload( 'ad_image' . $k, NULL, TRUE, array( 'image' => TRUE, 'storageExtension' => 'nexus_Ads' ) );
|
||||
$field->label = \IPS\Member::loggedIn()->language()->addToStack('ad_image');
|
||||
$field = new Upload( 'ad_image' . $k, NULL, TRUE, array( 'image' => TRUE, 'storageExtension' => 'nexus_Ads' ) );
|
||||
$field->label = Member::loggedIn()->language()->addToStack('ad_image');
|
||||
$form->add( $field );
|
||||
|
||||
$field = new \IPS\Helpers\Form\YesNo( 'ad_image_more' . $k, FALSE, FALSE, array( 'togglesOn' => array( 'ad_image_small' . $k, 'ad_image_medium' . $k ) ) );
|
||||
$field->label = \IPS\Member::loggedIn()->language()->addToStack('ad_image_more');
|
||||
$field = new YesNo( 'ad_image_more' . $k, FALSE, FALSE, array( 'togglesOn' => array( 'ad_image_small' . $k, 'ad_image_medium' . $k ) ) );
|
||||
$field->label = Member::loggedIn()->language()->addToStack('ad_image_more');
|
||||
$form->add( $field );
|
||||
|
||||
$field = new \IPS\Helpers\Form\Upload( 'ad_image_small' . $k, NULL, FALSE, array( 'image' => TRUE, 'storageExtension' => 'nexus_Ads' ), NULL, NULL, NULL, 'ad_image_small' . $k );
|
||||
$field->label = \IPS\Member::loggedIn()->language()->addToStack('ad_image_small');
|
||||
$field = new Upload( 'ad_image_small' . $k, NULL, FALSE, array( 'image' => TRUE, 'storageExtension' => 'nexus_Ads' ), NULL, NULL, NULL, 'ad_image_small' . $k );
|
||||
$field->label = Member::loggedIn()->language()->addToStack('ad_image_small');
|
||||
$form->add( $field );
|
||||
|
||||
$field = new \IPS\Helpers\Form\Upload( 'ad_image_medium' . $k, NULL, FALSE, array( 'image' => TRUE, 'storageExtension' => 'nexus_Ads' ), NULL, NULL, NULL, 'ad_image_medium' . $k );
|
||||
$field->label = \IPS\Member::loggedIn()->language()->addToStack('ad_image_medium');
|
||||
$field = new Upload( 'ad_image_medium' . $k, NULL, FALSE, array( 'image' => TRUE, 'storageExtension' => 'nexus_Ads' ), NULL, NULL, NULL, 'ad_image_medium' . $k );
|
||||
$field->label = Member::loggedIn()->language()->addToStack('ad_image_medium');
|
||||
$form->add( $field );
|
||||
}
|
||||
|
||||
/**
|
||||
* ACP Add to invoice
|
||||
*
|
||||
* @param \IPS\nexus\extensions\nexus\Item\Package $item The item
|
||||
* @param \IPS\nexus\Invoice\Item $item The item
|
||||
* @param array $values Values from form
|
||||
* @param string $k The key to add to the field names
|
||||
* @param \IPS\nexus\Invoice $invoice The invoice
|
||||
* @return void
|
||||
* @param string $k The key to add to the field names
|
||||
* @param Invoice $invoice The invoice
|
||||
* @return void
|
||||
*/
|
||||
public function acpAddToInvoice( \IPS\nexus\extensions\nexus\Item\Package $item, array $values, $k, \IPS\nexus\Invoice $invoice )
|
||||
public function acpAddToInvoice(\IPS\nexus\Invoice\Item $item, array $values, string $k, Invoice $invoice ): void
|
||||
{
|
||||
$item->extra['image'] = json_encode( array( 'large' => (string) $values[ 'ad_image' . $k ], 'medium' => (string) $values[ 'ad_image_medium' . $k ], 'small' => (string) $values[ 'ad_image_small' . $k ] ) );
|
||||
$item->extra['link'] = (string) $values[ 'advertisement_url' . $k ];
|
||||
@@ -379,35 +493,38 @@ class _Ad extends \IPS\nexus\Package
|
||||
/**
|
||||
* Get ACP Page HTML
|
||||
*
|
||||
* @param \IPS\nexus\Purchase $purchase Purchase record
|
||||
* @return string
|
||||
* @param Purchase $purchase Purchase record
|
||||
* @return string
|
||||
*/
|
||||
public function acpPage( \IPS\nexus\Purchase $purchase )
|
||||
public function acpPage( Purchase $purchase ): string
|
||||
{
|
||||
try
|
||||
{
|
||||
return \IPS\Theme::i()->getTemplate( 'purchases' )->advertisement( $purchase, \IPS\core\Advertisement::load( $purchase->extra['ad'] ) );
|
||||
return Theme::i()->getTemplate( 'purchases' )->advertisement( $purchase, Advertisement::load( $purchase->extra['ad'] ) );
|
||||
}
|
||||
catch ( OutOfRangeException )
|
||||
{
|
||||
return '';
|
||||
}
|
||||
catch ( \OutOfRangeException $e ) { }
|
||||
}
|
||||
|
||||
/**
|
||||
* Get ACP Page Buttons
|
||||
*
|
||||
* @param \IPS\nexus\Purchase $purchase The purchase
|
||||
* @param \IPS\Http\Url $url The page URL
|
||||
* @return array
|
||||
* @param Purchase $purchase The purchase
|
||||
* @param Url $url The page URL
|
||||
* @return array
|
||||
*/
|
||||
public function acpButtons( \IPS\nexus\Purchase $purchase, $url )
|
||||
public function acpButtons(Purchase $purchase, Url $url ): array
|
||||
{
|
||||
$return = parent::acpButtons( $purchase, $url );
|
||||
|
||||
if ( \IPS\Member::loggedIn()->hasAcpRestriction( 'core', 'promotion', 'advertisements_edit' ) and isset( $purchase->extra['ad'] ) )
|
||||
if ( Member::loggedIn()->hasAcpRestriction( 'core', 'promotion', 'advertisements_edit' ) and isset( $purchase->extra['ad'] ) )
|
||||
{
|
||||
$return['edit_advertisement'] = array(
|
||||
'icon' => 'list-alt',
|
||||
'title' => 'edit_advertisement',
|
||||
'link' => \IPS\Http\Url::internal( 'app=core&module=promotion&controller=advertisements&do=form&id=' . $purchase->extra['ad'] ),
|
||||
'link' => Url::internal( 'app=core&module=promotion&controller=advertisements&do=form&id=' . $purchase->extra['ad'] ),
|
||||
);
|
||||
}
|
||||
|
||||
@@ -419,13 +536,13 @@ class _Ad extends \IPS\nexus\Package
|
||||
/**
|
||||
* On Purchase Generated
|
||||
*
|
||||
* @param \IPS\nexus\Purchase $purchase The purchase
|
||||
* @param \IPS\nexus\Invoice $invoice The invoice
|
||||
* @return void
|
||||
* @param Purchase $purchase The purchase
|
||||
* @param Invoice $invoice The invoice
|
||||
* @return void
|
||||
*/
|
||||
public function onPurchaseGenerated( \IPS\nexus\Purchase $purchase, \IPS\nexus\Invoice $invoice )
|
||||
public function onPurchaseGenerated(Purchase $purchase, Invoice $invoice ): void
|
||||
{
|
||||
$insertId = \IPS\Db::i()->insert( 'core_advertisements', array(
|
||||
$insertId = Db::i()->insert( 'core_advertisements', array(
|
||||
'ad_location' => $this->locations,
|
||||
'ad_html' => NULL,
|
||||
'ad_images' => $purchase->extra['image'],
|
||||
@@ -439,10 +556,10 @@ class _Ad extends \IPS\nexus\Package
|
||||
'ad_end' => $purchase->expire ? $purchase->expire->getTimestamp() : 0,
|
||||
'ad_maximum_value' => $this->expire,
|
||||
'ad_maximum_unit' => $this->expire_unit,
|
||||
'ad_additional_settings'=> json_encode( array() ),
|
||||
'ad_additional_settings'=> $this->settings,
|
||||
'ad_html_https_set' => 0,
|
||||
'ad_member' => $purchase->member->member_id,
|
||||
'ad_type' => \IPS\core\Advertisement::AD_IMAGES,
|
||||
'ad_type' => Advertisement::AD_IMAGES,
|
||||
) );
|
||||
|
||||
$extra = $purchase->extra;
|
||||
@@ -450,7 +567,7 @@ class _Ad extends \IPS\nexus\Package
|
||||
$purchase->extra = $extra;
|
||||
$purchase->save();
|
||||
|
||||
\IPS\core\AdminNotification::send( 'nexus', 'Advertisement', NULL, TRUE, $purchase );
|
||||
AdminNotification::send( 'nexus', 'Advertisement', NULL, TRUE, $purchase );
|
||||
|
||||
parent::onPurchaseGenerated( $purchase, $invoice );
|
||||
}
|
||||
@@ -458,14 +575,14 @@ class _Ad extends \IPS\nexus\Package
|
||||
/**
|
||||
* On Expiration Date Change
|
||||
*
|
||||
* @param \IPS\nexus\Purchase $purchase The purchase
|
||||
* @return void
|
||||
* @param Purchase $purchase The purchase
|
||||
* @return void
|
||||
*/
|
||||
public function onExpirationDateChange( \IPS\nexus\Purchase $purchase )
|
||||
public function onExpirationDateChange( Purchase $purchase ): void
|
||||
{
|
||||
try
|
||||
{
|
||||
$ad = \IPS\core\Advertisement::load( $purchase->extra['ad'] );
|
||||
$ad = Advertisement::load( $purchase->extra['ad'] );
|
||||
$ad->end = $purchase->expire ? $purchase->expire->getTimestamp() : 0;
|
||||
|
||||
if ( ( !$ad->end or $ad->end > time() ) )
|
||||
@@ -507,7 +624,7 @@ class _Ad extends \IPS\nexus\Package
|
||||
|
||||
$ad->save();
|
||||
}
|
||||
catch ( \OutOfRangeException $e ) { }
|
||||
catch ( OutOfRangeException ) { }
|
||||
|
||||
parent::onExpirationDateChange( $purchase );
|
||||
}
|
||||
@@ -515,18 +632,18 @@ class _Ad extends \IPS\nexus\Package
|
||||
/**
|
||||
* On Purchase Expired
|
||||
*
|
||||
* @param \IPS\nexus\Purchase $purchase The purchase
|
||||
* @return void
|
||||
* @param Purchase $purchase The purchase
|
||||
* @return void
|
||||
*/
|
||||
public function onExpire( \IPS\nexus\Purchase $purchase )
|
||||
public function onExpire( Purchase $purchase ): void
|
||||
{
|
||||
try
|
||||
{
|
||||
$ad = \IPS\core\Advertisement::load( $purchase->extra['ad'] );
|
||||
$ad = Advertisement::load( $purchase->extra['ad'] );
|
||||
$ad->active = 0;
|
||||
$ad->save();
|
||||
}
|
||||
catch ( \OutOfRangeException $e ) { }
|
||||
catch ( OutOfRangeException ) { }
|
||||
|
||||
parent::onExpire( $purchase );
|
||||
}
|
||||
@@ -534,18 +651,18 @@ class _Ad extends \IPS\nexus\Package
|
||||
/**
|
||||
* On Purchase Canceled
|
||||
*
|
||||
* @param \IPS\nexus\Purchase $purchase The purchase
|
||||
* @return void
|
||||
* @param Purchase $purchase The purchase
|
||||
* @return void
|
||||
*/
|
||||
public function onCancel( \IPS\nexus\Purchase $purchase )
|
||||
public function onCancel( Purchase $purchase ): void
|
||||
{
|
||||
try
|
||||
{
|
||||
$ad = \IPS\core\Advertisement::load( $purchase->extra['ad'] );
|
||||
$ad = Advertisement::load( $purchase->extra['ad'] );
|
||||
$ad->active = 0;
|
||||
$ad->save();
|
||||
}
|
||||
catch ( \OutOfRangeException $e ) { }
|
||||
catch ( OutOfRangeException ) { }
|
||||
|
||||
parent::onCancel( $purchase );
|
||||
}
|
||||
@@ -553,16 +670,16 @@ class _Ad extends \IPS\nexus\Package
|
||||
/**
|
||||
* On Purchase Deleted
|
||||
*
|
||||
* @param \IPS\nexus\Purchase $purchase The purchase
|
||||
* @return void
|
||||
* @param Purchase $purchase The purchase
|
||||
* @return void
|
||||
*/
|
||||
public function onDelete( \IPS\nexus\Purchase $purchase )
|
||||
public function onDelete( Purchase $purchase ): void
|
||||
{
|
||||
try
|
||||
{
|
||||
\IPS\core\Advertisement::load( $purchase->extra['ad'] )->delete();
|
||||
Advertisement::load( $purchase->extra['ad'] )->delete();
|
||||
}
|
||||
catch ( \OutOfRangeException $e ) { }
|
||||
catch ( OutOfRangeException ) { }
|
||||
|
||||
parent::onDelete( $purchase );
|
||||
}
|
||||
@@ -570,10 +687,10 @@ class _Ad extends \IPS\nexus\Package
|
||||
/**
|
||||
* On Purchase Reactivated (renewed after being expired or reactivated after being canceled)
|
||||
*
|
||||
* @param \IPS\nexus\Purchase $purchase The purchase
|
||||
* @return void
|
||||
* @param Purchase $purchase The purchase
|
||||
* @return void
|
||||
*/
|
||||
public function onReactivate( \IPS\nexus\Purchase $purchase )
|
||||
public function onReactivate( Purchase $purchase ): void
|
||||
{
|
||||
$this->onExpirationDateChange( $purchase );
|
||||
|
||||
@@ -583,19 +700,19 @@ class _Ad extends \IPS\nexus\Package
|
||||
/**
|
||||
* On Transfer (is ran before transferring)
|
||||
*
|
||||
* @param \IPS\nexus\Purchase $purchase The purchase
|
||||
* @param \IPS\Member $newCustomer New Customer
|
||||
* @return void
|
||||
* @param Purchase $purchase The purchase
|
||||
* @param Member $newCustomer New Customer
|
||||
* @return void
|
||||
*/
|
||||
public function onTransfer( \IPS\nexus\Purchase $purchase, \IPS\Member $newCustomer )
|
||||
public function onTransfer( Purchase $purchase, Member $newCustomer ): void
|
||||
{
|
||||
try
|
||||
{
|
||||
$ad = \IPS\core\Advertisement::load( $purchase->extra['ad'] );
|
||||
$ad->member = $newCustomer->member_id;
|
||||
$ad = Advertisement::load( $purchase->extra['ad'] );
|
||||
$ad->member = $newCustomer->member_id;
|
||||
$ad->save();
|
||||
}
|
||||
catch ( \OutOfRangeException $e ) { }
|
||||
catch ( OutOfRangeException ) { }
|
||||
|
||||
parent::onTransfer( $purchase, $newCustomer );
|
||||
}
|
||||
@@ -603,23 +720,23 @@ class _Ad extends \IPS\nexus\Package
|
||||
/**
|
||||
* On Upgrade/Downgrade
|
||||
*
|
||||
* @param \IPS\nexus\Purchase $purchase The purchase
|
||||
* @param \IPS\nexus\Package $newPackage The package to upgrade to
|
||||
* @param int|NULL|\IPS\nexus\Purchase\RenewalTerm $chosenRenewalOption The chosen renewal option
|
||||
* @return void
|
||||
* @param Purchase $purchase The purchase
|
||||
* @param Package $newPackage The package to upgrade to
|
||||
* @param int|RenewalTerm|NULL $chosenRenewalOption The chosen renewal option
|
||||
* @return void
|
||||
*/
|
||||
public function onChange( \IPS\nexus\Purchase $purchase, \IPS\nexus\Package $newPackage, $chosenRenewalOption = NULL )
|
||||
public function onChange(Purchase $purchase, Package $newPackage, RenewalTerm|int|null $chosenRenewalOption = NULL ): void
|
||||
{
|
||||
try
|
||||
{
|
||||
$ad = \IPS\core\Advertisement::load( $purchase->extra['ad'] );
|
||||
$ad = Advertisement::load( $purchase->extra['ad'] );
|
||||
$ad->location = $newPackage->locations;
|
||||
$ad->exempt = $newPackage->exempt === '*' ? '*' : json_encode( explode( ',', $newPackage->exempt ) );
|
||||
$ad->maximum_value = $newPackage->expire;
|
||||
$ad->maximum_unit = $newPackage->expire_unit;
|
||||
$ad->save();
|
||||
}
|
||||
catch ( \OutOfRangeException $e ) { }
|
||||
catch ( OutOfRangeException ) { }
|
||||
|
||||
parent::onChange( $purchase, $newPackage );
|
||||
}
|
||||
|
||||
@@ -12,41 +12,58 @@
|
||||
namespace IPS\nexus\Package;
|
||||
|
||||
/* To prevent PHP errors (extending class does not exist) revealing path */
|
||||
if ( !\defined( '\IPS\SUITE_UNIQUE_KEY' ) )
|
||||
|
||||
use IPS\Content;
|
||||
use IPS\CustomField as SystemCustomField;
|
||||
use IPS\Helpers\Form;
|
||||
use IPS\Helpers\Form\FormAbstract;
|
||||
use IPS\Helpers\Form\Ftp;
|
||||
use IPS\Helpers\Form\Node;
|
||||
use IPS\Helpers\Form\Text;
|
||||
use IPS\Helpers\Form\YesNo;
|
||||
use IPS\nexus\Package;
|
||||
use IPS\Text\Encrypt;
|
||||
use IPS\Theme;
|
||||
use OutOfRangeException;
|
||||
use function defined;
|
||||
use function in_array;
|
||||
use function is_array;
|
||||
|
||||
if ( !defined( '\IPS\SUITE_UNIQUE_KEY' ) )
|
||||
{
|
||||
header( ( isset( $_SERVER['SERVER_PROTOCOL'] ) ? $_SERVER['SERVER_PROTOCOL'] : 'HTTP/1.0' ) . ' 403 Forbidden' );
|
||||
header( ( $_SERVER['SERVER_PROTOCOL'] ?? 'HTTP/1.0' ) . ' 403 Forbidden' );
|
||||
exit;
|
||||
}
|
||||
|
||||
/**
|
||||
* Custom Profile Field Node
|
||||
*/
|
||||
class _CustomField extends \IPS\CustomField
|
||||
class CustomField extends SystemCustomField
|
||||
{
|
||||
/**
|
||||
* @brief [ActiveRecord] Multiton Store
|
||||
*/
|
||||
protected static $multitons;
|
||||
protected static array $multitons;
|
||||
|
||||
/**
|
||||
* @brief [ActiveRecord] Database Table
|
||||
*/
|
||||
public static $databaseTable = 'nexus_package_fields';
|
||||
public static ?string $databaseTable = 'nexus_package_fields';
|
||||
|
||||
/**
|
||||
* @brief [ActiveRecord] Database Prefix
|
||||
*/
|
||||
public static $databasePrefix = 'cf_';
|
||||
public static string $databasePrefix = 'cf_';
|
||||
|
||||
/**
|
||||
* @brief [Node] Order Database Column
|
||||
*/
|
||||
public static $databaseColumnOrder = 'position';
|
||||
public static ?string $databaseColumnOrder = 'position';
|
||||
|
||||
/**
|
||||
* @brief [CustomField] Title/Description lang prefix
|
||||
*/
|
||||
protected static $langKey = 'nexus_pfield';
|
||||
protected static string $langKey = 'nexus_pfield';
|
||||
|
||||
/**
|
||||
* @brief [Node] ACP Restrictions
|
||||
@@ -64,7 +81,7 @@ class _CustomField extends \IPS\CustomField
|
||||
'prefix' => 'foo_', // [Optional] Rather than specifying each key in the map, you can specify a prefix, and it will automatically look for restrictions with the key "[prefix]_add/edit/permissions/delete"
|
||||
* @endcode
|
||||
*/
|
||||
protected static $restrictions = array(
|
||||
protected static ?array $restrictions = array(
|
||||
'app' => 'nexus',
|
||||
'module' => 'store',
|
||||
'prefix' => 'package_fields_',
|
||||
@@ -73,17 +90,17 @@ class _CustomField extends \IPS\CustomField
|
||||
/**
|
||||
* @brief [Node] Node Title
|
||||
*/
|
||||
public static $nodeTitle = 'custom_package_fields';
|
||||
public static string $nodeTitle = 'custom_package_fields';
|
||||
|
||||
/**
|
||||
* @brief [Node] Title prefix. If specified, will look for a language key with "{$key}_title" as the key
|
||||
*/
|
||||
public static $titleLangPrefix = 'nexus_pfield_';
|
||||
public static ?string $titleLangPrefix = 'nexus_pfield_';
|
||||
|
||||
/**
|
||||
* @brief [CustomField] Column Map
|
||||
*/
|
||||
public static $databaseColumnMap = array(
|
||||
public static array $databaseColumnMap = array(
|
||||
'content' => 'extra',
|
||||
'not_null' => 'required'
|
||||
);
|
||||
@@ -91,7 +108,7 @@ class _CustomField extends \IPS\CustomField
|
||||
/**
|
||||
* @brief [CustomField] Additional Field Classes
|
||||
*/
|
||||
public static $additionalFieldTypes = array(
|
||||
public static array $additionalFieldTypes = array(
|
||||
'UserPass' => 'sf_type_UserPass',
|
||||
'Ftp' => 'sf_type_Ftp'
|
||||
);
|
||||
@@ -99,17 +116,17 @@ class _CustomField extends \IPS\CustomField
|
||||
/**
|
||||
* @brief [CustomField] Upload Field Storage Extension
|
||||
*/
|
||||
public static $uploadStorageExtension = 'nexus_PurchaseFields';
|
||||
public static string $uploadStorageExtension = 'nexus_PurchaseFields';
|
||||
|
||||
/**
|
||||
* @brief [CustomField] Editor Options
|
||||
*/
|
||||
public static $editorOptions = array( 'app' => 'nexus', 'key' => 'Purchases' );
|
||||
public static array $editorOptions = array( 'app' => 'nexus', 'key' => 'Purchases' );
|
||||
|
||||
/**
|
||||
* @brief [CustomField] Additional Field Toggles
|
||||
*/
|
||||
public static $additionalFieldToggles = array(
|
||||
public static array $additionalFieldToggles = array(
|
||||
'Address' => array( 'cf_sticky' ),
|
||||
'Checkbox' => array( 'cf_sticky' ),
|
||||
'CheckboxSet' => array( 'cf_sticky' ),
|
||||
@@ -125,10 +142,10 @@ class _CustomField extends \IPS\CustomField
|
||||
/**
|
||||
* [Node] Add/Edit Form
|
||||
*
|
||||
* @param \IPS\Helpers\Form $form The form
|
||||
* @param Form $form The form
|
||||
* @return void
|
||||
*/
|
||||
public function form( &$form )
|
||||
public function form( Form &$form ) : void
|
||||
{
|
||||
parent::form( $form );
|
||||
|
||||
@@ -137,22 +154,22 @@ class _CustomField extends \IPS\CustomField
|
||||
{
|
||||
try
|
||||
{
|
||||
$packages[] = \IPS\nexus\Package::load( $id );
|
||||
$packages[] = Package::load( $id );
|
||||
}
|
||||
catch ( \OutOfRangeException $e ) { }
|
||||
catch ( OutOfRangeException ) { }
|
||||
}
|
||||
$form->add( new \IPS\Helpers\Form\Node( 'cf_packages', $packages, FALSE, array( 'class' => 'IPS\nexus\Package\Group', 'noParentNodes' => 'custom_packages', 'multiple' => TRUE, 'permissionCheck' => function( $node )
|
||||
$form->add( new Node( 'cf_packages', $packages, FALSE, array( 'class' => 'IPS\nexus\Package\Group', 'noParentNodes' => 'custom_packages', 'multiple' => TRUE, 'permissionCheck' => function( $node )
|
||||
{
|
||||
return !( $node instanceof \IPS\nexus\Package\Group );
|
||||
return !( $node instanceof Group);
|
||||
} ) ), 'pf_desc' );
|
||||
$form->add( new \IPS\Helpers\Form\YesNo( 'cf_sticky', $this->sticky ?: FALSE, FALSE, array(), NULL, NULL, NULL, 'cf_sticky' ), 'pf_type' );
|
||||
$form->add( new \IPS\Helpers\Form\YesNo( 'cf_allow_attachments', $this->id ? $this->allow_attachments : 1, FALSE, array( ), NULL, NULL, NULL, 'pf_allow_attachments' ) );
|
||||
$form->add( new YesNo( 'cf_sticky', $this->sticky ?: FALSE, FALSE, array(), NULL, NULL, NULL, 'cf_sticky' ), 'pf_type' );
|
||||
$form->add( new YesNo( 'cf_allow_attachments', $this->id ? $this->allow_attachments : 1, FALSE, array( ), NULL, NULL, NULL, 'pf_allow_attachments' ) );
|
||||
|
||||
$form->addHeader( 'display_settings' );
|
||||
$form->add( new \IPS\Helpers\Form\YesNo( 'cf_purchase', $this->purchase, FALSE ) );
|
||||
$form->add( new \IPS\Helpers\Form\YesNo( 'cf_editable', $this->editable, FALSE ) );
|
||||
$form->add( new \IPS\Helpers\Form\YesNo( 'cf_required', $this->required ?: FALSE, FALSE, array(), NULL, NULL, NULL, 'pf_not_null' ) );
|
||||
$form->add( new \IPS\Helpers\Form\YesNo( 'cf_invoice', $this->invoice ) );
|
||||
$form->add( new YesNo( 'cf_purchase', $this->purchase, FALSE ) );
|
||||
$form->add( new YesNo( 'cf_editable', $this->editable, FALSE ) );
|
||||
$form->add( new YesNo( 'cf_required', $this->required ?: FALSE, FALSE, array(), NULL, NULL, NULL, 'pf_not_null' ) );
|
||||
$form->add( new YesNo( 'cf_invoice', $this->invoice ) );
|
||||
|
||||
unset( $form->elements[''][1] );
|
||||
unset( $form->elements['']['pf_not_null'] );
|
||||
@@ -171,9 +188,9 @@ class _CustomField extends \IPS\CustomField
|
||||
* @param array $values Values from the form
|
||||
* @return array
|
||||
*/
|
||||
public function formatFormValues( $values )
|
||||
public function formatFormValues( array $values ): array
|
||||
{
|
||||
if( isset( $values['cf_packages'] ) AND \is_array( $values['cf_packages'] ) )
|
||||
if( isset( $values['cf_packages'] ) AND is_array( $values['cf_packages'] ) )
|
||||
{
|
||||
$values['packages'] = implode( ',', array_map( function( $node ){ return $node->id; }, $values['cf_packages'] ) );
|
||||
unset( $values['cf_packages'] );
|
||||
@@ -189,23 +206,24 @@ class _CustomField extends \IPS\CustomField
|
||||
}
|
||||
|
||||
/* Disable 'sticky' for fields that don't support it */
|
||||
if( !\in_array( 'cf_sticky', static::$additionalFieldToggles[ $values['pf_type'] ] ?? [] ) )
|
||||
if( !in_array( 'cf_sticky', static::$additionalFieldToggles[ $values['pf_type'] ] ?? [] ) )
|
||||
{
|
||||
$values['cf_sticky'] = false;
|
||||
}
|
||||
|
||||
return parent::formatFormValues( $values );
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Build Form Helper
|
||||
*
|
||||
* @param mixed $value The value
|
||||
* @param callback $customValidationCode Custom validation code
|
||||
* @param \IPS\Content|NULL $content The associated content, if editing
|
||||
* @return \IPS\Helpers\Form\FormAbstract
|
||||
* @param mixed|null $value The value
|
||||
* @param callback|null $customValidationCode Custom validation code
|
||||
* @param Content|NULL $content The associated content, if editing
|
||||
* @param int $flags
|
||||
* @return Text|FormAbstract
|
||||
*/
|
||||
public function buildHelper( $value=NULL, $customValidationCode=NULL, \IPS\Content $content = NULL )
|
||||
public function buildHelper( mixed $value=NULL, callable $customValidationCode=NULL, ?Content $content = NULL, int $flags=0 ): Text|FormAbstract
|
||||
{
|
||||
if ( $this->type === 'UserPass' )
|
||||
{
|
||||
@@ -214,7 +232,7 @@ class _CustomField extends \IPS\CustomField
|
||||
}
|
||||
elseif ( $this->type === 'Ftp' )
|
||||
{
|
||||
return new \IPS\Helpers\Form\Ftp( static::$langKey . '_' . $this->id, $value, $this->not_null, array( 'validate' => $this->validate ), NULL, NULL, NULL, static::$langKey . '_' . $this->id );
|
||||
return new Ftp( static::$langKey . '_' . $this->id, $value, $this->not_null, array( 'validate' => $this->validate ), NULL, NULL, NULL, static::$langKey . '_' . $this->id );
|
||||
}
|
||||
|
||||
return parent::buildHelper( $value, $customValidationCode, $content );
|
||||
@@ -225,16 +243,16 @@ class _CustomField extends \IPS\CustomField
|
||||
*
|
||||
* @param mixed $value The value
|
||||
* @param bool $showSensitiveInformation If TRUE, potentially sensitive data (like passwords) will be displayed - otherwise will be blanked out
|
||||
* @param string $separator Used to separate items when displaying a field with multiple values.
|
||||
* @return string
|
||||
* @param string|null $separator Used to separate items when displaying a field with multiple values.
|
||||
* @return string|null
|
||||
*/
|
||||
public function displayValue( $value=NULL, $showSensitiveInformation=FALSE, $separator=NULL )
|
||||
public function displayValue( mixed $value=NULL, bool $showSensitiveInformation=FALSE, ?string $separator=NULL ): ?string
|
||||
{
|
||||
if ( $this->type === 'UserPass' )
|
||||
{
|
||||
if ( !\is_array( $value ) )
|
||||
if ( !is_array( $value ) )
|
||||
{
|
||||
$value = json_decode( \IPS\Text\Encrypt::fromTag( $value )->decrypt(), TRUE );
|
||||
$value = json_decode( Encrypt::fromTag( $value )->decrypt(), TRUE );
|
||||
}
|
||||
|
||||
if ( !$showSensitiveInformation )
|
||||
@@ -242,19 +260,19 @@ class _CustomField extends \IPS\CustomField
|
||||
$value['pw'] = '********';
|
||||
}
|
||||
|
||||
return \IPS\Theme::i()->getTemplate( 'forms', 'nexus', 'global' )->usernamePasswordDisplay( $value );
|
||||
return Theme::i()->getTemplate( 'forms', 'nexus', 'global' )->usernamePasswordDisplay( $value );
|
||||
}
|
||||
|
||||
/* Select boxes store the value and not the index, but the parent method uses the index to determine the value.
|
||||
When using numeric options, this causes the wrong value to be returned. */
|
||||
if( $this->type == 'Select' )
|
||||
if ( $this->type == 'Select' )
|
||||
{
|
||||
if( $this->multiple )
|
||||
if ( $this->multiple )
|
||||
{
|
||||
return implode( ( $separator ) ? $separator : '<br>', explode( ',', htmlspecialchars( $value, ENT_DISALLOWED | ENT_QUOTES, 'UTF-8', FALSE ) ) );
|
||||
return implode( ( $separator ) ?: '<br>', explode( ',', htmlspecialchars( $value, ENT_DISALLOWED | ENT_QUOTES, 'UTF-8', false ) ) );
|
||||
}
|
||||
|
||||
return htmlspecialchars( $value, ENT_DISALLOWED | ENT_QUOTES, 'UTF-8', FALSE );
|
||||
return htmlspecialchars( $value, ENT_DISALLOWED | ENT_QUOTES, 'UTF-8', false );
|
||||
}
|
||||
|
||||
return parent::displayValue( $value, $showSensitiveInformation );
|
||||
|
||||
@@ -12,50 +12,62 @@
|
||||
namespace IPS\nexus\Package;
|
||||
|
||||
/* To prevent PHP errors (extending class does not exist) revealing path */
|
||||
if ( !\defined( '\IPS\SUITE_UNIQUE_KEY' ) )
|
||||
|
||||
use IPS\Db;
|
||||
use IPS\Helpers\Form;
|
||||
use IPS\Helpers\Form\Matrix;
|
||||
use IPS\Helpers\Form\Text;
|
||||
use IPS\Helpers\Form\Translatable;
|
||||
use IPS\Lang;
|
||||
use IPS\Member;
|
||||
use IPS\Node\Model;
|
||||
use function defined;
|
||||
use function intval;
|
||||
|
||||
if ( !defined( '\IPS\SUITE_UNIQUE_KEY' ) )
|
||||
{
|
||||
header( ( isset( $_SERVER['SERVER_PROTOCOL'] ) ? $_SERVER['SERVER_PROTOCOL'] : 'HTTP/1.0' ) . ' 403 Forbidden' );
|
||||
header( ( $_SERVER['SERVER_PROTOCOL'] ?? 'HTTP/1.0' ) . ' 403 Forbidden' );
|
||||
exit;
|
||||
}
|
||||
|
||||
/**
|
||||
* Package Filter
|
||||
*/
|
||||
class _Filter extends \IPS\Node\Model
|
||||
class Filter extends Model
|
||||
{
|
||||
/**
|
||||
* @brief [ActiveRecord] Multiton Store
|
||||
*/
|
||||
protected static $multitons;
|
||||
protected static array $multitons;
|
||||
|
||||
/**
|
||||
* @brief [ActiveRecord] Database Table
|
||||
*/
|
||||
public static $databaseTable = 'nexus_package_filters';
|
||||
public static ?string $databaseTable = 'nexus_package_filters';
|
||||
|
||||
/**
|
||||
* @brief [ActiveRecord] Database Prefix
|
||||
*/
|
||||
public static $databasePrefix = 'pfilter_';
|
||||
public static string $databasePrefix = 'pfilter_';
|
||||
/**
|
||||
* @brief [Node] Order Database Column
|
||||
*/
|
||||
public static $databaseColumnOrder = 'order';
|
||||
public static ?string $databaseColumnOrder = 'order';
|
||||
|
||||
/**
|
||||
* @brief [Node] Node Title
|
||||
*/
|
||||
public static $nodeTitle = 'menu__nexus_store_filters';
|
||||
public static string $nodeTitle = 'menu__nexus_store_filters';
|
||||
|
||||
/**
|
||||
* @brief [Node] Title prefix. If specified, will look for a language key with "{$key}_title" as the key
|
||||
*/
|
||||
public static $titleLangPrefix = 'nexus_product_filter_';
|
||||
public static ?string $titleLangPrefix = 'nexus_product_filter_';
|
||||
|
||||
/**
|
||||
* @brief [Node] Description suffix. If specified, will look for a language key with "{$titleLangPrefix}_{$id}_{$descriptionLangSuffix}" as the key
|
||||
*/
|
||||
public static $descriptionLangSuffix = '_public';
|
||||
public static ?string $descriptionLangSuffix = '_public';
|
||||
|
||||
/**
|
||||
* @brief [Node] ACP Restrictions
|
||||
@@ -73,7 +85,7 @@ class _Filter extends \IPS\Node\Model
|
||||
'prefix' => 'foo_', // [Optional] Rather than specifying each key in the map, you can specify a prefix, and it will automatically look for restrictions with the key "[prefix]_add/edit/permissions/delete"
|
||||
* @endcode
|
||||
*/
|
||||
protected static $restrictions = array(
|
||||
protected static ?array $restrictions = array(
|
||||
'app' => 'nexus',
|
||||
'module' => 'store',
|
||||
'all' => 'packages_manage',
|
||||
@@ -82,31 +94,31 @@ class _Filter extends \IPS\Node\Model
|
||||
/**
|
||||
* [Node] Add/Edit Form
|
||||
*
|
||||
* @param \IPS\Helpers\Form $form The form
|
||||
* @param Form $form The form
|
||||
* @return void
|
||||
*/
|
||||
public function form( &$form )
|
||||
public function form( Form &$form ) : void
|
||||
{
|
||||
$form->addHeader( 'pfilter_basic_settings' );
|
||||
$form->add( new \IPS\Helpers\Form\Translatable( 'pfilter_admin_name', NULL, TRUE, array( 'app' => 'nexus', 'key' => $this->id ? "nexus_product_filter_{$this->id}" : NULL ) ) );
|
||||
$form->add( new \IPS\Helpers\Form\Translatable( 'pfilter_public_name', NULL, TRUE, array( 'app' => 'nexus', 'key' => $this->id ? "nexus_product_filter_{$this->id}_public" : NULL ) ) );
|
||||
$form->add( new Translatable( 'pfilter_admin_name', NULL, TRUE, array( 'app' => 'nexus', 'key' => $this->id ? "nexus_product_filter_{$this->id}" : NULL ) ) );
|
||||
$form->add( new Translatable( 'pfilter_public_name', NULL, TRUE, array( 'app' => 'nexus', 'key' => $this->id ? "nexus_product_filter_{$this->id}_public" : NULL ) ) );
|
||||
|
||||
$matrix = new \IPS\Helpers\Form\Matrix;
|
||||
$matrix = new Matrix;
|
||||
$matrix->sortable = TRUE;
|
||||
foreach ( \IPS\Lang::languages() as $lang )
|
||||
foreach ( Lang::languages() as $lang )
|
||||
{
|
||||
if ( $lang->enabled )
|
||||
{
|
||||
\IPS\Member::loggedIn()->language()->words["lang_{$lang->id}"] = $lang->title;
|
||||
Member::loggedIn()->language()->words["lang_{$lang->id}"] = $lang->title;
|
||||
$matrix->columns["lang_{$lang->id}"] = function( $key, $value, $data )
|
||||
{
|
||||
return new \IPS\Helpers\Form\Text( $key, $value );
|
||||
return new Text( $key, $value );
|
||||
};
|
||||
}
|
||||
}
|
||||
if ( $this->id )
|
||||
{
|
||||
foreach ( \IPS\Db::i()->select( '*', 'nexus_package_filters_values', array( 'pfv_filter=?', $this->id ), 'pfv_order' ) as $filterValue )
|
||||
foreach ( Db::i()->select( '*', 'nexus_package_filters_values', array( 'pfv_filter=?', $this->id ), 'pfv_order' ) as $filterValue )
|
||||
{
|
||||
$matrix->rows[ $filterValue['pfv_value'] ][ 'lang_' . $filterValue['pfv_lang'] ] = $filterValue['pfv_text'];
|
||||
}
|
||||
@@ -122,7 +134,7 @@ class _Filter extends \IPS\Node\Model
|
||||
* @param array $values Values from the form
|
||||
* @return array
|
||||
*/
|
||||
public function formatFormValues( $values )
|
||||
public function formatFormValues( array $values ): array
|
||||
{
|
||||
if ( !$this->id )
|
||||
{
|
||||
@@ -131,32 +143,32 @@ class _Filter extends \IPS\Node\Model
|
||||
|
||||
if( isset( $values['pfilter_admin_name'] ) )
|
||||
{
|
||||
\IPS\Lang::saveCustom( 'nexus', "nexus_product_filter_{$this->id}", $values['pfilter_admin_name'] );
|
||||
Lang::saveCustom( 'nexus', "nexus_product_filter_{$this->id}", $values['pfilter_admin_name'] );
|
||||
unset( $values['pfilter_admin_name'] );
|
||||
}
|
||||
|
||||
if( isset( $values['pfilter_public_name'] ) )
|
||||
{
|
||||
\IPS\Lang::saveCustom( 'nexus', "nexus_product_filter_{$this->id}_public", $values['pfilter_public_name'] );
|
||||
Lang::saveCustom( 'nexus', "nexus_product_filter_{$this->id}_public", $values['pfilter_public_name'] );
|
||||
unset( $values['pfilter_public_name'] );
|
||||
}
|
||||
|
||||
$order = 1;
|
||||
$deletedIds = $this->id ? iterator_to_array( \IPS\Db::i()->select( 'pfv_value', 'nexus_package_filters_values', array( 'pfv_filter=?', $this->id ) )->setKeyField('pfv_value') ) : array();
|
||||
$deletedIds = $this->id ? iterator_to_array( Db::i()->select( 'pfv_value', 'nexus_package_filters_values', array( 'pfv_filter=?', $this->id ) )->setKeyField('pfv_value') ) : array();
|
||||
foreach ( $values['pfilter_options'] as $k => $_values )
|
||||
{
|
||||
unset( $deletedIds[ $k ] );
|
||||
|
||||
if ( mb_substr( $k, 0, 5 ) === '_new_' )
|
||||
{
|
||||
$id = \IPS\Db::i()->select( 'MAX(pfv_value)', 'nexus_package_filters_values', array( 'pfv_filter=?', $this->id ) )->first() + 1;
|
||||
$id = Db::i()->select( 'MAX(pfv_value)', 'nexus_package_filters_values', array( 'pfv_filter=?', $this->id ) )->first() + 1;
|
||||
|
||||
foreach ( $_values as $langId => $text )
|
||||
{
|
||||
\IPS\Db::i()->insert( 'nexus_package_filters_values', array(
|
||||
Db::i()->insert( 'nexus_package_filters_values', array(
|
||||
'pfv_filter' => $this->id,
|
||||
'pfv_value' => $id,
|
||||
'pfv_lang' => \intval( mb_substr( $langId, 5 ) ),
|
||||
'pfv_lang' => intval( mb_substr( $langId, 5 ) ),
|
||||
'pfv_text' => $text,
|
||||
'pfv_order' => $order
|
||||
) );
|
||||
@@ -166,10 +178,10 @@ class _Filter extends \IPS\Node\Model
|
||||
{
|
||||
foreach ( $_values as $langId => $text )
|
||||
{
|
||||
\IPS\Db::i()->update( 'nexus_package_filters_values', array(
|
||||
Db::i()->update( 'nexus_package_filters_values', array(
|
||||
'pfv_text' => $text,
|
||||
'pfv_order' => $order
|
||||
), array( 'pfv_filter=? AND pfv_value=? AND pfv_lang=?', $this->id, $k, \intval( mb_substr( $langId, 5 ) ) ) );
|
||||
), array( 'pfv_filter=? AND pfv_value=? AND pfv_lang=?', $this->id, $k, intval( mb_substr( $langId, 5 ) ) ) );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -177,7 +189,7 @@ class _Filter extends \IPS\Node\Model
|
||||
}
|
||||
if ( $deletedIds )
|
||||
{
|
||||
\IPS\Db::i()->delete( 'nexus_package_filters_values', \IPS\Db::i()->in( 'pfv_value', $deletedIds ) );
|
||||
Db::i()->delete( 'nexus_package_filters_values', Db::i()->in( 'pfv_value', $deletedIds ) );
|
||||
}
|
||||
unset( $values['pfilter_options'] );
|
||||
|
||||
@@ -187,13 +199,13 @@ class _Filter extends \IPS\Node\Model
|
||||
/**
|
||||
* [ActiveRecord] Delete Record
|
||||
*
|
||||
* @return void
|
||||
* @return void
|
||||
*/
|
||||
public function delete()
|
||||
public function delete(): void
|
||||
{
|
||||
\IPS\Db::i()->delete( 'nexus_package_filters_values', array( 'pfv_filter=?', $this->id ) );
|
||||
\IPS\Lang::deleteCustom( 'nexus', static::$titleLangPrefix . $this->_id );
|
||||
\IPS\Lang::deleteCustom( 'nexus', static::$titleLangPrefix . $this->_id . static::$descriptionLangSuffix );
|
||||
Db::i()->delete( 'nexus_package_filters_values', array( 'pfv_filter=?', $this->id ) );
|
||||
Lang::deleteCustom( 'nexus', static::$titleLangPrefix . $this->_id );
|
||||
Lang::deleteCustom( 'nexus', static::$titleLangPrefix . $this->_id . static::$descriptionLangSuffix );
|
||||
parent::delete();
|
||||
}
|
||||
|
||||
@@ -204,9 +216,9 @@ class _Filter extends \IPS\Node\Model
|
||||
* @param int $filterId ID of the filter
|
||||
* @param int|null $valueToAdd Value to add to the filter array
|
||||
* @param int|null $valueToRemove Value to remove from the filter array
|
||||
* @return void
|
||||
* @return array
|
||||
*/
|
||||
public static function queryString( $queryString, $filterId, $valueToAdd=NULL, $valueToRemove = NULL )
|
||||
public static function queryString( array $queryString, int $filterId, ?int $valueToAdd=NULL, ?int $valueToRemove = NULL ) : array
|
||||
{
|
||||
$queryString = $queryString ?: array();
|
||||
|
||||
|
||||
@@ -12,66 +12,87 @@
|
||||
namespace IPS\nexus\Package;
|
||||
|
||||
/* To prevent PHP errors (extending class does not exist) revealing path */
|
||||
if ( !\defined( '\IPS\SUITE_UNIQUE_KEY' ) )
|
||||
|
||||
use Exception;
|
||||
use InvalidArgumentException;
|
||||
use IPS\Db;
|
||||
use IPS\File;
|
||||
use IPS\Helpers\Form;
|
||||
use IPS\Helpers\Form\Node;
|
||||
use IPS\Helpers\Form\Stack;
|
||||
use IPS\Helpers\Form\Translatable;
|
||||
use IPS\Helpers\Form\Upload;
|
||||
use IPS\Http\Url;
|
||||
use IPS\Http\Url\Friendly;
|
||||
use IPS\Lang;
|
||||
use IPS\Member;
|
||||
use IPS\Node\Model;
|
||||
use IPS\Request;
|
||||
use OutOfRangeException;
|
||||
use function count;
|
||||
use function defined;
|
||||
use function get_called_class;
|
||||
|
||||
if ( !defined( '\IPS\SUITE_UNIQUE_KEY' ) )
|
||||
{
|
||||
header( ( isset( $_SERVER['SERVER_PROTOCOL'] ) ? $_SERVER['SERVER_PROTOCOL'] : 'HTTP/1.0' ) . ' 403 Forbidden' );
|
||||
header( ( $_SERVER['SERVER_PROTOCOL'] ?? 'HTTP/1.0' ) . ' 403 Forbidden' );
|
||||
exit;
|
||||
}
|
||||
|
||||
/**
|
||||
* Package Group
|
||||
*/
|
||||
class _Group extends \IPS\Node\Model
|
||||
class Group extends Model
|
||||
{
|
||||
/**
|
||||
* @brief [ActiveRecord] Multiton Store
|
||||
*/
|
||||
protected static $multitons;
|
||||
protected static array $multitons;
|
||||
|
||||
/**
|
||||
* @brief [ActiveRecord] Database Table
|
||||
*/
|
||||
public static $databaseTable = 'nexus_package_groups';
|
||||
public static ?string $databaseTable = 'nexus_package_groups';
|
||||
|
||||
/**
|
||||
* @brief [ActiveRecord] Database Prefix
|
||||
*/
|
||||
public static $databasePrefix = 'pg_';
|
||||
public static string $databasePrefix = 'pg_';
|
||||
|
||||
/**
|
||||
* @brief [Node] Parent ID Database Column
|
||||
*/
|
||||
public static $databaseColumnParent = 'parent';
|
||||
public static ?string $databaseColumnParent = 'parent';
|
||||
|
||||
/**
|
||||
* @brief [Node] Order Database Column
|
||||
*/
|
||||
public static $databaseColumnOrder = 'position';
|
||||
public static ?string $databaseColumnOrder = 'position';
|
||||
|
||||
/**
|
||||
* @brief [Node] Node Title
|
||||
*/
|
||||
public static $nodeTitle = 'product_groups';
|
||||
public static string $nodeTitle = 'product_groups';
|
||||
|
||||
/**
|
||||
* @brief [Node] Subnode class
|
||||
*/
|
||||
public static $subnodeClass = 'IPS\nexus\Package';
|
||||
public static ?string $subnodeClass = 'IPS\nexus\Package';
|
||||
|
||||
/**
|
||||
* @brief Content Item Class
|
||||
*/
|
||||
public static $contentItemClass = 'IPS\nexus\Package\Item';
|
||||
public static ?string $contentItemClass = 'IPS\nexus\Package\Item';
|
||||
|
||||
/**
|
||||
* @brief [Node] Title prefix. If specified, will look for a language key with "{$key}_title" as the key
|
||||
*/
|
||||
public static $titleLangPrefix = 'nexus_pgroup_';
|
||||
public static ?string $titleLangPrefix = 'nexus_pgroup_';
|
||||
|
||||
/**
|
||||
* @brief [Node] Description suffix. If specified, will look for a language key with "{$titleLangPrefix}_{$id}_{$descriptionLangSuffix}" as the key
|
||||
*/
|
||||
public static $descriptionLangSuffix = '_desc';
|
||||
public static ?string $descriptionLangSuffix = '_desc';
|
||||
|
||||
/**
|
||||
* @brief [Node] ACP Restrictions
|
||||
@@ -89,7 +110,7 @@ class _Group extends \IPS\Node\Model
|
||||
'prefix' => 'foo_', // [Optional] Rather than specifying each key in the map, you can specify a prefix, and it will automatically look for restrictions with the key "[prefix]_add/edit/permissions/delete"
|
||||
* @endcode
|
||||
*/
|
||||
protected static $restrictions = array(
|
||||
protected static ?array $restrictions = array(
|
||||
'app' => 'nexus',
|
||||
'module' => 'store',
|
||||
'prefix' => 'packages_',
|
||||
@@ -99,17 +120,17 @@ class _Group extends \IPS\Node\Model
|
||||
* Return only the root groups that have packages OR subcategories/groups
|
||||
*
|
||||
* @param string|NULL $permissionCheck The permission key to check for or NULl to not check permissions
|
||||
* @param \IPS\Member|NULL $member The member to check permissions for or NULL for the currently logged in member
|
||||
* @param mixed $where Additional WHERE clause
|
||||
* @param Member|NULL $member The member to check permissions for or NULL for the currently logged in member
|
||||
* @param array $where Additional WHERE clause
|
||||
* @return array
|
||||
*/
|
||||
public static function rootsWithViewablePackages( $permissionCheck='view', $member=NULL, $where=array() )
|
||||
public static function rootsWithViewablePackages( ?string $permissionCheck='view', ?Member $member=NULL, array $where=array() ) : array
|
||||
{
|
||||
$roots = static::roots( $permissionCheck, $member, $where );
|
||||
|
||||
foreach( $roots as $index => $group )
|
||||
{
|
||||
if( !$group->hasSubgroups() AND !$group->hasPackages( NULL, array( array( "p_store=1 AND ( p_member_groups='*' OR " . \IPS\Db::i()->findInSet( 'p_member_groups', \IPS\Member::loggedIn()->groups ) . ' )' ) ) ) )
|
||||
if( !$group->hasSubgroups() AND !$group->hasPackages( NULL, array( array( "p_store=1 AND ( p_member_groups='*' OR " . Db::i()->findInSet( 'p_member_groups', Member::loggedIn()->groups ) . ' )' ) ) ) )
|
||||
{
|
||||
unset( $roots[ $index ] );
|
||||
}
|
||||
@@ -121,12 +142,12 @@ class _Group extends \IPS\Node\Model
|
||||
/**
|
||||
* Load record based on a URL
|
||||
*
|
||||
* @param \IPS\Http\Url $url URL to load from
|
||||
* @param Url $url URL to load from
|
||||
* @return static
|
||||
* @throws \InvalidArgumentException
|
||||
* @throws \OutOfRangeException
|
||||
* @throws InvalidArgumentException
|
||||
* @throws OutOfRangeException
|
||||
*/
|
||||
public static function loadFromUrl( \IPS\Http\Url $url )
|
||||
public static function loadFromUrl( Url $url ): static
|
||||
{
|
||||
$qs = array_merge( $url->queryString, $url->hiddenQueryString );
|
||||
|
||||
@@ -135,20 +156,20 @@ class _Group extends \IPS\Node\Model
|
||||
return static::load( $qs['cat'] );
|
||||
}
|
||||
|
||||
throw new \InvalidArgumentException;
|
||||
throw new InvalidArgumentException;
|
||||
}
|
||||
|
||||
/**
|
||||
* [Node] Add/Edit Form
|
||||
*
|
||||
* @param \IPS\Helpers\Form $form The form
|
||||
* @param Form $form The form
|
||||
* @return void
|
||||
*/
|
||||
public function form( &$form )
|
||||
public function form( Form &$form ) : void
|
||||
{
|
||||
$form->addHeader('pg_basic_settings');
|
||||
$form->add( new \IPS\Helpers\Form\Translatable( 'pg_name', NULL, TRUE, array( 'app' => 'nexus', 'key' => $this->id ? "nexus_pgroup_{$this->id}" : NULL ) ) );
|
||||
$form->add( new \IPS\Helpers\Form\Translatable( 'pg_desc', NULL, FALSE, array(
|
||||
$form->add( new Translatable( 'pg_name', NULL, TRUE, array( 'app' => 'nexus', 'key' => $this->id ? "nexus_pgroup_{$this->id}" : NULL ) ) );
|
||||
$form->add( new Translatable( 'pg_desc', NULL, FALSE, array(
|
||||
'app' => 'nexus',
|
||||
'key' => ( $this->id ? "nexus_pgroup_{$this->id}_desc" : NULL ),
|
||||
'editor' => array(
|
||||
@@ -159,18 +180,18 @@ class _Group extends \IPS\Node\Model
|
||||
)
|
||||
) ) );
|
||||
|
||||
$class = \get_called_class();
|
||||
$class = get_called_class();
|
||||
|
||||
$form->add( new \IPS\Helpers\Form\Node( 'pg_parent', $this->id ? $this->parent : 0, TRUE, array( 'class' => 'IPS\nexus\Package\Group', 'subnodes' => FALSE, 'zeroVal' => 'no_parent', 'permissionCheck' => function( $node ) use ( $class )
|
||||
$form->add( new Node( 'pg_parent', $this->id ? $this->parent : 0, TRUE, array( 'class' => 'IPS\nexus\Package\Group', 'subnodes' => FALSE, 'zeroVal' => 'no_parent', 'permissionCheck' => function( $node ) use ( $class )
|
||||
{
|
||||
if( isset( $class::$subnodeClass ) AND $class::$subnodeClass AND $node instanceof $class::$subnodeClass )
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return !isset( \IPS\Request::i()->id ) or ( $node->id != \IPS\Request::i()->id and !$node->isChildOf( $node::load( \IPS\Request::i()->id ) ) );
|
||||
return !isset( Request::i()->id ) or ( $node->id != Request::i()->id and !$node->isChildOf( $node::load( Request::i()->id ) ) );
|
||||
} ) ) );
|
||||
$form->add( new \IPS\Helpers\Form\Upload( 'pg_image', $this->image ? \IPS\File::get( 'nexus_PackageGroups', $this->image ) : NULL, FALSE, array( 'storageExtension' => 'nexus_PackageGroups', 'image' => TRUE, 'allowStockPhotos' => TRUE ) ) );
|
||||
$form->add( new Upload( 'pg_image', $this->image ? File::get( 'nexus_PackageGroups', $this->image ) : NULL, FALSE, array( 'storageExtension' => 'nexus_PackageGroups', 'image' => TRUE, 'allowStockPhotos' => TRUE ) ) );
|
||||
|
||||
$priceFilters = array();
|
||||
if ( $this->price_filters )
|
||||
@@ -185,8 +206,8 @@ class _Group extends \IPS\Node\Model
|
||||
}
|
||||
|
||||
$form->addHeader('pg_filters_header');
|
||||
$form->add( new \IPS\Helpers\Form\Node( 'pg_filters', explode( ',', $this->filters ), FALSE, array( 'class' => 'IPS\nexus\Package\Filter', 'multiple' => TRUE ) ) );
|
||||
$form->add( new \IPS\Helpers\Form\Stack( 'pg_price_filters', $priceFilters, FALSE, array( 'stackFieldType' => 'IPS\nexus\Form\Money' ) ) );
|
||||
$form->add( new Node( 'pg_filters', $this->filters ? explode( ',', $this->filters ) : [], FALSE, array( 'class' => 'IPS\nexus\Package\Filter', 'multiple' => TRUE ) ) );
|
||||
$form->add( new Stack( 'pg_price_filters', $priceFilters, FALSE, array( 'stackFieldType' => 'IPS\nexus\Form\Money' ) ) );
|
||||
|
||||
}
|
||||
|
||||
@@ -196,7 +217,7 @@ class _Group extends \IPS\Node\Model
|
||||
* @param array $values Values from the form
|
||||
* @return array
|
||||
*/
|
||||
public function formatFormValues( $values )
|
||||
public function formatFormValues( array $values ): array
|
||||
{
|
||||
if( isset( $values['pg_parent'] ) )
|
||||
{
|
||||
@@ -211,7 +232,7 @@ class _Group extends \IPS\Node\Model
|
||||
if ( !$this->id )
|
||||
{
|
||||
$this->save();
|
||||
\IPS\File::claimAttachments( 'nexus-new-group', $this->id, NULL, 'pgroup', TRUE );
|
||||
File::claimAttachments( 'nexus-new-group', $this->id, NULL, 'pgroup', TRUE );
|
||||
}
|
||||
elseif( isset( $values['pg_name'] ) OR isset( $values['pg_desc'] ) )
|
||||
{
|
||||
@@ -220,13 +241,13 @@ class _Group extends \IPS\Node\Model
|
||||
|
||||
if( isset( $values['pg_name'] ) )
|
||||
{
|
||||
\IPS\Lang::saveCustom( 'nexus', "nexus_pgroup_{$this->id}", $values['pg_name'] );
|
||||
Lang::saveCustom( 'nexus', "nexus_pgroup_{$this->id}", $values['pg_name'] );
|
||||
unset( $values['pg_name'] );
|
||||
}
|
||||
|
||||
if( isset( $values['pg_desc'] ) )
|
||||
{
|
||||
\IPS\Lang::saveCustom( 'nexus', "nexus_pgroup_{$this->id}_desc", $values['pg_desc'] );
|
||||
Lang::saveCustom( 'nexus', "nexus_pgroup_{$this->id}_desc", $values['pg_desc'] );
|
||||
unset( $values['pg_desc'] );
|
||||
}
|
||||
|
||||
@@ -240,7 +261,7 @@ class _Group extends \IPS\Node\Model
|
||||
$priceFilters[ $currency ][] = $amount->amount->jsonSerialize();
|
||||
}
|
||||
}
|
||||
$values['pg_price_filters'] = \count( $priceFilters ) ? json_encode( $priceFilters ) : NULL;
|
||||
$values['pg_price_filters'] = count( $priceFilters ) ? json_encode( $priceFilters ) : NULL;
|
||||
|
||||
return $values;
|
||||
}
|
||||
@@ -248,18 +269,18 @@ class _Group extends \IPS\Node\Model
|
||||
/**
|
||||
* @brief Cached URL
|
||||
*/
|
||||
protected $_url = NULL;
|
||||
protected mixed $_url = NULL;
|
||||
|
||||
/**
|
||||
* Get URL
|
||||
*
|
||||
* @return \IPS\Http\Url
|
||||
* @return Url\Internal|string|null
|
||||
*/
|
||||
public function url()
|
||||
public function url(): Url\Internal|string|null
|
||||
{
|
||||
if( $this->_url === NULL )
|
||||
{
|
||||
$this->_url = \IPS\Http\Url::internal( "app=nexus&module=store&controller=store&cat={$this->id}", 'front', 'store_group', \IPS\Http\Url\Friendly::seoTitle( \IPS\Member::loggedIn()->language()->get( 'nexus_pgroup_' . $this->id ) ) );
|
||||
$this->_url = Url::internal( "app=nexus&module=store&controller=store&cat={$this->id}", 'front', 'store_group', Friendly::seoTitle( Member::loggedIn()->language()->get( 'nexus_pgroup_' . $this->id ) ) );
|
||||
}
|
||||
|
||||
return $this->_url;
|
||||
@@ -271,30 +292,30 @@ class _Group extends \IPS\Node\Model
|
||||
* @param array $indexData Data from the search index
|
||||
* @param array $itemData Basic data about the item. Only includes columns returned by item::basicDataColumns()
|
||||
* @param array|NULL $containerData Basic data about the container. Only includes columns returned by container::basicDataColumns()
|
||||
* @return \IPS\Http\Url
|
||||
* @return Url
|
||||
*/
|
||||
public static function urlFromIndexData( $indexData, $itemData, $containerData )
|
||||
public static function urlFromIndexData( array $indexData, array $itemData, ?array $containerData ): Url
|
||||
{
|
||||
return \IPS\Http\Url::internal( "app=nexus&module=store&controller=store&cat={$indexData['index_container_id']}", 'front', 'store_group', \IPS\Member::loggedIn()->language()->addToStack( 'nexus_pgroup_' . $indexData['index_container_id'], FALSE, array( 'seotitle' => TRUE ) ) );
|
||||
return Url::internal( "app=nexus&module=store&controller=store&cat={$indexData['index_container_id']}", 'front', 'store_group', Member::loggedIn()->language()->addToStack( 'nexus_pgroup_' . $indexData['index_container_id'], FALSE, array( 'seotitle' => TRUE ) ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Get full image URL
|
||||
*
|
||||
* @return string
|
||||
* @return string|null
|
||||
*/
|
||||
public function get_image()
|
||||
public function get_image() : string|null
|
||||
{
|
||||
return ( isset( $this->_data['image'] ) ) ? (string) \IPS\File::get( 'nexus_PackageGroups', $this->_data['image'] )->url : NULL;
|
||||
return ( isset( $this->_data['image'] ) ) ? (string) File::get( 'nexus_PackageGroups', $this->_data['image'] )->url : NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* Does this group have subgroups?
|
||||
*
|
||||
* @param mixed $_where Additional WHERE clause
|
||||
* @param array $_where Additional WHERE clause
|
||||
* @return bool
|
||||
*/
|
||||
public function hasSubgroups( $_where=array() )
|
||||
public function hasSubgroups( array $_where=array() ) : bool
|
||||
{
|
||||
return ( $this->childrenCount( NULL, NULL, FALSE, $_where ) > 0 );
|
||||
}
|
||||
@@ -302,18 +323,18 @@ class _Group extends \IPS\Node\Model
|
||||
/**
|
||||
* Does this group have packages?
|
||||
*
|
||||
* @param \IPS\Member|NULL|FALSE $member The member to perform the permission check for, or NULL for currently logged in member, or FALSE for no permission check
|
||||
* @param mixed $_where Additional WHERE clause
|
||||
* @param Member|NULL|FALSE $member The member to perform the permission check for, or NULL for currently logged in member, or FALSE for no permission check
|
||||
* @param array $_where Additional WHERE clause
|
||||
* @param bool $viewableOnly Only check packages the member can view
|
||||
* @return bool
|
||||
*/
|
||||
public function hasPackages( $member=NULL, $_where=array(), $viewableOnly=FALSE )
|
||||
public function hasPackages( Member|null|bool $member=NULL, array $_where=array(), bool $viewableOnly=FALSE ) : bool
|
||||
{
|
||||
if( $viewableOnly === TRUE )
|
||||
{
|
||||
$member = $member ?: \IPS\Member::loggedIn();
|
||||
$member = $member ?: Member::loggedIn();
|
||||
|
||||
$_where[] = array( "p_store=1 AND ( p_member_groups='*' OR " . \IPS\Db::i()->findInSet( 'p_member_groups', $member->groups ) . ' )' );
|
||||
$_where[] = array( "p_store=1 AND ( p_member_groups='*' OR " . Db::i()->findInSet( 'p_member_groups', $member->groups ) . ' )' );
|
||||
}
|
||||
|
||||
return ( $this->childrenCount( $member === FALSE ? FALSE : 'view', $member, NULL, $_where ) > 0 );
|
||||
@@ -322,21 +343,21 @@ class _Group extends \IPS\Node\Model
|
||||
/**
|
||||
* Get Filter Options
|
||||
*
|
||||
* @param \IPS\Lang $language The language to return options in
|
||||
* @param Lang $language The language to return options in
|
||||
* @return array
|
||||
*/
|
||||
public function filters( \IPS\Lang $language )
|
||||
public function filters( Lang $language ) : array
|
||||
{
|
||||
$return = array();
|
||||
|
||||
if ( $this->filters )
|
||||
{
|
||||
foreach ( \IPS\Db::i()->select( 'pfilter_id', 'nexus_package_filters', array( \IPS\Db::i()->in( 'pfilter_id', explode( ',', $this->filters ) ) ), 'pfilter_order' ) as $filterId )
|
||||
foreach ( Db::i()->select( 'pfilter_id', 'nexus_package_filters', array( Db::i()->in( 'pfilter_id', explode( ',', $this->filters ) ) ), 'pfilter_order' ) as $filterId )
|
||||
{
|
||||
$return[ $filterId ] = array();
|
||||
}
|
||||
|
||||
foreach ( \IPS\Db::i()->select( '*', 'nexus_package_filters_values', array( array( \IPS\Db::i()->in( 'pfv_filter', array_keys( $return ) ) ), array( 'pfv_lang=?', $language->id ) ), 'pfv_order' ) as $value )
|
||||
foreach ( Db::i()->select( '*', 'nexus_package_filters_values', array( array( Db::i()->in( 'pfv_filter', array_keys( $return ) ) ), array( 'pfv_lang=?', $language->id ) ), 'pfv_order' ) as $value )
|
||||
{
|
||||
$return[ $value['pfv_filter'] ][ $value['pfv_value'] ] = $value['pfv_text'];
|
||||
}
|
||||
@@ -350,7 +371,7 @@ class _Group extends \IPS\Node\Model
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function __clone()
|
||||
public function __clone() : void
|
||||
{
|
||||
if ( $this->skipCloneDuplication === TRUE )
|
||||
{
|
||||
@@ -365,11 +386,11 @@ class _Group extends \IPS\Node\Model
|
||||
{
|
||||
try
|
||||
{
|
||||
$icon = \IPS\File::get( 'nexus_PackageGroups', $oldImage );
|
||||
$newIcon = \IPS\File::create( 'nexus_PackageGroups', $icon->originalFilename, $icon->contents() );
|
||||
$icon = File::get( 'nexus_PackageGroups', $oldImage );
|
||||
$newIcon = File::create( 'nexus_PackageGroups', $icon->originalFilename, $icon->contents() );
|
||||
$this->image = (string) $newIcon;
|
||||
}
|
||||
catch ( \Exception $e )
|
||||
catch ( Exception )
|
||||
{
|
||||
$this->pg_image = NULL;
|
||||
}
|
||||
@@ -383,7 +404,7 @@ class _Group extends \IPS\Node\Model
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function deleteOrMoveQueued()
|
||||
public function deleteOrMoveQueued(): bool
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
@@ -393,21 +414,21 @@ class _Group extends \IPS\Node\Model
|
||||
* Example code explains return value
|
||||
*
|
||||
* @code
|
||||
array(
|
||||
array(
|
||||
'icon' => 'plus-circle', // Name of FontAwesome icon to use
|
||||
'title' => 'foo', // Language key to use for button's title parameter
|
||||
'link' => \IPS\Http\Url::internal( 'app=foo...' ) // URI to link to
|
||||
'class' => 'modalLink' // CSS Class to use on link (Optional)
|
||||
),
|
||||
... // Additional buttons
|
||||
);
|
||||
* array(
|
||||
* array(
|
||||
* 'icon' => 'plus-circle', // Name of FontAwesome icon to use
|
||||
* 'title' => 'foo', // Language key to use for button's title parameter
|
||||
* 'link' => \IPS\Http\Url::internal( 'app=foo...' ) // URI to link to
|
||||
* 'class' => 'modalLink' // CSS Class to use on link (Optional)
|
||||
* ),
|
||||
* ... // Additional buttons
|
||||
* );
|
||||
* @endcode
|
||||
* @param string $url Base URL
|
||||
* @param Url $url Base URL
|
||||
* @param bool $subnode Is this a subnode?
|
||||
* @return array
|
||||
*/
|
||||
public function getButtons( $url, $subnode=FALSE )
|
||||
public function getButtons( Url $url, bool $subnode=FALSE ):array
|
||||
{
|
||||
$buttons = parent::getButtons( $url, $subnode );
|
||||
|
||||
|
||||
@@ -12,56 +12,100 @@
|
||||
namespace IPS\nexus\Package;
|
||||
|
||||
/* To prevent PHP errors (extending class does not exist) revealing path */
|
||||
if ( !\defined( '\IPS\SUITE_UNIQUE_KEY' ) )
|
||||
|
||||
use BadMethodCallException;
|
||||
use DateInterval;
|
||||
use Exception;
|
||||
use InvalidArgumentException;
|
||||
use IPS\Application;
|
||||
use IPS\Content\Embeddable;
|
||||
use IPS\Content\Featurable;
|
||||
use IPS\Content\Filter;
|
||||
use IPS\Content\Hideable;
|
||||
use IPS\Content\Item as ContentItem;
|
||||
use IPS\Content\MetaData;
|
||||
use IPS\Content\Shareable;
|
||||
use IPS\Db;
|
||||
use IPS\File;
|
||||
use IPS\File\Iterator;
|
||||
use IPS\Http\Url;
|
||||
use IPS\Http\Url\Friendly;
|
||||
use IPS\Member;
|
||||
use IPS\nexus\Customer;
|
||||
use IPS\nexus\Money;
|
||||
use IPS\nexus\Package;
|
||||
use IPS\nexus\Purchase\RenewalTerm;
|
||||
use IPS\nexus\Tax;
|
||||
use IPS\Node\Model;
|
||||
use IPS\Output;
|
||||
use IPS\Patterns\ActiveRecordIterator;
|
||||
use IPS\Request;
|
||||
use IPS\Theme;
|
||||
use OutOfRangeException;
|
||||
use RuntimeException;
|
||||
use function count;
|
||||
use function defined;
|
||||
use function in_array;
|
||||
|
||||
if ( !defined( '\IPS\SUITE_UNIQUE_KEY' ) )
|
||||
{
|
||||
header( ( isset( $_SERVER['SERVER_PROTOCOL'] ) ? $_SERVER['SERVER_PROTOCOL'] : 'HTTP/1.0' ) . ' 403 Forbidden' );
|
||||
header( ( $_SERVER['SERVER_PROTOCOL'] ?? 'HTTP/1.0' ) . ' 403 Forbidden' );
|
||||
exit;
|
||||
}
|
||||
|
||||
/**
|
||||
* Package Item Model
|
||||
*/
|
||||
class _Item extends \IPS\Content\Item implements \IPS\Content\Featurable, \IPS\Content\Shareable, \IPS\Content\Embeddable, \IPS\Content\MetaData, \IPS\Content\Searchable
|
||||
class Item extends ContentItem implements Embeddable
|
||||
{
|
||||
use MetaData,
|
||||
Shareable,
|
||||
Hideable,
|
||||
Featurable
|
||||
{
|
||||
Hideable::moderateNewReviews as public _moderateNewReviews;
|
||||
Hideable::hiddenStatus as public _hidden;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Application
|
||||
*/
|
||||
public static $application = 'nexus';
|
||||
public static string $application = 'nexus';
|
||||
|
||||
/**
|
||||
* @brief Module
|
||||
*/
|
||||
public static $module = 'store';
|
||||
public static string $module = 'store';
|
||||
|
||||
/**
|
||||
* @brief Database Table
|
||||
*/
|
||||
public static $databaseTable = 'nexus_packages';
|
||||
public static ?string $databaseTable = 'nexus_packages';
|
||||
|
||||
/**
|
||||
* @brief Database Prefix
|
||||
*/
|
||||
public static $databasePrefix = 'p_';
|
||||
public static string $databasePrefix = 'p_';
|
||||
|
||||
/**
|
||||
* @brief Multiton Store
|
||||
*/
|
||||
protected static $multitons;
|
||||
protected static array $multitons;
|
||||
|
||||
/**
|
||||
* @brief Node Class
|
||||
*/
|
||||
public static $containerNodeClass = 'IPS\nexus\Package\Group';
|
||||
public static ?string $containerNodeClass = 'IPS\nexus\Package\Group';
|
||||
|
||||
/**
|
||||
* @brief Review Class
|
||||
*/
|
||||
public static $reviewClass = 'IPS\nexus\Package\Review';
|
||||
public static string $reviewClass = 'IPS\nexus\Package\Review';
|
||||
|
||||
/**
|
||||
* @brief Database Column Map
|
||||
*/
|
||||
public static $databaseColumnMap = array(
|
||||
public static array $databaseColumnMap = array(
|
||||
'title' => 'name',
|
||||
'container' => 'group',
|
||||
'featured' => 'featured',
|
||||
@@ -77,115 +121,138 @@ class _Item extends \IPS\Content\Item implements \IPS\Content\Featurable, \IPS\C
|
||||
/**
|
||||
* @brief Title
|
||||
*/
|
||||
public static $title = 'product';
|
||||
public static string $title = 'product';
|
||||
|
||||
/**
|
||||
* @brief Icon
|
||||
*/
|
||||
public static $icon = 'archive';
|
||||
public static string $icon = 'box';
|
||||
|
||||
/**
|
||||
* @brief Include In Sitemap
|
||||
*/
|
||||
public static $includeInSitemap = FALSE;
|
||||
public static bool $includeInSitemap = FALSE;
|
||||
|
||||
/**
|
||||
* @brief Can this content be moderated normally from the front-end (will be FALSE for things like Pages and Commerce Products)
|
||||
*/
|
||||
public static $canBeModeratedFromFrontend = FALSE;
|
||||
public static bool $canBeModeratedFromFrontend = FALSE;
|
||||
|
||||
/**
|
||||
* Get title
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function get_title()
|
||||
public function get_title() : string
|
||||
{
|
||||
return \IPS\Member::loggedIn()->language()->addToStack("nexus_package_{$this->id}");
|
||||
return Member::loggedIn()->language()->addToStack("nexus_package_{$this->id}");
|
||||
}
|
||||
|
||||
/**
|
||||
* Get description
|
||||
*
|
||||
* @return string
|
||||
* @return string|null
|
||||
*/
|
||||
public function content()
|
||||
public function content(): ?string
|
||||
{
|
||||
return \IPS\Member::loggedIn()->language()->get("nexus_package_{$this->id}_desc"); // Has to be get() rather than addToStack() so we can reliably strips tags, etc.
|
||||
return Member::loggedIn()->language()->get("nexus_package_{$this->id}_desc"); // Has to be get() rather than addToStack() so we can reliably strips tags, etc.
|
||||
}
|
||||
|
||||
/**
|
||||
* Can view?
|
||||
*
|
||||
* @param \IPS\Member|NULL $member The member to check for or NULL for the currently logged in member
|
||||
* @param Member|NULL $member The member to check for or NULL for the currently logged in member
|
||||
* @return bool
|
||||
*/
|
||||
public function canView( $member=NULL )
|
||||
public function canView( ?Member $member=null ): bool
|
||||
{
|
||||
if ( !$this->store )
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
$member = $member ?: \IPS\Member::loggedIn();
|
||||
$member = $member ?: Member::loggedIn();
|
||||
return $this->member_groups === '*' or $member->inGroup( explode( ',', $this->member_groups ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete Package Data
|
||||
*
|
||||
* @return void
|
||||
* @return void
|
||||
*/
|
||||
public function delete()
|
||||
public function delete(): void
|
||||
{
|
||||
/* Delete Images */
|
||||
foreach( \IPS\Db::i()->select( '*', 'nexus_package_images', array( 'image_product=?', $this->id ) ) as $image )
|
||||
foreach( Db::i()->select( '*', 'nexus_package_images', array( 'image_product=?', $this->id ) ) as $image )
|
||||
{
|
||||
try
|
||||
{
|
||||
\IPS\File::get( 'nexus_Products', $image['image_location'] )->delete();
|
||||
File::get( 'nexus_Products', $image['image_location'] )->delete();
|
||||
}
|
||||
catch ( \Exception $e ) { }
|
||||
catch ( Exception ) { }
|
||||
}
|
||||
\IPS\Db::i()->delete( 'nexus_package_images', array( 'image_product=?', $this->id ) );
|
||||
Db::i()->delete( 'nexus_package_images', array( 'image_product=?', $this->id ) );
|
||||
|
||||
/* Delete Product Options */
|
||||
\IPS\Db::i()->delete( 'nexus_product_options', array( 'opt_package=?', $this->id ) );
|
||||
Db::i()->delete( 'nexus_product_options', array( 'opt_package=?', $this->id ) );
|
||||
|
||||
/* Delete Base Prices */
|
||||
\IPS\Db::i()->delete( 'nexus_package_base_prices', array( 'id=?', $this->id ) );
|
||||
Db::i()->delete( 'nexus_package_base_prices', array( 'id=?', $this->id ) );
|
||||
|
||||
parent::delete();
|
||||
|
||||
if( Application::appIsEnabled( 'downloads') )
|
||||
{
|
||||
/* Look for files linked to this product */
|
||||
foreach( Db::i()->select( '*', 'downloads_files', array( Db::i()->findInSet( 'file_nexus', array( $this->id ) ) ) ) as $file )
|
||||
{
|
||||
$packages = explode( ',', $file['file_nexus'] );
|
||||
$packages = array_filter( $packages, function( $packageId ){
|
||||
return $packageId != $this->id;
|
||||
} );
|
||||
|
||||
/* If the only package was the one we just deleted, set it as not purchasable but do not remove the file_nexus value or the product will become downloadable by anyone */
|
||||
if( !count( $packages ) )
|
||||
{
|
||||
Db::i()->update( 'downloads_files', array( 'file_purchasable' => 0 ), array( 'file_id=?', $file['file_id'] ) );
|
||||
}
|
||||
/* Otherwise if there are other products that can be purchased, remove this product from the purchasable list */
|
||||
else
|
||||
{
|
||||
Db::i()->update( 'downloads_files', array( 'file_nexus' => implode( ',', $packages ) ), array( 'file_id=?', $file['file_id'] ) );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get items with permisison check
|
||||
*
|
||||
* @param array $where Where clause
|
||||
* @param string $order MySQL ORDER BY clause (NULL to order by date)
|
||||
* @param int|array $limit Limit clause
|
||||
* @param string|NULL $permissionKey A key which has a value in the permission map (either of the container or of this class) matching a column ID in core_permission_index or NULL to ignore permissions
|
||||
* @param mixed $includeHiddenItems Include hidden items? NULL to detect if currently logged in member has permission, -1 to return public content only, TRUE to return unapproved content and FALSE to only return unapproved content the viewing member submitted
|
||||
* @param int $queryFlags Select bitwise flags
|
||||
* @param \IPS\Member $member The member (NULL to use currently logged in member)
|
||||
* @param bool $joinContainer If true, will join container data (set to TRUE if your $where clause depends on this data)
|
||||
* @param bool $joinComments If true, will join comment data (set to TRUE if your $where clause depends on this data)
|
||||
* @param bool $joinReviews If true, will join review data (set to TRUE if your $where clause depends on this data)
|
||||
* @param bool $countOnly If true will return the count
|
||||
* @param array|null $joins Additional arbitrary joins for the query
|
||||
* @param mixed $skipPermission If you are getting records from a specific container, pass the container to reduce the number of permission checks necessary or pass TRUE to skip conatiner-based permission. You must still specify this in the $where clause
|
||||
* @param bool $joinTags If true, will join the tags table
|
||||
* @param bool $joinAuthor If true, will join the members table for the author
|
||||
* @param bool $joinLastCommenter If true, will join the members table for the last commenter
|
||||
* @param bool $showMovedLinks If true, moved item links are included in the results
|
||||
* @param array|null $location Array of item lat and long
|
||||
* @return \IPS\Patterns\ActiveRecordIterator|int
|
||||
* @param array $where Where clause
|
||||
* @param string|null $order MySQL ORDER BY clause (NULL to order by date)
|
||||
* @param int|array|null $limit Limit clause
|
||||
* @param string $permissionKey A key which has a value in the permission map (either of the container or of this class) matching a column ID in core_permission_index or NULL to ignore permissions
|
||||
* @param int|bool|null $includeHiddenItems Include hidden items? NULL to detect if currently logged in member has permission, -1 to return public content only, TRUE to return unapproved content and FALSE to only return unapproved content the viewing member submitted
|
||||
* @param int $queryFlags Select bitwise flags
|
||||
* @param Member|null $member The member (NULL to use currently logged in member)
|
||||
* @param bool $joinContainer If true, will join container data (set to TRUE if your $where clause depends on this data)
|
||||
* @param bool $joinComments If true, will join comment data (set to TRUE if your $where clause depends on this data)
|
||||
* @param bool $joinReviews If true, will join review data (set to TRUE if your $where clause depends on this data)
|
||||
* @param bool $countOnly If true will return the count
|
||||
* @param array|null $joins Additional arbitrary joins for the query
|
||||
* @param bool|Model $skipPermission If you are getting records from a specific container, pass the container to reduce the number of permission checks necessary or pass TRUE to skip conatiner-based permission. You must still specify this in the $where clause
|
||||
* @param bool $joinTags If true, will join the tags table
|
||||
* @param bool $joinAuthor If true, will join the members table for the author
|
||||
* @param bool $joinLastCommenter If true, will join the members table for the last commenter
|
||||
* @param bool $showMovedLinks If true, moved item links are included in the results
|
||||
* @param array|null $location Array of item lat and long
|
||||
* @return ActiveRecordIterator|int
|
||||
*/
|
||||
public static function getItemsWithPermission( $where=array(), $order=NULL, $limit=10, $permissionKey='read', $includeHiddenItems=\IPS\Content\Hideable::FILTER_AUTOMATIC, $queryFlags=0, \IPS\Member $member=NULL, $joinContainer=FALSE, $joinComments=FALSE, $joinReviews=FALSE, $countOnly=FALSE, $joins=NULL, $skipPermission=FALSE, $joinTags=TRUE, $joinAuthor=TRUE, $joinLastCommenter=TRUE, $showMovedLinks=FALSE, $location=NULL )
|
||||
public static function getItemsWithPermission( array $where=array(), string $order=NULL, int|array|null $limit=10, string $permissionKey='read', int|bool|null $includeHiddenItems= Filter::FILTER_AUTOMATIC, int $queryFlags=0, ?Member $member=null, bool $joinContainer=FALSE, bool $joinComments=FALSE, bool $joinReviews=FALSE, bool $countOnly=FALSE, array|null $joins=null, bool|Model $skipPermission=FALSE, bool $joinTags=TRUE, bool $joinAuthor=TRUE, bool $joinLastCommenter=TRUE, bool $showMovedLinks=FALSE, array|null $location=null ): ActiveRecordIterator|int
|
||||
{
|
||||
$member = $member ?: \IPS\Member::loggedIn();
|
||||
$member = $member ?: Member::loggedIn();
|
||||
|
||||
$where[] = "( p_member_groups='*' OR " . \IPS\Db::i()->findInSet( 'p_member_groups', $member->groups ) . ' )';
|
||||
$where[] = "( p_member_groups='*' OR " . Db::i()->findInSet( 'p_member_groups', $member->groups ) . ' )';
|
||||
$where[] = array( 'p_store=?', 1 );
|
||||
|
||||
$return = parent::getItemsWithPermission( $where, $order, $limit, $permissionKey, $includeHiddenItems, $queryFlags, $member, $joinContainer, $joinComments, $joinReviews, $countOnly, $joins, $skipPermission, $joinTags, $joinAuthor, $joinLastCommenter, $showMovedLinks );
|
||||
@@ -196,21 +263,21 @@ class _Item extends \IPS\Content\Item implements \IPS\Content\Featurable, \IPS\C
|
||||
/**
|
||||
* @brief Cached URLs
|
||||
*/
|
||||
protected $_url = array();
|
||||
protected mixed $_url = array();
|
||||
|
||||
/**
|
||||
* Get URL
|
||||
*
|
||||
* @param string|NULL $action Action
|
||||
* @return \IPS\Http\Url
|
||||
* @return Url
|
||||
*/
|
||||
public function url( $action=NULL )
|
||||
public function url( ?string $action=NULL ): Url
|
||||
{
|
||||
$_key = md5( $action );
|
||||
$_key = $action ? md5( $action ) : NULL;
|
||||
|
||||
if( !isset( $this->_url[ $_key ] ) )
|
||||
{
|
||||
$this->_url[ $_key ] = \IPS\Http\Url::internal( "app=nexus&module=store&controller=product&id={$this->id}", 'front', 'store_product', \IPS\Http\Url\Friendly::seoTitle( \IPS\Member::loggedIn()->language()->get( 'nexus_package_' . $this->id ) ) );
|
||||
$this->_url[ $_key ] = Url::internal( "app=nexus&module=store&controller=product&id={$this->id}", 'front', 'store_product', Friendly::seoTitle( Member::loggedIn()->language()->get( 'nexus_package_' . $this->id ) ) );
|
||||
|
||||
if ( $action )
|
||||
{
|
||||
@@ -220,61 +287,32 @@ class _Item extends \IPS\Content\Item implements \IPS\Content\Featurable, \IPS\C
|
||||
|
||||
return $this->_url[ $_key ];
|
||||
}
|
||||
|
||||
/**
|
||||
* Can review?
|
||||
*
|
||||
* @param \IPS\Member\NULL $member The member (NULL for currently logged in member)
|
||||
* @param bool $considerPostBeforeRegistering If TRUE, and $member is a guest, will return TRUE if "Post Before Registering" feature is enabled
|
||||
* @return bool
|
||||
*/
|
||||
public function canReview( $member=NULL, $considerPostBeforeRegistering = TRUE )
|
||||
{
|
||||
if ( !$this->reviewable )
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
$member = $member ?: \IPS\Member::loggedIn();
|
||||
|
||||
if ( !parent::canReview( $member, $considerPostBeforeRegistering ) )
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if ( !\IPS\Db::i()->select( 'COUNT(*)', 'nexus_purchases', array( 'ps_app=? AND ps_type=? AND ps_item_id=? AND ps_member=?', 'nexus', 'package', $this->id, $member->member_id ) )->first() )
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Should new reviews be moderated?
|
||||
*
|
||||
* @param \IPS\Member $member The member posting
|
||||
* @param Member $member The member posting
|
||||
* @param bool $considerPostBeforeRegistering If TRUE, and $member is a guest, will check if a newly registered member would be moderated
|
||||
* @return bool
|
||||
*/
|
||||
public function moderateNewReviews( \IPS\Member $member, $considerPostBeforeRegistering = FALSE )
|
||||
public function moderateNewReviews( Member $member, bool $considerPostBeforeRegistering = FALSE ): bool
|
||||
{
|
||||
if ( $this->review_moderate )
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
return parent::moderateNewReviews( $member, $considerPostBeforeRegistering );
|
||||
|
||||
return $this->_moderateNewReviews( $member, $considerPostBeforeRegistering );
|
||||
}
|
||||
|
||||
/**
|
||||
* Images
|
||||
*
|
||||
* @return \IPS\File\Iterator
|
||||
* @return Iterator
|
||||
*/
|
||||
public function images()
|
||||
public function images() : Iterator
|
||||
{
|
||||
return new \IPS\File\Iterator( \IPS\Db::i()->select( 'image_location', 'nexus_package_images', array( 'image_product=?', $this->id ),'image_primary desc' ), 'nexus_Products', NULL, TRUE );
|
||||
return new Iterator( Db::i()->select( 'image_location', 'nexus_package_images', array( 'image_product=?', $this->id ),'image_primary desc' ), 'nexus_Products', NULL, TRUE );
|
||||
}
|
||||
|
||||
/* !Embeddable */
|
||||
@@ -285,46 +323,45 @@ class _Item extends \IPS\Content\Item implements \IPS\Content\Featurable, \IPS\C
|
||||
* @param array $params Additional parameters to add to URL
|
||||
* @return string
|
||||
*/
|
||||
public function embedContent( $params )
|
||||
public function embedContent( array $params ): string
|
||||
{
|
||||
$memberCurrency = ( ( isset( \IPS\Request::i()->cookie['currency'] ) and \in_array( \IPS\Request::i()->cookie['currency'], \IPS\nexus\Money::currencies() ) ) ? \IPS\Request::i()->cookie['currency'] : \IPS\nexus\Customer::loggedIn()->defaultCurrency() );
|
||||
$package = \IPS\nexus\Package::load( $this->id );
|
||||
$memberCurrency = ( ( isset( Request::i()->cookie['currency'] ) and in_array( Request::i()->cookie['currency'], Money::currencies() ) ) ? Request::i()->cookie['currency'] : Customer::loggedIn()->defaultCurrency() );
|
||||
$package = Package::load( $this->id );
|
||||
|
||||
/* Do we have renewal terms? */
|
||||
$renewalTerm = NULL;
|
||||
$renewOptions = $package->renew_options ? json_decode( $package->renew_options, TRUE ) : array();
|
||||
if ( \count( $renewOptions ) )
|
||||
if ( count( $renewOptions ) )
|
||||
{
|
||||
$renewalTerm = TRUE;
|
||||
if ( \count( $renewOptions ) === 1 )
|
||||
if ( count( $renewOptions ) === 1 )
|
||||
{
|
||||
$renewalTerm = array_pop( $renewOptions );
|
||||
$renewalTerm = new \IPS\nexus\Purchase\RenewalTerm( new \IPS\nexus\Money( $renewalTerm['cost'][ $memberCurrency ]['amount'], $memberCurrency ), new \DateInterval( 'P' . $renewalTerm['term'] . mb_strtoupper( $renewalTerm['unit'] ) ), $package->tax ? \IPS\nexus\Tax::load( $package->tax ) : NULL, $renewalTerm['add'] );
|
||||
$renewalTerm = new RenewalTerm( new Money( $renewalTerm['cost'][ $memberCurrency ]['amount'], $memberCurrency ), new DateInterval( 'P' . $renewalTerm['term'] . mb_strtoupper( $renewalTerm['unit'] ) ), $package->tax ? Tax::load( $package->tax ) : NULL, $renewalTerm['add'] );
|
||||
}
|
||||
}
|
||||
|
||||
\IPS\Output::i()->cssFiles = array_merge( \IPS\Output::i()->cssFiles, \IPS\Theme::i()->css( 'embed.css', 'nexus', 'front' ) );
|
||||
return \IPS\Theme::i()->getTemplate( 'global', 'nexus' )->embedProduct( $this, $renewalTerm, $this->url()->setQueryString( $params ), $this->embedImage() );
|
||||
Output::i()->cssFiles = array_merge( Output::i()->cssFiles, Theme::i()->css( 'embed.css', 'nexus', 'front' ) );
|
||||
return Theme::i()->getTemplate( 'global', 'nexus' )->embedProduct( $this, $renewalTerm, $this->url()->setQueryString( $params ), $this->embedImage() );
|
||||
}
|
||||
|
||||
/**
|
||||
* Get image for embed
|
||||
*
|
||||
* @return \IPS\File|NULL
|
||||
* @return File|NULL
|
||||
*/
|
||||
public function embedImage()
|
||||
public function embedImage(): ?File
|
||||
{
|
||||
$product = \IPS\nexus\Package::load( $this->id );
|
||||
return $product->_data['image'] ? \IPS\File::get( 'nexus_Products', $product->_data['image'] ) : NULL;
|
||||
return $this->_data['image'] ? File::get( 'nexus_Products', $this->_data['image'] ) : NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get mapped value
|
||||
*
|
||||
* @param string $key date,content,ip_address,first
|
||||
* @param string $key date,content,ip_address,first
|
||||
* @return mixed
|
||||
*/
|
||||
public function mapped( $key )
|
||||
public function mapped( string $key ): mixed
|
||||
{
|
||||
if ( $key === 'title' )
|
||||
{
|
||||
@@ -342,72 +379,19 @@ class _Item extends \IPS\Content\Item implements \IPS\Content\Featurable, \IPS\C
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public static function supportedMetaDataTypes()
|
||||
public static function supportedMetaDataTypes(): array
|
||||
{
|
||||
return array();
|
||||
}
|
||||
|
||||
/* !Search */
|
||||
|
||||
/**
|
||||
* Title for search index
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function searchIndexTitle()
|
||||
{
|
||||
$titles = array();
|
||||
foreach ( \IPS\Lang::languages() as $lang )
|
||||
{
|
||||
try
|
||||
{
|
||||
$titles[] = $lang->get( "nexus_package_{$this->id}" );
|
||||
}
|
||||
catch( \UnderflowException $e )
|
||||
{
|
||||
}
|
||||
}
|
||||
return implode( ' ', $titles );
|
||||
}
|
||||
|
||||
/**
|
||||
* Content for search index
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function searchIndexContent()
|
||||
{
|
||||
$descriptions = array();
|
||||
foreach ( \IPS\Lang::languages() as $lang )
|
||||
{
|
||||
try
|
||||
{
|
||||
$descriptions[] = $lang->get("nexus_package_{$this->id}_desc");
|
||||
}
|
||||
catch ( \UnderflowException $e ) { }
|
||||
}
|
||||
return implode( ' ', $descriptions );
|
||||
}
|
||||
|
||||
/**
|
||||
* Search Index Permissions
|
||||
*
|
||||
* @return string Comma-delimited values or '*'
|
||||
* @li Number indicates a group
|
||||
* @li Number prepended by "m" indicates a member
|
||||
* @li Number prepended by "s" indicates a social group
|
||||
*/
|
||||
public function searchIndexPermissions()
|
||||
{
|
||||
return $this->store ? $this->member_groups : '';
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Columns needed to query for search result / stream view
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public static function basicDataColumns()
|
||||
public static function basicDataColumns(): array
|
||||
{
|
||||
return array( 'p_id', 'p_base_price', 'p_reviews', 'p_discounts', 'p_renew_options', 'p_tax', 'p_stock', 'p_initial_term' );
|
||||
}
|
||||
@@ -418,34 +402,11 @@ class _Item extends \IPS\Content\Item implements \IPS\Content\Featurable, \IPS\C
|
||||
* @param array $indexData Data from the search index
|
||||
* @param array $itemData Basic data about the item. Only includes columns returned by item::basicDataColumns()
|
||||
* @param string|NULL $action Action
|
||||
* @return \IPS\Http\Url
|
||||
* @return Url
|
||||
*/
|
||||
public static function urlFromIndexData( $indexData, $itemData, $action = NULL )
|
||||
{
|
||||
return \IPS\Http\Url::internal( "app=nexus&module=store&controller=product&id={$indexData['index_item_id']}", 'front', 'store_product', \IPS\Member::loggedIn()->language()->addToStack( 'nexus_package_' . $indexData['index_item_id'], FALSE, array( 'seotitle' => TRUE ) ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Get HTML for search result display
|
||||
*
|
||||
* @param array $indexData Data from the search index
|
||||
* @param array $authorData Basic data about the author. Only includes columns returned by \IPS\Member::columnsForPhoto()
|
||||
* @param array $itemData Basic data about the item. Only includes columns returned by item::basicDataColumns()
|
||||
* @param array|NULL $containerData Basic data about the container. Only includes columns returned by container::basicDataColumns()
|
||||
* @param array $reputationData Array of people who have given reputation and the reputation they gave
|
||||
* @param int|NULL $reviewRating If this is a review, the rating
|
||||
* @param bool $iPostedIn If the user has posted in the item
|
||||
* @param string $view 'expanded' or 'condensed'
|
||||
* @param bool $asItem Displaying results as items?
|
||||
* @param bool $canIgnoreComments Can ignore comments in the result stream? Activity stream can, but search results cannot.
|
||||
* @param array $template Optional custom template
|
||||
* @param array $reactions Reaction Data
|
||||
* @return string
|
||||
*/
|
||||
public static function searchResult( array $indexData, array $authorData, array $itemData, ?array $containerData, array $reputationData, $reviewRating, $iPostedIn, $view, $asItem, $canIgnoreComments=FALSE, $template=NULL, $reactions=array() )
|
||||
public static function urlFromIndexData( array $indexData, array $itemData, ?string $action = NULL ) : Url
|
||||
{
|
||||
$indexData['index_title'] = \IPS\Member::loggedIn()->language()->addToStack( 'nexus_package_' . $indexData['index_item_id'] );
|
||||
return parent::searchResult( $indexData, $authorData, $itemData, $containerData, $reputationData, $reviewRating, $iPostedIn, $view, $asItem, $canIgnoreComments, $template, $reactions );
|
||||
return Url::internal( "app=nexus&module=store&controller=product&id={$indexData['index_item_id']}", 'front', 'store_product', Member::loggedIn()->language()->addToStack( 'nexus_package_' . $indexData['index_item_id'], FALSE, array( 'seotitle' => TRUE ) ) );
|
||||
}
|
||||
|
||||
|
||||
@@ -455,12 +416,12 @@ class _Item extends \IPS\Content\Item implements \IPS\Content\Featurable, \IPS\C
|
||||
* @param array $items Item data (will be an array containing values from basicDataColumns())
|
||||
* @return array
|
||||
*/
|
||||
public static function searchResultExtraData( $items )
|
||||
public static function searchResultExtraData( array $items ): array
|
||||
{
|
||||
$images = iterator_to_array( \IPS\Db::i()->select( array( 'image_product', 'image_location' ), 'nexus_package_images', array( array( \IPS\Db::i()->in( 'image_product', array_keys( $items ) ) ), array( 'image_primary=1' ) ) )->setKeyField( 'image_product' )->setValueField( 'image_location' ) );
|
||||
$images = iterator_to_array( Db::i()->select( array( 'image_product', 'image_location' ), 'nexus_package_images', array( array( Db::i()->in( 'image_product', array_keys( $items ) ) ), array( 'image_primary=1' ) ) )->setKeyField( 'image_product' )->setValueField( 'image_location' ) );
|
||||
|
||||
$taxIds = array();
|
||||
foreach ( $items as $k => $data )
|
||||
foreach ( $items as $data )
|
||||
{
|
||||
if ( $data['p_tax'] )
|
||||
{
|
||||
@@ -471,58 +432,32 @@ class _Item extends \IPS\Content\Item implements \IPS\Content\Featurable, \IPS\C
|
||||
$taxData = array();
|
||||
if ( $taxIds )
|
||||
{
|
||||
$taxData = iterator_to_array( \IPS\Db::i()->select( '*', 'nexus_tax', \IPS\Db::i()->in( 't_id', $taxIds ) )->setKeyField('t_id') );
|
||||
$taxData = iterator_to_array( Db::i()->select( '*', 'nexus_tax', Db::i()->in( 't_id', $taxIds ) )->setKeyField('t_id') );
|
||||
}
|
||||
|
||||
$return = array();
|
||||
foreach ( $items as $k => $data )
|
||||
{
|
||||
$return[ $k ]['image'] = isset( $images[ $k ] ) ? $images[ $k ] : NULL;
|
||||
$return[ $k ]['image'] = $images[$k] ?? NULL;
|
||||
$return[ $k ]['tax'] = ( $data['p_tax'] and isset( $taxData[ $data['p_tax'] ] ) ) ? $taxData[ $data['p_tax'] ] : NULL;
|
||||
}
|
||||
|
||||
return $return;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get snippet HTML for search result display
|
||||
*
|
||||
* @param array $indexData Data from the search index
|
||||
* @param array $authorData Basic data about the author. Only includes columns returned by \IPS\Member::columnsForPhoto()
|
||||
* @param array $itemData Basic data about the item. Only includes columns returned by item::basicDataColumns()
|
||||
* @param array|NULL $containerData Basic data about the container. Only includes columns returned by container::basicDataColumns()
|
||||
* @param array $reputationData Array of people who have given reputation and the reputation they gave
|
||||
* @param int|NULL $reviewRating If this is a review, the rating
|
||||
* @param string $view 'expanded' or 'condensed'
|
||||
* @return callable
|
||||
*/
|
||||
public static function searchResultSnippet( array $indexData, array $authorData, array $itemData, ?array $containerData, array $reputationData, $reviewRating, $view )
|
||||
{
|
||||
$url = static::urlFromIndexData( $indexData, $itemData );
|
||||
|
||||
/* Work out the price to display */
|
||||
$customer = \IPS\nexus\Customer::loggedIn();
|
||||
$currency = ( isset( \IPS\Request::i()->cookie['currency'] ) and \in_array( \IPS\Request::i()->cookie['currency'], \IPS\nexus\Money::currencies() ) ) ? \IPS\Request::i()->cookie['currency'] : $customer->defaultCurrency();
|
||||
$renewOptions = $itemData['p_renew_options'] ? json_decode( $itemData['p_renew_options'], TRUE ) : array();
|
||||
$priceInfo = \IPS\nexus\Package::fullPriceInfoFromData( $customer, $currency, $indexData['index_item_id'], json_decode( $itemData['p_base_price'], TRUE ), json_decode( $itemData['p_discounts'], TRUE ), $renewOptions, $itemData['p_stock'], $itemData['extra']['tax'] ? \IPS\nexus\Tax::constructFromData( $itemData['extra']['tax'] ) : NULL, $itemData['p_initial_term'] ? new \DateInterval("P{$itemData['p_initial_term']}") : NULL );
|
||||
|
||||
/* Display */
|
||||
return \IPS\Theme::i()->getTemplate( 'global', 'nexus', 'front' )->searchResultProductSnippet( $indexData, $itemData, isset( $itemData['extra']['image'] ) ? $itemData['extra']['image'] : NULL, $url, $priceInfo, $view == 'condensed' );
|
||||
}
|
||||
|
||||
/**
|
||||
* Check Moderator Permission
|
||||
*
|
||||
* @param string $type 'edit', 'hide', 'unhide', 'delete', etc.
|
||||
* @param \IPS\Member|NULL $member The member to check for or NULL for the currently logged in member
|
||||
* @param \IPS\Node\Model|NULL $container The container
|
||||
* @param Member|NULL $member The member to check for or NULL for the currently logged in member
|
||||
* @param Model|NULL $container The container
|
||||
* @return bool
|
||||
*/
|
||||
public static function modPermission( $type, \IPS\Member $member = NULL, \IPS\Node\Model $container = NULL )
|
||||
public static function modPermission( string $type, Member $member = NULL, Model $container = NULL ): bool
|
||||
{
|
||||
/* Commerce Items have no own content type, so we can use only the general mod permissions */
|
||||
$member = $member ?: \IPS\Member::loggedIn();
|
||||
if ( \in_array( $type, array( 'hide', 'unhide', 'delete' ) ) and $container )
|
||||
$member = $member ?: Member::loggedIn();
|
||||
if ( in_array( $type, array( 'hide', 'unhide', 'delete' ) ) and $container )
|
||||
{
|
||||
if ( $member->modPermission( "can_{$type}" ) )
|
||||
{
|
||||
@@ -536,77 +471,119 @@ class _Item extends \IPS\Content\Item implements \IPS\Content\Featurable, \IPS\C
|
||||
/**
|
||||
* Should posting this increment the poster's post count?
|
||||
*
|
||||
* @param \IPS\Node\Model|NULL $container Container
|
||||
* @return void
|
||||
* @param Model|NULL $container Container
|
||||
* @return bool
|
||||
*/
|
||||
public static function incrementPostCount( \IPS\Node\Model $container = NULL )
|
||||
public static function incrementPostCount( Model $container = NULL ): bool
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Can edit?
|
||||
* Check if a specific action is available for this Content.
|
||||
* Default to TRUE, but used for overrides in individual Item/Comment classes.
|
||||
*
|
||||
* @param \IPS\Member|NULL $member The member to check for (NULL for currently logged in member)
|
||||
* @return bool
|
||||
* @param string $action
|
||||
* @param Member|null $member
|
||||
* @return bool
|
||||
*/
|
||||
public function canEdit( $member=NULL )
|
||||
public function actionEnabled( string $action, ?Member $member=null ) : bool
|
||||
{
|
||||
return FALSE;
|
||||
switch( $action )
|
||||
{
|
||||
case 'edit':
|
||||
case 'move':
|
||||
return FALSE;
|
||||
|
||||
case 'review':
|
||||
if ( !$this->reviewable )
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
$member = $member ?: Member::loggedIn();
|
||||
if ( !Db::i()->select( 'COUNT(*)', 'nexus_purchases', array( 'ps_app=? AND ps_type=? AND ps_item_id=? AND ps_member=?', 'nexus', 'package', $this->id, $member->member_id ) )->first() )
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
return parent::actionEnabled( $action, $member );
|
||||
}
|
||||
|
||||
/**
|
||||
* Do Moderator Action
|
||||
*
|
||||
* @param string $action The action
|
||||
* @param \IPS\Member|NULL $member The member doing the action (NULL for currently logged in member)
|
||||
* @param Member|NULL $member The member doing the action (NULL for currently logged in member)
|
||||
* @param string|NULL $reason Reason (for hides)
|
||||
* @param bool $immediately Delete immediately
|
||||
* @return void
|
||||
* @throws \OutOfRangeException|\InvalidArgumentException|\RuntimeException
|
||||
* @throws OutOfRangeException|InvalidArgumentException|RuntimeException
|
||||
*/
|
||||
public function modAction( $action, \IPS\Member $member = NULL, $reason = NULL, $immediately = FALSE )
|
||||
public function modAction( string $action, Member $member = NULL, mixed $reason = NULL, bool $immediately=FALSE ): void
|
||||
{
|
||||
throw new \InvalidArgumentException;
|
||||
}
|
||||
|
||||
/**
|
||||
* Can move?
|
||||
*
|
||||
* @param \IPS\Member|NULL $member The member to check for (NULL for currently logged in member)
|
||||
* @return bool
|
||||
*/
|
||||
public function canMove( $member=NULL )
|
||||
{
|
||||
return FALSE;
|
||||
throw new InvalidArgumentException;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the meta description
|
||||
*
|
||||
* @param string|NULL $return Specific description to use (useful for paginated displays to prevent having to run extra queries)
|
||||
* @param string|null $return Specific description to use (useful for paginated displays to prevent having to run extra queries)
|
||||
* @return string
|
||||
* @throws \BadMethodCallException
|
||||
* @throws BadMethodCallException
|
||||
*/
|
||||
public function metaDescription( $return = NULL )
|
||||
public function metaDescription( string $return = NULL ): string
|
||||
{
|
||||
return \IPS\Member::loggedIn()->language()->addToStack("nexus_package_{$this->id}_desc", FALSE, array( 'striptags' => TRUE, 'removeNewlines' => TRUE ) );
|
||||
return Member::loggedIn()->language()->addToStack("nexus_package_{$this->id}_desc", FALSE, array( 'striptags' => TRUE, 'removeNewlines' => TRUE ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Get container
|
||||
*
|
||||
* @return \IPS\Node\Model
|
||||
* @return Model
|
||||
* @note Certain functionality requires a valid container but some areas do not use this functionality (e.g. messenger)
|
||||
* @throws \OutOfRangeException|\BadMethodCallException
|
||||
* @throws OutOfRangeException|BadMethodCallException
|
||||
*/
|
||||
public function container()
|
||||
public function container(): Model
|
||||
{
|
||||
if( $this->custom > 0 )
|
||||
{
|
||||
throw new \BadMethodCallException;
|
||||
throw new BadMethodCallException;
|
||||
}
|
||||
|
||||
return parent::container();
|
||||
}
|
||||
|
||||
/**
|
||||
* Content is hidden?
|
||||
*
|
||||
* @return int
|
||||
* @li -3 is a post made by a guest using the "post before register" feature
|
||||
* @li -2 is pending deletion
|
||||
* @li -1 is hidden having been hidden by a moderator
|
||||
* @li 0 is unhidden
|
||||
* @li 1 is hidden needing approval
|
||||
* @note The actual column may also contain 2 which means the item is hidden because the parent is hidden, but it is not hidden in itself. This method will return -1 in that case.
|
||||
*
|
||||
* @note A piece of content (item and comment) can have an alias for hidden OR approved.
|
||||
* With hidden: 0=not hidden, 1=hidden (needs moderator approval), -1=hidden by moderator, 2=parent item is hidden, -2=pending deletion, -3=guest post before register
|
||||
* With approved: 1=not hidden, 0=hidden (needs moderator approval), -1=hidden by moderator, -2=pending deletion, -3=guest post before register
|
||||
*
|
||||
* User posting has moderator approval set: When adding an unapproved ITEM (approved=0, hidden=1) you should *not* increment container()->_comments but you should update container()->_unapprovedItems
|
||||
* User posting has moderator approval set: When adding an unapproved COMMENT (approved=0, hidden=1) you should *not* increment item()->num_comments in item or container()->_comments but you should update item()->unapproved_comments and container()->_unapprovedComments
|
||||
*
|
||||
* User post is hidden by moderator (approved=-1, hidden=0) you should decrement item()->num_comments and decrement container()->_comments but *not* increment item()->unapproved_comments or container()->_unapprovedComments
|
||||
* User item is hidden by a moderator (approved=-1, hidden=0) you should decrement container()->comments and subtract comment count from container()->_comments, but *not* increment container()->_unapprovedComments
|
||||
*
|
||||
* Moderator hides item (approved=-1, hidden=-1) you should substract num_comments from container()->_comments. Comments inside item are flagged as approved=-1, hidden=2 but item()->num_comments should not be substracted from
|
||||
*
|
||||
* Comments with a hidden value of 2 should increase item()->num_comments but not container()->_comments
|
||||
* @throws RuntimeException
|
||||
*/
|
||||
public function hiddenStatus(): int
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large.
Load diff
@@ -12,70 +12,71 @@
|
||||
namespace IPS\nexus\Package;
|
||||
|
||||
/* To prevent PHP errors (extending class does not exist) revealing path */
|
||||
if ( !\defined( '\IPS\SUITE_UNIQUE_KEY' ) )
|
||||
|
||||
use DomainException;
|
||||
use IPS\Db;
|
||||
use IPS\Dispatcher;
|
||||
use IPS\Helpers\Form\Number;
|
||||
use IPS\Helpers\Form\Radio;
|
||||
use IPS\Helpers\Form\Select;
|
||||
use IPS\Helpers\Form\YesNo;
|
||||
use IPS\IPS;
|
||||
use IPS\Member;
|
||||
use IPS\nexus\Invoice;
|
||||
use IPS\nexus\Purchase;
|
||||
use IPS\nexus\Purchase\LicenseKey;
|
||||
use IPS\nexus\Package as NexusPackage;
|
||||
use IPS\Output;
|
||||
use IPS\Request;
|
||||
use IPS\Session;
|
||||
use IPS\Theme;
|
||||
use OutOfRangeException;
|
||||
use function defined;
|
||||
|
||||
if ( !defined( '\IPS\SUITE_UNIQUE_KEY' ) )
|
||||
{
|
||||
header( ( isset( $_SERVER['SERVER_PROTOCOL'] ) ? $_SERVER['SERVER_PROTOCOL'] : 'HTTP/1.0' ) . ' 403 Forbidden' );
|
||||
header( ( $_SERVER['SERVER_PROTOCOL'] ?? 'HTTP/1.0' ) . ' 403 Forbidden' );
|
||||
exit;
|
||||
}
|
||||
|
||||
/**
|
||||
* Product Package
|
||||
*/
|
||||
class _Product extends \IPS\nexus\Package
|
||||
class Product extends NexusPackage
|
||||
{
|
||||
/**
|
||||
* @brief Database Table
|
||||
*/
|
||||
protected static $packageDatabaseTable = 'nexus_packages_products';
|
||||
protected static string $packageDatabaseTable = 'nexus_packages_products';
|
||||
|
||||
/**
|
||||
* @brief Which columns belong to the local table
|
||||
*/
|
||||
protected static $packageDatabaseColumns = array( 'p_physical', 'p_subscription', 'p_shipping', 'p_weight', 'p_lkey', 'p_lkey_identifier', 'p_lkey_uses', 'p_show', 'p_length', 'p_width', 'p_height' );
|
||||
protected static array $packageDatabaseColumns = array( 'p_subscription', 'p_lkey', 'p_lkey_identifier', 'p_lkey_uses', 'p_show' );
|
||||
|
||||
/**
|
||||
* ACP Fields
|
||||
*
|
||||
* @param \IPS\nexus\Package $package The package
|
||||
* @param bool $custom If TRUE, is for a custom package
|
||||
* @param bool $customEdit If TRUE, is editing a custom package
|
||||
* @return array
|
||||
* @param NexusPackage $package The package
|
||||
* @param bool $custom If TRUE, is for a custom package
|
||||
* @param bool $customEdit If TRUE, is editing a custom package
|
||||
* @return array
|
||||
*/
|
||||
public static function acpFormFields( \IPS\nexus\Package $package, $custom=FALSE, $customEdit=FALSE )
|
||||
public static function acpFormFields(NexusPackage $package, bool $custom=FALSE, bool $customEdit=FALSE ): array
|
||||
{
|
||||
$return = array();
|
||||
$formId = $package->id ? "form_{$package->id}" : 'form_new';
|
||||
|
||||
if ( !$customEdit ) // After the package has been created, these are unimportant
|
||||
{
|
||||
$return['package_settings']['physical'] = new \IPS\Helpers\Form\YesNo( 'p_physical', $package->type === 'product' ? $package->physical : FALSE, FALSE, array( 'disableCopy' => TRUE, 'togglesOn' => array( 'p_weight', 'p_length', 'p_width', 'p_height', 'p_shipping' ), 'togglesOff' => array( 'elProductTaxWarningContainer' ) ) );
|
||||
$return['package_settings']['weight'] = new \IPS\nexus\Form\Weight( 'p_weight', $package->type === 'product' ? new \IPS\nexus\Shipping\Weight( $package->weight ) : NULL, FALSE, array( 'disableCopy' => TRUE ), NULL, NULL, NULL, 'p_weight' );
|
||||
$return['package_settings']['length'] = new \IPS\nexus\Form\Length( 'p_length', $package->type === 'product' ? new \IPS\nexus\Shipping\Length( $package->length ) : NULL, FALSE, array( 'disableCopy' => TRUE ), NULL, NULL, NULL, 'p_length' );
|
||||
$return['package_settings']['width'] = new \IPS\nexus\Form\Length( 'p_width', $package->type === 'product' ? new \IPS\nexus\Shipping\Length( $package->width ) : NULL, FALSE, array( 'disableCopy' => TRUE ), NULL, NULL, NULL, 'p_width' );
|
||||
$return['package_settings']['height'] = new \IPS\nexus\Form\Length( 'p_height', $package->type === 'product' ? new \IPS\nexus\Shipping\Length( $package->height ) : NULL, FALSE, array( 'disableCopy' => TRUE ), NULL, NULL, NULL, 'p_height' );
|
||||
|
||||
$availableShippingMethods = array();
|
||||
foreach ( \IPS\nexus\Shipping\FlatRate::roots() as $rate )
|
||||
{
|
||||
$availableShippingMethods[ $rate->_id ] = $rate->_title;
|
||||
}
|
||||
if ( \IPS\Settings::i()->easypost_api_key and \IPS\Settings::i()->easypost_show_rates )
|
||||
{
|
||||
$availableShippingMethods['easypost'] = 'enhancements__nexus_EasyPost';
|
||||
}
|
||||
$return['package_settings']['shipping'] = new \IPS\Helpers\Form\CheckboxSet( 'p_shipping', ( $package->type === 'product' and $package->shipping !== '*' ) ? explode( ',', $package->shipping ) : '*', FALSE, array( 'options' => $availableShippingMethods, 'multiple' => TRUE, 'unlimited' => '*', 'impliedUnlimited' => TRUE ), NULL, NULL, NULL, 'p_shipping' );
|
||||
}
|
||||
|
||||
$return['package_settings']['show'] = new \IPS\Helpers\Form\YesNo( 'p_show', $package->type === 'product' ? $package->show : TRUE, FALSE, array( 'togglesOn' => array( "{$formId}_tab_package_client_area", "{$formId}_header_package_associations", "{$formId}_header_package_associations_desc", 'p_associate', "{$formId}_header_package_renewals", 'p_renews', 'p_support_severity', 'p_lkey' ) ) );
|
||||
|
||||
$return['package_settings']['show'] = new YesNo( 'p_show', $package->type === 'product' ? $package->show : TRUE, FALSE, array( 'togglesOn' => array( "{$formId}_tab_package_client_area", "{$formId}_header_package_associations", "{$formId}_header_package_associations_desc", 'p_associate', "{$formId}_header_package_renewals", 'p_renews', 'p_lkey' ) ) );
|
||||
|
||||
if ( !$custom )
|
||||
{
|
||||
$return['store_permissions']['subscription'] = new \IPS\Helpers\Form\YesNo( 'p_subscription', $package->type === 'product' ? !$package->subscription : TRUE );
|
||||
$return['store_permissions']['subscription'] = new YesNo( 'p_subscription', $package->type === 'product' ? !$package->subscription : TRUE );
|
||||
}
|
||||
|
||||
$licenseKeyOptions = array();
|
||||
$licenseKeyToggles = array();
|
||||
foreach ( \IPS\nexus\Purchase\LicenseKey::licenseKeyTypes() as $key => $class )
|
||||
foreach ( LicenseKey::licenseKeyTypes() as $key => $class )
|
||||
{
|
||||
$licenseKeyOptions[ mb_strtolower( $key ) ] = 'lkey_' . $key;
|
||||
$licenseKeyToggles[ mb_strtolower( $key ) ] = array( 'p_lkey_identifier', 'p_lkey_uses' );
|
||||
@@ -83,10 +84,10 @@ class _Product extends \IPS\nexus\Package
|
||||
if ( !empty( $licenseKeyOptions ) )
|
||||
{
|
||||
array_unshift( $licenseKeyOptions, 'lkey_none' );
|
||||
$return['package_benefits']['lkey'] = new \IPS\Helpers\Form\Radio( 'p_lkey', $package->type === 'product' ? $package->lkey : 0, FALSE, array( 'options' => $licenseKeyOptions, 'toggles' => $licenseKeyToggles ), NULL, NULL, NULL, 'p_lkey' );
|
||||
$return['package_benefits']['lkey'] = new Radio( 'p_lkey', $package->type === 'product' ? $package->lkey : 0, FALSE, array( 'options' => $licenseKeyOptions, 'toggles' => $licenseKeyToggles ), NULL, NULL, NULL, 'p_lkey' );
|
||||
}
|
||||
|
||||
$return['package_benefits']['lkey_uses'] = new \IPS\Helpers\Form\Number( 'p_lkey_uses', $package->type === 'product' ? $package->lkey_uses : -1, FALSE, array( 'unlimited' => -1 ) );
|
||||
$return['package_benefits']['lkey_uses'] = new Number( 'p_lkey_uses', $package->type === 'product' ? $package->lkey_uses : -1, FALSE, array( 'unlimited' => -1 ) );
|
||||
|
||||
$identifierOptions = array(
|
||||
'name' => 'lkey_identifier_name',
|
||||
@@ -95,13 +96,13 @@ class _Product extends \IPS\nexus\Package
|
||||
);
|
||||
if ( $package->id )
|
||||
{
|
||||
foreach ( \IPS\nexus\Package\CustomField::roots( NULL, NULL, array( array( \IPS\Db::i()->findInSet( 'cf_packages', array( $package->id ) ) ) ) ) as $field )
|
||||
foreach (CustomField::roots( NULL, NULL, array( array( Db::i()->findInSet( 'cf_packages', array( $package->id ) ) ) ) ) as $field )
|
||||
{
|
||||
$identifierOptions[ $field->id ] = $field->_title;
|
||||
}
|
||||
}
|
||||
|
||||
$return['package_benefits']['lkey_identifier'] = new \IPS\Helpers\Form\Select( 'p_lkey_identifier', $package->type === 'product' ? $package->lkey_identifier : '0', FALSE, array( 'options' => $identifierOptions, 'unlimited' => '0', 'unlimitedLang' => 'lkey_identifier_none' ), NULL, NULL, NULL, 'p_lkey_identifier' );
|
||||
$return['package_benefits']['lkey_identifier'] = new Select( 'p_lkey_identifier', $package->type === 'product' ? $package->lkey_identifier : '0', FALSE, array( 'options' => $identifierOptions, 'unlimited' => '0', 'unlimitedLang' => 'lkey_identifier_none' ), NULL, NULL, NULL, 'p_lkey_identifier' );
|
||||
|
||||
return $return;
|
||||
}
|
||||
@@ -112,53 +113,9 @@ class _Product extends \IPS\nexus\Package
|
||||
* @param array $values Values from the form
|
||||
* @return array
|
||||
*/
|
||||
public function formatFormValues( $values )
|
||||
{
|
||||
if( isset( $values['p_subscription'] ) )
|
||||
{
|
||||
$values['p_subscription'] = isset( $values['p_subscription'] ) ? !$values['p_subscription'] : FALSE;
|
||||
}
|
||||
|
||||
if( isset( $values['p_weight'] ) )
|
||||
{
|
||||
$values['p_weight'] = \is_object( $values['p_weight'] ) ? $values['p_weight']->kilograms : 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
$values['p_weight'] = 0;
|
||||
}
|
||||
|
||||
if( isset( $values['p_length'] ) )
|
||||
{
|
||||
$values['p_length'] = \is_object( $values['p_length'] ) ? $values['p_length']->metres : 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
$values['p_length'] = 0;
|
||||
}
|
||||
|
||||
if( isset( $values['p_width'] ) )
|
||||
{
|
||||
$values['p_width'] = \is_object( $values['p_width'] ) ? $values['p_width']->metres : 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
$values['p_width'] = 0;
|
||||
}
|
||||
|
||||
if( isset( $values['p_height'] ) )
|
||||
{
|
||||
$values['p_height'] = \is_object( $values['p_height'] ) ? $values['p_height']->metres : 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
$values['p_height'] = 0;
|
||||
}
|
||||
|
||||
if( isset( $values['p_shipping'] ) )
|
||||
{
|
||||
$values['p_shipping'] = \is_array( $values['p_shipping'] ) ? implode( ',', $values['p_shipping'] ) : '*';
|
||||
}
|
||||
public function formatFormValues( array $values ): array
|
||||
{
|
||||
$values['p_subscription'] = isset( $values['p_subscription'] ) ? !$values['p_subscription'] : FALSE;
|
||||
|
||||
return parent::formatFormValues( $values );
|
||||
}
|
||||
@@ -168,7 +125,7 @@ class _Product extends \IPS\nexus\Package
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public static function updateableFields()
|
||||
public static function updateableFields() : array
|
||||
{
|
||||
return array_merge( parent::updateableFields(), array(
|
||||
'lkey',
|
||||
@@ -181,17 +138,15 @@ class _Product extends \IPS\nexus\Package
|
||||
/**
|
||||
* Update existing purchases
|
||||
*
|
||||
* @param \IPS\nexus\Purchase $purchase The purchase
|
||||
* @param array $changes The old values
|
||||
* @param bool $cancelBillingAgreementIfNecessary If making changes to renewal terms, TRUE will cancel associated billing agreements. FALSE will skip that change
|
||||
* @return void
|
||||
* @param Purchase $purchase The purchase
|
||||
* @param array $changes The old values
|
||||
* @param bool $cancelBillingAgreementIfNecessary If making changes to renewal terms, TRUE will cancel associated billing agreements. FALSE will skip that change
|
||||
* @return void
|
||||
*/
|
||||
public function updatePurchase( \IPS\nexus\Purchase $purchase, $changes, $cancelBillingAgreementIfNecessary=FALSE )
|
||||
public function updatePurchase(Purchase $purchase, array $changes, bool $cancelBillingAgreementIfNecessary=FALSE ): void
|
||||
{
|
||||
if ( array_key_exists( 'lkey', $changes ) )
|
||||
{
|
||||
$oldKey = NULL;
|
||||
|
||||
$lKey = $purchase->licenseKey();
|
||||
|
||||
if ( $lKey )
|
||||
@@ -199,11 +154,11 @@ class _Product extends \IPS\nexus\Package
|
||||
$lKey->delete();
|
||||
}
|
||||
|
||||
$licenseTypes = \IPS\nexus\Purchase\LicenseKey::licenseKeyTypes();
|
||||
$licenseTypes = LicenseKey::licenseKeyTypes();
|
||||
|
||||
if( class_exists( $licenseTypes[ mb_ucfirst( $this->lkey ) ]) )
|
||||
if( class_exists( $licenseTypes[ IPS::mb_ucfirst( $this->lkey ) ]) )
|
||||
{
|
||||
$class = $licenseTypes[ mb_ucfirst( $this->lkey ) ];
|
||||
$class = $licenseTypes[ IPS::mb_ucfirst( $this->lkey ) ];
|
||||
$licenseKey = new $class;
|
||||
$licenseKey->identifier = $this->lkey_identifier;
|
||||
$licenseKey->purchase = $purchase;
|
||||
@@ -230,7 +185,7 @@ class _Product extends \IPS\nexus\Package
|
||||
$purchase->save();
|
||||
}
|
||||
|
||||
return parent::updatePurchase( $purchase, $changes, $cancelBillingAgreementIfNecessary );
|
||||
parent::updatePurchase( $purchase, $changes, $cancelBillingAgreementIfNecessary );
|
||||
}
|
||||
|
||||
/* !Actions */
|
||||
@@ -238,23 +193,23 @@ class _Product extends \IPS\nexus\Package
|
||||
/**
|
||||
* Add To Cart
|
||||
*
|
||||
* @param \IPS\nexus\extensions\nexus\Item\Package $item The item
|
||||
* @param \IPS\nexus\Invoice\Item $item The item
|
||||
* @param array $values Values from form
|
||||
* @param string $memberCurrency The currency being used
|
||||
* @return array Additional items to add
|
||||
* @param string $memberCurrency The currency being used
|
||||
* @return array Additional items to add
|
||||
*/
|
||||
public function addToCart( \IPS\nexus\extensions\nexus\Item\Package $item, array $values, $memberCurrency )
|
||||
public function addToCart(\IPS\nexus\Invoice\Item $item, array $values, string $memberCurrency ): array
|
||||
{
|
||||
if ( $this->subscription )
|
||||
{
|
||||
if ( $item->quantity > 1 )
|
||||
{
|
||||
\IPS\Output::i()->error( 'err_subscription_qty', '1X247/2', 403, '' );
|
||||
Output::i()->error( 'err_subscription_qty', '1X247/2', 403, '' );
|
||||
}
|
||||
|
||||
if ( $this->_memberHasPurchasedSubscription( \IPS\Member::loggedIn() ) )
|
||||
if ( $this->_memberHasPurchasedSubscription( Member::loggedIn() ) )
|
||||
{
|
||||
\IPS\Output::i()->error( 'err_subscription_bought', '1X247/1', 403, '' );
|
||||
Output::i()->error( 'err_subscription_bought', '1X247/1', 403, '' );
|
||||
}
|
||||
|
||||
if ( isset( $_SESSION['cart'] ) )
|
||||
@@ -263,7 +218,7 @@ class _Product extends \IPS\nexus\Package
|
||||
{
|
||||
if ( $_item->id === $this->id )
|
||||
{
|
||||
\IPS\Output::i()->error( 'err_subscription_in_cart', '1X247/3', 403, '' );
|
||||
Output::i()->error( 'err_subscription_in_cart', '1X247/3', 403, '' );
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -278,31 +233,31 @@ class _Product extends \IPS\nexus\Package
|
||||
* is ran to check the items they are purchasing can be bought.
|
||||
* Is expected to throw a DomainException with an error message to display to the user if not valid
|
||||
*
|
||||
* @param \IPS\Member $member The new member
|
||||
* @return void
|
||||
* @throws \DomainException
|
||||
* @param Member $member The new member
|
||||
* @return void
|
||||
* @throws DomainException
|
||||
*/
|
||||
public function memberCanPurchase( \IPS\Member $member )
|
||||
public function memberCanPurchase( Member $member ): void
|
||||
{
|
||||
if ( $this->subscription and $this->_memberHasPurchasedSubscription( $member ) )
|
||||
{
|
||||
throw new \DomainException( $member->language()->addToStack( 'err_subscription_bought_login', FALSE, array( 'sprintf' => array( $member->language()->addToStack( "nexus_package_{$this->id}" ) ) ) ) );
|
||||
throw new DomainException( $member->language()->addToStack( 'err_subscription_bought_login', FALSE, array( 'sprintf' => array( $member->language()->addToStack( "nexus_package_{$this->id}" ) ) ) ) );
|
||||
}
|
||||
if ( ! ( $this->member_groups == "*" or !empty( ( array_intersect( explode( ",", $this->member_groups ), $member->groups ) ) ) ) )
|
||||
{
|
||||
throw new \DomainException( $member->language()->addToStack( 'err_group_cant_purchase', FALSE, array( 'sprintf' => array( $member->language()->addToStack( "nexus_package_{$this->id}" ) ) ) ) );
|
||||
throw new DomainException( $member->language()->addToStack( 'err_group_cant_purchase', FALSE, array( 'sprintf' => array( $member->language()->addToStack( "nexus_package_{$this->id}" ) ) ) ) );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if a member has purchased this subscription product
|
||||
*
|
||||
* @param \IPS\Member $member The new member
|
||||
* @param Member $member The new member
|
||||
* @return bool
|
||||
*/
|
||||
protected function _memberHasPurchasedSubscription( \IPS\Member $member )
|
||||
protected function _memberHasPurchasedSubscription( Member $member ) : bool
|
||||
{
|
||||
return (bool) \IPS\Db::i()->select( 'COUNT(*)', 'nexus_purchases', array( 'ps_app=? AND ps_type=? AND ps_item_id=? AND ps_cancelled=0 AND ps_member=?', 'nexus', 'package', $this->id, $member->member_id ) )->first();
|
||||
return (bool) Db::i()->select( 'COUNT(*)', 'nexus_purchases', array( 'ps_app=? AND ps_type=? AND ps_item_id=? AND ps_cancelled=0 AND ps_member=?', 'nexus', 'package', $this->id, $member->member_id ) )->first();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -310,7 +265,7 @@ class _Product extends \IPS\nexus\Package
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function showPurchaseRecord()
|
||||
public function showPurchaseRecord(): bool
|
||||
{
|
||||
return $this->show;
|
||||
}
|
||||
@@ -318,36 +273,39 @@ class _Product extends \IPS\nexus\Package
|
||||
/**
|
||||
* Get ACP Page HTML
|
||||
*
|
||||
* @return string
|
||||
* @param Purchase $purchase
|
||||
* @return string
|
||||
*/
|
||||
public function acpPage( \IPS\nexus\Purchase $purchase )
|
||||
public function acpPage( Purchase $purchase ): string
|
||||
{
|
||||
if ( $this->lkey and \IPS\Member::loggedIn()->hasAcpRestriction( 'nexus', 'customers', 'lkeys_view' ) )
|
||||
if ( $this->lkey and Member::loggedIn()->hasAcpRestriction( 'nexus', 'customers', 'lkeys_view' ) )
|
||||
{
|
||||
if ( $lkey = $purchase->licenseKey() )
|
||||
{
|
||||
return \IPS\Theme::i()->getTemplate('purchases')->lkey( $lkey );
|
||||
return Theme::i()->getTemplate('purchases')->lkey( $lkey );
|
||||
}
|
||||
else
|
||||
{
|
||||
return \IPS\Theme::i()->getTemplate('purchases')->noLkey( $purchase );
|
||||
return Theme::i()->getTemplate('purchases')->noLkey( $purchase );
|
||||
}
|
||||
}
|
||||
|
||||
return '';
|
||||
}
|
||||
|
||||
/**
|
||||
* ACP Action
|
||||
*
|
||||
* @param \IPS\nexus\Purchase $purchase The purchase
|
||||
* @return void
|
||||
* @param Purchase $purchase The purchase
|
||||
* @return string|null
|
||||
*/
|
||||
public function acpAction( \IPS\nexus\Purchase $purchase )
|
||||
public function acpAction( Purchase $purchase ): string|null
|
||||
{
|
||||
switch ( \IPS\Request::i()->act )
|
||||
switch ( Request::i()->act )
|
||||
{
|
||||
case 'lkeyReset':
|
||||
\IPS\Dispatcher::i()->checkAcpPermission( 'lkeys_reset' );
|
||||
\IPS\Session::i()->csrfCheck();
|
||||
Dispatcher::i()->checkAcpPermission( 'lkeys_reset' );
|
||||
Session::i()->csrfCheck();
|
||||
|
||||
$oldKey = NULL;
|
||||
try
|
||||
@@ -358,13 +316,13 @@ class _Product extends \IPS\nexus\Package
|
||||
$old->delete();
|
||||
}
|
||||
}
|
||||
catch ( \OutOfRangeException $e ) { }
|
||||
catch ( OutOfRangeException ) { }
|
||||
|
||||
/* Invalidate License Key Cache so old data is not loaded */
|
||||
$purchase->licenseKey = NULL;
|
||||
|
||||
$licenseTypes = \IPS\nexus\Purchase\LicenseKey::licenseKeyTypes();
|
||||
$class = $licenseTypes[ mb_ucfirst( $this->lkey ) ];
|
||||
$licenseTypes = LicenseKey::licenseKeyTypes();
|
||||
$class = $licenseTypes[ IPS::mb_ucfirst( $this->lkey ) ];
|
||||
$licenseKey = new $class;
|
||||
$licenseKey->identifier = $this->lkey_identifier;
|
||||
$licenseKey->purchase = $purchase;
|
||||
@@ -372,7 +330,7 @@ class _Product extends \IPS\nexus\Package
|
||||
$licenseKey->save();
|
||||
|
||||
$purchase->member->log( 'lkey', array( 'type' => 'reset', 'key' => $oldKey, 'new' => $licenseKey->key, 'ps_id' => $purchase->id, 'ps_name' => $purchase->name ) );
|
||||
break;
|
||||
return null;
|
||||
|
||||
default:
|
||||
return parent::acpAction( $purchase );
|
||||
@@ -382,16 +340,16 @@ class _Product extends \IPS\nexus\Package
|
||||
/**
|
||||
* On Purchase Generated
|
||||
*
|
||||
* @param \IPS\nexus\Purchase $purchase The purchase
|
||||
* @param \IPS\nexus\Invoice $invoice The invoice
|
||||
* @return void
|
||||
* @param Purchase $purchase The purchase
|
||||
* @param Invoice $invoice The invoice
|
||||
* @return void
|
||||
*/
|
||||
public function onPurchaseGenerated( \IPS\nexus\Purchase $purchase, \IPS\nexus\Invoice $invoice )
|
||||
public function onPurchaseGenerated(Purchase $purchase, Invoice $invoice ): void
|
||||
{
|
||||
if ( $this->lkey )
|
||||
{
|
||||
$licenseTypes = \IPS\nexus\Purchase\LicenseKey::licenseKeyTypes();
|
||||
$class = $licenseTypes[ mb_ucfirst( $this->lkey ) ];
|
||||
$licenseTypes = LicenseKey::licenseKeyTypes();
|
||||
$class = $licenseTypes[ IPS::mb_ucfirst( $this->lkey ) ];
|
||||
$licenseKey = new $class;
|
||||
$licenseKey->identifier = $this->lkey_identifier;
|
||||
$licenseKey->purchase = $purchase;
|
||||
@@ -405,10 +363,10 @@ class _Product extends \IPS\nexus\Package
|
||||
/**
|
||||
* Warning to display to admin when cancelling a purchase
|
||||
*
|
||||
* @param \IPS\nexus\Purchase $purchase The purchase
|
||||
* @return string
|
||||
* @param Purchase $purchase The purchase
|
||||
* @return string|null
|
||||
*/
|
||||
public function onCancelWarning( \IPS\nexus\Purchase $purchase )
|
||||
public function onCancelWarning( Purchase $purchase ): string|null
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -12,53 +12,78 @@
|
||||
namespace IPS\nexus\Package;
|
||||
|
||||
/* To prevent PHP errors (extending class does not exist) revealing path */
|
||||
if ( !\defined( '\IPS\SUITE_UNIQUE_KEY' ) )
|
||||
|
||||
use DateInterval;
|
||||
use IPS\Content\EditHistory;
|
||||
use IPS\Content\Embeddable;
|
||||
use IPS\Content\Filter;
|
||||
use IPS\Content\Hideable;
|
||||
use IPS\Content\Reportable;
|
||||
use IPS\Content\Review as ContentReview;
|
||||
use IPS\Content\Shareable;
|
||||
use IPS\core\Approval;
|
||||
use IPS\nexus\Customer;
|
||||
use IPS\nexus\Money;
|
||||
use IPS\nexus\Package;
|
||||
use IPS\nexus\Purchase\RenewalTerm;
|
||||
use IPS\nexus\Tax;
|
||||
use IPS\Output;
|
||||
use IPS\Request;
|
||||
use IPS\Theme;
|
||||
use OutOfRangeException;
|
||||
use function count;
|
||||
use function defined;
|
||||
use function get_called_class;
|
||||
use function in_array;
|
||||
|
||||
if ( !defined( '\IPS\SUITE_UNIQUE_KEY' ) )
|
||||
{
|
||||
header( ( isset( $_SERVER['SERVER_PROTOCOL'] ) ? $_SERVER['SERVER_PROTOCOL'] : 'HTTP/1.0' ) . ' 403 Forbidden' );
|
||||
header( ( $_SERVER['SERVER_PROTOCOL'] ?? 'HTTP/1.0' ) . ' 403 Forbidden' );
|
||||
exit;
|
||||
}
|
||||
|
||||
/**
|
||||
* Package Review
|
||||
*/
|
||||
class _Review extends \IPS\Content\Review implements \IPS\Content\EditHistory, \IPS\Content\Hideable, \IPS\Content\Embeddable
|
||||
class Review extends ContentReview implements Embeddable,
|
||||
Filter
|
||||
{
|
||||
use \IPS\Content\Reportable;
|
||||
use Reportable, Shareable, EditHistory, Hideable;
|
||||
|
||||
/**
|
||||
* @brief [ActiveRecord] Multiton Store
|
||||
*/
|
||||
protected static $multitons;
|
||||
protected static array $multitons;
|
||||
|
||||
/**
|
||||
* @brief [Content\Comment] Item Class
|
||||
*/
|
||||
public static $itemClass = 'IPS\nexus\Package\Item';
|
||||
public static ?string $itemClass = 'IPS\nexus\Package\Item';
|
||||
|
||||
/**
|
||||
* @brief [ActiveRecord] Database Table
|
||||
*/
|
||||
public static $databaseTable = 'nexus_reviews';
|
||||
public static ?string $databaseTable = 'nexus_reviews';
|
||||
|
||||
/**
|
||||
* @brief [ActiveRecord] Database Prefix
|
||||
*/
|
||||
public static $databasePrefix = 'review_';
|
||||
public static string $databasePrefix = 'review_';
|
||||
|
||||
/**
|
||||
* @brief Title
|
||||
*/
|
||||
public static $title = 'product_reviews';
|
||||
public static string $title = 'product_reviews';
|
||||
|
||||
/**
|
||||
* @brief Icon
|
||||
*/
|
||||
public static $icon = 'archive';
|
||||
public static string $icon = 'box';
|
||||
|
||||
/**
|
||||
* @brief Database Column Map
|
||||
*/
|
||||
public static $databaseColumnMap = array(
|
||||
public static array $databaseColumnMap = array(
|
||||
'item' => 'product',
|
||||
'author' => 'author_id',
|
||||
'author_name' => 'author_name',
|
||||
@@ -81,36 +106,36 @@ class _Review extends \IPS\Content\Review implements \IPS\Content\EditHistory, \
|
||||
/**
|
||||
* @brief Application
|
||||
*/
|
||||
public static $application = 'nexus';
|
||||
public static string $application = 'nexus';
|
||||
|
||||
/**
|
||||
* @brief Module
|
||||
*/
|
||||
public static $module = 'store';
|
||||
public static string $module = 'store';
|
||||
|
||||
/**
|
||||
* @brief [Content] Key for hide reasons
|
||||
*/
|
||||
public static $hideLogKey = 'nexus-products';
|
||||
public static ?string $hideLogKey = 'nexus-products';
|
||||
|
||||
/**
|
||||
* @brief [Content\Item] First "comment" is part of the item?
|
||||
*/
|
||||
public static $firstCommentRequired = FALSE;
|
||||
public static bool $firstCommentRequired = FALSE;
|
||||
|
||||
/**
|
||||
* @brief Include In Sitemap
|
||||
*/
|
||||
public static $includeInSitemap = FALSE;
|
||||
public static bool $includeInSitemap = FALSE;
|
||||
|
||||
/**
|
||||
* Get content for header in content tables
|
||||
*
|
||||
* @return callable
|
||||
*/
|
||||
public function contentTableHeader()
|
||||
public function contentTableHeader(): string
|
||||
{
|
||||
return \IPS\Theme::i()->getTemplate( 'global', static::$application )->commentTableHeader( $this, \IPS\nexus\Package::load( $this->item()->id ), $this->item() );
|
||||
return (string) Theme::i()->getTemplate( 'global', static::$application )->commentTableHeader( $this, Package::load( $this->item()->id ), $this->item() );
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -119,26 +144,26 @@ class _Review extends \IPS\Content\Review implements \IPS\Content\EditHistory, \
|
||||
* @param array $params Additional parameters to add to URL
|
||||
* @return string
|
||||
*/
|
||||
public function embedContent( $params )
|
||||
public function embedContent( array $params ): string
|
||||
{
|
||||
$memberCurrency = ( ( isset( \IPS\Request::i()->cookie['currency'] ) and \in_array( \IPS\Request::i()->cookie['currency'], \IPS\nexus\Money::currencies() ) ) ? \IPS\Request::i()->cookie['currency'] : \IPS\nexus\Customer::loggedIn()->defaultCurrency() );
|
||||
$package = \IPS\nexus\Package::load( $this->id );
|
||||
$memberCurrency = ( ( isset( Request::i()->cookie['currency'] ) and in_array( Request::i()->cookie['currency'], Money::currencies() ) ) ? Request::i()->cookie['currency'] : Customer::loggedIn()->defaultCurrency() );
|
||||
$package = Package::load( $this->id );
|
||||
|
||||
/* Do we have renewal terms? */
|
||||
$renewalTerm = NULL;
|
||||
$renewOptions = $package->renew_options ? json_decode( $package->renew_options, TRUE ) : array();
|
||||
if ( \count( $renewOptions ) )
|
||||
if ( count( $renewOptions ) )
|
||||
{
|
||||
$renewalTerm = TRUE;
|
||||
if ( \count( $renewOptions ) === 1 )
|
||||
if ( count( $renewOptions ) === 1 )
|
||||
{
|
||||
$renewalTerm = array_pop( $renewOptions );
|
||||
$renewalTerm = new \IPS\nexus\Purchase\RenewalTerm( new \IPS\nexus\Money( $renewalTerm['cost'][ $memberCurrency ]['amount'], $memberCurrency ), new \DateInterval( 'P' . $renewalTerm['term'] . mb_strtoupper( $renewalTerm['unit'] ) ), $package->tax ? \IPS\nexus\Tax::load( $package->tax ) : NULL, $renewalTerm['add'] );
|
||||
$renewalTerm = new RenewalTerm( new Money( $renewalTerm['cost'][ $memberCurrency ]['amount'], $memberCurrency ), new DateInterval( 'P' . $renewalTerm['term'] . mb_strtoupper( $renewalTerm['unit'] ) ), $package->tax ? Tax::load( $package->tax ) : NULL, $renewalTerm['add'] );
|
||||
}
|
||||
}
|
||||
|
||||
\IPS\Output::i()->cssFiles = array_merge( \IPS\Output::i()->cssFiles, \IPS\Theme::i()->css( 'embed.css', 'nexus', 'front' ) );
|
||||
return \IPS\Theme::i()->getTemplate( 'global', 'nexus' )->embedProductReview( $this, $this->item(), $renewalTerm, $this->url()->setQueryString( $params ) );
|
||||
Output::i()->cssFiles = array_merge( Output::i()->cssFiles, Theme::i()->css( 'embed.css', 'nexus', 'front' ) );
|
||||
return Theme::i()->getTemplate( 'global', 'nexus' )->embedProductReview( $this, $this->item(), $renewalTerm, $this->url()->setQueryString( $params ) );
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -146,7 +171,7 @@ class _Review extends \IPS\Content\Review implements \IPS\Content\EditHistory, \
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function postCreate()
|
||||
public function postCreate(): void
|
||||
{
|
||||
parent::postCreate();
|
||||
|
||||
@@ -155,15 +180,15 @@ class _Review extends \IPS\Content\Review implements \IPS\Content\EditHistory, \
|
||||
{
|
||||
try
|
||||
{
|
||||
\IPS\core\Approval::loadFromContent( \get_called_class(), $this->id );
|
||||
Approval::loadFromContent( get_called_class(), $this->id );
|
||||
}
|
||||
catch( \OutOfRangeException $e )
|
||||
catch( OutOfRangeException )
|
||||
{
|
||||
/* No reason found - see if product requires approval of reviews */
|
||||
if ( $this->item()->review_moderate )
|
||||
{
|
||||
$log = new \IPS\core\Approval;
|
||||
$log->content_class = \get_called_class();
|
||||
$log = new Approval;
|
||||
$log->content_class = get_called_class();
|
||||
$log->content_id = $this->id;
|
||||
$log->held_reason = 'item';
|
||||
$log->save();
|
||||
|
||||
Reference in new issue
Block a user