Version 4.7.6
This commit is contained in:
1 parent
8ba7d43898
commit
7b7404e741
1085 files changed
+30590
-7837
No files matched your search
+234
-32
@@ -404,6 +404,12 @@ abstract class _Content extends \IPS\Patterns\ActiveRecord
|
||||
\IPS\Db::i()->delete( 'core_content_featured', [ 'feature_content_id=? and feature_content_class=?', $this->$idColumn, \get_class( $this ) ] );
|
||||
|
||||
\IPS\Api\Webhook::fire( str_replace( '\\', '', \substr( \get_called_class(), 3 ) ) . '_delete', $this, $this->webhookFilters() );
|
||||
|
||||
try
|
||||
{
|
||||
\IPS\core\Approval::loadFromContent( \get_called_class(), $this->$idColumn )->delete();
|
||||
}
|
||||
catch( \OutOfRangeException $e ) { }
|
||||
|
||||
parent::delete();
|
||||
|
||||
@@ -455,9 +461,10 @@ abstract class _Content extends \IPS\Patterns\ActiveRecord
|
||||
* @param string $autoSaveLocation The autosave location key of any editors to check, or NULL to use the default.
|
||||
* @param string|NULL $autoSaveKeys The autosave keys (for new content) or attach lookup ids (for an edit) of any editors to check, or NULL to use the default.
|
||||
* @param array $imageUploads Images that have been uploaded that may require moderation
|
||||
* @param array|NULL $filtersMatched What matched, passed by reference
|
||||
* @return bool Whether to send unapproved notifications (i.e. true if the content was hidden)
|
||||
*/
|
||||
public function shouldTriggerProfanityFilters( $first=FALSE, $edit=TRUE, $content=NULL, $title=NULL, $autoSaveLocation=NULL, $autoSaveKeys=NULL, $imageUploads=[], &$hiddenByFilter = FALSE, &$itemHiddenByFilter = FALSE )
|
||||
public function shouldTriggerProfanityFilters( $first=FALSE, $edit=TRUE, $content=NULL, $title=NULL, $autoSaveLocation=NULL, $autoSaveKeys=NULL, $imageUploads=[], &$hiddenByFilter = FALSE, &$itemHiddenByFilter = FALSE, array &$filtersMatched = array() )
|
||||
{
|
||||
/* Set our content */
|
||||
$content = $content ?: $this->content();
|
||||
@@ -528,11 +535,23 @@ abstract class _Content extends \IPS\Patterns\ActiveRecord
|
||||
$binds = array_merge( $binds, $_autoSaveKeys );
|
||||
}
|
||||
|
||||
$hiddenByFilter = \IPS\core\Profanity::hiddenByFilters( $content, $member );
|
||||
|
||||
if ( $title AND !$hiddenByFilter )
|
||||
if ( $this instanceof \IPS\Content\Item OR ( $first AND $item::$firstCommentRequired ) )
|
||||
{
|
||||
$hiddenByFilter = \IPS\core\Profanity::hiddenByFilters( $title, $member );
|
||||
$itemHiddenByFilter = \IPS\core\Profanity::hiddenByFilters( $content, $member, $filtersMatched );
|
||||
|
||||
if ( $title AND !$itemHiddenByFilter )
|
||||
{
|
||||
$itemHiddenByFilter = \IPS\core\Profanity::hiddenByFilters( $title, $member, $filtersMatched );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
$hiddenByFilter = \IPS\core\Profanity::hiddenByFilters( $content, $member, $filtersMatched );
|
||||
|
||||
if ( $title AND !$hiddenByFilter )
|
||||
{
|
||||
$hiddenByFilter = \IPS\core\Profanity::hiddenByFilters( $title, $member, $filtersMatched );
|
||||
}
|
||||
}
|
||||
|
||||
$attachmentsMapWhere = array_merge( array( 'location_key=? AND ( ' . implode( ' OR ', $clauses ) . ' )', $autoSaveLocation ), $binds );
|
||||
@@ -559,11 +578,23 @@ abstract class _Content extends \IPS\Patterns\ActiveRecord
|
||||
}
|
||||
}
|
||||
|
||||
$itemHiddenByFilter = \IPS\core\Profanity::hiddenByFilters( $content, $member );
|
||||
|
||||
if ( $title AND !$itemHiddenByFilter )
|
||||
if ( $this instanceof \IPS\Content\Item OR ( $first AND $item::$firstCommentRequired ) )
|
||||
{
|
||||
$itemHiddenByFilter = \IPS\core\Profanity::hiddenByFilters( $title, $member );
|
||||
$itemHiddenByFilter = \IPS\core\Profanity::hiddenByFilters( $content, $member, $filtersMatched );
|
||||
|
||||
if ( $title AND !$itemHiddenByFilter )
|
||||
{
|
||||
$itemHiddenByFilter = \IPS\core\Profanity::hiddenByFilters( $title, $member, $filtersMatched );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
$hiddenByFilter = \IPS\core\Profanity::hiddenByFilters( $content, $member, $filtersMatched );
|
||||
|
||||
if ( $title AND !$hiddenByFilter )
|
||||
{
|
||||
$hiddenByFilter = \IPS\core\Profanity::hiddenByFilters( $title, $member, $filtersMatched );
|
||||
}
|
||||
}
|
||||
|
||||
$attachmentsMapWhere = \IPS\Db::i()->in( 'temp', array_map( 'md5', $autoSaveKeys ) );
|
||||
@@ -602,6 +633,15 @@ abstract class _Content extends \IPS\Patterns\ActiveRecord
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if ( $hiddenByFilter OR $itemHiddenByFilter )
|
||||
{
|
||||
$log = new \IPS\core\Approval;
|
||||
$log->content_class = \get_called_class();
|
||||
$log->content_id = $this->$idColumn;
|
||||
$log->held_reason = 'image';
|
||||
$log->save();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -612,22 +652,22 @@ abstract class _Content extends \IPS\Patterns\ActiveRecord
|
||||
{
|
||||
if ( !$itemHiddenByFilter )
|
||||
{
|
||||
$itemHiddenByFilter = \IPS\core\Profanity::hiddenByFilters( $content );
|
||||
$itemHiddenByFilter = \IPS\core\Profanity::hiddenByFilters( $content, $member, $filtersMatched );
|
||||
}
|
||||
if ( !$itemHiddenByFilter and $title )
|
||||
{
|
||||
$itemHiddenByFilter = \IPS\core\Profanity::hiddenByFilters( $title );
|
||||
$itemHiddenByFilter = \IPS\core\Profanity::hiddenByFilters( $title, $member, $filtersMatched );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( !$hiddenByFilter )
|
||||
{
|
||||
$hiddenByFilter = \IPS\core\Profanity::hiddenByFilters( $content );
|
||||
$hiddenByFilter = \IPS\core\Profanity::hiddenByFilters( $content, $member, $filtersMatched );
|
||||
}
|
||||
if ( !$hiddenByFilter and $title )
|
||||
{
|
||||
$hiddenByFilter = \IPS\core\Profanity::hiddenByFilters( $title );
|
||||
$hiddenByFilter = \IPS\core\Profanity::hiddenByFilters( $title, $member, $filtersMatched );
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -650,13 +690,20 @@ abstract class _Content extends \IPS\Patterns\ActiveRecord
|
||||
* @return bool Whether to send unapproved notifications (i.e. true if the content was hidden)
|
||||
*/
|
||||
public function checkProfanityFilters( $first=FALSE, $edit=TRUE, $content=NULL, $title=NULL, $autoSaveLocation=NULL, $autoSaveKeys=NULL, $imageUploads=[] )
|
||||
{
|
||||
{
|
||||
/* Check this content type is hideable */
|
||||
if ( !( $this instanceof \IPS\Content\Hideable ) )
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* Check it */
|
||||
$hiddenByFilter = FALSE;
|
||||
$itemHiddenByFilter = FALSE;
|
||||
$sendNotifications = FALSE;
|
||||
$filtersMatched = array();
|
||||
$item = ( $this instanceof \IPS\Content\Item ) ? $this : $this->item();
|
||||
$this->shouldTriggerProfanityFilters( $first, $edit, $content, $title, $autoSaveLocation, $autoSaveKeys, $imageUploads, $hiddenByFilter, $itemHiddenByFilter );
|
||||
$this->shouldTriggerProfanityFilters( $first, $edit, $content, $title, $autoSaveLocation, $autoSaveKeys, $imageUploads, $hiddenByFilter, $itemHiddenByFilter, $filtersMatched );
|
||||
|
||||
/* If we need to hide the item, then do that */
|
||||
if ( $itemHiddenByFilter )
|
||||
@@ -698,6 +745,54 @@ abstract class _Content extends \IPS\Patterns\ActiveRecord
|
||||
$this->$column = ( $itemHiddenByFilter and $this instanceof \IPS\Content\Comment ) ? 2 : 1; # We use the special 2 flag to note it is only hidden because the parent is
|
||||
$this->save();
|
||||
}
|
||||
|
||||
$idColumn = static::$databaseColumnId;
|
||||
$itemColumnId = $item::$databaseColumnId;
|
||||
|
||||
try
|
||||
{
|
||||
if ( $this instanceof \IPS\Content\Comment AND $item::$firstCommentRequired AND $this->isFirst() )
|
||||
{
|
||||
\IPS\core\Approval::loadFromContent( \get_class( $item ), $item->$itemColumnId );
|
||||
}
|
||||
else
|
||||
{
|
||||
\IPS\core\Approval::loadFromContent( \get_called_class(), $this->$idColumn );
|
||||
}
|
||||
}
|
||||
catch( \OutOfRangeException $e )
|
||||
{
|
||||
if ( isset( $filtersMatched['type'] ) AND isset( $filtersMatched['match'] ) )
|
||||
{
|
||||
$log = new \IPS\core\Approval;
|
||||
if ( $this instanceof \IPS\Content\Comment AND $item::$firstCommentRequired AND $this->isFirst() )
|
||||
{
|
||||
$log->content_class = \get_class( $item );
|
||||
$log->content_id = $item->$itemColumnId;
|
||||
}
|
||||
else
|
||||
{
|
||||
$log->content_class = \get_called_class();
|
||||
$log->content_id = $this->$idColumn;
|
||||
}
|
||||
$log->held_reason = $filtersMatched['type'];
|
||||
switch( $filtersMatched['type'] )
|
||||
{
|
||||
case 'profanity':
|
||||
$log->held_data = array( 'word' => $filtersMatched['match'] );
|
||||
break;
|
||||
|
||||
case 'url':
|
||||
$log->held_data = array( 'url' => $filtersMatched['match'] );
|
||||
break;
|
||||
|
||||
case 'email':
|
||||
$log->held_data = array( 'email' => $filtersMatched['match'] );
|
||||
break;
|
||||
}
|
||||
$log->save();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* If we did either, then recount number of comments */
|
||||
@@ -706,8 +801,8 @@ abstract class _Content extends \IPS\Patterns\ActiveRecord
|
||||
$item->resyncCommentCounts();
|
||||
$item->resyncLastComment();
|
||||
$item->save();
|
||||
|
||||
if ( $container = $item->containerWrapper() )
|
||||
|
||||
if ( $first AND $container = $item->containerWrapper() )
|
||||
{
|
||||
$container->resetCommentCounts();
|
||||
$container->save();
|
||||
@@ -959,7 +1054,7 @@ abstract class _Content extends \IPS\Patterns\ActiveRecord
|
||||
$this->$column = $val;
|
||||
$this->save();
|
||||
|
||||
if ( $action == 'feature' )
|
||||
if ( $action == 'feature' and $this->author()->member_id )
|
||||
{
|
||||
\IPS\Db::i()->insert( 'core_content_featured', [
|
||||
'feature_content_id' => $this->$idColumn,
|
||||
@@ -1092,6 +1187,8 @@ abstract class _Content extends \IPS\Patterns\ActiveRecord
|
||||
|
||||
try
|
||||
{
|
||||
$idColumn = static::$databaseColumnId;
|
||||
|
||||
if ( $this->container() AND !$this->skipContainerRebuild )
|
||||
{
|
||||
$this->container()->resetCommentCounts();
|
||||
@@ -1109,10 +1206,11 @@ abstract class _Content extends \IPS\Patterns\ActiveRecord
|
||||
}
|
||||
else
|
||||
{
|
||||
$idColumn = static::$databaseColumnId;
|
||||
$this->container()->rebuildPostedIn( array($this->$idColumn) );
|
||||
}
|
||||
}
|
||||
|
||||
\IPS\core\Approval::loadFromContent( \get_called_class(), $this->$idColumn )->delete();
|
||||
}
|
||||
catch( \BadMethodCallException $e ) {}
|
||||
catch( \OutOfRangeException $e ) {}
|
||||
@@ -1256,9 +1354,9 @@ abstract class _Content extends \IPS\Patterns\ActiveRecord
|
||||
$this->save();
|
||||
$this->onHide( $member );
|
||||
|
||||
$idColumn = static::$databaseColumnId;
|
||||
if ( static::$hideLogKey )
|
||||
{
|
||||
$idColumn = static::$databaseColumnId;
|
||||
\IPS\Db::i()->delete( 'core_soft_delete_log', array( 'sdl_obj_id=? AND sdl_obj_key=?', $this->$idColumn, static::$hideLogKey ) );
|
||||
\IPS\Db::i()->insert( 'core_soft_delete_log', array(
|
||||
'sdl_obj_id' => $this->$idColumn,
|
||||
@@ -1283,6 +1381,12 @@ abstract class _Content extends \IPS\Patterns\ActiveRecord
|
||||
|
||||
$this->expireWidgetCaches();
|
||||
$this->adjustSessions();
|
||||
|
||||
try
|
||||
{
|
||||
\IPS\core\Approval::loadFromContent( \get_called_class(), $this->$idColumn )->delete();
|
||||
}
|
||||
catch( \OutOfRangeException $e ) { }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1346,10 +1450,10 @@ abstract class _Content extends \IPS\Patterns\ActiveRecord
|
||||
}
|
||||
$this->save();
|
||||
$this->onUnhide( ( $approving OR ( $pbr AND $this->hidden() === 0 ) ), $member );
|
||||
|
||||
|
||||
$idColumn = static::$databaseColumnId;
|
||||
if ( static::$hideLogKey )
|
||||
{
|
||||
$idColumn = static::$databaseColumnId;
|
||||
\IPS\Db::i()->delete('core_soft_delete_log', array('sdl_obj_id=? AND sdl_obj_key=?', $this->$idColumn, static::$hideLogKey));
|
||||
}
|
||||
|
||||
@@ -1405,6 +1509,12 @@ abstract class _Content extends \IPS\Patterns\ActiveRecord
|
||||
|
||||
$this->expireWidgetCaches();
|
||||
$this->adjustSessions();
|
||||
|
||||
try
|
||||
{
|
||||
\IPS\core\Approval::loadFromContent( \get_called_class(), $this->$idColumn )->delete();
|
||||
}
|
||||
catch( \OutOfRangeException $e ) { }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1443,7 +1553,42 @@ abstract class _Content extends \IPS\Patterns\ActiveRecord
|
||||
}
|
||||
catch ( \UnderflowException $e )
|
||||
{
|
||||
$this->hiddenBlurb = \IPS\Member::loggedIn()->language()->addToStack('hidden');
|
||||
/* If this is requiring approval and has a logged reason */
|
||||
$hidden = $this->hidden();
|
||||
$item = NULL;
|
||||
if ( ( $this instanceof \IPS\Content\Comment ) )
|
||||
{
|
||||
$item = $this->item();
|
||||
/* If this is the first comment, and it's required, then we need to check the items hidden status instead */
|
||||
if ( $item::$firstCommentRequired AND $this->isFirst() AND $hidden !== 1 )
|
||||
{
|
||||
$hidden = $this->item()->hidden();
|
||||
}
|
||||
}
|
||||
|
||||
if ( $hidden === 1 )
|
||||
{
|
||||
/* If moderator, show the reason */
|
||||
$reason = NULL;
|
||||
if( $this->modPermission( 'unhide' ) )
|
||||
{
|
||||
$reason = ( $item and $item::$firstCommentRequired AND $this->isFirst() ) ? $item->approvalQueueReason() : $this->approvalQueueReason();
|
||||
}
|
||||
|
||||
if ( $reason )
|
||||
{
|
||||
$this->hiddenBlurb = \IPS\Member::loggedIn()->language()->addToStack( 'hidden_with_reason', FALSE, array( 'sprintf' => array( $reason ) ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Otherwise show a message that the content requires approval before it can be edited. */
|
||||
$this->hiddenBlurb = \IPS\Member::loggedIn()->language()->addToStack( 'hidden_awaiting_approval' );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
$this->hiddenBlurb = \IPS\Member::loggedIn()->language()->addToStack('hidden');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1482,6 +1627,33 @@ abstract class _Content extends \IPS\Patterns\ActiveRecord
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Reason for requiring approval
|
||||
*/
|
||||
protected $_approvalQueueReason = NULL;
|
||||
|
||||
/**
|
||||
* Approval Queue Reason
|
||||
*
|
||||
* @return bool|string
|
||||
*/
|
||||
public function approvalQueueReason()
|
||||
{
|
||||
if ( $this->_approvalQueueReason === NULL )
|
||||
{
|
||||
try
|
||||
{
|
||||
$idColumn = static::$databaseColumnId;
|
||||
$this->_approvalQueueReason = \IPS\core\Approval::loadFromContent( \get_class( $this ), $this->$idColumn )->reason();
|
||||
}
|
||||
catch( \OutOfRangeException $e )
|
||||
{
|
||||
$this->_approvalQueueReason = NULL;
|
||||
}
|
||||
}
|
||||
return $this->_approvalQueueReason;
|
||||
}
|
||||
|
||||
/**
|
||||
* Can promote this comment/item?
|
||||
*
|
||||
@@ -1615,6 +1787,9 @@ abstract class _Content extends \IPS\Patterns\ActiveRecord
|
||||
|
||||
/* Find or create an index */
|
||||
$idColumn = static::$databaseColumnId;
|
||||
$item = ( $this instanceof \IPS\Content\Comment ) ? $this->item() : $this;
|
||||
$itemIdColumn = $item::$databaseColumnId;
|
||||
|
||||
try
|
||||
{
|
||||
$index = \IPS\core\Reports\Report::load( $this->$idColumn, 'content_id', array( 'class=?', \get_called_class() ) );
|
||||
@@ -1633,6 +1808,8 @@ abstract class _Content extends \IPS\Patterns\ActiveRecord
|
||||
$index->num_reports = 1;
|
||||
$index->num_comments = 0;
|
||||
$index->auto_moderation_exempt = 0;
|
||||
$index->item_id = $item->$itemIdColumn;
|
||||
$index->node_id = $item->containerWrapper() ? $item->containerWrapper()->_id : 0;
|
||||
}
|
||||
|
||||
/* Only set this to a new report if it is not already under review */
|
||||
@@ -1658,7 +1835,7 @@ abstract class _Content extends \IPS\Patterns\ActiveRecord
|
||||
|
||||
/* Run automatic moderation */
|
||||
$index->runAutomaticModeration();
|
||||
|
||||
|
||||
/* Send notification to mods */
|
||||
$moderators = array( 'm' => array(), 'g' => array() );
|
||||
foreach ( \IPS\Db::i()->select( '*', 'core_moderators' ) as $mod )
|
||||
@@ -1671,21 +1848,38 @@ abstract class _Content extends \IPS\Patterns\ActiveRecord
|
||||
if ( $canView === FALSE )
|
||||
{
|
||||
$perms = json_decode( $mod['perms'], TRUE );
|
||||
|
||||
|
||||
if ( isset( $perms['can_view_reports'] ) AND $perms['can_view_reports'] === TRUE )
|
||||
{
|
||||
$canView = TRUE;
|
||||
}
|
||||
|
||||
/* Got nodes? */
|
||||
if ( $canView === TRUE and $container = $item->containerWrapper() and isset( $container::$modPerm ) )
|
||||
{
|
||||
if ( isset( $perms[ $container::$modPerm ] ) and $perms[ $container::$modPerm ] != '*' and $perms[ $container::$modPerm ] != -1 )
|
||||
{
|
||||
if ( empty( $perms[ $container::$modPerm ] ) or ! in_array( $item->mapped('container'), $perms[ $container::$modPerm ] ) )
|
||||
{
|
||||
$canView = FALSE;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if ( $canView === TRUE )
|
||||
{
|
||||
$moderators[ $mod['type'] ][] = $mod['id'];
|
||||
}
|
||||
}
|
||||
|
||||
$notification = new \IPS\Notification( \IPS\Application::load('core'), 'report_center', $index, array( $index, $reportInsert, $this ) );
|
||||
foreach ( \IPS\Db::i()->select( '*', 'core_members', ( \count( $moderators['m'] ) ? \IPS\Db::i()->in( 'member_id', $moderators['m'] ) . ' OR ' : '' ) . \IPS\Db::i()->in( 'member_group_id', $moderators['g'] ) . ' OR ' . \IPS\Db::i()->findInSet( 'mgroup_others', $moderators['g'] ) ) as $member )
|
||||
foreach ( \IPS\Db::i()->select( '*', 'core_members', ( \count( $moderators['m'] ) ? \IPS\Db::i()->in( 'member_id', $moderators['m'] ) . ' OR ' : '' ) . \IPS\Db::i()->in( 'member_group_id', $moderators['g'] ) . ' OR ' . \IPS\Db::i()->findInSet( 'mgroup_others', $moderators['g'] ) ) as $mem )
|
||||
{
|
||||
$notification->recipients->attach( \IPS\Member::constructFromData( $member ) );
|
||||
$memberObj = \IPS\Member::constructFromData( $mem );
|
||||
if( $this->canView( $memberObj ) )
|
||||
{
|
||||
$notification->recipients->attach( $memberObj );
|
||||
}
|
||||
}
|
||||
$notification->send();
|
||||
|
||||
@@ -1696,7 +1890,7 @@ abstract class _Content extends \IPS\Patterns\ActiveRecord
|
||||
/* Return */
|
||||
return $index;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Change IP Address
|
||||
* @param string $ip The new IP address
|
||||
@@ -2433,10 +2627,11 @@ abstract class _Content extends \IPS\Patterns\ActiveRecord
|
||||
$notification = new \IPS\Notification( \IPS\Application::load('core'), 'unapproved_content', $this, array( $this, $this->author() ) );
|
||||
foreach ( \IPS\Db::i()->select( '*', 'core_members', ( \count( $moderators['m'] ) ? \IPS\Db::i()->in( 'member_id', $moderators['m'] ) . ' OR ' : '' ) . \IPS\Db::i()->in( 'member_group_id', $moderators['g'] ) . ' OR ' . \IPS\Db::i()->findInSet( 'mgroup_others', $moderators['g'] ) ) as $member )
|
||||
{
|
||||
/* We don't need to notify the author of the content */
|
||||
if( $this->author()->member_id != $member['member_id'] )
|
||||
$member = \IPS\Member::constructFromData( $member );
|
||||
/* We don't need to notify the author of the content or when member cannot view this content*/
|
||||
if( $this->author()->member_id != $member->member_id AND $this->canView( $member ) )
|
||||
{
|
||||
$notification->recipients->attach(\IPS\Member::constructFromData($member));
|
||||
$notification->recipients->attach( $member );
|
||||
}
|
||||
}
|
||||
$notification->send();
|
||||
@@ -2607,7 +2802,14 @@ abstract class _Content extends \IPS\Patterns\ActiveRecord
|
||||
{
|
||||
if( $this instanceof \IPS\Content\Comment )
|
||||
{
|
||||
$item = $this->item();
|
||||
try
|
||||
{
|
||||
$item = $this->item();
|
||||
}
|
||||
catch( \OutOfRangeException $e )
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
Reference in new issue
Block a user