Version 5.0.13
This commit is contained in:
1 parent
b89858b2ff
commit
5efe744c5f
1407 files changed
+69690
-30177
No files matched your search
@@ -14,19 +14,27 @@ namespace IPS\core;
|
||||
|
||||
use Exception;
|
||||
use IPS\Application;
|
||||
use IPS\Content;
|
||||
use IPS\Db;
|
||||
use IPS\Dispatcher;
|
||||
use IPS\Email;
|
||||
use IPS\Extensions\AdvertisementLocationsAbstract;
|
||||
use IPS\File;
|
||||
use IPS\Helpers\Form\CheckboxSet;
|
||||
use IPS\Helpers\Form\Node;
|
||||
use IPS\Helpers\Form\Number;
|
||||
use IPS\Helpers\Form\Radio;
|
||||
use IPS\Helpers\Form\Select;
|
||||
use IPS\Lang;
|
||||
use IPS\Member;
|
||||
use IPS\Member\Group;
|
||||
use IPS\Output;
|
||||
use IPS\Patterns\ActiveRecord;
|
||||
use IPS\Redis;
|
||||
use IPS\Request;
|
||||
use IPS\Settings;
|
||||
use IPS\Theme;
|
||||
use OutOfRangeException;
|
||||
use function count;
|
||||
use function defined;
|
||||
|
||||
@@ -102,11 +110,245 @@ class Advertisement extends ActiveRecord
|
||||
* @brief List all default location codes
|
||||
*/
|
||||
public static array $defaultLocations = [
|
||||
'ad_global_header',
|
||||
'ad_global_footer',
|
||||
'ad_sidebar'
|
||||
'ad_global_header' => array( 'ad_apps' ),
|
||||
'ad_global_footer' => array( 'ad_apps' ),
|
||||
'ad_sidebar' => array( 'ad_apps' )
|
||||
];
|
||||
|
||||
/**
|
||||
* Return an array of form elements that will handle location-based settings
|
||||
*
|
||||
* @param array $currentValues
|
||||
* @param array $currentLocations
|
||||
* @return array
|
||||
*/
|
||||
public static function locationFields( array $currentValues, array $currentLocations ) : array
|
||||
{
|
||||
$settingFields = [];
|
||||
$applications = [];
|
||||
$appToggles = [];
|
||||
$nodeFields = [];
|
||||
$defaultLocations = static::$defaultLocations;
|
||||
foreach( Application::enabledApplications() as $app )
|
||||
{
|
||||
$applications[ $app->directory ] = $app->_title;
|
||||
foreach( $app->extensions( 'core', 'ContentRouter' ) as $router )
|
||||
{
|
||||
if( !isset( $appToggles[ $app->directory ] ) )
|
||||
{
|
||||
$appToggles[ $app->directory ] = [];
|
||||
}
|
||||
|
||||
foreach( $router->classes as $itemClass )
|
||||
{
|
||||
if( isset( $itemClass::$containerNodeClass ) )
|
||||
{
|
||||
$nodeClass = $itemClass::$containerNodeClass;
|
||||
|
||||
/* Skip nodes that can be created by users, such as blogs */
|
||||
if( !empty( $nodeClass::$ownerTypes ) )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
$key = str_replace( '\\', '_', $nodeClass );
|
||||
$field = new Node( $key, $currentValues[ $key ] ?? 0, false, [
|
||||
'class' => $nodeClass,
|
||||
'multiple' => true,
|
||||
'zeroVal' => 'all',
|
||||
'nodeGroups' => true
|
||||
], null, null, null, $key );
|
||||
$field->label = Member::loggedIn()->language()->addToStack( $nodeClass::$nodeTitle );
|
||||
$nodeFields[] = $field;
|
||||
$appToggles[ $app->directory ][] = $key;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Add a field to restrict by app */
|
||||
$settingFields['ad_apps'] = new Select( 'ad_apps', $currentValues['ad_apps'] ?? -1, false, array(
|
||||
'options' => $applications,
|
||||
'multiple' => true,
|
||||
'unlimitedLang' => 'all',
|
||||
'toggles' => $appToggles
|
||||
), null, null, null, 'ad_apps' );
|
||||
|
||||
foreach( $nodeFields as $field )
|
||||
{
|
||||
$settingFields[ $field->htmlId ] = $field;
|
||||
}
|
||||
|
||||
/* Now grab ad location extensions */
|
||||
foreach ( Application::allExtensions( 'core', 'AdvertisementLocations', FALSE, 'core' ) as $key => $extension )
|
||||
{
|
||||
/* @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['ad_view_type'] = new Radio( 'ad_view_type', $currentValues['ad_view_type'] ?? null, true, [
|
||||
'options' => [
|
||||
'interval' => 'ad_view_type__interval',
|
||||
'fixed' => 'ad_view_type__fixed'
|
||||
],
|
||||
'toggles' => [
|
||||
'interval' => [ 'ad_view_number', 'ad_view_repeat' ],
|
||||
'fixed' => [ 'ad_view_position' ]
|
||||
]
|
||||
], null, null, null, 'ad_view_type' );
|
||||
|
||||
$settingFields['ad_view_number'] = new Number( 'ad_view_number', ( isset( $currentValues['ad_view_number'] ) AND $currentValues['ad_view_number'] ) ? $currentValues['ad_view_number'] : 1, null, array( 'min' => 1 ), NULL, NULL, Member::loggedIn()->language()->addToStack('ad_view_number_suffix'), 'ad_view_number' );
|
||||
|
||||
$settingFields['ad_view_repeat'] = 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' );
|
||||
|
||||
$settingFields['ad_view_position'] = new Number( 'ad_view_position', $currentValues['ad_view_position'] ?? 1, null, id: 'ad_view_position' );
|
||||
|
||||
foreach( $result['locations'] as $location => $toggles )
|
||||
{
|
||||
$defaultLocations[ $location ][] = 'ad_view_type';
|
||||
}
|
||||
}
|
||||
|
||||
if( isset( $result['settings'] ) )
|
||||
{
|
||||
$settingFields = $settingFields + $result['settings'];
|
||||
}
|
||||
}
|
||||
|
||||
/* Make location optional so that you can have an active ad for widgets only */
|
||||
$locationField = new CheckboxSet( 'ad_location',
|
||||
array_intersect( array_keys( $defaultLocations ), $currentLocations ),
|
||||
false,
|
||||
array(
|
||||
'options' => array_combine( array_keys( $defaultLocations ), array_keys( $defaultLocations ) ),
|
||||
'toggles' => $defaultLocations,
|
||||
'noDefault' => true
|
||||
),
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
'ad_location'
|
||||
);
|
||||
|
||||
return [ 'ad_location' => $locationField ] + $settingFields;
|
||||
}
|
||||
|
||||
/**
|
||||
* Format the location settings for saving
|
||||
*
|
||||
* @param array $values
|
||||
* @return array
|
||||
*/
|
||||
public static function processLocationFields( array $values ) : array
|
||||
{
|
||||
/* Any additional settings to save? */
|
||||
$additionalSettings = array(
|
||||
'ad_apps' => ( isset( $values['ad_apps'] ) AND is_array( $values['ad_apps'] ) ) ? array_values( $values['ad_apps'] ) : 0
|
||||
);
|
||||
|
||||
if( is_array( $additionalSettings['ad_apps'] ) )
|
||||
{
|
||||
foreach( $additionalSettings['ad_apps'] as $app )
|
||||
{
|
||||
foreach( Application::load( $app )->extensions( 'core', 'ContentRouter' ) as $router )
|
||||
{
|
||||
foreach( $router->classes as $itemClass )
|
||||
{
|
||||
if( isset( $itemClass::$containerNodeClass ) )
|
||||
{
|
||||
$key = str_replace( '\\', '_', $itemClass::$containerNodeClass );
|
||||
if( !empty( $values[ $key ] ) and is_array( $values[ $key ] ) )
|
||||
{
|
||||
$additionalSettings[ $key ] = array_keys( $values[ $key ] );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
foreach ( Application::allExtensions( 'core', 'AdvertisementLocations', FALSE, 'core' ) as $key => $extension )
|
||||
{
|
||||
if( $extension::$listView )
|
||||
{
|
||||
$additionalSettings['ad_view_type'] = $values['ad_view_type'] ?? 'interval';
|
||||
if( $additionalSettings['ad_view_type'] == 'fixed' )
|
||||
{
|
||||
$additionalSettings['ad_view_position'] = $values['ad_view_position'] ?? 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
$additionalSettings['ad_view_number'] = $values['ad_view_number'] ?? 1;
|
||||
$additionalSettings['ad_view_repeat'] = $values['ad_view_repeat'] ?? 0;
|
||||
}
|
||||
}
|
||||
|
||||
$settings = $extension->parseSettings( $values );
|
||||
|
||||
$additionalSettings = array_merge( $additionalSettings, $settings );
|
||||
}
|
||||
|
||||
return $additionalSettings;
|
||||
}
|
||||
|
||||
/**
|
||||
* Array of form elements for email advertisement configuration
|
||||
*
|
||||
* @param array $currentValues
|
||||
* @return array
|
||||
*/
|
||||
public static function emailFields( array $currentValues ) : array
|
||||
{
|
||||
$fields = [];
|
||||
|
||||
/* Container restrictions for email ads */
|
||||
$containerClasses = array();
|
||||
$containerToggles = array();
|
||||
|
||||
foreach( Content::routedClasses( FALSE, FALSE, TRUE ) as $contentItemClass )
|
||||
{
|
||||
if( isset( $contentItemClass::$containerNodeClass ) AND $contentItemClass::$containerNodeClass AND !isset( $containerClasses[ $contentItemClass::$containerNodeClass ] ) )
|
||||
{
|
||||
$containerClass = $contentItemClass::$containerNodeClass;
|
||||
|
||||
$containerClasses[ $containerClass ] = $contentItemClass::$title . '_pl';
|
||||
$containerToggles[ $containerClass ] = array( 'node_' . md5( $containerClass ) );
|
||||
}
|
||||
}
|
||||
|
||||
if( count( $containerClasses ) )
|
||||
{
|
||||
$fields['_ad_email_container'] = new Select( '_ad_email_container', $currentValues['email_container'] ?? '*', FALSE, array( 'options' => $containerClasses, 'multiple' => FALSE, 'unlimited' => '*', 'unlimitedLang' => 'unrestricted', 'toggles' => $containerToggles ), NULL, NULL, NULL, '_ad_email_container' );
|
||||
|
||||
foreach( $containerClasses as $classname => $lang )
|
||||
{
|
||||
$containerField = new Node( 'ad_node_' . md5( $classname ), $currentValues['email_node'] ?? 0, FALSE, array( 'class' => $classname, 'zeroVal' => 'any', 'multiple' => TRUE, 'forceOwner' => FALSE ), NULL, NULL, NULL, 'node_' . md5( $classname ) );
|
||||
$containerField->label = Member::loggedIn()->language()->addToStack( $classname::$nodeTitle );
|
||||
$fields[ 'node_' . md5( $classname ) ] = $containerField;
|
||||
}
|
||||
}
|
||||
|
||||
return $fields;
|
||||
}
|
||||
|
||||
/**
|
||||
* Format email fields for saving
|
||||
*
|
||||
* @param array $values
|
||||
* @return array
|
||||
*/
|
||||
public static function processEmailFields( array $values ) : array
|
||||
{
|
||||
return [
|
||||
'email_container' => $values['_ad_email_container'],
|
||||
'email_node' => ( $values['_ad_email_container'] != '*' ) ? ( ( $values['ad_node_' . md5( $values['_ad_email_container'] ) ] == 0 ) ? 0 : array_keys( $values['ad_node_' . md5( $values['_ad_email_container'] ) ] ) ) : 0
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetch advertisements and return the appropriate one to display
|
||||
*
|
||||
@@ -162,17 +404,55 @@ class Advertisement extends ActiveRecord
|
||||
}
|
||||
|
||||
/* Weed out any ads that we don't see due to the application settings */
|
||||
if ( in_array( $adLocation, static::$defaultLocations ) and isset( $ad->_additional_settings['ad_apps'] ) and is_array( $ad->_additional_settings['ad_apps'] ) and $ad->_additional_settings != 0 )
|
||||
if ( array_key_exists( $adLocation, static::$defaultLocations ) and isset( $ad->_additional_settings['ad_apps'] ) and ( is_array( $ad->_additional_settings['ad_apps'] ) and count( $ad->_additional_settings['ad_apps'] ) ) and $ad->_additional_settings != 0 )
|
||||
{
|
||||
if ( !in_array( Dispatcher::i()->application->directory, $ad->_additional_settings['ad_apps'] ) )
|
||||
{
|
||||
unset( static::$advertisements[ $adLocation ][ $index ] );
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Check if we have a content class defined */
|
||||
if( isset( Output::i()->bodyAttributes['contentClass'] ) )
|
||||
{
|
||||
$contentId = Request::i()->id ?? 0;
|
||||
$class = Output::i()->bodyAttributes['contentClass'];
|
||||
if( isset( $class::$containerNodeClass ) )
|
||||
{
|
||||
if( isset( Request::i()->id ) )
|
||||
{
|
||||
try
|
||||
{
|
||||
$item = $class::load( Request::i()->id );
|
||||
$contentId = $item->mapped( 'container' );
|
||||
}
|
||||
catch( OutOfRangeException ){}
|
||||
}
|
||||
|
||||
$class = $class::$containerNodeClass;
|
||||
}
|
||||
|
||||
$key = str_replace( '\\', '_', $class );
|
||||
if( isset( $ad->_additional_settings[ $key ] ) and is_array( $ad->_additional_settings[ $key ] ) and !in_array( $contentId, $ad->_additional_settings[ $key ] ) )
|
||||
{
|
||||
unset( static::$advertisements[ $adLocation ][ $index ] );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* If we defined specific nodes, and we are on a general page (e.g. an index page), skip this ad */
|
||||
foreach( $ad->_additional_settings as $k => $v )
|
||||
{
|
||||
if( str_starts_with( $k, 'IPS_' . Dispatcher::i()->application->directory ) )
|
||||
{
|
||||
unset( static::$advertisements[ $adLocation ][ $index ] );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if( !in_array( $adLocation, static::$defaultLocations ) )
|
||||
if( !array_key_exists( $adLocation, static::$defaultLocations ) )
|
||||
{
|
||||
foreach ( $ads as $index => $ad )
|
||||
{
|
||||
@@ -461,8 +741,23 @@ class Advertisement extends ActiveRecord
|
||||
break;
|
||||
}
|
||||
|
||||
$indexNumber = $ad->_additional_settings[ 'ad_view_number' ] ?? false;
|
||||
$repeat = $ad->_additional_settings[ 'ad_view_repeat' ] ?? false;
|
||||
/* Fixed position ads have a set position and do not repeat */
|
||||
if( isset( $ad->_additional_settings['ad_view_type'] ) and $ad->_additional_settings['ad_view_type'] == 'fixed' )
|
||||
{
|
||||
$indexNumber = $ad->_additional_settings['ad_view_position'] ?? 1;
|
||||
$repeat = 1;
|
||||
|
||||
/* Ignore this entirely if we are not in the correct position */
|
||||
if( $position != $indexNumber )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
$indexNumber = $ad->_additional_settings[ 'ad_view_number' ] ?? false;
|
||||
$repeat = $ad->_additional_settings[ 'ad_view_repeat' ] ?? false;
|
||||
}
|
||||
|
||||
if( $indexNumber !== false )
|
||||
{
|
||||
@@ -724,6 +1019,4 @@ class Advertisement extends ActiveRecord
|
||||
Db::i()->update( 'core_advertisements', "ad_impressions=ad_impressions+" . $by . ", ad_daily_impressions=ad_daily_impressions+" . $by, "ad_id IN(" . implode( ',', $ids ) . ")" );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
Reference in new issue
Block a user